Android图像表示
我正在尝试访问Android中图像的原始像素数据。Android图像表示,android,image,pixels,Android,Image,Pixels,我正在尝试访问Android中图像的原始像素数据。 代码如下所示: Bitmap bitmap = BitmapFactory.decodeFile("image.png"); // assert valid input if ((bitmap.getConfig() == null) || bitmap.getConfig() == Config.ARGB_8888) throw new Exception("bad config"); ByteBuff
代码如下所示:
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();
线性1Dbuffer.array()中的像素是如何存储的
第一个元素是左上像素还是左下像素(或其他)
行主要(行后的行)还是列主要(列后的列)
频道订单ARGB还是BGRA
每个频道分别采用行主频道还是列主频道
别的
要在大小为width
xheight
且每像素字节数为bytesperpoixel
的图像中获得给定像素x
,y
的偏移量,请使用以下公式:
offsetForPixel = (y * width + x) * bytesPerPixel
换句话说,数组中的第一个元素是左上角的像素,下面的元素是行主元素。一个像素的所有数据都存储在相邻的字节中,并且不会基于通道展开。这是上面1、2和4的答案。现在让我们讨论3,这是事情变得复杂的地方
copyPixelsToBuffer()是Android的低级绘图库使用的原始位图数据表示形式。这有三个重要后果:
- 通道顺序取决于端度
- 通道与alpha进行预乘
- 如何将通道打包为包含数据类型是可配置的
最后一点是,如果您想检查单个像素,就很难使用Bitmap.copyPixelsToBuffer()
,因为您根本不知道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);
}
我们可以看到,我们正在处理big-endian,内存中的表示是预乘的,通道已经从ARGB重新排列到RGBA(在skia源代码中,它的动机是内存中的表示与OpenGL相同)
如果您想读取像素数据,我建议您使用。需要进行一些复制,但至少API指定了返回数据的格式
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