Bitmap.Config.HARDWARE与Bitmap.Config.RGB_565

API 26 添加了新的选项 Bitmap.Config.HARDWARE

位图仅存储在graphics内存中时的特殊configuration。 此configuration中的位图始终是不可变的。 这是最佳的情况下,当唯一的操作与位图是画在屏幕上。

文档中未解释的问题:

  1. 如果我们现在Bitmap.Config.HARDWARE喜欢Bitmap.Config.HARDWARE ,当速度是最重要的,质量和可变性不是(比如缩略图等),我们是否总是比较喜欢Bitmap.Config.HARDWARE
  2. 使用此选项解码后的像素数据实际上是否不消耗任何堆内存并仅驻留在GPU内存中? 如果是这样,这似乎最终是一个解决OutOfMemoryException关心处理图像
  3. 与RGB_565,RGBA_F16或ARGB_8888相比,我们应该从这个选项中得到什么样的质量?
  4. 与使用RGB_565进行解码相比,解码速度是否相同/更好?
  5. (感谢@CommonsWare在注释中指向它)使用此选项解码图像时,如果超过GPU内存,会发生什么情况? 会抛出一些exception(也许是相同的OutOfMemoryException :)?

Solutions Collecting From Web of "Bitmap.Config.HARDWARE与Bitmap.Config.RGB_565"

文档和公共源代码还没有推到Google的git上 。 所以我的研究仅仅基于部分信息,一些实验以及根据我自己的经验将JVM移植到各种设备上。

我的testing创build了大的可变位图,并通过点击一个button将其复制到新的硬件位图中,并将其添加到位图列表中。 我成功创build了大型位图的实例,然后崩溃了。

我能够在android-o-preview-4 git push中find这个:

 +struct AHardwareBuffer; +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer); +#else +typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const struct AHardwareBuffer *buffer); 

并寻找AHardwareBuffer的文档,它正在创build一个由Android共享内存(“ashmem”)中的ANativeWindowBuffer (本地graphics缓冲区)支持的ANativeWindowBuffer 。 但实际的实施可能会因硬件而异。

至于这些问题:

  1. 如果我们现在总是喜欢Bitmap.Config.HARDWARE而不是Bitmap.Config.RGB_565 …?

对于SDK> = 26, HARDWAREconfiguration可以通过防止每次将相同的位图返回到屏幕时将像素数据复制到GPU来改善低级别的位图绘制。 我想这可以防止在将位图添加到屏幕时丢失一些帧。

内存不计算在您的应用程序,我的testing证实了这一点。

本地库文档说,如果内存分配不成功,它将返回null 。 如果没有源代码,在这种情况下,Java实现(API实现者)会做什么不清楚 – 它可能决定抛出OutOfMemoryException或回OutOfMemoryException不同types的分配。

更新:实验显示不引发OutOfMemoryException。 虽然分配是成功的 – 一切正常。 分配失败后 – 模拟器崩溃(刚刚离开)。 在其他场合,当在应用程序内存中分配位图时,我有一个奇怪的NullPointerException

由于不可预知的稳定性,目前我不推荐在生产中使用这个新的API 。 至less不是没有广泛的testing。

  1. 使用此选项解码后的像素数据实际上是否不消耗任何堆内存并仅驻留在GPU内存中? 如果是这样,这似乎最终是一个解决OutOfMemoryException关心处理图像。

像素数据将在共享内存中(可能是纹理内存),但Java中仍然有一个小的Bitmap对象引用它(所以“ANY”是不准确的)。

每个供应商都可以决定以不同的方式实现实际的分配,这不是一个公有的API。 所以OutOfMemoryException可能仍然是一个问题。 我不确定如何正确处理它。

  1. 什么质量比较RGB_565 / ARGB_8888?

HARDWARE标志不是关于质量,而是关于像素存储位置。 由于configuration标志不能被OR -ed,所以我想用默认的( ARGB_8888 )来解码。

(其实HARDWARE枚举对我来说就像是一个黑客)。

  1. 解码本身的速度是相同/更好/更差…?

HARDWARE标志似乎与解码无关,所以和ARGB_8888

  1. 如果我们超过GPU内存会发生什么?

内存不足时,我的testing结果非常糟糕。 模拟器有时候会崩溃,而且在其他场合我有一些意想不到的无关NPE。 没有OutOfMemoryException发生,也没有办法告诉GPU内存何时用完,所以没办法预见到这一点。