I'm trying to draw images on the iPhone using with rounded corners, a la the contact images in the Contacts app. I've got code that generally work, but it occasionally crashes inside of the UIImage drawing routines with an EXEC_BAD_ACCESS
- KERN_INVALID_ADDRESS
. I thought this might be related to the cropping question I asked a few weeks back, but I believe I'm setting up the clipping path correctly.
Here's the code I'm using - when it doesn't crash, the result looks fine and anybody looking to get a similar look is free to borrow the code.
- (UIImage *)borderedImageWithRect: (CGRect)dstRect radius:(CGFloat)radius { UIImage *maskedImage = nil; radius = MIN(radius, .5 * MIN(CGRectGetWidth(dstRect), CGRectGetHeight(dstRect))); CGRect interiorRect = CGRectInset(dstRect, radius, radius); UIGraphicsBeginImageContext(dstRect.size); CGContextRef maskedContextRef = UIGraphicsGetCurrentContext(); CGContextSaveGState(maskedContextRef); CGMutablePathRef borderPath = CGPathCreateMutable(); CGPathAddArc(borderPath, NULL, CGRectGetMinX(interiorRect), CGRectGetMinY(interiorRect), radius, PNDegreeToRadian(180), PNDegreeToRadian(270), NO); CGPathAddArc(borderPath, NULL, CGRectGetMaxX(interiorRect), CGRectGetMinY(interiorRect), radius, PNDegreeToRadian(270.0), PNDegreeToRadian(360.0), NO); CGPathAddArc(borderPath, NULL, CGRectGetMaxX(interiorRect), CGRectGetMaxY(interiorRect), radius, PNDegreeToRadian(0.0), PNDegreeToRadian(90.0), NO); CGPathAddArc(borderPath, NULL, CGRectGetMinX(interiorRect), CGRectGetMaxY(interiorRect), radius, PNDegreeToRadian(90.0), PNDegreeToRadian(180.0), NO); CGContextBeginPath(maskedContextRef); CGContextAddPath(maskedContextRef, borderPath); CGContextClosePath(maskedContextRef); CGContextClip(maskedContextRef); [self drawInRect: dstRect]; maskedImage = UIGraphicsGetImageFromCurrentImageContext(); CGContextRestoreGState(maskedContextRef); UIGraphicsEndImageContext(); return maskedImage; }
and here's the crash log. It looks the same whenever I get one of these crashes
Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x6e2e6181 Crashed Thread: 0 Thread 0 Crashed: 0 com.apple.CoreGraphics 0x30fe56d8 CGGStateGetRenderingIntent + 4 1 libRIP.A.dylib 0x33c4a7d8 ripc_RenderImage + 104 2 libRIP.A.dylib 0x33c51868 ripc_DrawImage + 3860 3 com.apple.CoreGraphics 0x30fecad4 CGContextDelegateDrawImage + 80 4 com.apple.CoreGraphics 0x30feca40 CGContextDrawImage + 368 5 UIKit 0x30a6a708 -[UIImage drawInRect:blendMode:alpha:] + 1460 6 UIKit 0x30a66904 -[UIImage drawInRect:] + 72 7 MyApp 0x0003f8a8 -[UIImage(PNAdditions) borderedImageWithRect:radius:] (UIImage+PNAdditions.m:187)
To make an image with round corners or to make any view or button or any UI element with round corners in swift, we need to access the corner radius property of its layer. Every UI element in iOS is based on a layer.
Select the view that you want to round and open its Identity Inspector. In the User Defined Runtime Attributes section, add the following two entries: Key Path: layer. cornerRadius , Type: Number, Value: (whatever radius you want)
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 view CALayer * l = [roundedView layer]; [l setMasksToBounds:YES]; [l setCornerRadius:10.0]; // You can even add a border [l setBorderWidth:4.0]; [l setBorderColor:[[UIColor blueColor] CGColor]];
I'm gonna go ahead here and actually answer the question in the title.
Try this category.
UIImage+additions.h
#import <UIKit/UIKit.h> @interface UIImage (additions) -(UIImage*)makeRoundCornersWithRadius:(const CGFloat)RADIUS; @end
UIImage+additions.m
#import "UIImage+additions.h" @implementation UIImage (additions) -(UIImage*)makeRoundCornersWithRadius:(const CGFloat)RADIUS { UIImage *image = self; // Begin a new image that will be the new image with the rounded corners // (here with the size of an UIImageView) UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale); const CGRect RECT = CGRectMake(0, 0, image.size.width, image.size.height); // Add a clip before drawing anything, in the shape of an rounded rect [[UIBezierPath bezierPathWithRoundedRect:RECT cornerRadius:RADIUS] addClip]; // Draw your image [image drawInRect:RECT]; // Get the image, here setting the UIImageView image //imageView.image UIImage* imageNew = UIGraphicsGetImageFromCurrentImageContext(); // Lets forget about that we were drawing UIGraphicsEndImageContext(); return imageNew; } @end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With