Reputation: 1331
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?
Upvotes: 7
Views: 2770
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.
Use CIEdges
to detect edges from the mask.
Then make edges thicker by applying disk maximum filter (CIMorphologyMaximum
).
Convert borders image from black-and-white to transparent-and-white with CIMaskToAlpha
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
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
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
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