Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any idea why this image masking code does not work?

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.

like image 258
Thanks Avatar asked Jul 15 '09 18:07

Thanks


People also ask

What is masking in Photoshop?

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.

What is masking in OpenCV?

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.

How do I apply a mask to an image in Python?

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.

Is it possible to show only the faces in the image?

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.


2 Answers

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

like image 61
Shanmugaraja G Avatar answered Sep 21 '22 19:09

Shanmugaraja G


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:

  1. Create a bitmap graphics context that is in an acceptable format for image masks (you can't use UIGraphicsBeginImageContext() for this)
  2. Draw your image into this bitmap graphics context
  3. Create the image mask from the bits of the bitmap graphics context.

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;
}
like image 27
bunnyhero Avatar answered Sep 19 '22 19:09

bunnyhero