12

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?

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
Steven Baughman
  • 1,076
  • 2
  • 13
  • 22

4 Answers4

25

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);
Reed Olsen
  • 9,099
  • 4
  • 37
  • 47
  • THANKS! Been wondering how to do this. For posterity, there's a small typo in your first UIImage alloc: should say `imageNamed` like your second one does. – dooleyo Aug 07 '13 at 20:25
  • Needed to update `imageWithCGImage:` to `imageWIthCGImage:scale:orientation:` – jowie Jul 09 '15 at 16:59
6

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;
}
Jeroen de Leeuw
  • 907
  • 1
  • 9
  • 18
  • I've been looking over this, and unfortunately I just cannot get it to work. I put the image in the first parameter, than B&W image in the second, both the same size, and the output is exactly the same as the first image. – jowie Jul 09 '15 at 17:27
  • Your tutorial link is broken. – capikaw Sep 09 '16 at 17:54
3

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:.

Noah Witherspoon
  • 57,021
  • 16
  • 130
  • 131
0

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?

Community
  • 1
  • 1
Chris Nelson
  • 466
  • 5
  • 4