UIImage masking problems iOS 7

2019-03-17 01:41发布

问题:

I have heavily borrowed (standard) code which applies a grayscale UIImage mask to a UIImage.

- (void) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {

    CGImageRef imageRef = image.CGImage;  // main UIImage
    CGImageRef maskRef = maskImage.CGImage;  // grayscale UIImage mask

    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                    CGImageGetHeight(maskRef),
                                    CGImageGetBitsPerComponent(maskRef),
                                    CGImageGetBitsPerPixel(maskRef),
                                    CGImageGetBytesPerRow(maskRef),
                                    CGImageGetDataProvider(maskRef), NULL, false);

    CGImageRef masked = CGImageCreateWithMask(imageRef, mask);

    maskedImage = [UIImage imageWithCGImage:masked];
    CGImageRelease(mask);
    CGImageRelease(masked);

    imageView.image = maskedImage;

}

I then save the imageView.image to a file. The code works like a charm in iOS 6 and 6.1; the saved image contains the main UIImage with the mask applied. However, I have noticed that this code does not perform in the same way in iOS 7 (iPhone). In iOS 7, the saved image contains only main UIImage without the mask applied. I am not sure whether the problem lies in the CGImageCreateWithMask() method or elsewhere.

Any insight would be appreciated. Thank you so much in advance.

回答1:

I found this issue on my app too and I solve it by following code.

- (UIImage*)image:(UIImage*)image withMask:(UIImage*)maskImage
{
    CGImageRef maskRef = maskImage.CGImage;
    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                    CGImageGetHeight(maskRef),
                                    CGImageGetBitsPerComponent(maskRef),
                                    CGImageGetBitsPerPixel(maskRef),
                                    CGImageGetBytesPerRow(maskRef),
                                    CGImageGetDataProvider(maskRef), NULL, false);

    CGImageRef maskedImageRef = CGImageCreateWithMask([handledImage CGImage], mask);
    CGImageRelease(mask);

    // Under iOS 7, UIImage with mask no longer applied mask when saving it.
    // We draw the image to context and obtain image from context to get the image applied mask
    CGContextRef context = CGBitmapContextCreate(nil,
                                                 CGImageGetWidth(maskedImageRef),
                                                 CGImageGetHeight(maskedImageRef),
                                                 CGImageGetBitsPerComponent(maskedImageRef),
                                                 CGImageGetBytesPerRow(maskedImageRef),
                                                 CGImageGetColorSpace(maskedImageRef),
                                                 CGImageGetBitmapInfo(maskedImageRef));

    CGRect imageRect = CGRectMake(0, 0, CGImageGetWidth(maskedImageRef), CGImageGetHeight(maskedImageRef));
    CGContextDrawImage(context, imageRect, maskedImageRef);
    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    UIImage *maskedImage = [UIImage imageWithCGImage:imageRef];

    CFRelease(imageRef);
    CGContextRelease(context);
    CGImageRelease(maskedImageRef);

    return maskedImage;
}


回答2:

The above code gives a good idea of how to approach the problem(drawing over a context) but did not work for me. The code below works both on IOS 7 and previous versions(IOS 6.x).

+(UIImage*)maskImageExt:(UIImage *)image withMask:(UIImage *)maskImage {
    CGImageRef maskRef = maskImage.CGImage;
    CGImageRef imageRef = image.CGImage;

    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                        CGImageGetHeight(maskRef),
                                        CGImageGetBitsPerComponent(maskRef),
                                        CGImageGetBitsPerPixel(maskRef),
                                        CGImageGetBytesPerRow(maskRef),
                                        CGImageGetDataProvider(maskRef), NULL, true);

    CGImageRef maskImageRef = CGImageCreateWithMask([image CGImage], mask);

    CGContextRef context = CGBitmapContextCreate(nil,
                                                 CGImageGetWidth(imageRef),
                                                 CGImageGetHeight(imageRef),
                                                 CGImageGetBitsPerComponent(imageRef),
                                                 CGImageGetBytesPerRow(imageRef),
                                                 CGImageGetColorSpace(imageRef),
                                                 CGImageGetBitmapInfo(imageRef));
    CGRect imageRect = CGRectMake(0, 0, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
    CGContextDrawImage(context, imageRect, maskImageRef);
    CGImageRef maskedImageRef = CGBitmapContextCreateImage(context);
    UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];

    CGImageRelease(mask);
    CGContextRelease(context);
    CGImageRelease(maskedImageRef);

    return maskedImage;
}


回答3:

Make sure that both images (the image to be masked and the mask itself) have an alpha channel! This solved the issue for me on iOS7.

Then you should be able to use the old code you have used for iOS6.



标签: ios uiimage mask