Java Bitmap.Config.HARDWARE vs Bitmap.Config.RGB_565

Java Bitmap.Config.HARDWARE vs Bitmap.Config.RGB_565,java,android,image,performance,bitmap,Java,Android,Image,Performance,Bitmap,API 26Bitmap.Config.HARDWARE: 特殊配置,当位图仅存储在图形内存中时。 此配置中的位图始终是不可变的。这是最佳的选择 情况下,使用位图的唯一操作是在 屏幕 文档中未解释的问题: 我们是否应该总是选择现在Bitmap.Config.HARDWARE而不是 Bitmap.Config.RGB_565当速度是最高优先级和质量时 和可变性不是(例如缩略图等) 使用此选项解码后的像素数据实际上是否没有 是否使用任何堆内存并仅驻留在GPU内存中?如果是这样的话,这似乎是错误的 最

API 26
Bitmap.Config.HARDWARE

特殊配置,当位图仅存储在图形内存中时。 此配置中的位图始终是不可变的。这是最佳的选择 情况下,使用位图的唯一操作是在 屏幕

文档中未解释的问题:

  • 我们是否应该总是选择现在
    Bitmap.Config.HARDWARE
    而不是
    Bitmap.Config.RGB_565
    当速度是最高优先级和质量时 和可变性不是(例如缩略图等)
  • 使用此选项解码后的像素数据实际上是否没有 是否使用任何堆内存并仅驻留在GPU内存中?如果是这样的话,这似乎是错误的 最终缓解
    OutOfMemoryException
    问题 处理图像
  • 与RGB_565、RGBA_F16或ARGB_8888相比,我们应该期望什么样的质量 从这个选项
  • 解码本身的速度是否与之相同/更好/值得 用RGB_565解码
  • (感谢@commonware在评论中指出它)你会怎么做 如果我们在解码图像时超出了GPU内存,就会发生这种情况 选项是否会引发一些异常(可能是相同的
    OutOfMemoryException
    :)

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

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

    我在git推送中找到了这个:

    +struct AHardwareBuffer;
    +#ifdef EGL_EGLEXT_PROTOTYPES
    +EGLAPI EGLClientBuffer eglGetNativeClientBufferANDROID (const struct AHardwareBuffer *buffer);
    +#else
    +typedef EGLClientBuffer (EGLAPIENTRYP PFNEGLGETNATIVECLIENTBUFFERANDROID) (const struct AHardwareBuffer *buffer);
    
    为了寻找新的缓冲区,它正在创建一个
    EGLClientBuffer
    ,由安卓共享内存(“ashmem”)中的(本机图形缓冲区)支持。但实际实现可能因硬件而异

    关于这些问题:

  • 我们是否应该总是选择Bitmap.Config.HARDWARE而不是Bitmap.Config.RGB_565
  • 对于SDK>=26,
    硬件
    配置可以通过防止每次相同位图返回屏幕时都需要将像素数据复制到GPU来改进低级位图绘制。我想它可以防止在屏幕上添加位图时丢失一些帧

    你的应用程序没有计算内存,我的测试证实了这一点

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

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

    由于不可预测的稳定性,我不建议在当前生产中使用此新API。至少没有广泛的测试

  • 使用此选项解码后的像素数据是否实际上不消耗任何堆内存,并且仅驻留在GPU内存中?若有,这 似乎终于缓解了
    OutOfMemoryException
    在 处理图像
  • 像素数据将在共享内存中(可能是纹理内存),但Java中仍有一个小的
    位图
    对象引用它(因此“ANY”是不准确的)

    每个供应商都可以决定以不同的方式实现实际的分配,这不是他们必须使用的公共API。 因此,
    OutOfMemoryException
    可能仍然是一个问题。我不知道怎样才能正确处理

  • 与RGB_565/ARGB_8888相比,质量如何
  • 硬件
    标志不是关于质量,而是关于像素存储位置。由于配置标志不能
    -ed,因此我假设默认(
    ARGB_8888
    )用于解码

    (事实上,
    HARDWARE
    enum对我来说似乎是个黑客)

  • 解码本身的速度是否相同/更好/更差
  • 硬件
    标志似乎与解码无关,因此与
    ARGB_8888
    相同

  • 如果超过GPU内存,会发生什么
  • 当内存耗尽时,我的测试结果非常糟糕。
    模拟器有时崩溃得很厉害,我在其他场合也遇到了意想不到的无关NPE。没有发生OutOfMemoryException,也无法判断GPU内存何时耗尽,因此无法预见这一情况。

    请注意,GPU没有无限内存,因此加载太多图像仍会在某些地方导致问题。但是我同意这个选项是非法的。有人能找到这个选项的源代码吗?浏览网页没有透露任何有关这方面的细节feature@Distjubo,安卓O的官方来源尚未公开。当然会帮助解决这个问题。另请参阅。使用此解码时是否有任何方法可以防止内存问题?@androiddeveloper我没有找到这样做的方法。。。那就没有理由使用它了?你有办法获得GPU上的内存量吗(免费与总容量)?@androiddeveloper我8个月前的研究没有找到办法获得GPU内存量,这是我在回答中写的。我没有检查是否有更新。干得好。令人难以置信的是,官方文件中对这一点的记录是多么糟糕。