Bitmap.Config.HARDWARE与Bitmap.Config.RGB_565 [英] Bitmap.Config.HARDWARE vs Bitmap.Config.RGB_565
问题描述
API 26 添加新选项 Bitmap.Config.HARDWARE
:
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.
文档中未解释的问题:
- 我们是否应该现在总是优先选择
Bitmap.Config.HARDWARE
Bitmap.Config.RGB_565
当速度是最高优先级和质量时 和可变性不是(例如,缩略图等)? - 使用此选项解码后的像素数据实际上不是吗
消耗任何堆内存并且仅驻留在GPU内存中?如果是这样,这似乎
最终减轻了
OutOfMemoryException
的关注 处理图像. - 与RGB_565,RGBA_F16或ARGB_8888相比,我们应该期待什么质量? 从这个选项?
- 解码本身的速度是否与 用RGB_565解码吗?
- (感谢@CommonsWare在注释中指向它)
如果使用此解码图像时我们超过了GPU内存,则会发生这种情况
选项?会抛出一些异常(也许与
OutOfMemoryException
相同)吗?
- Should we ALWAYS prefer now
Bitmap.Config.HARDWARE
overBitmap.Config.RGB_565
when speed is of top priority and quality and mutability are not (e.g. for thumbnails, etc)? - 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. - What quality compared to RGB_565, RGBA_F16 or ARGB_8888 should we expect from this option?
- Is speed of decoding itself the same/better/worth compared to decoding with RGB_565?
- (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);
并在AHardwareBuffer的文档下查找文档.它正在创建由 ANativeWindowBuffer
支持的EGLClientBuffer
(本地图形缓冲区)在Android共享内存("ashmem")中.但是实际的实现可能会因硬件而异.
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.
关于这些问题:
- 我们现在是否应该总是选择Bitmap.Config.HARDWARE而不是Bitmap.Config.RGB_565 ...?
对于SDK> = 26,HARDWARE
配置可以通过避免每次相同的位图返回到屏幕时将像素数据复制到GPU来改善低级位图的绘制.我猜它可以防止在将位图添加到屏幕时丢失某些帧.
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.
本机库文档说如果内存分配失败,它将返回null
.
如果没有源代码,目前尚不清楚Java实现(API实现者)在这种情况下会做什么-它可能决定将OutOfMemoryException
抛出或回退到其他类型的分配.
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.
更新:实验表明没有抛出OutOfMemoryException.分配成功后-一切正常.分配失败后,模拟器崩溃(刚消失).在其他情况下,在应用程序内存中分配位图时,我会遇到奇怪的NullPointerException
.
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.
由于不可预测的稳定性,我不建议当前在生产环境中使用此新API .至少在没有大量测试的情况下.
Due to the unpredictable stability, I would not recommend using this new API in production currently. At least not without extensive testing.
- 使用此选项解码后的像素数据是否实际上不消耗任何堆内存,而仅驻留在GPU内存中?如果是这样
似乎终于可以缓解
OutOfMemoryException
的关注, 处理图像.
- 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.
像素数据将位于共享内存(可能是纹理内存)中,但是Java中仍然有一个小的Bitmap
对象引用该对象(因此"ANY"是不准确的).
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).
每个供应商都可以决定以不同的方式实现实际分配,这不是它们所绑定的公共API.
因此OutOfMemoryException
可能仍然是一个问题.我不确定如何正确处理它.
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.
- 与RGB_565/ARGB_8888相比,质量如何?
HARDWARE
标志与质量无关,而与像素存储位置有关.由于不能对配置标志进行OR
-ed,我假设默认值(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.
(实际上,HARDWARE
枚举对我来说似乎是一种hack).
(Actually, the HARDWARE
enum seem like a hack to me).
- 解码自身的速度是否相同/更好/更差?
HARDWARE
标志似乎与解码无关,因此与ARGB_8888
相同.
HARDWARE
flag seem unrelated to decoding, so the same as ARGB_8888
.
- 如果我们超过GPU内存会发生什么?
当内存用尽时,我的测试结果很不好. 模拟器有时会崩溃,而在其他情况下,我遇到了意外的无关的NPE.没有OutOfMemoryException发生,也没有办法告诉GPU内存何时耗尽,因此也没有办法预见到这一点.
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屋!