反锯齿,UIImage和性能

6

我有一个加载到UIImageView中的UIImageUIImageUIImageView要大,因此已缩小以适应。 显然,缩小后的UIImage显示锯齿状边缘。

如何以性能为考虑对该图像进行抗锯齿处理?

我看过使用drawInRect的方法,但我也读过drawInRect不提供最佳性能

我阅读了几篇不同的文章,并尝试了一些方法。 但是,在阅读了关于使用UIViews和Core Graphics之间性能差异的几篇 更多 文章之后,我想知道哪种抗锯齿技术能够提供最佳性能?

3个回答

6

请查看可用的核心图像滤镜列表。具体而言,通过CILanczosScaleTransform可用的Lanczos比例变换似乎正是您所需的。它应该在所有iOS版本>= 6.0上都可用。

通常情况下,使用核心图像滤镜比手动使用核心图形更加高效。但是,我建议您在特定情况下验证结果以及性能。


嗨,这在大图像上效果很好,但我的小图像非常模糊 - 我正在研究CIUnsharpMask,但有没有一种方法可以使用CILanczosScaleTransform而不使图像模糊? - Jimmery
2
好的,Lanczos比例变换通常只用于缩小图像并仍然获得高质量的结果。您可以检测到您的图像是否足够大于图像视图,并仅有条件地应用滤镜。当然,对于缺乏足够细节的图像,在放大时某些模糊是不可避免的。 - Buzzy

2
最佳解决方案是在你的UIImageView中始终使用正确的图像大小。但是,如果您无法获得正确的图像大小并且需要调整大小,则另一个很好的解决方案是使用CoreGraphics在主线程之外执行图像缩放操作。
自SDK 4.0以来,CoreGraphics操作是线程安全的,因此您可以将所有调整大小的内容放入后台队列中,并在那里处理调整大小。调整大小完成后,您必须在主线程中为您的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类别,具有调整大小缓存,并使用后台线程执行Core Graphics操作。

谢谢,你有这个代码的 Swift 版本吗? - Jimmery

1

既然你在评论中提到了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()),否则它会出现断言。


这应该放在Alamofire自述文件的顶部大信息框中:D - 谢谢! - heyfrank

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接