I'm working on an app that can change the borders or a rectangular UIImage. The borders will vary, but will look like the UIImage was cut out with scissors, or something to that affect.
What is the best way to do this?
My first thought is to prep a bunch of transparent PNGs with the correct border effect I'm looking for, and then somehow use that as a mask for my UIImage. Is this the right path? Or is there a more flexible programmatic way to do this?
Here are the Core Graphics calls that you can use to mask the image:
//Mask Image
UIImage *inputImage = [UIImage imageNamed:@"inputImage.png"];
CGImageRef maskRef = [UIImage imageNamed:@"mask.png"].CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef masked = CGImageCreateWithMask([inputImage CGImage], mask);
CGImageRelease(mask);
UIImage *maskedImage = [UIImage imageWithCGImage:masked];
CGImageRelease(masked);
You need image masking for that, I wrote a tutorial on how to use it and how I've used it in my own application.
The following example code should help you get started, it needs the original image and a mask image as input and it returns the masked image as output.
- (UIImage*) maskImage:(UIImage *) image withMask:(UIImage *) mask
{
CGImageRef imageReference = image.CGImage;
CGImageRef maskReference = mask.CGImage;
CGImageRef imageMask = CGImageMaskCreate(CGImageGetWidth(maskReference),
CGImageGetHeight(maskReference),
CGImageGetBitsPerComponent(maskReference),
CGImageGetBitsPerPixel(maskReference),
CGImageGetBytesPerRow(maskReference),
CGImageGetDataProvider(maskReference),
NULL, // Decode is null
YES // Should interpolate
);
CGImageRef maskedReference = CGImageCreateWithMask(imageReference, imageMask);
CGImageRelease(imageMask);
UIImage *maskedImage = [UIImage imageWithCGImage:maskedReference];
CGImageRelease(maskedReference);
return maskedImage;
}
Yep, that's pretty much what you need to do. The best approach is to use Core Graphics; the Quartz 2D Programming guide has an article describing how to mask images with other images. You can obtain a CGImageRef
(which these Core Graphics methods use) from a UIImage
object via its CGImage
property, and then get a UIImage
back from your altered (masked) CGImageRef
using the UIImage
class method +imageWithCGImage:
.
There is another way of doing this with a path. I've posted code that does it with an circle and could easily be edited to work with any closed path.
How to crop UIImage on oval shape or circle shape?