Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CGContextClipToMask returning blank image

I'm new to Quartz. I have 2 images, a background, and a mask with cutout shape that I want to lay over the background in order to cut out a section. The resulting image should be the shape of the cutout. This is my mask (the shape in the middle is 0 alpha):

image mask

And this is my code:

UIView *canvas = [[[sender superview] subviews] objectAtIndex:0];

UIGraphicsBeginImageContext(canvas.bounds.size);
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef cgContext = CGBitmapContextCreate(NULL, canvas.bounds.size.width, canvas.bounds.size.height, 8, 0, colourSpace, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colourSpace);

CGImageRef maskImage = [[UIImage imageNamed:@"Mask.png"] CGImage];
CGContextClipToMask(cgContext, CGRectMake(0, 0, canvas.frame.size.width, canvas.frame.size.height), maskImage);

CGImageRef maskedImageRef = CGBitmapContextCreateImage(cgContext);
CGContextRelease(cgContext);

UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];
UIGraphicsEndImageContext();

[button setBackgroundImage:maskedImage forState:UIControlStateNormal];

Except nothing appears... Any idea where I'm going wrong? Many thanks.

like image 677
Smikey Avatar asked May 29 '12 15:05

Smikey


1 Answers

After you clip context with mask you should actually draw something on that context.

Besides that:

  • you should use UIGraphicsBeginImageContextWithOptions to support scale factor.
  • you're creating two context, one with UIGraphicsBeginImageContext and the other with CGBitmapContextCreate. One is enough :)
  • you should "flip" alpha of your mask, because according to docs The source samples of mask determine which points of the clipping area are changed. The other words transparent will become transparent

Simple example code, where I clip image inside imageView and then set it back:

UIGraphicsBeginImageContextWithOptions(self.imageView.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();

CGContextTranslateCTM(context, 0.0, self.imageView.frame.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGImageRef maskImage = [[UIImage imageNamed:@"mask.png"] CGImage];
CGContextClipToMask(context, self.imageView.bounds, maskImage); 

CGContextTranslateCTM(context, 0.0, self.imageView.frame.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

[[self.imageView image] drawInRect:self.imageView.bounds];

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

self.imageView.image = image;

Example using CGImageCreateWithMask:

UIImage *image = [UIImage imageNamed:@"image"];

CGImageRef originalMask = [UIImage imageNamed:@"mask"].CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(originalMask),
                                    CGImageGetHeight(originalMask),
                                    CGImageGetBitsPerComponent(originalMask),
                                    CGImageGetBitsPerPixel(originalMask),
                                    CGImageGetBytesPerRow(originalMask),
                                    CGImageGetDataProvider(originalMask), nil, YES);

CGImageRef maskedImageRef = CGImageCreateWithMask(image.CGImage, mask);

UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef scale:image.scale orientation:image.imageOrientation];

CGImageRelease(mask);
CGImageRelease(maskedImageRef);
like image 96
Evgeny Shurakov Avatar answered Sep 22 '22 10:09

Evgeny Shurakov