android camera2 相机切换模糊效果实现

前言

最近有客户反馈,camera2相机切换时,会黑屏一段时间很不美观,影响体验,客户要求能够像小米,华为等品牌机一样,中间有一个模糊的效果。
这个问题由于关联问题比较多,包括,录像,照相,半屏预览,全屏预览,第三方应用调用,以及google GMS 测试的问题。最后还是和客户沟通掉了,不做修改。
但是,这里我们需要知道,相机模糊的原理。

实现步骤

1.点击切换时,获取相机预览的一帧。
2.获取的帧,转为为bitmap
3.在camera surfaceview 之上添加view ,并setBackground 为步骤2中处理的bitmap

具体实现

1.获取预览帧

mCameraDevice.setOneShotPreviewCallback(mHandler, new CameraManager.CameraPreviewDataCallback() {
    @TargetApi(Build.VERSION_CODES.FROYO)
    @Override
    public void onPreviewFrame(byte[] data, CameraProxy camera) {
        Log.d(TAG,"wangjicong  onPreviewFrame");
        Camera.Size size = camera.getParameters().getPreviewSize();
        Log.d(TAG, "wangjicong size, width = " + size.width + " height = " + size.height);
        mYuvImage = null;
        mYuvImage = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);

通过setOneShotPreviewCallback 获取data 帧数据,由于预览数据时Yuv的,需要需要转化为得到YuvImage
2.通过 YuvImage 得到bitmap

ByteArrayOutputStream stream = new ByteArrayOutputStream();
//Log.d(TAG,"wangjicong blur bitmap  size.width = "+size.width+" size.height = "+size.height);
mYuvImage.compressToJpeg(new Rect(0, 0, mYuvImage.getWidth(), mYuvImage.getHeight()), 40, stream);
Bitmap bitmap = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());

由于我们得到的bitmap,旋转方向和我们手机屏时不同的,以及前摄情况下,bitmap存在镜像,需要bitmap镜像处理。

private Bitmap rotateBitmap(Bitmap origin, int rotate) {
    if (origin == null) {
        return null;
    }
    int width = origin.getWidth();
    int height = origin.getHeight();
    Matrix matrix = new Matrix();
    matrix.setRotate(rotate);
    if (rotate==-90){
        matrix.postScale(-1, 1);
    }
    Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
    if (newBM.equals(origin)) {
        return newBM;
    }
    origin.recycle();
    return newBM;
}

3.模糊处理
将我们步骤2中的旋转,镜像处理之后的bitmap 做模糊处理。

private static final float SCALE_DEGREE = 0.4f;
private static final float BLUR_RADIUS = 25f;
private HandlerThread mBlurHandlerThread;
private Handler mBlurHandler;
private YuvImage mYuvImage;

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static Bitmap blur(Bitmap bitmap,Context context) {
    //计算图片缩小的长宽
    int width = Math.round(bitmap.getWidth()*SCALE_DEGREE);
    int height = Math.round(bitmap.getHeight() * SCALE_DEGREE);
    //将缩小后的图片作为预渲染的图片
    Bitmap inputBitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
    //创建一张渲染后的输入图片
    Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
    //创建RenderScript内核对象
    RenderScript renderScript = RenderScript.create(context);
    //创建一个模糊效果的RenderScript的工具对象
    ScriptIntrinsicBlur scriptIntrinsicBlur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));

    /**
     * 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间。
     * 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去。
     */
    Allocation inputAllocation = Allocation.createFromBitmap(renderScript, inputBitmap);
    Allocation outputAllocation = Allocation.createFromBitmap(renderScript, outputBitmap);

    //设置渲染的模糊程度,25f是最大模糊度
    scriptIntrinsicBlur.setRadius(BLUR_RADIUS);
    //设置ScriptIntrinsicBlur对象的输入内存
    scriptIntrinsicBlur.setInput(inputAllocation);
    //将ScriptIntrinsicBlur输出数据保存到输出内存中
    scriptIntrinsicBlur.forEach(outputAllocation);

    //将数据填充到Allocation中
    outputAllocation.copyTo(outputBitmap);
    return  outputBitmap;
}

备注

由于bitmap处理比较耗时,这里定义了一个private HandlerThread mBlurHandlerThread; 来处理。

发布了376 篇原创文章 · 获赞 40 · 访问量 46万+

猜你喜欢

转载自blog.csdn.net/wangjicong_215/article/details/105296012