UIImage上的圆angular
我试图在iPhone上使用圆angular来绘制图像,在联系人应用程序中使用联系人图像。 我已经得到了一般工作的代码,但它偶尔会在UIImage绘图例程中崩溃,并带有EXEC_BAD_ACCESS
– KERN_INVALID_ADDRESS
。 我认为这可能与我几周前提出的裁剪问题有关,但是我相信我正确设置了裁剪path。
这里是我正在使用的代码 – 当它没有崩溃时,结果看起来很好,任何想要获得类似外观的人都可以自由地借用代码。
- (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; }
这里是崩溃日志。 每当我遇到这些崩溃之一,它看起来都是一样的
exceptiontypes:EXC_BAD_ACCESS(SIGSEGV) 例外代码:0x6e2e6181处的KERN_INVALID_ADDRESS 坠毁的线程:0 线程0崩溃: 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)
这是iPhone 3.0及更高版本中更简单的方法。 每个基于视图的对象都有一个关联的图层。 每个图层都可以有一个圆angular半径设置,这会给你正是你想要的:
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]];
我会在这里继续,并真正回答标题中的问题。
试试这个类别。
的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
如果appIconImage是一个UIImageView,那么:
appIconImage.image = [UIImage imageWithContentsOfFile:@"image.png"]; appIconImage.layer.masksToBounds = YES; appIconImage.layer.cornerRadius = 10.0; appIconImage.layer.borderWidth = 1.0; appIconImage.layer.borderColor = [[UIColor grayColor] CGColor];
还请记住:
#import <QuartzCore/QuartzCore.h>
我不能提供任何洞察你的崩溃,但我想我会提供另一个select四舍五入的angular落。 我有一个类似的问题出现在我正在处理的应用程序中。 而不是写任何代码,我覆盖了另一个掩盖了angular落的图像。
如果您在后台线程中调用方法(borderedImageWithRect),则可能会发生崩溃,因为UIGraphics函数不是线程安全的。 在这种情况下,您必须使用CGBitmapContextCreate()创build上下文 – 请参阅SDK中的“reflection”示例代码。
最简单的方法是在视图中embedded一个禁用的[!]圆angular[非定制!]button(甚至可以在界面生成器中完成),并将图像与其关联。 UIButton的图像设置信息是不同的(与UIImageView相比),但整体kludge的作品像一个魅力。 使用setImage:forState:如果你想要一个居中的图标或setBackgroundImage:forState:如果你想整个图像的angular落切(如联系人)。 当然,如果你想在你的drawRect中显示大量这些图像,这不是正确的方法,但是更可能的是embedded视图正是你所需要的。
我会重申fjoachim的回答 :试图在单独的线程上运行绘图时要小心,否则可能会得到EXC_BAD_ACCESS
错误。
我的解决方法是这样的:
UIImage *originalImage = [UIImage imageNamed:@"OriginalImage.png"] [self performSelectorOnMainThread:@selector(displayImageWithRoundedCorners:) withObject:originalImage waitUntilDone:YES];
(在我的情况下,我正在调整/缩放UIImages。)
我真的有机会在纽约的iPhone技术讲座上与苹果公司的人讨论这个问题。 当我们谈到这件事的时候,他很确定这不是一个穿线。 相反,他认为我需要保留在调用UIGraphicsBeginImageContext
时生成的graphics上下文。 这似乎违反了处理保留规则和命名scheme的一般规则,但这个人很确定他之前看到过这个问题。
如果记忆被潦草写下,或许是另一个线索,那肯定会解释为什么我偶尔会看到这个问题。
我没有时间重新访问代码并testing修复,但是PCheese的评论让我意识到我没有在这里发布信息。
…除非我写错了, UIGraphicsBeginImageContext
应该已经CGBitmapContextCreate
…
如果它只是在一些时间崩溃,找出碰撞事件的共同点。 dstRect每次都一样吗? 图像是否有不同的大小?
此外,你需要CGPathRelease(borderPath)
,虽然我怀疑泄漏是造成你的问题。
UIImage *originalImage = [UIImage imageNamed:@"OriginalImage.png"] [self performSelectorOnMainThread:@selector(displayImageWithRoundedCorners:) withObject:originalImage waitUntilDone:YES];
在xib或storyboard中设置图像(图像宽度和高度41×41)。
FirstViewController.h
@interface.... IBOutlet UIImageView *testImg; @end
FirstViewController.m
-(void)viewDidLoad{ testImg.layer.backgroundColor=[[UIColor clearColor] CGColor]; testImg.layer.cornerRadius=20; testImg.layer.masksToBounds = YES; }