【问题标题】:Converting 4-Bit grayscale byte array to Bitmap Android将 4 位灰度字节数组转换为 Android 位图
【发布时间】:2013-07-19 21:29:44
【问题描述】:

我正在从相机中检索原始图像,图像的规格如下:

  • 80 x 60 分辨率
  • 4 位灰度

我以字节数组的形式检索图像,并拥有一个 2400 (1/2 * 80 * 60) 字节长的数组。下一步是将字节数组转换为位图。我已经用过

BitmapFactory.decodeByteArray(bytes, 0, bytes.length)

但这并没有返回可显示的图像。我查看了 this post 并将下面的代码复制到我的 Android 应用程序中,但我得到了“缓冲区不够大,无法容纳像素”运行时错误。

byte [] Src; //Comes from somewhere...
byte [] Bits = new byte[Src.length*4]; //That's where the RGBA array goes.
int i;
for(i=0;i<Src.length;i++)
{
    Bits[i*4] =
        Bits[i*4+1] =
        Bits[i*4+2] = ~Src[i]; //Invert the source bits
    Bits[i*4+3] = -1;//0xff, that's the alpha.
}

//Now put these nice RGBA pixels into a Bitmap object

Bitmap bm = Bitmap.createBitmap(Width, Height, Bitmap.Config.ARGB_8888);
bm.copyPixelsFromBuffer(ByteBuffer.wrap(Bits));

在帖子的底部,原始海报与我目前遇到的错误相同。但是,上面粘贴的代码解决了他的问题。有人对我应该如何将原始图像或 RGBA 数组转换为位图有任何建议吗?

非常感谢!

更新:

我遵循 Geobits 的建议,这是我的新代码

byte[]  seperatedBytes = new byte[jpegBytes.length * 8];
for (int i = 0; i < jpegBytes.length; i++) {
    seperatedBytes[i * 8] = seperatedBytes[i * 8 + 1] = seperatedBytes[i * 8 + 2] = (byte) ((jpegBytes[i] >> 4) & (byte) 0x0F);
    seperatedBytes[i * 8 + 4] = seperatedBytes[i * 8 + 5] = seperatedBytes[i * 8 + 6] = (byte) (jpegBytes[i] & 0x0F);
    seperatedBytes[i * 8 + 3] = seperatedBytes[i * 8 + 7] = -1; //0xFF
}

现在,我可以使用此命令获取位图

Bitmap bm = BitmapFactory.decodeByteArray(seperatedBytes, 0, seperatedBytes.length);

但位图的大小为 0KB。

我得到的图像是来自this camera 的原始图像。不幸的是,检索预压缩的 JPEG 图像不是一种选择,因为我需要 4 位灰度。

【问题讨论】:

    标签: java android bitmap grayscale android-image


    【解决方案1】:

    如果输入的图像只有 2400 字节,这意味着每个字节有两个像素(每个 4 位)。当 ARGB_8888 每个像素需要 4 个字节或 60 * 80 * 4 = 19200 时,您只提供字节缓冲区 2400 * 4 = 9600 字节。

    您需要将每个传入字节拆分为一个上/下半字节值,然后将其应用于以下 8 个字节(不包括 alpha)。您可以查看this answer 了解如何拆分字节的示例。

    基本上:

    • 将传入字节i分成两个半字节,iaib
    • ia 应用于传出字节i*8(i*8)+2
    • ib 应用于传出字节(i*8)+4(i*8)+6
    • 字节 (i*8)+3(i*8)+7 是 alpha (0xFF)

    一旦你有正确大小的字节缓冲区,你应该可以毫无问题地使用decodeByteArry()

    【讨论】:

    • 感谢您的回复。我试过了,不幸的是它没有用。这就是我所拥有的:byte[] seperatedBytes = new byte[jpegBytes.length * 8]; for (int i = 0; i &lt; jpegBytes.length; i++) { seperatedBytes[i * 8] = seperatedBytes[i * 8 + 1] = seperatedBytes[i * 8 + 2] = seperatedBytes[i * 8 + 3] = (byte) ((jpegBytes[i] &gt;&gt; 4) &amp; (byte) 0x0F); seperatedBytes[i * 8 + 4] = seperatedBytes[i * 8 + 5] = seperatedBytes[i * 8 + 6] = seperatedBytes[i * 8 + 7] = (byte) (jpegBytes[i] &amp; 0x0F); }
    • 然后这个:Bitmap bm = BitmapFactory.decodeByteArray(seperatedBytes, 0, seperatedBytes.length); 我将 .jpg 保存到 Android,它显示文件大小为 0KB。数组 jpegBytes 的长度为 2400,而 separatedBytes 数组的长度为 19200。
    • 传入的字节数组是JPG吗?如果是这样,您需要先将其转换为位图格式。另外,我应该提到,每组的字节 3 和 7 仍然是 alpha,就像你以前做的那样。不过,我不知道为什么您保存的图像的大小为零。您可能需要考虑将其中一些代码作为更新添加到问题中。
    • This is the datasheet of the camera I am retrieving an image from。虽然它可以发送 JPEG 图像,但我需要 4 位灰度图像。此外,我将代码更改为使每组的字节 3 和 7 等于 Alpha。更新后的代码在“UPDATE”中,我仍然得到一个大小为 0KB 的位图。
    • 这可能是问题所在 - 字节数组 jpegBytes 的长度为 2400 字节。它是相机传输的4位灰度图像的阵列。我是否在更新的代码中正确地将其转换为 ARGB 数组?
    【解决方案2】:

    如果我理解正确,您有一个字节数组,每个字节包含 2 个灰度值。 我想说灰度值可以被认为是一个简单的强度值,不是吗?

    因此,您需要做的第一件事是将灰度值分成单个字节,因为 BitmapFactory.decodeByteArray 可能无法处理您的“半字节”。 这可以通过位操作轻松完成。 要获得字节 `0bxxxxxxxx` 值的前 4 位,您需要右移 4 次: `0bxxxxxxxx >> 4` 这将导致 `0b0000xxxx`。 第二个值可以按位或使用模式“0b00001111”获得:“0b00001111 ^ 0bxxxxxxxx”将导致“0b0000xxxx”。 (有关位操作的详细信息,请参见此处: Bit-Operations

    这两个值现在可以存储到一个新的字节数组中。 如果您对每对半字节执行此操作,您将得到一个完整字节数组,并且最后会加倍大小。

    我不确定这对于“BitmapFactory.decodeByteArray”是否已经足够了,或者您是否必须为每个 RGBA 通道重复每个字节 4 次,这会使您的字节数组的大小再次增加原始大小的四倍. 我希望我没有误解任何东西,我的建议会有所帮助;)

    【讨论】:

    • 我遇到了和上面描述的一样的问题——每张图片都是0KB。我还将图像解码为this post 之后的RGBA 数组。即使这样,图像也是空白的。
    猜你喜欢
    • 2014-09-29
    • 2012-03-30
    • 2013-12-15
    • 2012-11-09
    • 2018-05-06
    • 2011-03-23
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    相关资源
    最近更新 更多