美文网首页
2022-07-21 Android 相机预览数据转Bitmap

2022-07-21 Android 相机预览数据转Bitmap

作者: 颈椎以上瘫痪 | 来源:发表于2022-07-21 11:40 被阅读0次

    背景

    在Android开发中我们有时候会需要拿到相机预览数据转成bitmap自己做处理。

    常用方式

    在Android API中提供了 一套转换方式:

    private Bitmap convertBitmap(byte[] data) {
        try {
            Camera.Size size = mCameraParameters.getPreviewSize();
            YuvImage img = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream(data.length);
            img.compressToJpeg(new Rect(0, 0, size.width, size.height), 100, baos);
            byte[] bytes = baos.toByteArray();
            Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
            baos.close();
            return bitmap ;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    //logcat
    2022-07-21 11:07:36.389 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:199
    2022-07-21 11:07:36.813 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:228
    2022-07-21 11:07:37.181 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:199
    2022-07-21 11:07:37.552 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:199
    2022-07-21 11:07:37.951 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:207
    2022-07-21 11:07:38.352 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:201
    2022-07-21 11:07:38.750 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:207
    2022-07-21 11:07:39.174 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:232
    2022-07-21 11:07:39.542 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:199
    2022-07-21 11:07:39.907 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:200
    2022-07-21 11:07:40.277 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:200
    2022-07-21 11:07:40.675 18675-18675/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:201
    

    通过日志看到这种方式转换耗时约200ms

    优化方案1

    在上述转换过程中img.compressToJpeg()函数中第2个参数表示转换图像的质量,参数范围在0-100,100表示最高质量,我们可以把质量降低一些,这里改成80:

    private Bitmap convertBitmap2(byte[] data) {
        try {
            Camera.Size size = mCameraParameters.getPreviewSize();
            YuvImage img = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream(data.length);
            img.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, baos);
            byte[] bytes = baos.toByteArray();
            Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
            baos.close();
            return bitmap ;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    //logcat
    2022-07-21 11:12:33.946 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:112
    2022-07-21 11:12:34.074 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:111
    2022-07-21 11:12:34.378 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:113
    2022-07-21 11:12:34.505 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:111
    2022-07-21 11:12:34.815 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:118
    2022-07-21 11:12:34.942 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:114
    2022-07-21 11:12:35.248 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:117
    2022-07-21 11:12:35.544 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:118
    2022-07-21 11:12:35.675 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:115
    2022-07-21 11:12:35.981 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:116
    2022-07-21 11:12:36.280 19171-19171/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:117
    

    通过日志看到耗时约110ms,优化空间还是很大的,但是牺牲了图像的质量,不过通过在设备中的观察,降低到80的质量与100质量的图像看起来差别不大,因此也还可以用。

    下面继续将质量降低到40

    private Bitmap convertBitmap2(byte[] data) {
        try {
            Camera.Size size = mCameraParameters.getPreviewSize();
            YuvImage img = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream(data.length);
            img.compressToJpeg(new Rect(0, 0, size.width, size.height), 40, baos);
            byte[] bytes = baos.toByteArray();
            Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
            baos.close();
            return bitmap ;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    //logcat
    2022-07-21 11:15:48.097 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:104
    2022-07-21 11:15:48.226 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:104
    2022-07-21 11:15:48.530 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:107
    2022-07-21 11:15:48.656 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:103
    2022-07-21 11:15:48.927 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:104
    2022-07-21 11:15:49.059 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:103
    2022-07-21 11:15:49.364 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:108
    2022-07-21 11:15:49.488 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:104
    2022-07-21 11:15:49.757 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:105
    2022-07-21 11:15:49.888 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:104
    2022-07-21 11:15:50.191 19529-19529/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:104
    

    查看日志看到质量40时耗时约100,这个优化空间是很小的,并且图像的质量已经很差了,因此不推荐。

    优化方案2

    使用Android的RenderScript来转换

    private Bitmap convertBitmap4RenderScript(byte[] data) {
        Camera.Size size = mCameraParameters.getPreviewSize();
        if (yuvType == null) {
            yuvType = new Type.Builder(rs, Element.U8(rs)).setX(data.length);
            in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
        }
    
        if (rgbaType == null) {
            rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(size.width).setY(size.height);
            out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
        }
    
        in.copyFrom(data);
        yuvToRgbIntrinsic.setInput(in);
        yuvToRgbIntrinsic.forEach(out);
    
        Bitmap bitmap = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888);
        out.copyTo(bitmap);
    
        return bitmap;
    }
    
    //logcat
    2022-07-21 11:21:01.082 19879-19879/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:25
    2022-07-21 11:21:01.147 19879-19879/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:24
    2022-07-21 11:21:01.215 19879-19879/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:25
    2022-07-21 11:21:01.280 19879-19879/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:23
    2022-07-21 11:21:01.348 19879-19879/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:25
    2022-07-21 11:21:01.414 19879-19879/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:24
    2022-07-21 11:21:01.480 19879-19879/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:23
    2022-07-21 11:21:01.548 19879-19879/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:25
    2022-07-21 11:21:01.610 19879-19879/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:22
    2022-07-21 11:21:01.680 19879-19879/org.venus.ar.ocr I/System.out: 相机数据转换bitmap时间:23
    

    通过日志可以看出使用RenderScript的内联函数转换bitmap耗时约25ms,相较于使用BitmapFactory.decodeByteArray()函数转换耗时少了很多。

    其中使用到RenderScript相关变量的定义和初始化:

    //相机预览数据byte[]转bitmap耗时优化方案对象
    private RenderScript rs;
    private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
    private Type.Builder yuvType;
    private Type.Builder rgbaType;
    private Allocation in;
    private Allocation out;
    
    private void initRender() {
        rs = RenderScript.create(this);
        yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
    }
    

    在使用yuvToRgbIntrinsic对象之前执行initRender()函数初始化即可,一般放在onCreate()函数中。

    相关文章

      网友评论

          本文标题:2022-07-21 Android 相机预览数据转Bitmap

          本文链接:https://www.haomeiwen.com/subject/rvsuirtx.html