Pooja M. Bohora
Pooja M. Bohora

Reputation: 1331

Applying border to image shape

In my application I am having various images of different different shapes. Like tree, cloud. (Sample image is attached). I want to add border to those shapes pro-grammatically. Like if image is of tree then need to highlight tree shape. I cannot use calayer as it will apply border to UIImageView. Can anyone guide me how to achieve this?

sample image

Upvotes: 7

Views: 2770

Answers (4)

nikstar
nikstar

Reputation: 51

This can be achieved this by using a series of CIFilters. See images corresponding to steps below. In my example base image is a color image with transparent background and mask is black and white.

  1. Use CIEdges to detect edges from the mask.

  2. Then make edges thicker by applying disk maximum filter (CIMorphologyMaximum).

  3. Convert borders image from black-and-white to transparent-and-white with CIMaskToAlpha

  4. Overlay original image on top of borders.

Full code below:

let base = CIImage(cgImage: baseImage.cgImage!)
let mask = CIImage(cgImage: maskImage.cgImage!)
        
// 1
let edges = mask.applyingFilter("CIEdges", parameters: [
   kCIInputIntensityKey: 1.0
])
    
// 2    
let borderWidth = 0.02 * min(baseImage.size.width, baseImage.size.height)
let wideEdges = edges.applyingFilter("CIMorphologyMaximum", parameters: [
    kCIInputRadiusKey: borderWidth
])
        
// 3
let background = wideEdges.applyingFilter("CIMaskToAlpha")
      
// 4  
let composited = base.composited(over: background)
        
// Convert back to UIImage
let context = CIContext(options: nil)
let cgImageRef = context.createCGImage(composited, from: composited.extent)!
return UIImage(cgImage: cgImageRef)

Upvotes: 3

greg
greg

Reputation: 2006

I just did the same thing but with a white border. I created a mask with a white body and 4px black stroke around the outside to give me the uniform border I want around my target image. The followng takes advantage of Core Image filters to mask off a solid color background (to be used as the border) and then to mask off and composite the target image.

// The two-tone mask image
UIImage *maskImage = [UIImage imageNamed: @"Mask"];

// Create a filler image of whatever color we want the border to be (in my case white)
UIGraphicsBeginImageContextWithOptions(maskImage.size, NO, maskImage.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, UIColor.whiteColor.CGColor);
CGContextFillRect(context, CGRectMake(0.f, 0.f, maskImage.size.width, maskImage.size.height));
UIImage *whiteImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

// Use CoreImage to mask the colored background to the mask (the entire opaque region of the mask)
CIContext *ciContext = [CIContext contextWithOptions: nil];
CIFilter *filter = [CIFilter filterWithName: @"CIBlendWithAlphaMask"];
[filter setValue: [CIImage imageWithCGImage: whiteImage.CGImage]
          forKey: kCIInputImageKey];
[filter setValue: [CIImage imageWithCGImage: maskImage.CGImage]
          forKey: kCIInputMaskImageKey];

CIImage *whiteBackground = filter.outputImage;

// scale the target image to the size of the mask (accounting for image scale) 
// ** Uses NYXImageKit
image = [image scaleToSize: CGSizeMake(maskImage.size.width * maskImage.scale, maskImage.size.height * maskImage.scale)
                 usingMode: NYXResizeModeAspectFill];

 // finally use Core Image to create our image using the masked white from above for our border and the inner (white) area of our mask image to mask the target image before compositing
 filter = [CIFilter filterWithName: @"CIBlendWithMask"];
 [filter setValue: [CIImage imageWithCGImage: image.CGImage]
           forKey: kCIInputImageKey];
 [filter setValue: whiteBackground
           forKey: kCIInputBackgroundImageKey];
 [filter setValue: [CIImage imageWithCGImage: maskImage.CGImage]
           forKey: kCIInputMaskImageKey];

 image = [UIImage imageWithCGImage: [ciContext createCGImage: filter.outputImage
                                                    fromRect: [filter.outputImage extent]]];

Upvotes: 2

Wain
Wain

Reputation: 119031

Simple option is to draw the image twice, first with a small scale applied to grow the image a little. Masking if the images aren't transparent (but are black&white).

Upvotes: 2

Suyog Patil
Suyog Patil

Reputation: 1616

You can apply border to objects present in the image using OpenCV framework.

Check this link. Here edges are detected of an image and border is applied to it. I hope this will give exact idea which you want.

https://github.com/BloodAxe/OpenCV-Tutorial

Upvotes: 1

Related Questions