26

我有一个使用 CGAffineTransform 旋转的 UIImageView(全帧和矩形)。UIImageView 的 UIImage 填满了整个框架。当图像被旋转和绘制时,边缘出现明显的锯齿状。我能做些什么让它看起来更好吗?它显然没有与背景抗锯齿。

4

8 回答 8

55

在 iOS 上默认情况下 CoreAnimation 层的边缘没有抗锯齿。但是,您可以在 Info.plist 中设置一个启用边缘抗锯齿的键:UIViewEdgeAntialiasing。

https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html

如果您不希望启用此选项的性能开销,解决方法是在图像边缘周围添加 1px 透明边框。这意味着图像的“边缘”不再在边缘,所以不需要特殊处理!

于 2011-11-22T06:11:00.177 回答
28

新 API – iOS 6/7

正如@Chris 所指出的,也适用于 iOS 6,但直到 iOS 7 才公开。

从 iOS 7 开始,CALayer 有了一个新属性allowsEdgeAntialiasing,在这种情况下完全可以满足您的需求,而不会产生为应用程序中的所有视图启用它的开销!这是 CALayer 的一个属性,因此要为您使用的 UIView 启用它 myView.layer.allowsEdgeAntialiasing = YES

于 2014-02-15T01:54:34.320 回答
17

只需为您的图像添加 1px 透明边框

CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0.0);
[image drawInRect:CGRectMake(1,1,image.size.width-2,image.size.height-2)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
于 2011-02-20T14:00:25.963 回答
10

请记住设置适当的抗锯齿选项:

CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);
于 2009-07-16T12:23:46.943 回答
6

只需在 plist 中添加“带有边缘抗锯齿的渲染”和 YES 即可。

于 2013-09-26T06:08:22.130 回答
5

我完全推荐以下库。

http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/

它包含许多有用的 UIImage 扩展来解决这个问题,还包括用于生成缩略图等的代码。

享受!

于 2010-02-11T01:59:39.013 回答
2

我发现拥有平滑边缘和清晰图像的最佳方法是这样做:

CGRect imageRect = CGRectMake(0, 0, self.photo.image.size.width, self.photo.image.size.height);
UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0.0);
[self.photo.image drawInRect:CGRectMake(1, 1, self.photo.image.size.width - 2, self.photo.image.size.height - 2)];
self.photo.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

像某些人描述的那样添加 Info.plist 键会对性能产生很大影响,如果您使用它,那么您基本上会将其应用于所有内容,而不仅仅是您需要的地方。

另外,不要只使用,UIGraphicsBeginImageContext(imageRect.size);否则图层会模糊。你必须UIGraphicsBeginImageContextWithOptions像我展示的那样使用。

于 2013-04-25T21:07:26.870 回答
0

我从这里找到了这个解决方案,它很完美:

+ (UIImage *)renderImageFromView:(UIView *)view withRect:(CGRect)frame transparentInsets:(UIEdgeInsets)insets {
    CGSize imageSizeWithBorder = CGSizeMake(frame.size.width + insets.left + insets.right, frame.size.height + insets.top + insets.bottom);
    // Create a new context of the desired size to render the image
    UIGraphicsBeginImageContextWithOptions(imageSizeWithBorder, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Clip the context to the portion of the view we will draw
    CGContextClipToRect(context, (CGRect){{insets.left, insets.top}, frame.size});
    // Translate it, to the desired position
    CGContextTranslateCTM(context, -frame.origin.x + insets.left, -frame.origin.y + insets.top);

    // Render the view as image
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    // Fetch the image
    UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();

    // Cleanup
    UIGraphicsEndImageContext();

    return renderedImage;
}

用法:

UIImage *image = [UIImage renderImageFromView:view withRect:view.bounds transparentInsets:UIEdgeInsetsZero];
于 2016-09-13T08:53:25.373 回答