Question

I want to add rounded corners to an UIImageView without using QuartzCore to avoid performance issues in a UIScrollView so I solved it like that:

    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:CGSizeMake(self.cornerRadius, self.cornerRadius)];
    [path addClip];

    UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetBlendMode(UIGraphicsGetCurrentContext( ),kCGBlendModeClear); CGContextSetStrokeColorWithColor(context, [UIColor clearColor].CGColor);
    CGContextAddPath(context,path.CGPath);
    CGContextClip(context);
    CGContextClearRect(context,CGRectMake(0,0,width,height));

    [_image drawInRect:rect];

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

Sadly, called in drawRect, this takes a little bit of processing time which produces a lag while scrolling in a UIScrollView. Hence I tried to process this in a seperate thread with the help of a dispatch_async. This removed the lag and everything works smoothly like it should be. But now I have another problem. I get many many invalid context messages in the debugger because the GraphicsContext is not always present when the thread starts the image processing asynchronously. Is there a way to process the rounded corners in my Image without getting invalid context messages? Please note that I do not want to use QuarzCore's cornerRadius or mask-functions.

Was it helpful?

Solution

You are doing more work than you need to. The "invalid context" messages are caused by calling [path addClip] before calling UIGraphicsBeginImageContextWithOptions(). The UIBezierPath tries to access the thread's current graphics context, but you haven't set one up yet.

Here's a simpler way to get the same results. Note that you don't need to use CGContext at all.

UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);

UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:CGSizeMake(self.cornerRadius, self.cornerRadius)];
[path addClip];

[_image drawInRect:rect];

UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

OTHER TIPS

I want to add rounded corners to an UIImageView without using QuartzCore to avoid performance issues

One approach is to round the corners of the image instead of the corners of the UIImageView. See my answer here:

https://stackoverflow.com/a/8125604/341994

We start with any UIImage and round its corners by drawing into a clipped context. This takes no "processing time" and causes no performance issues.

(NOTE: In a table view or other very fast scrolling or animation situation, there can be performance issues caused by the transparency at the rounded corners. But that is a much more general problem and has little to do without how the rounding is done; it has to do with the fact that we must constantly composite the moving shape onto the background. If the background is a solid color and you know in advance what it will be, it is more efficient to make an opaque image where the rounded corner areas have the color of the background.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top