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.
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;
}
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With