Camera2字节构成的位图巨大

时间:2019-06-25 16:00:37

标签: android android-camera2

我使用的是here给出的Google示例。我以以下方式更改了OnImageAvailableListener

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
        = reader -> {
            Image image = reader.acquireLatestImage();
            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            byte[] bytes = new byte[buffer.remaining()];
            buffer.get(bytes);
            image.close();

            String pictureId = "asdasd";

            Bitmap bitmap = createMutableBitmap(bytes);
            StorageClass.getInstance().put(pictureId, bitmap);


            Intent intent = new Intent(Camera2MainActivity.this, TPCameraPreviewSnapActivity.class);
            intent.setType("image/*");
            intent.putExtra("pictureId", pictureId);

            startActivityForResult(intent, 1123);
        };

我要开始的新Intent正在使用PhotoView来显示位图。 StorageClass提供了一种静态方法,可以在意图之间共享大数据(例如这些位图)。

此外,方法createMutableBitmap是:

public static Bitmap createMutableBitmap(byte[] data){
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inMutable = true;
    Log.d(TAG, "BT1: " + data.length);
    Bitmap mutableBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
    Log.d(TAG, "BT2: " + mutableBitmap.getByteCount());
    return mutableBitmap;
}

在Huawei P30 Pro上执行此代码后,我得到如下输出:

W/ImageReader_JNI: Unable to acquire a buffer item, very likely client tried to acquire more than maxImages buffers
E/ion: ioctl c0044901 failed with code -1: Invalid argument
D/Camera2BasicFragment: BT1: 1019119
W/ServiceManagement: getService: unable to call into hwbinder service for vendor.huawei.hardware.jpegdec@1.0::IJpegDecode/default.
D/HwAppInnerBoostImpl: asyncReportData rs.tp.camera2verifiedbypi,1,1,10,0 interval=2774
D/Camera2BasicFragment: BT2: 159694848

无论我如何更改图像的JPEG质量,都会弹出数字159694848。 159694848字节为〜160MB。

随后,当尝试将Bitmap设置为

的来源时
`PhotoView`, I get an exception:
E/BitmapDrawable: Canvas: trying to use a recycled bitmap
W/System.err: java.lang.RuntimeException: Canvas: trying to draw too large(159694848bytes) bitmap.

这个示例,经过我的更改,可以在我尝试过的所有其他手机上正常运行,但它们运行的​​是Android 8或更低版本。

那么,此问题的起因是什么,我该如何缓解呢?

2 个答案:

答案 0 :(得分:2)

您要捕获的JPEG的分辨率是多少?假设ARGB内部存储,一个160 MB的位图是每个像素4个字节,因此160/4 = 4000万像素。

https://www.gsmarena.com/huawei_p30_pro-9635.php起,Huawei P30 Pro确实确实具有40 MP主摄像头(在四Bayer模式下使用时),因此这一切都是一致的。

也就是说,Android View组件并不是真的希望通过40百万像素的Bitmap。由于屏幕分辨率仅为1080 x 2340像素= 2.5 MP,因此没有理由在该屏幕上绘制40 MP。

如果只想在屏幕上显示JPEG,则在解码图像时应使用BitmapFactory选项将图像重新缩放到更接近屏幕分辨率的水平。这样也可以节省大量内存。

答案 1 :(得分:0)

位图始终是无懈可击的,它与JPEG压缩无关。 ARGB格式的位图始终是其大小的像素数x 4(alpha,红色,绿色,蓝色每个1字节)。因此,如果您有1000x1000像素的位图,则在加载到内存中时,它的大小始终为4MB。 JPEG压缩仅适用于存储到磁盘的文件,在内存中的图像始终未压缩。

您可以通过在每个通道中使用4位来使用较小的位图,而这会牺牲颜色保真度,或者您可以调整它们的大小。