How to create reverse masks on CALayers

Louis Boux picture Louis Boux · Nov 16, 2011 · Viewed 8.6k times · Source

I'll make this as simple as possible.

How do I create reverse masks on CALayers in iOS?

I have a red view and an image that is used to mask the red view. enter image description here

I use the view's CALayer's mask property to apply the mask, the result is the following. enter image description here

However what I desire would be the opposite result, such as (imagine that the white part here is actually the wood in the background, because I am not very good with image editing software) enter image description here

To put in other words: I want the masking image to punch a hole through the view, and not act as an actual masking layer. Answers in both C# (MonoTouch) or Obj-C are fine either way

Answer

Gary picture Gary · Mar 7, 2013

Hope it is helpful

Step 1: Create a mask without any alpha channel.

Step 2: Create a invert mask by following method

- (UIImage*)createInvertMask:(UIImage *)maskImage withTargetImage:(UIImage *) image {

    CGImageRef maskRef = maskImage.CGImage;

    CGBitmapInfo bitmapInfo = kCGImageAlphaNone;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

    CGImageRef mask = CGImageCreate(CGImageGetWidth(maskRef),
                                    CGImageGetHeight(maskRef),
                                    CGImageGetBitsPerComponent(maskRef),
                                    CGImageGetBitsPerPixel(maskRef),
                                    CGImageGetBytesPerRow(maskRef),
                                    CGColorSpaceCreateDeviceGray(),
                                    bitmapInfo,
                                    CGImageGetDataProvider(maskRef),
                                    nil, 
                                    NO, 
                                    renderingIntent);


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

    CGImageRelease(mask);
    CGImageRelease(maskRef);

    return [UIImage imageWithCGImage:masked];
}

Step 3: Set the invert mask to a UIView by following method

- (void)maskWithImage:(UIImage*) maskImage TargetView:(UIView*) targetView {
    CALayer *_maskingLayer = [CALayer layer];
    _maskingLayer.frame = targetView.bounds;
    [_maskingLayer setContents:(id)[maskImage CGImage]];
    [targetView.layer setMask:_maskingLayer];
}

Finished.

How to call?

UIImage* targetImage = [UIImage imageNamed:@"sky_bg.png"];
UIImage* mask = [UIImage imageNamed:@"mask01.png"];

UIImage* invertMask = [self createInvertMask:mask withTargetImage:targetImage];

[self maskWithImage:invertMask TargetView:targetview];