Reputation: 1215
I want to mask an image by another image using CGLayerRef in off-screen rendering since it's suitable for high-quality rendering as it's mentioned in documentation
Core Graphics Layer Drawing : CGLayer objects allow your application to use layers for drawing. Layers are suited for the following: High-quality offscreen rendering of drawing that you plan to reuse.
But I couldn't find any example in objective-c that I could understand how it works. On my context, I want to mask an image with a shape image (solid color shape) I used to do it this way
//The context I use to mask my image with the mask image.
CGColorSpaceRef colorSpace= CGColorSpaceCreateDeviceRGB();
CGContextRef mainViewContentContext = CGBitmapContextCreate (NULL, _bigImageRect.size.width, _bigImageRect.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
//Mask image
CGContextClipToMask(mainViewContentContext,
CGRectMake(0,
-_bigImageRect.origin.y,
_bigImageRect.size.width,
_bigImageRect.size.height),
_maskImage.CGImage);
//Drawing the image on the mask image.
CGContextDrawImage(mainViewContentContext,
CGRectMake(0,
0,
_bigImageRect.size.width,
_bigImageRect.size.height),
_ImageToBeMasked.CGImage);
CGImageRef mainViewContentBitmapContext = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
UIImage*maskedImage = [UIImage imageWithCGImage:mainViewContentBitmapContext];
CGImageRelease(mainViewContentBitmapContext)
return maskedImage;
But how can I mask using CGLayers as below? I appreciate any help.
CGLayerRef layer = CGLayerCreateWithContext(mainViewContentContext, _bigImageRect.size, NULL);
CGContextDrawLayerInRect(mainViewContentContext, _bigImageRect, layer);
CGLayerRelease(layer);
//And then.. how can I do the masking using this CGLayerRef???
Upvotes: 2
Views: 919
Reputation: 1215
It doesn't really answer the question but I finally ended up using the conventional methods such as CGContextClipToMask
and CGContextDrawImage
but I managed to gain my desired high-quality before masking. Again, I need to mention that this works just in my case (which was masking an image with a rendered bezier path on it but at image's full resolution) If you have the same problem for more information you can check my other related question here
Masking an image using bezierpath with image's full resolution
and my github working project as well.
https://github.com/Reza-Abdolahi/HighResMasking
Here's the code that worked for me:
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef maskImageRef = [_maskImage CGImage];
CGContextRef myContext = CGBitmapContextCreate (NULL, _highResolutionImage.size.width, _highResolutionImage.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
if (myContext==NULL)
return NULL;
CGFloat ratio = 0;
ratio = _maskImage.size.width/ _highResolutionImage.size.width;
if(ratio * _highResolutionImage.size.height < _maskImage.size.height) {
ratio = _maskImage.size.height/ _highResolutionImage.size.height;
}
CGRect rectForMask = {{0, 0}, {_maskImage.size.width, _maskImage.size.height}};
CGRect rectForImageDrawing = {{-((_highResolutionImage.size.width*ratio)-_maskImage.size.width)/2 , -((_highResolutionImage.size.height*ratio)-_maskImage.size.height)/2},
{_highResolutionImage.size.width*ratio, _highResolutionImage.size.height*ratio}};
CGContextClipToMask(myContext, rectForMask, maskImageRef);
CGContextDrawImage(myContext, rectForImageDrawing, _highResolutionImage.CGImage);
CGImageRef newImage = CGBitmapContextCreateImage(myContext);
CGContextRelease(myContext);
UIImage *theImage = [UIImage imageWithCGImage:newImage];
CGImageRelease(newImage);
return theImage;
Upvotes: 1
Reputation: 116
I normaly write Swift code, but once I also had to deal with masking and CGLayer.
I solved the problem with the following steps:
CGBlendMode.sourceIn
This works because CGBlendMode.sourceIn
tells the context to multiply the alpha value of the source image with the color of the existing pixel. Therefore invisible parts of the mask (alpha = 0.0
) will stay invisible.
Apple docs for CGBlendMode: https://developer.apple.com/documentation/coregraphics/cgblendmode
Upvotes: 3