How to mask a square image into an image with round corners in iOS? How to mask a square image into an image with round corners in iOS? ios ios

How to mask a square image into an image with round corners in iOS?


You can use CoreGraphics to create a path for a round rectangle with this code snippet:

static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight){    float fw, fh;    if (ovalWidth == 0 || ovalHeight == 0) {        CGContextAddRect(context, rect);        return;    }    CGContextSaveGState(context);    CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));    CGContextScaleCTM (context, ovalWidth, ovalHeight);    fw = CGRectGetWidth (rect) / ovalWidth;    fh = CGRectGetHeight (rect) / ovalHeight;    CGContextMoveToPoint(context, fw, fh/2);    CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);    CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);    CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);    CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);    CGContextClosePath(context);    CGContextRestoreGState(context);}

And then call CGContextClip(context); to clip it to the rectangle path. Now any drawing done, including drawing an image, will be clipped to the round rectangle shape.

As an example, assuming "image" is a UIImage, and this is in a drawRect: method:

CGContextRef context = UIGraphicsGetCurrentContext();CGContextSaveGState(context);addRoundedRectToPath(context, self.frame, 10, 10);CGContextClip(context);[image drawInRect:self.frame];CGContextRestoreGState(context);


Here is an even easier method that is available in iPhone 3.0 and up. Every View-based object has an associated layer. Each layer can have a corner radius set, this will give you just what you want:

UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];// Get the Layer of any viewCALayer * layer = [roundedView layer];[layer setMasksToBounds:YES];[layer setCornerRadius:10.0];// You can even add a border[layer setBorderWidth:4.0];[layer setBorderColor:[[UIColor blueColor] CGColor]];

To use these methods you might need to add:

#import <QuartzCore/QuartzCore.h>


I realize this is old news but just to boil it down a bit:

There are two possible questions here: (1) how do I apply rounded corners to a UIView (such as a UIImageView), which will be displayed on screen, and (2) how do I mask a square image (that is, a UIImage) to produce a new image with rounded corners.

For (1), the easiest course is to use CoreAnimation and set the view.layer.cornerRadius property

 // Because we're using CoreAnimation, we must include QuartzCore.h // and link QuartzCore.framework in a build phases  #import <QuartzCore/QuartzCore.h>  // start with an image  UIImage * fooImage = [UIImage imageNamed:@"foo.png"]; // put it in a UIImageView UIView * view = [UIImageView alloc] initWithImage:fooImage]; // round its corners. This mask now applies to the view's layer's *background* view.layer.cornerRadius = 10.f // enable masksToBounds, so the mask applies to its foreground, the image view.layer.masksToBounds = YES;

For (2), the best way is to use the UIKit graphics operations:

// start with an image UIImage * fooImage = [UIImage imageNamed:@"foo.png"];CGRect imageRect = CGRectMake(0, 0, fooImage.size.width, fooImage.size.height);// set the implicit graphics context ("canvas") to a bitmap context for imagesUIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0);// create a bezier path defining rounded cornersUIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:10.f];// use this path for clipping in the implicit context[path addClip];// draw the image into the implicit context[fooImage drawInRect:imageRect];// save the clipped image from the implicit context into an image UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();// cleanupUIGraphicsEndImageContext();

What's tricky about problem (2) is that you might think you could do the whole operation using the view.layer.mask property in CoreAnimation. But you can't because the CALayer renderInContext: method, which you'd use to generate a UIImage from the masked layer, seems to ignore the mask. Worse, the documentation for renderInContext: doesn't mention this, and only alludes to the behavior for OSX 10.5.

Some further context: the above approach to (2) is using UIKit's wrappers around more basic CoreGraphics functionality. You can do the same thing using the CoreGraphics calls directly – that is what the chosen answer is doing -- but then you need build the rounded rect bezier path manually from curves and lines and you also need to compensate for the fact that CoreGraphics uses a drawing coordinate system which is flipped with respect to UIKit's.