1

I'm trying to mask a picture taken with my iphone. Here I found a way how to do that. However, the image-to-be-masked apparently needs an alpha channel, and pictures from the iPhone don't have that. So, I found this topic discussing how to add such a channel. Unfortunately, that code doesn't work for me (Xcode 6, iOS 7/8)

Does any of you know how to accomplish this?

Thanks in advance

Community
  • 1
  • 1
Sjakelien
  • 2,255
  • 3
  • 25
  • 43
  • 1
    What exactly are you trying to achieve? What do you mean by a "native iPhone picture"? A photo taken with the iPhone's camera? Is the question about how to determine the shape of the mask? Or is just about adding an alpha channel to an image with only three channels (red, green, blue)? In what technical form is your picture? Do you have *UIImage* instance of it? And why doesn't the referred code work? Do you get a compile-time or run-time error? Does it run but not produce the expected result? – Codo Sep 27 '14 at 18:31
  • I mean: I have this picture taken with the iPhone camera, as a UIImage. I a have a separate file (B/W) representing the mask. If I use the code from the first URL, trying to apply the mask to the iPhone Camera image, the result is...the iPhone Camera Image. After having read the comments on that code, I concluded, that the image that I want to apply a mask to needs to have an alpha channel already. That'a what brought me to the code at the second URL. However, running my iPhone camera image through that code, doesn't seem to result in that image with an added alpha channel. – Sjakelien Sep 28 '14 at 08:09
  • When you try the code from the second URL, are you saving the image out as a PNG? JPG's don't save the alpha channel even if the CGImage data has alpha channel info. – Mr. T Sep 30 '14 at 23:06
  • could you describe more in detail what you are trying to accomplish? because it seems you are going at it the wrong way, the iphone camera pictures do not have alpha channel because theres no transparency at all in them. Do you want to mask them descructively or non descructively? that is, will the original image be modified too? what exactly do you expect to have as your output. – Pochi Oct 03 '14 at 01:00
  • I have no experience masking images, but if a piece of your puzzle is simply to convert your camera-taken-jpg to png, this will do it. http://stackoverflow.com/questions/501699/data-url-png-from-uiimage – Miles Alden Oct 04 '14 at 03:35
  • @Chiquis I want to cut out a circle from the iPhoto image. For that I created a circular mask. The result should be a round part of the original image. – Sjakelien Oct 09 '14 at 08:47
  • @Sjakelien check this answer http://stackoverflow.com/questions/3800278/iphone-draw-transparent-rectangle-on-uiview-to-reveal-view-beneath the lower part describes how to draw a transparent eclipse, its basically the same inner method, you have to create a context, draw your photo FIRST, then draw this transparent eclipse in where you want to "erase" the contents. – Pochi Oct 10 '14 at 02:15

2 Answers2

1

I tried the code from the first link:

- (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];

}

Initially it didn't work, because the mask image that I used was partially transparent. I recreated the mask image making sure than the entire image was either black or white and it worked.

I found the following information on another website, which led me to this conclusion:

NOTE: The mask image cannot have ANY transparency. Instead, transparent areas must be white or some value between black and white. The more towards black a pixel is the less transparent it becomes.

In case it's related to the code that you're using to load the image from the image picker, here's the code that I used to load the image and the mask:

-(IBAction)selectImageFromCameraRoll:(UIButton *)sender
{
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary])
    {
        NSArray *media = [UIImagePickerController
                          availableMediaTypesForSourceType: UIImagePickerControllerSourceTypePhotoLibrary];

        if ([media containsObject:(NSString*)kUTTypeImage] == YES) {
            UIImagePickerController *picker = [[UIImagePickerController alloc] init];
            picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            [picker setMediaTypes:[NSArray arrayWithObject:(NSString *)kUTTypeImage]];

            picker.delegate = self;

            [self presentViewController:picker animated:YES completion:nil];
        }
    }
    else
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Oops!"
                                                        message:@"This device does not have a photo library."
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    }
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];

    if([mediaType isEqualToString:(NSString*)kUTTypeImage])
    {
        UIImage *photoTaken = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
        self.imageView.image = [self maskImage:photoTaken withMask:[UIImage imageNamed:@"mask.png"]];
    }

    [picker dismissViewControllerAnimated:NO completion:nil];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [picker dismissViewControllerAnimated:YES completion:nil];
}

Here's a link to the mask image that I used:

mask.png Download and rename the file.

Brian Shamblen
  • 4,653
  • 1
  • 23
  • 37
  • Thanks, but my mask is purely b/w. – Sjakelien Oct 09 '14 at 08:45
  • I amended some additional code above, to include the call to the UIImagePickerController and the delegate methods that are called after an image is selected. There's also a link to the mask image that I used at the very bottom. – Brian Shamblen Oct 09 '14 at 16:04
  • OK, thanks. I'm closer to a solution now. What happens, if I use your code, is that indeed, a masked image is displayed in self.imageView.image. However, if I save [UIImage imageWithCGImage:masked] as a file to the Apps home directory, it is saved as a .png WITHOUT an alpha channel/circular mask. – Sjakelien Oct 11 '14 at 14:02
  • For my purpose, I need to take the resulting masked image, and combine it with another image, and eventually send it out of the iphone as a physical file. So, apparently, this is the bottle neck of my situation. – Sjakelien Oct 11 '14 at 14:09
0

OK, I have the honour to answer my own question, just because my question itself was ill-formulated, and built upon assumptions, that likely were not clear to anyone. I hope though, that someone with the same poor logic as me will end up at this page, and find this all very useful.

Let me first explain what went wrong:

  1. I assumed that the -

    (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage

    that I ran into would affect the image, but in fact it affects the DISPLAY of that image in an UIImageView.

  2. In my debug chain, I saved the masked image to a file, just to end up with a file without a mask.
  3. Google's results suggested that I needed first to add an alpha channel to the image, before I could apply an alpha at all.

So I got lost several times, dragging you into this.

Being stuck with that unmasked image, I sent out another query to Google, ending up with the following:

http://iphonedevsdk.com/forum/iphone-sdk-development/96918-round-corners-on-uiimage-not-uiimageview.html

This actually answered my question. The

-(UIImage *)makeRoundedImage:(UIImage *) image radius: (float) radius;

method returns a destructed image with an alpha mask. Since I needed a perfect circle, I could just get rid of the radius parameter.

Thank you for all your thinking and patience. I dearly apologise for the inconvenience.

Sushil Sharma
  • 2,321
  • 3
  • 29
  • 49
Sjakelien
  • 2,255
  • 3
  • 25
  • 43