cocoa-touch - UIImage 到原始 NSData/避免压缩

标签 cocoa-touch uiimage compression core-graphics nsdata

我有自己的图片下载器类,它拥有一个队列并一次下载一张(或一定数量)图片,将它们写入缓存文件夹并在必要时从缓存文件夹中检索它们。我还有一个 UIImageView 子类,我可以向其传递一个 URL,通过图像下载器类,它将查看图像是否已存在于设备上并显示它,如果存在,或者在完成后下载并显示它。

图像下载完成后,我执行以下操作。我从下载的 NSData 创建一个 UIImage,将下载的 NSData 保存到磁盘并返回 UIImage。

// This is executed in a background thread
downloadedImage = [UIImage imageWithData:downloadedData];
BOOL saved = [fileManager createFileAtPath:filePath contents:downloadedData attributes:attributes];
// Send downloadedImage to the main thread and do something with it

我这样做是为了检索现有图像。

// This is executed in a background thread
if ([fileManager fileExistsAtPath:filePath])
{
    NSData* imageData = [fileManager contentsAtPath:filePath];
    retrievedImage = [UIImage imageWithData:imageData];
    // Send retrievedImage to the main thread and do something with it
}

如您所见,我总是直接从下载的 NSData 创建 UIImage,我从不使用 UIImagePNGRepresentation 创建 NSData,因此图像永远不会被压缩。当您从压缩的 NSData 创建 UIImage 时,UIImage 将在主线程上渲染之前解压缩它,从而阻塞 UI。由于我现在有一个 UITableView,其中包含大量必须从磁盘下载或检索的小图像,这是 Not Acceptable ,因为它会极大地减慢我的滚动速度。

现在是我的问题。用户还可以从相机胶卷中选择一张照片,保存它,它也必须出现在我的 UITableView 中。但是我似乎找不到不使用 UIImagePNGRepresentation 将 UIImage 从相机胶卷转换为 NSData 的方法。所以这是我的问题。

如何将 UIImage 转换为未压缩的 NSData,以便稍后使用 imageWithData 将其转换回 UIImage,这样它就不必在渲染前解压缩?

有什么办法可以在将 UIImage 发送到主线程并缓存它之前进行解压,这样它只需解压一次?

提前致谢。

最佳答案

How can I convert a UIImage into uncompressed NSData so I can convert it back to a UIImage later using imageWithData so that it doesn't have to be decompressed before rendering?

我认为您在这里真正要问的是如何将 UIImage 存储在磁盘上,以便您以后可以从磁盘读取 UIImage尽可能快。你真的不在乎它是否存储为 NSData;您只是希望能够快速阅读它。我建议你使用 ImageIO 框架。通过图像目标保存,稍后通过图像源获取。

http://developer.apple.com/library/ios/#documentation/GraphicsImaging/Conceptual/ImageIOGuide/ikpg_dest/ikpg_dest.html

Is there any way I can do the decompression before sending the UIImage to the main thread and cache it so it only has to be decompressed once?

是的,问得好。那将是我的第二个建议:使用线程。这就是人们一直与 table 打交道的原因。当表格要求图像时,您要么已经有图像,要么没有。如果不这样做,则提供填充图像,并在后台获取真实图像。当真实图像准备就绪时,您已安排接收通知。回到主线程,您告诉 TableView 再次请求该行的数据;这次你得到了图像并提供了它。因此,用户会在图像出现之前看到轻微的延迟。我敢肯定,您已经见过很多这样的应用程序(纽约时报就是一个很好的例子)。

我还有一个建议,它可能是最好的。你说从磁盘解压缩图像需要时间。但如果图像很小,这根本不需要时间。但是图片应该很小,因为它会进入一个很小的地方——一个表格单元格。换句话说,当您第一次收到图像时,您应该事先缩小图像,以便在被询问时准备好每张图像的版本。将大图像提供到小空间中是对时间和内存的巨大浪费。

稍后添加:您当然明白,如果您不将图像保存到磁盘,那么很多这种担心都是不必要的。我一点也不清楚你为什么需要这样做。我希望你有充分的理由;但显然,如果您只是将图像保存在内存中,速度会快得多。

关于cocoa-touch - UIImage 到原始 NSData/避免压缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15693965/

相关文章:

objective-c - 在 SQLite 数据库中保存经度和纬度

iphone - iOS——将 UIImage 对象的 R、G、B 和 A 分量乘以常量?

java - 编程问题 - 传真压缩

iphone - 使用 NSOperationQueue 作为 View Controller 实例变量

iOS、Swift、UIImagePicker 允许编辑裁剪工具移除透明度。有修吗?

ios - 如何在 EarlGrey 中使用 tapAtPoint

ios - 以正确的方向保存图像 - Swift & Core Image

ios - 如何在 Swift 中以编程方式从另一个图像中剪切 Logo (png 图像)的形状?

mongodb - Golang-gzip将mongodb查找查询的游标数据,写入文件并将其解压缩时出错

video - H.264 编码视频中的显示顺序语法