I have this code to mask an image. Basically, I only work with PNG images. So I have a 300x400 PNG image with 24bits of color (PNG-24). I am not sure if it also has an alpha channel. But there's no transparency in it.
Then, there is the image mask which is PNG-8bit without alpha channel. It is just black, grayscale and white.
I create both images as UIImage. Both display correctly when putting them into an UIImageView.
Then I create an UIImage out of them which contains the results of the masking operation, with this code:
+ (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];
}
here's what I do with that:
UIImage *image = [UIImage imageNamed:@"coloredImagePNG24.png"];
UIImage *maskImage = [UIImage imageNamed:@"theMaskPNG8_Grayscale_NoAlpha.png"];
UIImage *maskedImage = [MyGraphicUtils maskImage:image withMask:maskImage];
UIImageView *testImageView = [[UIImageView alloc] initWithImage:maskedImage];
testImageView.backgroundColor = [UIColor clearColor];
testImageView.opaque = NO;
After all that, the coloredImagePNG24.png stays totally intact as it is. No masking is happening. But now the weird thing is: If I turn that around, i.e. use this image as the mask, and the mask as the color-image-to-mask, then I get something very ugly in grayscale (but masked ;) ).
Any idea what's wrong with my code?
UPDATE: I just googled for an different b/w png to use it as a mask. And then this one worked! But the one I made by myself does not work. So I assume that the code has big image decoding problems. I would have to "normalize" the images to a specific format, so that it works.
This masking technique employs a layer to establish the visibility or transparency of another layer. While using this method, the editor usually places a layer at the bottom of the layer that he plans to apply the transparency or visibility. Then, he can control the transparency of the top layer.
In this tutorial, you learned the basics of masking using OpenCV. The key point of masks is that they allow us to focus our computation only on regions of the image that interest us. Focusing our computations on regions that interest us dramatically impacts when we explore topics such as machine learning, image classification, and object detection.
It turns out that this function is used extensively when applying masks to images. We apply our mask on Line 26 using the cv2.bitwise_and function. The first two parameters are the image itself (i.e., the image where we want to apply the bitwise operation). However, the important part of this function is the mask keyword.
The only part of the image we are interested in finding and describing is the parts of the image that contain faces — we simply don’t care about the rest of the image’s content. Provided that we could find the faces in the image, we may construct a mask to show only the faces in the image.
This code may help you
- (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];
}
refer this example demonstration
As you discovered, how you save the file can make a difference, because Core Graphics is very particular about the format of the bits it uses for masking.
I’ve found that the best and most reliable way to generate an image mask from an arbitrary image is to do this:
Try this function:
CGImageRef createMaskWithImage(CGImageRef image)
{
int maskWidth = CGImageGetWidth(image);
int maskHeight = CGImageGetHeight(image);
// round bytesPerRow to the nearest 16 bytes, for performance's sake
int bytesPerRow = (maskWidth + 15) & 0xfffffff0;
int bufferSize = bytesPerRow * maskHeight;
// allocate memory for the bits
CFMutableDataRef dataBuffer = CFDataCreateMutable(kCFAllocatorDefault, 0);
CFDataSetLength(dataBuffer, bufferSize);
// the data will be 8 bits per pixel, no alpha
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceGray();
CGContextRef ctx = CGBitmapContextCreate(CFDataGetMutableBytePtr(dataBuffer),
maskWidth, maskHeight,
8, bytesPerRow, colourSpace, kCGImageAlphaNone);
// drawing into this context will draw into the dataBuffer.
CGContextDrawImage(ctx, CGRectMake(0, 0, maskWidth, maskHeight), image);
CGContextRelease(ctx);
// now make a mask from the data.
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(dataBuffer);
CGImageRef mask = CGImageMaskCreate(maskWidth, maskHeight, 8, 8, bytesPerRow,
dataProvider, NULL, FALSE);
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colourSpace);
CFRelease(dataBuffer);
return mask;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With