【问题标题】:Is Android's ARGB_8888 Bitmap internal format always RGBA?Android的ARGB_8888位图内部格式总是RGBA吗?
【发布时间】:2017-11-14 00:08:30
【问题描述】:

在收到来自外部源的字节后,我正在尝试使用 Bitmap.Config.ARGB_8888 在 Android 中创建一个 Bitmap。据我了解,在Bitmap(不使用JNI)中设置原始字节的最快方法是使用copyPixelsFromBuffer() 方法,但是问题在于该缓冲区中字节的正确顺序。

经过反复试验,尽管Config.ARGB_8888 建议ARGB 的正确顺序,但Bitmap 使用的内部格式似乎是RGBA。您可以在ActivityonCreate() 中使用以下方法测试此行为(我已经在Android 4.4.4 中对其进行了测试,该方法确实测试了copyPixelsToBuffer(),但根据我的测试copyPixelsFromBuffer() 的行为同样):

private void testBitmap() {
    // one pixel bitmap
    Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);

    // as per javadoc, the int value is in ARGB format, so A=0xFF, R=0x11, G=0x22, B=0x33
    bitmap.setPixel(0, 0, 0xFF112233);

    ByteBuffer buffer = ByteBuffer.allocateDirect(4);   // 4 bytes for the single pixel
    bitmap.copyPixelsToBuffer(buffer);
    buffer.position(0);

    // prints "Bytes: 0x11 0x22 0x33 0xFF"  (RGBA)
    System.out.println(String.format(Locale.ENGLISH, "Bytes: %s %s %s %s",
            toHexString(buffer.get()),
            toHexString(buffer.get()),
            toHexString(buffer.get()),
            toHexString(buffer.get())
    ));
}

private static String toHexString(byte b) {
    return Integer.toHexString(b & 0xFF).toUpperCase();
}

我的问题是:这种内部格式是否记录在任何地方?如果不是,那么我们怎么知道上面的代码在未来的 Android 版本中是否不会中断?或者也许还有其他建议的方法来复制 Bitmap 中的原始字节?

【问题讨论】:

  • 不是和ByteBuffer#order()有关吗?只是猜测......
  • @pskink 不,不是。无论缓冲区的字节顺序如何,结果都是相同的。如果是字节顺序问题,我会期待不同的输出,即BGRA。我提到的格式仅在 alpha 通道上有所不同
  • 哦,确实,我想念你得到RGBA,而不是你说的BGRA,你不能用int[] arr = new int[1]; bitmap.getPixels(arr, 0, 1, 0, 0, 1, 1); Log.d(TAG, "test: " + Integer.toHexString(arr[0]));代替吗?
  • @pskink 我可能会这样做,但是我对字节的情况感兴趣,因为 javadocs 提到涉及缓冲区的复制操作“按原样”复制数据,而 getPixels()/@ 987654343@ 将字节转换为打包的ints。我正在寻找一种方法来避免尽可能多的转化。
  • 我明白了,这似乎就是他们命名那些 ARGB_* 常量的方式,对于 ndk,它们更精确:developer.android.com/ndk/reference/…

标签: android android-bitmap


【解决方案1】:

关于文档:

https://developer.android.com/reference/android/graphics/Color.html

即RGBA模型有几种用法。

例如pack(int color) 方法。将指定的 ARGB 颜色 int 转换为 sRGB 颜色空间中的一个 RGBA 颜色 long。

您可以尝试在我提供的页面中找到“RGBA”字样。大部分基础概念都使用RGBA模型。

【讨论】:

  • 谢谢。我知道RGBA 可能是常用的,但是如果我找到专门针对Bitmap 类的官方内容,我会更加放心。
【解决方案2】:

由于我最近对此感到困惑,所以我想我会给出一个更新的答案。

调用setPixels()copyPixelsFromBuffer() 时的行为确实反映了高级API 中颜色的表示方式与位图中字节的实际内部排序方式的差异。这有点记录在 Bitmap 类中(至少现在是这样),但不容易解析。

setPixels() 的更高级接口需要整数,因为它们在资源和 Color 类等其他高级接口中也是如此,因此 ARGB as noted here。然后,您可以轻松地执行以下操作:bitmap.setPixel(0,0,Color.RED)。 Color 类提到排序here 为:

int color = (A & 0xff) << 24 | (R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff);

尽管您从copyPixelsFromBuffer() 发现,内部表示是 RGBA。它在 Bitmap.Config here 中有所暗示,如下所示,在 NDK 位图标头中也有所暗示,将其命名为枚举 ANDROID_BITMAP_FORMAT_RGBA_8888:

int color = (A & 0xff) << 24 | (B & 0xff) << 16 | (G & 0xff) << 8 | (R & 0xff);

【讨论】:

    猜你喜欢
    • 2015-11-01
    • 1970-01-01
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    相关资源
    最近更新 更多