首页 文章

iOS UIImageView缩小图像会在iPad 2上生成别名图像

提问于
浏览
35

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

图像通常从大约500px x 500px缩小到100px x 100px . 在视网膜iPad上,它们显示得非常好,而在iPad2上,它们被严重混淆,直到尺寸接近原始图像尺寸 .

例子:

Original Image

原始图像

Retina iPad 100x100

Retina iPad渲染速度为100px x 100px

iPad 2 100x100

iPad 2渲染为100px x 100px

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

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

在我继续下载图像复制/调整大道之前,我想检查一下我没有找到更简单的东西 . 我很欣赏UIImage不是可以缩放的,但我的印象是UIImageView可以处理扩展,但目前它似乎没有做好缩小的工作 . 我错过了什么(如果有的话)?

Update :注意:渲染/调整大小的图像上的阴影会添加到代码中 . 禁用此功能对缩放的质量没有任何影响 .

5 回答

  • 7

    我试过的另一种方法似乎是改进的方法是设置minificationFilter:

    [imageView.layer setMinificationFilter:kCAFilterTrilinear]
    

    质量肯定有所改善,我没有注意到性能受到影响 .

  • 1

    如果你只是将大图像放在一个小的图像视图中,它看起来真的很糟糕 .

    解决方案是正确调整图像大小...我将添加一个示例函数来完成这个技巧:

    - (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;
    }
    

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

  • 6

    如果你不害怕浪费记忆并知道你为特定情况做了什么,这种方法很有效 .

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

    结果质量比setMinificationFilter好得多 .

    我正在使用256x256的图像,并将它们缩放到像48像素 . 显然,这里更安全的解决方案是将图像缩小到精确的目标尺寸 .

  • 73

    如果您不想自己重新取样,请应用小的缩小滤镜偏差可以解决此问题:

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

    enter image description here

    左图没有应用过滤 . 右图有0.1偏滤 .

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

    使用非常小的值,你通常可以提出一个值来平滑缩放工件,这比自己调整位图大小要容易得多 . 当然,随着偏差的增加,你会丢失细节,所以即使小于0.1的值也可能就足够了,尽管这一切都取决于图像视图显示图像的帧的大小 .

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

    这项技术的另一个潜在优势,虽然我自己没有尝试过,但你可以动画 minificationFilterBias . 因此,如果您要将图像视图作为动画的一部分进行相当大的缩放,请考虑将过滤器偏差从 0.0 设置为您确定的适合缩小尺寸的任何小值 .

    最后,正如其他人所指出的,如果您的源图像非常大,如果过度使用此技术则不合适,因为Core Animation将始终保留原始位图 . 在大多数情况下,最好调整图像大小然后丢弃源图像而不是使用mipmapping,但是对于一次性或者图像视图将要足够快地解除分配的情况,这很好 .

  • 5

    接下来对我有帮助:

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

    Keep an eye on performance 如果在滚动列表中使用 .

相关问题