iOS UIImage存储格式,内存使用情况和编码/解码

iOS如何存储从压缩数据加载的图像(jpeg2000,png,jpg等)

例如: [UIImage imageWithData:pngData]

是否在内部存储实际编码字节并按需解压缩,或者是否永久解压缩为原始像素或其他格式?

我使用以下三种方法在[UIImage imageNamed][UIImage imageWithContentsOfFile:][UIImage imageWithData]上创build了一个加载200 384×384像素jpeg2000图像文件(117,964,800字节的原始像素值)的testing应用程序。 jpeg2000文件集是100个纹理,然后我复制到一个额外的100个带有“复制”后缀的文件中,以查看iOS是否执行任何重复的文件检查。 更多关于下面。

testing分两步完成

  1. 只需加载图像并将其存储在一个数组中。
  2. 一个单独的button为每个图像创buildUIImageView并显示它们。

结果如下:

[UIImage imageNamed:]

第1步:内存只增加了所有jpeg2000文件的总和(每个文件约为50K,因此内存增加了大约5 MB)。 我认为重复的文件在这一点上是不重复的,并且由iOS以某种方式整合,因为如果没有重复的检查,内存现在会增加10MB。

第2步:内存显着上升(大约200 MB),大概是因为图像被解码为BGRA格式,准备在UIImageView中显示。 看起来在这个阶段没有重复的过滤,并且为每个图像分配了单独的原始内存。 我不知道为什么,但是这比实际的原始像素内存使用应该大约多80 MB。

[UIImage imageWithContentsOfFile:]

步骤1:内存使用与[UIImage imageNamed:]完全相同,所以在这个阶段有重复的过滤。

第2步:内存使用量上升到130 MB。 出于某种原因,这是比[UIImage imageNamed:]低70 MB。 这个数字非常接近200张图像的原始像素存储量。

[UIImage imageWithData:]

首先使用[NSData dataWithContentsOfFile:]

第1步:内存使用量是15 MB。 我假设这里没有重复的过滤,因为这接近所有jpeg2000数据的总文件大小。

第2步:内存使用增加到139 MB。 这不仅仅是[UIImage imageWithContentsOfFile:] ,但不是太多。

概要

iOS似乎引用了使用上述三种方法加载的UIImage的压缩数据,直到实际需要原始像素为止,然后解码。

[UIImage imageNamed:]从来没有释放内存,因为我所有的图像视图引用的图像。 如果我交错加载并允许运行循环执行,它将释放未引用图像的内存。 一个好处是重复的[UIImage imageNamed:]调用相同的图像基本上是免费的。 除了GUI图像以外,不要使用此方法,否则可能会导致内存不足。

[UIImage imageWithContentsOfFile:]在内存使用中的行为类似于[UIImage imageNamed:] ,直到需要原始像素为止,此时由于某种原因,内存使用效率更高。 这个方法也会导致UIImage解除分配时立即释放内存。 重复调用具有相同文件的[UIImage imageWithContentsOfFile:]似乎使用caching副本,直到所有UIImage引用文件都被释放。

[UIImage imageWithData:]没有caching或重复检查,总是创build一个新的图像。

我testing了与PNG文件相同的设置,imageNamed和imageWithContentsOfFile的第1步结果显示使用的内存更less(大约0.5 MB),imageWithData显示所有压缩的PNG文件的总和。 我的猜测是,iOS只是存储对文件的引用,在解码时间之前不会执行任何操作。 PNG的第2步结果是相同的。

一旦加载到内存中, UIImage就是未压缩的RGBA格式。 这意味着图像在内存中需要width x height x 4字节,其中widthheight是以像素为单位的图像大小。

在某些情况下, UIImage可能会提供一些优化,但是您应该在上面进行计划。

更新:

我觉得以上情况并非总是如此。 UIImage具有CGImage属性。 然后有像CGImageGetBitmapInfoCGImageGetAlphaInfo和其他一些相关的函数的各种function。 这些函数的返回值表示图像可以有许多不同的格式。 有各种32位格式,以及24位和16位格式。 alpha可以是第一个,最后一个,或者根本不存在。 字节顺序可以是大或小的。