masking a UIImage

2019-01-16 15:09发布

问题:

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?

回答1:

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);


回答2:

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;
}


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



回答4:

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?