【问题标题】:Any quick and dirty anti-aliasing techniques for a rotated UIImageView?旋转 UIImageView 的任何快速而肮脏的抗锯齿技术?
【发布时间】:2010-11-11 06:56:09
【问题描述】:

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

【问题讨论】:

  • 图像是否在内部进行了抗锯齿处理——是锯齿状的边缘还是整个图像?顺便说一句,如果可能的话,我建议使用 CALayer。
  • 它适用于 iPhone,所以我相信它已经支持 CALayer。
  • 确实如此,但如果不需要,为什么还要携带所有 UIView/UIResponder 包袱呢?
  • 好吧,在我的情况下,他们需要查看需要注册触摸
  • 只有边缘是锯齿状的......图像本身抗锯齿很好。

标签: iphone cocoa-touch uiimageview uiimage antialiasing


【解决方案1】:

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

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

如果您不希望启用此选项的性能开销,解决方法是add a 1px transparent border around the edge of the image。这意味着图像的“边缘”不再在边缘,所以不需要特殊处理!

【讨论】:

  • 这太甜了!如此简单,却又如此强大! :D
  • 疯了,这不是最佳答案
  • 对效率的影响有什么提示吗?
  • @MathieuGodart 没有测试自己,因为它在我需要的地方运行得很好。使用 Instruments 来确定它对您的性能有多大影响。当然,Apple 默认关闭此功能是有原因的。
  • 我注意到在 Info.plist 文件中将 UIViewEdgeAntialiasing 设置为 YES 会弄乱UIAlertView 的所有角落。
【解决方案2】:

新 API – iOS 6/7

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

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

【讨论】:

  • 这是一个很棒的 AP​​I。请注意,它也适用于 iOS 6(尽管显然只在 iOS 7 SDK 中添加/启用)。
  • 这可能是解决这个问题的最佳问题
【解决方案3】:

只需为您的图像添加 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();

【讨论】:

  • 在这里也很好用。仅供参考:更简单的插图计算:CGRectInset(imageRect, 1.0, 1.0)
【解决方案4】:

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

CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

【讨论】:

  • 在添加这些抗锯齿线以封闭 UIImageView 的 drawRect ......以及封闭的超级视图时,我没有看到任何区别。甚至尝试过:CGContextSetInterpolationQuality(context, kCGInterpolationHigh);无济于事......当 UIImageView 矩形被转换(旋转)时,边缘总是锯齿状......
  • 解决该问题的最佳方法是在旋转之前为图像添加 1px 透明边框。
  • 如何添加透明边框?我在使用透视旋转 CALayer 时遇到了同样的问题。
  • 有人可以提供关于这个 1px 透明边框技巧的提示吗?我已经设置了 UIView 的 layer.borderColor 和 layer.borderWidth,但它并没有为我修复它。
  • 我的图像来自 glReadPixels(OpenGL ES 帧缓冲区捕获),因此我可以直接在 RGBA 内存缓冲区上设置 alpha。对于那些也处于这种情况的人,请确保不要在 CGImageCreate 调用中使用预乘(即我为 CGBitmapInfo 提供了 kCGImageAlphaLast | kCGBitmapByteOrder32Big)。
【解决方案5】:

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

【讨论】:

    【解决方案6】:

    我完全推荐以下库。

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

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

    享受吧!

    【讨论】:

      【解决方案7】:

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

      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

      【讨论】:

      • 这是关于 UIGraphicsBeginImageContextWithOptions 的一个很好的观点。通常你必须将 opaque 选项设置为 NO。我正在绘制线条(即透明背景上的线条),然后使用 renderInContext 将线条的图像绘制到现有照片中。 当然,使用不透明的“NO”很重要。所以,这对我来说非常明显 - 在 iWasRobbed 告诉我之后 :) 谢谢,被抢劫了! :)
      • @JoeBlow 很高兴它有帮助!
      【解决方案8】:

      我从here 找到了这个解决方案,非常完美:

      + (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];
      

      【讨论】:

        猜你喜欢
        • 2010-12-02
        • 1970-01-01
        • 2010-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多