Search code examples
iphoneobjective-ccore-graphicscore-animationquartz-graphics

drawing image from CALayers


I'm building some sort of censoring app. I've gotten so far that i can completele pixelate an image taken with my iPhone.

But I want to achieve in the end an image like this: http://images-mediawiki-sites.thefullwiki.org/11/4/8/8/8328511755287292.jpg

So my thought was to fully pixelate my image and then add a mask on top of it, to achieve the desired effect. So in terms of layers it goes like: originalImage + maskedPixelatedVersionOfImage.. I was thinking to animate the mask when touching the image, to scale the mask to the desired size. The longer you hold your finger on the image, the bigger the mask becomes...

After some searching, I guess this can be done using CALayers and CAAnimation. But how do I then composite those layers to an image that I can save in the photoalbum on the iphone?

Am I taking the right approach here?

EDIT:

Okay, I guess Ole's solution is the correct one, though I'm still not getting what I want: the code I use is:

    CALayer *maskLayer = [CALayer layer];
    CALayer *mosaicLayer = [CALayer layer];

    // Mask image ends with 0.15 opacity on both sides. Set the background color of the layer
    // to the same value so the layer can extend the mask image.
    mosaicLayer.contents = (id)[img CGImage];
    mosaicLayer.frame = CGRectMake(0,0, img.size.width, img.size.height);
    UIImage *maskImg = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"mask" ofType:@"png"]];
    maskLayer.contents = (id)[maskImg CGImage];
    maskLayer.frame = CGRectMake(100,150, maskImg.size.width, maskImg.size.height);

    mosaicLayer.mask = maskLayer;

    [imageView.layer addSublayer:mosaicLayer];

    UIGraphicsBeginImageContext(imageView.layer.bounds.size);
    [imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *saver = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

So in my imageView i did: setImage, which has the original (unedited) version of the photo. On top of that i add a sublayer, mosaicLayer, which has a mask property: maskLayer. I thought by rendering the rootlayer of the imageView, everything would turn out ok. Is that not correct?

Also, I figured out something else: my mask is stretched and rotated, which i'm guessing has something to do with imageOrientation? I noticed by accidentally saving mosaicLayer to my library, which also explains the problem I had that the mask seemed to mask the wrong part of my image...


Solution

  • To render a layer tree, put all layers in a common container layer and call:

    UIGraphicsBeginImageContext(containerLayer.bounds.size);
    [containerLayer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();