我正在尝试访问Android中图像的原始像素数据 代码看起来像这样:
Bitmap bitmap = BitmapFactory.decodeFile("image.png");
// assert valid input
if ((bitmap.getConfig() == null) || bitmap.getConfig() == Config.ARGB_8888)
throw new Exception("bad config");
ByteBuffer buffer = ByteBuffer.allocate(4 * bitmap.getWidth() * bitmap.getHeight());
bitmap.copyPixelsToBuffer(buffer);
return buffer.array();
如何存储线性1D buffer.array()
中的像素?
答案 0 :(得分:5)
要获得buffer.array()
的特定像素x
的偏移,y
,尺寸为width
x height
且bytesPerPixel
的图片中为offsetForPixel = (y * width + x) * bytesPerPixel
每个像素的字节数,使用以下公式:
Bitmap.copyPixelsToBuffer()
换句话说,数组中的第一个元素是左上角像素,以下元素是行主要元素。像素的所有数据都存储在相邻的字节中,并且不会基于通道展开。这是上面1,2和4的答案。现在让我们讨论3,这就是事情变得复杂的地方。
您使用Bitmap.copyPixelsToBuffer()获得的是Android的低级绘图库skia使用的原始位图数据表示。这有三个重要的后果:
如果你想检查单个像素,最后一点会让你很难使用int inputPixel = 0x336699cc;
int[] pixels = new int[] { inputPixel };
Bitmap bm = Bitmap.createBitmap(pixels, 1, 1, Config.ARGB_8888);
ByteBuffer bb = ByteBuffer.allocate(4);
bm.copyPixelsToBuffer(bb);
Log.i("TAG", "inputPixel = 0x" + Integer.toHexString(inputPixel));
for (int i = 0; i < 4; i++) {
String byteString = "0x" + Integer.toHexString(bb.array()[i] & 0xff);
Log.i("TAG", "outputPixel byte " + i + " = " + byteString);
}
,因为你根本无法知道如何配置skia来打包频道。作为实验,请尝试以下代码:
I/TAG ( 1995): inputPixel = 0x336699cc
I/TAG ( 1995): outputPixel byte 0 = 0x14
I/TAG ( 1995): outputPixel byte 1 = 0x1f
I/TAG ( 1995): outputPixel byte 2 = 0x29
I/TAG ( 1995): outputPixel byte 3 = 0x33
当我运行时,我得到了这个输出:
{{1}}
我们可以看到我们正在处理大端,内存表示是预乘的,并且频道已经从ARGB重新排列到RGBA(在skia源代码中的动机是相同的-memory表示为OpenGL)。
如果您想要读取像素数据,建议您改用Bitmap.getPixels()。涉及一些复制,但至少API指定了如何格式化返回的数据。