探索Camera ImageReader YUV420_888 快速转bitmap argb888的方式

2024-05-27 20:49:28 浏览数 (2)

从 Android 12 开始,RenderScript API 已被弃用。

Google推荐使用更加高效的Vulkan。

不过这篇文件还是介绍RenderScript 的使用,RenderScript 相对比较简单一些。

RenderScript 是用于在 Android 上以高性能运行计算密集型任务的框架。

RenderScript 专为数据并行计算而设计,不过串行工作负载也可以从中受益。

RenderScript 运行时可以并行安排设备上可用的多个处理器(如多核 CPU 和 GPU)上的工作负载,使开发者能够专注于表达算法而不是调度工作。RenderScript 对于专注于图像处理、计算摄影或计算机视觉的应用来说尤其有用。

关于RenderScript ,Google的官方介绍文档。

https://source.android.google.cn/docs/core/architecture/vndk/renderscript?hl=zh-cn

RenderScript 使用示例:

下面示例内容是,在imageReader的回调里面,实时的将yuv420_888转为bitmap。

代码语言:javascript复制
mYuvImageReader = ImageReader.newInstance(1920, 1080,
                    ImageFormat.YUV_420_888, 4);

private final ImageReader.OnImageAvailableListener mOnYuvImageAvailableListener
            = new ImageReader.OnImageAvailableListener() {

        @Override
        public void onImageAvailable(ImageReader reader) {
            Image image = reader.acquireLatestImage();

            if (image != null) {
                Log.e(TAG,"YUV_420_888_toRGBIntrinsics start");
                mBitMap = YUV_420_888_toRGBIntrinsics(image,getActivity());
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                       showImage(mBitMap);
                    }
                });
                Log.e(TAG,"YUV_420_888_toRGBIntrinsics end");
            }
        }
    };
代码语言:javascript复制
private static RenderScript rs;

private static Bitmap YUV_420_888_toRGBIntrinsics(Image image,Context context) {

        if (image == null) return null;

        int W = image.getWidth();
        int H = image.getHeight();

        Image.Plane Y = image.getPlanes()[0];
        Image.Plane U = image.getPlanes()[1];
        Image.Plane V = image.getPlanes()[2];

        int Yb = Y.getBuffer().remaining();
        int Ub = U.getBuffer().remaining();
        int Vb = V.getBuffer().remaining();

        byte[] data = new byte[Yb   Ub   Vb];


        Y.getBuffer().get(data, 0, Yb);
        V.getBuffer().get(data, Yb, Vb);
        U.getBuffer().get(data, Yb   Vb, Ub);



        rs = RenderScript.create(context);
        ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));

        Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(data.length);
        Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);

        Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(W).setY(H);
        Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);

        final Bitmap bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888);

        in.copyFromUnchecked(data);

        yuvToRgbIntrinsic.setInput(in);
        yuvToRgbIntrinsic.forEach(out);
        out.copyTo(bmpout);
        image.close();
        return bmpout ;
    }

日志打印:从下面日志可以看到,1920 * 1080的分辨率下,转换耗时在30 ms左右。

代码语言:javascript复制
2023-12-25 14:06:27.294 15912-22157 Camera2BasicFragment    com.android.camera2demo              E  YUV_420_888_toRGBIntrinsics end
2023-12-25 14:06:27.311 15912-22157 Camera2BasicFragment    com.android.camera2demo              E  YUV_420_888_toRGBIntrinsics start
2023-12-25 14:06:27.352 15912-22157 Camera2BasicFragment    com.android.camera2demo              E  YUV_420_888_toRGBIntrinsics end
2023-12-25 14:06:27.353 15912-22157 Camera2BasicFragment    com.android.camera2demo              E  YUV_420_888_toRGBIntrinsics start
2023-12-25 14:06:27.371 15912-22157 Camera2BasicFragment    com.android.camera2demo              E  YUV_420_888_toRGBIntrinsics end
2023-12-25 14:06:27.398 15912-22157 Camera2BasicFragment    com.android.camera2demo              E  YUV_420_888_toRGBIntrinsics start
2023-12-25 14:06:27.415 15912-22157 Camera2BasicFragment    com.android.camera2demo              E  YUV_420_888_toRGBIntrinsics end
2023-12-25 14:06:27.435 15912-22157 Camera2BasicFragment    com.android.camera2demo              E  YUV_420_888_toRGBIntrinsics start

扩展:

1、Vulkan

Vulkan在Android使用Compute shader

https://zhuanlan.zhihu.com/p/258130830 https://blog.51cto.com/u_16099335/6861390

2、libyuv

https://github.com/GitLqr/LQRLibyuv

0 人点赞