Bitmap.Config.HARDWARE 与 Bitmap.Config.RGB_565 [英] Bitmap.Config.HARDWARE vs Bitmap.Config.RGB_565

查看:103
本文介绍了Bitmap.Config.HARDWARE 与 Bitmap.Config.RGB_565的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

API 26 添加新选项 Bitmap.Config.HARDWARE:

<块引用>

特殊配置,当位图仅存储在图形内存中时.此配置中的位图始终不可变.它最适合情况下,当对位图的唯一操作是将其绘制在屏幕.

文档中没有解释的问题:

  1. 我们现在是否应该总是喜欢 Bitmap.Config.HARDWARE 而不是Bitmap.Config.RGB_565 当速度是重中之重和质量时和可变性不是(例如缩略图等)?
  2. 使用此选项解码后的像素数据实际上不是消耗任何堆内存并仅驻留在 GPU 内存中?如果是这样,这似乎最终缓解 OutOfMemoryException 的担忧处理图像.
  3. 与 RGB_565、RGBA_F16 或 ARGB_8888 相比,我们应该期待什么质量从这个选项?
  4. 解码本身的速度是否与使用 RGB_565 解码?
  5. (感谢@CommonsWare 在评论中指出)如果我们在使用此解码图像时超出 GPU 内存,就会发生选项?是否会抛出一些异常(可能是相同的 OutOfMemoryException :)?

解决方案

文档和公共源代码尚未推送到 Google 的 git.因此,我的研究仅基于部分信息、一些实验以及我自己将 JVM 移植到各种设备的经验.

我的测试创建了大型可变位图,然后单击按钮将其复制到新的硬件位图中,并将其添加到位图列表中.在它崩溃之前,我设法创建了几个大位图的实例.

我能够在 android-o-preview-4 git push:

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

