通过使用低分辨率图像来加速 UIImagePickerController 然后稍后交换高分辨率图像

Posted

技术标签:

【中文标题】通过使用低分辨率图像来加速 UIImagePickerController 然后稍后交换高分辨率图像【英文标题】:Speed up UIImagePickerController by using a low res image then later swapping in the high res image 【发布时间】:2012-10-03 13:03:07 【问题描述】:

关于image loading from the camera picker 有一个很棒的维基。这让我意识到以全分辨率拍摄图像的成本。

此刻,当一张照片被选中时,我推送一个新的视图控制器并以全分辨率显示图像。推动视图是一种非常缓慢且不稳定的体验(大约 1 fps!),我想平滑它。与在 Instagram 上挑选照片相比,我注意到他们使用的是低分辨率图像,然后换成了完整图像。 (我需要完整的分辨率图像,因为用户应该能够缩放和平移)

我想要的想法是这样的:

- (void)imagePickerController:(UIImagePickerController *)picker
        didFinishPickingMediaWithInfo:(NSDictionary *)info 


    UIImage* fullImage = [info objectForKey:UIImagePickerControllerOriginalImage];

    // Push a view controller and give it the image.....


- (void) viewDidLoad 

    CGSize smallerImageSize = _imageView.bounds;
    UIImage* smallerImage = [MyHelper quickAndDirtyImageResize:_fullImage     
                                                        toSize:smallerImageSize];

    // Set the low res image for now... then later swap in the high res
    _imageView.image = smallerImage;

    // Swap in high res image async
    // This is the part im unsure about... Im sure UIKit isn't thread-safe!
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, NULL), ^
        _imageView.image = _fullImage;
    );

我认为 UIImage 在使用之前不是内存映射的。因此,它不会减慢速度,直到将其提供给 imageView。这是正确的吗?

我认为图像解码已经由系统异步完成,但是,它仍然会在加载时大大降低手机速度。

有没有办法在一个非常低优先级的背景队列中执行显示图像所需的一些工作?

【问题讨论】:

【参考方案1】:

您正在尝试以最复杂的方式做事 :) 为什么不在推送视图控制器之前准备好小图像并将其传递给它们呢?看这段代码:

- (void)imagePickerController:(UIImagePickerController *)picker
        didFinishPickingMediaWithInfo:(NSDictionary *)info 


    UIImage *fullImage = [info objectForKey:UIImagePickerControllerOriginalImage];
    UIImage *smallImage = [fullImage imageScaledToSize:self.view.bounds];

    // Push a view controller and give it BOTH images


// And in your pushed view controller

- (void)viewDidLoad

    _imageView.image = self.smallImage;


- (void)viewDidAppear:(BOOL)animated

    [super viewDidAppear:animated];

    _imageView.image = self.fullImage;

主要是viewDidAppear:会在动画完成后立即被调用,所以你可以在这里切换图像而无需担心。

【讨论】:

感谢您的建议。我就这样试一试。我认为imageScaledToSize 方法无论如何都会导致性能下降,因为它必须解压缩 UIImage 访问再见以调整大小。 是的,它可能会降低性能,但它会在推送控制器之前执行,因此不会出现低 fps 动画。【参考方案2】:

除了安德烈的回答,不要使用imageScaledToSize,而是使用CGImageSourceCreateThumbnailAtIndex。事实上,很可能(我很确定是这种情况)相册中使用的任何图像都已经有缩略图。因此,与其打扰图像本身,不如抓取现有的缩略图并显示它,然后使用 Andrey 的代码切换主图像。这样你在动画期间做的工作尽可能少。

调用CGImageSourceCreateThumbnailAtIndex 将返回缩略图,无论它已经存在还是需要生成。所以它使用起来会很安全,而且可能至少和imageScaledToSize一样快。

您可以在 Apple 文档中找到完整的代码示例以使用它,此处无需复制。

【讨论】:

太好了,我试试看!【参考方案3】:

您是否尝试过使用 ALAssetsLibrary 加载该图像的缩略图,而不是尝试以全分辨率加载图像?它也比调整大小更快。

【讨论】:

谢谢你的回答,我去看看 这实际上工作得很好,不幸的是在使用 ALAssets 时有一个位置警告,所以为了更好的 FPS 真的不值得。 位置警告?怎么了?如果你解释得更好,我可以(也许:))帮助你。很高兴听到它有效! 这是一个已知问题,已在 ios 6 中修复。基本上照片资产中有位置数据。该消息说该应用程序想要使用您的位置,而实际上它只是想要访问照片。在 iOS 6 中,我注意到该消息已得到更正。 哦!谢谢罗伯特,我不知道 :) 很高兴知道!

以上是关于通过使用低分辨率图像来加速 UIImagePickerController 然后稍后交换高分辨率图像的主要内容,如果未能解决你的问题,请参考以下文章

IBM Watson Machine Learning Accelerator 加速深度学习和大规模高分辨率的图像处理

如何针对低分辨率/模糊素材优化 OpenCV 的 Canny 边缘检测

超分辨率 | 反卷积deconvolution存在的弊端及引起的棋盘效应

小米游戏加速原神gpu设置

HarmonyOS之AI能力·图像超分辨率

使用 pytesseract 读取低分辨率图像