【发布时间】:2019-09-10 09:45:52
【问题描述】:
我对 ByteBuffer 中 Bitmap 像素的内部表示有点困惑(在 ARM/little endian 上测试):
1) 在 Java 层中,我创建了一个 ARGB 位图并用 0xff112233 颜色填充它:
Bitmap sampleBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(sampleBitmap);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.rgb(0x11,0x22, 0x33));
canvas.drawRect(0,0, sampleBitmap.getWidth(), sampleBitmap.getHeight(), paint);
为了测试,sampleBitmap.getPixel(0,0) 确实返回了匹配 ARGB 像素格式的 0xff112233。
2) 位图在传递到native层之前被打包到直接的ByteBuffer中:
final int byteSize = sampleBitmap.getAllocationByteCount();
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(byteSize);
//byteBuffer.order(ByteOrder.LITTLE_ENDIAN);// See below
sampleBitmap.copyPixelsToBuffer(byteBuffer);
为了测试,不管缓冲区的顺序设置如何,在调试器中我看到的字节布局与 ARGB 不太匹配,但更像是大端 RGBA(或小端 ABGR!?)
byteBuffer.rewind();
final byte [] out = new byte[4];
byteBuffer.get(out, 0, out.length);
out = {byte[4]@12852} 0 = (0x11) 1 = (0x22) 2 = (0x33) 3 = (0xFF)
现在,我将此位图传递到必须提取像素的本机层,我希望 Bitmap.Config.ARGB_8888 被表示,具体取决于缓冲区的字节顺序:
a) byteBuffer.order(ByteOrder.LITTLE_ENDIAN):
out = {byte[4]@12852} 0 = (0x33) 1 = (0x22) 2 = (0x11) 3 = (0xFF)
或
b) byteBuffer.order(ByteOrder.BIG_ENDIAN):
out = {byte[4]@12852} 0 = (0xFF) 1 = (0x11) 2 = (0x22) 3 = (0x33)
我可以根据上面的输出使提取像素的代码工作,但我不喜欢它,因为我无法解释我希望有人会做的行为:)
谢谢!
【问题讨论】:
-
我不确定我是否理解。 little-endian 布局在我看来完全正确。你期待什么?
-
我期待 a) 或 b)。我所拥有的看起来不像任何 ARGB 布局,而是 RGBA 的一些变体。
-
好的。
Bitmap.Config.ARGB_8888的文档说 “使用此公式打包成 32 位:int color = (A & 0xff) << 24 | (B & 0xff) << 16 | (G & 0xff) << 8 | (R & 0xff);” -
是的,这显然是个问题:stackoverflow.com/questions/56832572/…
-
另外,可以通过 bitmap.getPixel() 验证,它按预期返回 0xff112233 (ARGB)。
标签: android bitmap arm endianness bytebuffer