I have a UIView
which I want to save as a UIImage
. I do this using UIGraphicsBeginImageContext
, and it works OK. But when I apply mask to the images in the (view/layer.mask), the image that I capture through UIGraphicsBeginImageContext
is wrong (the masking is working when running the app but not when trying to get a UIImage
from a UIView
). Anyone encountered similar problem?
If I understand correctly, you wish to create a UIImage from a UIView layer, while that layer is masked. I assume that you want the target UIImage to have transparent background.
I encountered no problems implementing this and I have a demo project you can take a look at:
https://bitbucket.org/reydan/so_imagemask
You first need to press the Mask button. It will load a mask image (black and white) from the bundle and set it as the layer mask for the UIView container above.
Then, you can press the Copy Image button which renders the UIView container into an UIImage, and then set it to the destination image view below to see the result.
I will also post the 2 methods here:
- (IBAction)onMask:(id)sender {
UIImage* maskImage = [UIImage imageNamed:@"star.png"];
UIImageView* maskImageView = [[UIImageView alloc] initWithImage:maskImage];
maskImageView.contentMode = UIViewContentModeScaleAspectFit;
maskImageView.frame = _mainContainerView.bounds;
_mainContainerView.layer.mask = maskImageView.layer;
}
- (IBAction)onCopyImage:(id)sender {
UIGraphicsBeginImageContextWithOptions(_mainContainerView.bounds.size, FALSE, [[UIScreen mainScreen] scale]);
[_mainContainerView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
_destImageView.image = img;
}
EDIT
Apparently renderInContext:
on IOS6 does not use the mask (as it is also said here on SO).
My solution was to manually apply mask to the image. The mask is taken from the mask property of the layer and rendered in a context too so we don't have any problems with transformations/contentModes/etc.
Here is the updated source code (it is also available on bitbucket):
- (IBAction)onCopyImage:(id)sender {
// Get the image from the mainImageView
UIGraphicsBeginImageContextWithOptions(_mainContainerView.bounds.size, FALSE, [[UIScreen mainScreen] scale]);
[_mainContainerView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Use the next block if targeting IOS6
{
// Manually create a mask image (taken from the mask layer)
UIGraphicsBeginImageContextWithOptions(_mainContainerView.bounds.size, TRUE, [[UIScreen mainScreen] scale]);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGContextFillRect(ctx, _mainContainerView.bounds);
[_mainContainerView.layer.mask renderInContext:ctx];
UIImage * maskimg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Create a image mask from the UIImage
CGImageRef maskRef = maskimg.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
// Apply the mask to our source image
CGImageRef maskedimg= CGImageCreateWithMask(img.CGImage, mask);
// Convert to UIImage so we can easily display it in a UIImageView
img = [UIImage imageWithCGImage:maskedimg scale:img.scale orientation:img.imageOrientation];
CGImageRelease(mask);
CGImageRelease(maskedimg);
}
_destImageView.image = img;
}
EDIT Please check the latest project on bitbucket as it contains the latest version.
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