41

我正在使用 UIImageView 显示图像的缩略图,然后可以选择以全尺寸查看。UIImageView 将其内容模式设置为宽高比合适。

图像通常从大约 500 像素 x 500 像素缩小到 100 像素 x 100 像素。在视网膜 iPad 上,它们显示得非常好,而在 iPad2 上,它们的锯齿很严重,直到尺寸接近原始图像尺寸。

例子:

原始图像

原始图像

视网膜 iPad 100x100

100px x 100px 的 Retina iPad 渲染

iPad 2 100x100

iPad 2 以 100 像素 x 100 像素渲染

iPad 2 和新 iPad 之间的区别可能只是屏幕分辨率,也可能是 GPU 更适合缩放图像。无论哪种方式,iPad 2 的渲染效果都很差。

我首先尝试通过创建一个新的上下文来减小图像大小,将插值质量设置为高并将图像绘制到上下文中。在这种情况下,图像在两台 iPad 上看起来都很好。

在我继续图像复制/调整大小之前,我想检查一下我是否遗漏了一些更简单的东西。我很欣赏 UIImage 不是要缩放的,但我的印象是 UIImageView 可以处理缩放,但目前它似乎并没有很好地缩小。我错过了什么(如果有的话)?

更新:注意:在代码中添加了渲染/调整大小图像上的阴影。禁用此功能对缩放质量没有影响。

4

5 回答 5

75

我尝试过的另一种似乎确实可以改善事情的方法是设置 minificationFilter:

[imageView.layer setMinificationFilter:kCAFilterTrilinear]

质量肯定有所提高,我没有注意到性能受到影响。

于 2012-10-05T09:01:24.273 回答
10

如果您不想自己重新采样图像,应用一个小的缩小过滤器偏差可以帮助解决这个问题:

imageView.layer.minificationFilter = kCAFilterTrilinear
imageView.layer.minificationFilterBias = 0.1

在此处输入图像描述

左侧图像没有应用过滤。右图的过滤器偏差为 0.1。

请注意,不需要显式光栅化。

使用非常小的值,您通常可以想出一个足够平滑缩放伪影的值,这比自己调整位图的大小要容易得多。当然,随着偏差的增加,您会丢失细节,因此小于 0.1 的值可能就足够了,尽管这完全取决于显示图像的图像视图框架的大小。

只需意识到三线性过滤有效地启用了层上的mipmapping,这基本上意味着它会以越来越小的比例生成位图的额外副本。这是一种非常常见的渲染技术,用于提高渲染速度并减少缩放锯齿。权衡是它需要更多内存,尽管连续下采样位图的内存使用量呈指数级减少。

尽管我自己没有尝试过,但这种技术的另一个潜在优势是您可以为minificationFilterBias. 因此,如果您要将图像视图作为动画的一部分大幅缩小,请考虑将过滤器偏差0.0设置为您确定适合缩小尺寸的任何小值。

最后,正如其他人所指出的,如果您的源图像非常大,那么过度使用这种技术是不合适的,因为核心动画将始终围绕原始位图。在大多数情况下,最好调整图像大小然后丢弃源图像,而不是使用 mipmapping,但对于一次性或图像视图将被足够快地释放的情况,这很好。

于 2017-04-08T21:46:51.217 回答
7

If you're not afraid of wasting memory and know what you're doing for a particular case, this works beautifully.

myView.layer.shouldRasterize = YES;
myView.layer.rasterizationScale = 2;

The resulting quality is much better than setMinificationFilter.

I am using images that are 256x256 and scaling them to something like 48 px. Obviously a saner solution here would be to downscale the images to the exact destination size.

于 2014-06-25T23:06:26.473 回答
7

如果您只是将大图像放在小图像视图中,它看起来会很糟糕。

解决方案是正确调整图像大小......我将添加一个可以解决问题的示例函数:

- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGImageRef imageRef = image.CGImage;

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);

    CGContextConcatCTM(context, flipVertical);
    CGContextDrawImage(context, newRect, imageRef);

    CGImageRef newImageRef = CGBitmapContextCreateImage(context);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    CGImageRelease(newImageRef);
    UIGraphicsEndImageContext();

    return newImage;
}

此功能可能需要一些时间..因此您可能希望将结果保存到缓存文件。

于 2012-10-04T16:12:02.653 回答
1

Next helped to me:

imageView.layer.minificationFilter = kCAFilterTrilinear
imageView.layer.shouldRasterize = true
imageView.layer.rasterizationScale = UIScreen.mainScreen().scale

Keep an eye on performance if used in scroll lists.

于 2016-07-05T10:38:42.743 回答