并查找 AHardwareBuffer 文档,位于它正在创建一个由 EGLClientBuffer>ANativeWindowBuffer(原生图形缓冲区)在 Android 共享内存(ashmem")中.但实际实现可能因硬件而异.

关于问题:

<块引用>

  1. 我们现在是否应该总是更喜欢 Bitmap.Config.HARDWARE 而不是 Bitmap.Config.RGB_565...?

对于 SDK >= 26,HARDWARE 配置可以通过防止每次相同位图返回屏幕时都需要将像素数据复制到 GPU 来改进低级别位图绘制.我想它可以防止在将位图添加到屏幕时丢失一些帧.

内存不计入您的应用,我的测试证实了这一点.

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

更新: 实验表明没有抛出 OutOfMemoryException.虽然分配成功 - 一切正常.分配失败时 - 模拟器崩溃(刚刚消失).在其他情况下,我在应用内存中分配位图时会遇到一个奇怪的 NullPointerException.

由于不可预测的稳定性,我目前不建议在生产中使用这个新 API.至少在没有大量测试的情况下是这样.

<块引用>

  1. 使用此选项解码后的像素数据是否实际上不消耗任何堆内存而仅驻留在 GPU 内存中?如果是这样,这似乎终于缓解了 OutOfMemoryException 的担忧,当处理图像.

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

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

<块引用>

  1. 与 RGB_565/ARGB_8888 相比质量如何?

HARDWARE 标志与质量无关,而与像素存储位置有关.由于配置标志不能是 OR-ed,我想默认 (ARGB_8888) 用于解码.

(实际上,HARDWARE 枚举对我来说似乎是一个黑客).

<块引用>

  1. 解码速度是否相同/更好/更差...?

HARDWARE 标志似乎与解码无关,所以与 ARGB_8888 相同.

<块引用>

  1. 如果超过 GPU 内存会怎样?

当内存耗尽时,我的测试结果非常糟糕.模拟器有时会严重崩溃,而在其他情况下,我遇到了意外的无关 NPE.没有发生OutOfMemoryException,也无法判断GPU内存何时耗尽,因此无法预见.

API 26 adds new option Bitmap.Config.HARDWARE:

Special configuration, when bitmap is stored only in graphic memory. Bitmaps in this configuration are always immutable. It is optimal for cases, when the only operation with the bitmap is to draw it on a screen.

Questions that aren't explained in docs:

  1. Should we ALWAYS prefer now Bitmap.Config.HARDWARE over Bitmap.Config.RGB_565 when speed is of top priority and quality and mutability are not (e.g. for thumbnails, etc)?
  2. Does pixel data after decoding using this option actually NOT consume ANY heap memory and resides in GPU memory only? If so, this seems to finally be a relief for OutOfMemoryException concern when working with images.
  3. What quality compared to RGB_565, RGBA_F16 or ARGB_8888 should we expect from this option?
  4. Is speed of decoding itself the same/better/worth compared to decoding with RGB_565?
  5. (Thanks @CommonsWare for pointing to it in comments) What would happen if we exceed GPU memory when decoding an image using this option? Would some exception be thrown (maybe the same OutOfMemoryException :)?

解决方案

Documentation and public source code is not pushed yet to Google's git. So my research is based only on partial information, some experiments, and on my own experience porting JVM's to various devices.

My test created large mutable Bitmap and copied it into a new HARDWARE Bitmap on a click of a button, adding it into a bitmap list. I managed to create several instances of the large bitmaps before it crashed.

I was able to find this in the android-o-preview-4 git push:

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

And looking for the documentation of AHardwareBuffer, under the hood it is creating an EGLClientBuffer backed by ANativeWindowBuffer (native graphic buffer) in Android shared memory ("ashmem"). But the actual implementation may vary across hardware.

So as to the questions:

  1. Should we ALWAYS prefer now Bitmap.Config.HARDWARE over Bitmap.Config.RGB_565...?

For SDK >= 26, HARDWARE configuration can improve the low level bitmap drawing by preventing the need to copy the pixel data to the GPU every time the same bitmap returns to the screen. I guess it can prevent losing some frames when a bitmap is added to the screen.

The memory is not counted against your app, and my test confirmed this.

The native library docs say it will return null if memory allocation was unsuccessful. Without the source code, it is not clear what the Java implementation (the API implementors) will do in this case - it might decide to throw OutOfMemoryException or fallback to a different type of allocation.

Update: Experiment reveals that no OutOfMemoryException is thrown. While the allocation is successful - everything works fine. Upon failed allocation - the emulator crashed (just gone). On other occasions I've got a weird NullPointerException when allocating Bitmap in app memory.

Due to the unpredictable stability, I would not recommend using this new API in production currently. At least not without extensive testing.

  1. Does pixel data after decoding using this option actually NOT consume ANY heap memory and resides in GPU memory only? If so, this seems to finally be a relief for OutOfMemoryException concern when working with images.

Pixel data will be in shared memory (probably texture memory), but there still be a small Bitmap object in Java referencing it (so "ANY" is inaccurate).

Every vendor can decide to implement the actual allocation differently, it's not a public API they are bound to. So OutOfMemoryException may still be an issue. I'm not sure how it can be handled correctly.

  1. What quality compared to RGB_565/ARGB_8888?

The HARDWARE flag is not about quality, but about pixel storage location. Since the configuration flags cannot be OR-ed, I suppose that the default (ARGB_8888) is used for the decoding.

(Actually, the HARDWARE enum seem like a hack to me).

  1. Is speed of decoding itself the same/better/worse...?

HARDWARE flag seem unrelated to decoding, so the same as ARGB_8888.

  1. What would happen if we exceed GPU memory?

My test result in very bad things when memory is running out. The emulator crashed horribly sometimes, and I've got unexpected unrelated NPE on other occasions. No OutOfMemoryException occurred, and there was also no way to tell when the GPU memory is running out, so no way to foresee this.

这篇关于Bitmap.Config.HARDWARE 与 Bitmap.Config.RGB_565的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