daspianist daspianist - 2 months ago 27
Objective-C Question

Cropping UIImage by custom shape

I have a background UIImage, and I would like to crop the background UIImage with a custom shape so this background image only "appears" through the custom shape. For example, I have a moon-shaped custom shape, and I would like the background image to only come through on the moon-shaped part.

Based on another answer, I am trying to impose a mask on the image like so:

- (UIImage *)createImageFromImage:(UIImage *)image
withMaskImage:(UIImage *)mask {
CGImageRef imageRef = image.CGImage;
CGImageRef maskRef = mask.CGImage;

CGImageRef imageMask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef),
NULL,
YES);

CGImageRef maskedReference = CGImageCreateWithMask(imageRef, imageMask);
CGImageRelease(imageMask);

UIImage *maskedImage = [UIImage imageWithCGImage:maskedReference];
CGImageRelease(maskedReference);

return maskedImage;
}


However, the result of this looks like enter image description here, and there are several issues with it:


  1. the moon I have is 100*100, this has stretched do a strange proportion

  2. My goal is only for the image to come through the moon - however, at the moment the moon is a white shape that is coming over the image



Any ideas about how I could fix the crop issue would be much appreciated. Thanks!

Answer

On your background image you'll have to add a custom mask through CALayer. Keep in mind, everything you color in the mask.png (moon) will be visible, everything transparent will not display.

UIImage *moonImage = [UIImage imageNamed:@"mask.png"];
CALayer *maskLayer = [CALayer layer];
[maskLayer setContents:(id)moonImage.CGImage];
[maskLayer setFrame:CGRectMake(0.0f, 0.0f, moonImage.size.width, moonImage.size.height)];

UIImageView *yourBackgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
// Keep your image view in tact here, just add:
[yourBackgroundImageView.layer setMask:maskLayer];