【问题标题】:Anti Alias, UIImage and Performance抗锯齿、UIImage 和性能
【发布时间】:2015-03-04 09:02:31
【问题描述】:

我将UIImage 加载到UIImageView 中。 UIImageUIImageView 大,并且已按比例缩小以适合。显然,缩小的UIImage 显示出锯齿状边缘。

在性能方面对该图像进行抗锯齿处理的最佳方法是什么?

我见过this method using drawInRectI've also read that drawInRect does not give the best performance

我已经阅读了几篇不同的文章,并且我自己也尝试了一些方法。但是在阅读了few more posts 关于使用UIViews 和Core Graphics 之间的性能差异之后,我想知道哪种图像抗锯齿方法可以提供最佳性能?

【问题讨论】:

    标签: ios performance uiimageview uiimage antialiasing


    【解决方案1】:

    调查可用Core Image Filters 的列表。具体来说,CILanczosScaleTransform 提供的 Lanczos Scale Transform 似乎正是您所需要的。它应该适用于所有 iOS 版本 >= 6.0。

    通常,使用 Core Image 过滤器比手动使用 Core Graphics 更高效。但是,我敦促您验证结果以及在您的特定情况下的性能。

    【讨论】:

    • 嗨,这在较大的图像上效果很好,但我的较小图像真的很模糊 - 我正在研究 CIUnsharpMask,但有没有办法使用 CILanczosScaleTransform 而不会模糊图像?
    • 嗯,Lanczos 比例变换通常仅用于缩小图像并仍然获得高质量的结果。您可以检测图像何时比图像视图大得多,并且仅有条件地应用过滤器。当然,对于缺乏足够细节的图像,在放大时不可避免地会出现一定的模糊。
    【解决方案2】:

    最好的解决方案是始终在您的 UIImageView 中使用正确的图像尺寸。但是,如果您无法获得正确的图像大小并且需要调整其大小,另一个不错的解决方案是使用 CoreGraphics 在主线程之外执行图像缩放操作。

    从 SDK 4.0 开始,CoreGraphics operations are thread safe,因此您可以将所有调整大小的内容放入后台队列并在那里处理调整大小。调整大小完成后,您必须在主线程的UIImageView 中分配裁剪后的图像,因为所有UIKit 的东西都必须在该线程中完成。使用这种方法,您不会在每次调整图像大小时都阻塞主线程。

    完成此操作后,您还可以缓存裁剪结果以避免重复裁剪计算(即每次滚动到相同的UITableViewCell)并提高性能。

    您可以将此实现为UIImage 类别,以我的代码为例:

    - (void)resizeImageWithSize:(CGSize)size
                       cacheKey:(NSString *)cacheKey
                completionBlock:(void (^)(UIImage *croppedImage))completionBlock
    {
        dispatch_async([[self class] sharedBackgroundQueue], ^{
            // Check if we have the image cached
            UIImage *resizedImage = [[[self class] resizedImageCache] objectForKey:cacheKey];
            if (nil == resizedImage) {
                // If not, resize and cache it
                @autoreleasepool {
                   resizedImage = [self resizeImageWithSize:size];
                   [[[self class] resizedImageCache] setObject:resizedImage forKey:cacheKey];
                }
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                completionBlock(resizedImage);
            });
        });
    }
    

    然后,resizeImageWithSize: 方法实现是所有 CoreGraphics 事情发生的地方。您可能会发现 Nick Lockwood 的 FXImageView 库很有趣,它使用相同的方法:UIImageView 类别,具有调整大小缓存并使用后台线程来处理核心图形。

    【讨论】:

    • 谢谢你,你有这段 Swift 代码的副本吗?
    【解决方案3】:

    既然您在 cmets 中询问了 Swift:

    Alamofire 内置了所有这些功能,包括自动缓存层。如果您没有将它用于网络请求,那么至少它是一个很好的示例。

    例子:

    // Note: this seamlessly handles both scaling AND caching the scaled image
    let filter = AspectScaledToFillSizeFilter(size: imageView.frame)
    imageView.af_setImage(withURL: url, filter: filter)
    

    只需确保事先设置了imageView.frame(例如,首先调用layoutIfNeeded() 进行自动布局),否则它会断言。

    【讨论】:

    • Wtf,这应该在 Alamofire 自述文件顶部的一个大信息框中:D - 谢谢!
    猜你喜欢
    • 2011-08-30
    • 2013-01-02
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    • 1970-01-01
    • 2016-06-28
    相关资源
    最近更新 更多