我有自己的图片下载器类,它拥有一个队列并一次下载一张(或一定数量)图片,将它们写入缓存文件夹并在必要时从缓存文件夹中检索它们。我还有一个 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 框架。通过图像目标保存,稍后通过图像源获取。
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/