27

I'm working on an app where I draw a UIView via code and I fill it with a UIColor. Next thing I want to load a mask.png file (no transparency, just black and white) and mask the UIView to change its visual appearance.

Any idea how to do this?

6 Answers 6

52
// Create your mask layer CALayer* maskLayer = [CALayer layer]; maskLayer.frame = CGRectMake(0,0,yourMaskWidth ,yourMaskHeight); maskLayer.contents = (__bridge id)[[UIImage imageNamed:@"yourMaskImage.png"] CGImage]; // Apply the mask to your uiview layer yourUIView.layer.mask = maskLayer; 

Remember to import QuartzCore and add the framework

#import <QuartzCore/QuartzCore.h> 

It is very easy but I didn't find the answer anywhere!

Sign up to request clarification or add additional context in comments.

1 Comment

Any answer that uses Core Animation instead of Core Graphics should be preferred. CA's API is much easier to understand and use.
12

iOS 8 introduces the maskView property which allows you to use an alternate view to provide the mask image. In Swift:

if let maskImage = UIImage(named: "MaskImage") { myView.maskView = UIImageView(image: maskImage) } 

Note that you need to supply an image which actually has transparency; an image with white parts (for opaque) and black parts (for transparent) won't work.

1 Comment

Any idea why this might crash with EXC_BAD_ACCESS? (-[UIImageView _maskView]: message sent to deallocated instance)
5

You might be able to use CGContextClipToMask:

-(void) drawRect:(CGRect)dirty { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSaveGState( context ); CGContextClipToMask( context , [self bounds] , [self maskImage] ); [super drawRect:dirty]; // or draw your color manually CGContextRestoreGState( context ); } 

Comments

5

I have create a category with the code above :

UIView+ImageMask.h :

#import <UIKit/UIKit.h> @interface UIView (ImageMask) - (void) maskWithImage:(UIImage*) mask; - (void) maskWithImage:(UIImage*)mask size:(CGSize)maskSize; - (void) removeMask; @end 

UIView+ImageMask.m :

#import <QuartzCore/QuartzCore.h> #import "UIView+ImageMask.h" @implementation UIView (ImageMask) - (void) maskWithImage:(UIImage*) mask { [self maskWithImage:mask size:mask.size]; } - (void) maskWithImage:(UIImage*)mask size:(CGSize)maskSize { CALayer* maskLayer = [CALayer layer]; maskLayer.frame = CGRectMake(0, 0, maskSize.size.width, maskSize.size.height); maskLayer.contents = (__bridge id)[mask CGImage]; // Apply the mask to your uiview layer self.layer.mask = maskLayer; } - (void) removeMask { self.layer.mask = nil; } @end 

4 Comments

What kind of image do you have in input ? black& white or translucent and white or translucent and black ?
I used a black image with alpha. But I don't think this will make a difference. If you try it, let me know :).
I tried. Actually have a difference. Only alpha component will make effect
yes, image needs to be PNG with alpha component. only the alpha will be masked, the rest can be white or black it doesn't matter
3

Thanks drawnonward,

ended up with this function:

- (UIImage*) maskImage:(UIView *)image withMask:(UIImage *)maskImage { UIGraphicsBeginImageContext(image.bounds.size); [image.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CGImageRef maskRef = maskImage.CGImage; CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef), CGImageGetHeight(maskRef), CGImageGetBitsPerComponent(maskRef), CGImageGetBitsPerPixel(maskRef), CGImageGetBytesPerRow(maskRef), CGImageGetDataProvider(maskRef), NULL, false); CGImageRef masked = CGImageCreateWithMask([viewImage CGImage], mask); return [UIImage imageWithCGImage:masked]; } 

Comments

0

Swift 2.0

Pass a UIImage and a mask image to this function, and you will get a masked image as a UIImage.

func maskImage(image:UIImage, mask:(UIImage))->UIImage{ let imageReference = image.CGImage let maskReference = mask.CGImage let imageMask = CGImageMaskCreate(CGImageGetWidth(maskReference), CGImageGetHeight(maskReference), CGImageGetBitsPerComponent(maskReference), CGImageGetBitsPerPixel(maskReference), CGImageGetBytesPerRow(maskReference), CGImageGetDataProvider(maskReference), nil, true) let maskedReference = CGImageCreateWithMask(imageReference, imageMask) let maskedImage = UIImage(CGImage:maskedReference!) return maskedImage } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.