Search code examples
iosuiimageantialiasinguibezierpath

Anti-aliasing of clipped image


I have been trying to experiment with clipping an image in a circular path. But, I can't seem to get the clipping path to be anti-aliased.

I have tried a few different things, but none seem to work. How do I get the clipped image to be anti-aliased?

UIImage*originalImage = [UIImage imageNamed:@"grandpa.png"];
int minWidth = originalImage.size.width;
bool isWidth = YES;
if(minWidth > originalImage.size.height){
        minWidth = originalImage.size.height;
        isWidth = NO;
}

UIBezierPath *path;
if(isWidth)
    path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, (originalImage.size.height - minWidth)/2, minWidth, minWidth)];
else
    path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake((originalImage.size.width - minWidth)/2, 0, minWidth, minWidth)];


UIGraphicsBeginImageContextWithOptions(originalImage.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, true);
CGContextSetShouldAntialias(context, true);
[path addClip];
[originalImage drawAtPoint:CGPointZero];
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

//This is based on the full size image
CGRect imageRect = CGRectMake(0, 0, maskedImage.size.width + 2, maskedImage.size.height + 2);
UIGraphicsBeginImageContext(imageRect.size);
[maskedImage drawInRect:CGRectMake(1,1,maskedImage.size.width,maskedImage.size.height)];
maskedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Aliasing Image


Solution

  • I had this problem and it took me several hours on google and debugging but I finally figured this one out.

    Whats happening is when you set the maskedImage to your imageView.image there is some resizing going on which includes the rounded clipping (on the image) and the result comes out funky.

    A small example would be if your imageView has a bounds of 100x100 and the maskedImage has a bounds of 300x300 then when the imageView.image sets the maskedImage there will be reduced resizing to fit the image. This reduced sizing wont updated the rounded clipping, so your result is what appears to be jagged edges. If before you add the rounded clipping you scale the maskedImage to a size close to the imageView then your rounded edges will look exactly how you want!