如何在安卓设备上将相机的原始数据转换为位图

3

我从一个库函数中获取了类型为byte[]、格式为RGBA、大小为640x480、每个像素4个字节的原始相机数据rawData。我需要将其转换为位图并在屏幕上的ImageView中显示。

我的做法如下:

byte[] JPEGData = convertToJpeg(rawData, 640, 480, 80);
Bitmap bitmap = BitmapFactory.decodeByteArray(JPEGData , 0, JPEGData .length);    
imageView.setImageBitmap(bitmap);

其中 convertToJpeg() 函数是:

    public static byte[] convertToJpeg(byte[] buffer, int w, int h, int quality) {
        YuvImage yuv_image = new YuvImage(buffer, ImageFormat.NV21, w, h, null);

        Rect rect = new Rect(0, 0, w, h);
        ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
        yuv_image.compressToJpeg(rect, quality, output_stream);

        Bitmap sourceBmp = BitmapFactory.decodeByteArray(output_stream.toByteArray(), 0, output_stream.size());
        Bitmap destBmp = Bitmap.createScaledBitmap(sourceBmp, (int) (w * 0.75), (int) (h * 0.75), true);

        ByteArrayOutputStream pictureStream = new ByteArrayOutputStream();
        destBmp.compress(CompressFormat.JPEG, quality, pictureStream);
        byte[] pictureByteArray = pictureStream.toByteArray();

        return pictureByteArray;
    }
decodeByteArray()调用后,我的bitmap.getConfig() == ARGB_8888
然而,我在屏幕上看到的是一些混乱的图片,有一些模糊的绿色形状,但它们与原始图片相比不符。
这是怎么回事?

没有人知道任何解决方案吗? - Alexander Shmuratko
它看起来模糊只是因为位图的内容被编码了(我认为是NV21格式)。因此,如果您尝试将其视为png或jpg文件进行查看,它将无法正常工作。您需要先解码它才能保存。 - Simon Marquis
@Simon,我不明白你的意思。Bitmap将在ImageView中进一步显示,如下所示:(imageView.setBitmap(bitmap));。我该怎么办? - Alexander Shmuratko
你必须在使用之前对其进行解码。将此指令用于 ImageView 上,它将尝试将其解码为常规的 ARGB 位图。但是,byte[] 不是以 ARGB 格式存储的。(可能类似于 YUYV) - Simon Marquis
你应该在开始时这样做。在你的例子中,byte[] buffer 应该转换为 ARGB 格式。我认为 compressToJpeg 期望得到一个 ARGB 格式。 - Simon Marquis
显示剩余3条评论
2个回答

7
解决方案很简单,而且不需要转换为JPEG。
Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bm.copyPixelsFromBuffer(ByteBuffer.wrap(rawData));

3
我刚试了一下你的代码,但是出现了错误:"java.lang.RuntimeException: Buffer not large enough for pixels" @Alexander Shmuratko。 - Jigar Shekh
@JigarShekh 请检查您的宽度和高度是否正确。 :) - Sipty
@Sipty 想知道在哪里可以找到高度和宽度? - Pat Marx
如果你可以访问相机设置,直接从设置中获取捕获分辨率即可。或者,如果你在使用ImageReader作为相机数据的输出,也可以尝试从其中获取分辨率。 - Sipty

0

使用ByteBuffer().rewind将缓冲区位置重置为0,然后问题“缓冲区不足以容纳像素”得到解决


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接