I'am trying to create profile picture image with custom shape pattern with using masking in ios. Here is what i've used to create masked image :
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
CGImageRef maskRef = maskImage.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef maskedImageRef = CGImageCreateWithMask([image CGImage], mask);
UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];
CGImageRelease(mask);
CGImageRelease(maskedImageRef);
// returns new image with mask applied
return maskedImage;
}
After implementing instance , i am calling : *(_profileImage is global UIImage)
UIImage *maskImage = [UIImage imageNamed:#"maskProfilePicture.png"];
UIImage *maskedImage = [self maskImage:_profileImage withMask:maskImage];
and result (Image should be added in subview of mask. But it seems , mask image overlap on Image that need to be masked ):
The mask image : (Maybe mask image properties are wrong that i created in photoshop :)
The Core Graphics calls look correct.
Change the mask image to be have a black where you want the image to show through, and white elsewhere.
You can use CALayer's mask property to achieve the result.
CALayer Apple Documentation
Your masking layer should be transparent in places where you want to cut out the image.
Related
I am working on a project where I need to show an screen same as below
Here the image should be cropped which is visible only in the circle. I have tried image masking as below. But it always crop in square.
- (UIImage*) maskImage1:(UIImage *) image withMask:(UIImage *) mask
{
CGImageRef imageReference = image.CGImage;
CGImageRef maskReference = mask.CGImage;
CGImageRef imageMask = CGImageMaskCreate(CGImageGetWidth(maskReference),
CGImageGetHeight(maskReference),
CGImageGetBitsPerComponent(maskReference),
CGImageGetBitsPerPixel(maskReference),
CGImageGetBytesPerRow(maskReference),
CGImageGetDataProvider(maskReference),
NULL, // Decode is null
YES // Should interpolate
);
CGImageRef maskedReference = CGImageCreateWithMask(imageReference, imageMask);
CGImageRelease(imageMask);
UIImage *maskedImage = [UIImage imageWithCGImage:maskedReference];
CGImageRelease(maskedReference);
return maskedImage;
}
Please suggest how can I achieve this?
Use the demo to scale and crop image circle.Circle Image Crop
for Masking your image in to circle as below cede.
//Masking the image
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
CGImageRef maskRef = maskImage.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef masked = CGImageCreateWithMask([image CGImage], mask);
return [UIImage imageWithCGImage:masked];
}
UIGraphicsBeginImageContextWithOptions(hiddenView.bounds.size, self.view.opaque, 0.0); //In this I have take screenshot of a hiddenView that I have added from IB with a background color anything( in this case it's orange).
//Replace this hiddenView object with your object of whom you want to take screenshot.
[hiddenView.layer renderInContext:UIGraphicsGetCurrentContext()]; //Similarly replace hiddenView here with your object.
UIImage*theImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData*theImageData=UIImageJPEGRepresentation(theImage, 1.0 );
imgView.image = [UIImage imageWithData:theImageData]; //I placed a UIImageView to check and place the screenshot into it as Image ,simply to cross check if I'm getting a right screenshot or not.
//So you could also remove this line after your have verified that your getting right screen shot.
I get an ordinary image from the designer every new network call. But the design is that the image must be in the shape like this:
How can I do that? On android I use a path to create such a shape and then use a shader to draw the image in that shape. I don't find something like that on iOS?
Thanks to Krivoblotsky. You can use this piece of code to mask an image:
- (UIImage*) _maskImage:(UIImage *) image withMask:(UIImage *) mask
{
CGImageRef imageReference = image.CGImage;
CGImageRef maskReference = mask.CGImage;
CGImageRef imageMask = CGImageMaskCreate(CGImageGetWidth(maskReference),
CGImageGetHeight(maskReference),
CGImageGetBitsPerComponent(maskReference),
CGImageGetBitsPerPixel(maskReference),
CGImageGetBytesPerRow(maskReference),
CGImageGetDataProvider(maskReference),
NULL,
YES
);
CGImageRef maskedReference = CGImageCreateWithMask(imageReference, imageMask);
CGImageRelease(imageMask);
UIImage *maskedImage = [UIImage imageWithCGImage:maskedReference];
CGImageRelease(maskedReference);
return maskedImage;
}
You only need to make sure that your image is black and not a sort of black because it then will be used as transparency.
This is a very good tutorial and shows you the mask image:
http://jeroendeleeuw.com/post/33638733049/how-to-mask-images-with-core-graphics-in-ios
How to mask an image with another image by non transparent pixels?
E.g.
When the mask image is black&white, I use this function:
- (UIImage *)maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
CGImageRef maskRef = maskImage.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef masked = CGImageCreateWithMask([image CGImage], mask);
return [UIImage imageWithCGImage:masked];
}
But how to do this in my case?
Here are the steps, to achieve the result
1) Create an image view, and calculate the optimal size for it (+ set aspectFit option)
2) Get the image view frame, and create a mask with that options (i.e. scale your predefined mask image)
3) Mask image view, with your created mask
UIImageView *maskView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"star_mask_alpha.png"]];
self.needsMaskImageView.layer.mask = maskView.layer;
[self.needsMaskImageView setNeedsDisplay];
I'm trying to develop an easy game. But then, I came across this problem with my UIImage.
When I import an image, I get this annoying background on this ball, not just the ball itself. So when I play with this ball, this background has to match the UIView color, or else it will look weird. How do I solve this problem?
You can use following code to get a mask shape image with a mask:
//beCroppedImage is the image be cropped, maskImage is a image with a white background color and a black sharp that ever you want.
theShapeImage = [beCroppedImage maskImageWithMask:maskImage];
- (UIImage *)maskImageWithMask:(UIImage*)mask {
CGImageRef imgRef = [self CGImage];
CGImageRef maskRef = [mask CGImage];
CGImageRef actualMask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef masked = CGImageCreateWithMask(imgRef, actualMask);
UIImage *image = [UIImage imageWithCGImage:masked];
CGImageRelease(masked);
CGImageRelease(actualMask);
return image;
}
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.
I use the view's CALayer's mask property to apply the mask, the result is the following.
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)
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
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];
You need to reverse the alpha of your mask, so the "holes" are the transparent pixels. You'll also want to stretch your image to cover the whole red view.