2

I want to crop an image with feathered circle. I use this to crop an image but it is only cropped square.

 CGImageRef imref = CGImageCreateWithImageInRect([newImage CGImage], faceRect);
 newSubImage = [UIImage imageWithCGImage:imref];

What I want is to crop with feather edges? What should I use to achieve it?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • See if this can help http://stackoverflow.com/questions/17161088/how-to-refine-or-blur-or-smooth-just-the-edges/17175381#17175381 – iphonic Mar 24 '15 at 07:18
  • Hey, what kind of crop is this? SomeGuy's answer looks pretty good! He gets it or there will be mutiny on the bounty! – clearlight Mar 24 '15 at 16:44

2 Answers2

4

This snippet will create a circular cut with feathered edges

result

The first featherLocations variable is likely the only one you'll need to adjust

- (UIImage *) featheredImageWithImage:(UIImage *) image
{
    //  Locations of where the feather starts and ends (0 -> 1)
    const CGFloat featherLocations[] = {0.9, 1};

    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    //  Draw the original image
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];

    //  A 'knock-out' gradient is used to generate a feather effect,
    //  the alpha channel on the colors defines the alpha of the drawn image
    NSArray *gradientColors = @[(id)[UIColor colorWithWhite:0 alpha:1].CGColor,
                                (id)[UIColor colorWithWhite:0 alpha:0].CGColor];

    CGGradientRef gradient = CGGradientCreateWithColors(CGImageGetColorSpace(image.CGImage), (__bridge CFArrayRef)gradientColors, featherLocations);

    //  Because we're changing the draw mode below,
    //  take a snapshot of the current draw settings so we can reset them after
    CGContextSaveGState(ctx);

    //  The kCGBlendModeDestinationIn blend mode will provide a'knock-out' effect on
    //  the previously drawn content, using the alpha channels of the gradient's colors
    CGContextSetBlendMode(ctx, kCGBlendModeDestinationIn);

    const CGPoint gradientCenter = CGPointMake(image.size.width / 2, image.size.height / 2);

    //  The gradient will start at the center (0) and extend to the closest edge (horizontal or vertical)
    const CGFloat startRadius = 0;
    const CGFloat endRadius = MIN(image.size.width,
                                  image.size.height) / 2;

    //  Draw the gradient to eliminate the pixels we don't want
    CGContextDrawRadialGradient(ctx, gradient, gradientCenter, startRadius, gradientCenter, endRadius, (kCGGradientDrawsAfterEndLocation));

    CGGradientRelease(gradient);
    gradient = NULL;

    //  Finally, restore state
    //  (note that in this example CGContextSaveGState and CGContextRestoreGState
    //  are optional because no further drawing happens after this point)
    CGContextRestoreGState(ctx);

    //  Get the UIImage version
    UIImage *featheredImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return featheredImage;
}
SomeGuy
  • 9,670
  • 3
  • 32
  • 35
  • Any chance we could do it without using shadows and any color gradients? I want the edges of my image (which is defined by a custom uibezierpath) to fade from image to literally nothing, I dont want it to have a shadow or a gradient on its borders, is that possible? Thanks a lot. – Reza.Ab Mar 03 '17 at 13:32
0

What about this... first round the image:

 //round the image

UIImageView *roundView = [[UIImageView alloc] initWithImage:smallImage];
UIGraphicsBeginImageContextWithOptions(roundView.bounds.size, NO, [UIScreen mainScreen].scale);
[[UIBezierPath bezierPathWithRoundedRect:roundView.bounds
                            cornerRadius:roundView.frame.size.width/2] addClip];
[smallImage drawInRect:roundView.bounds];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

and then round it again but with a smaller circle and set the bezier path colour again to white but make it semi transparent by adjusting the alpha...

Kex
  • 8,023
  • 9
  • 56
  • 129