Camera1 拍照速度优化

943 阅读1分钟

背景

使用Android的camera1,最后都是需要调用camera.takePicture()这个方法来进行拍摄,但是这个方法的回调时间在1-2s,这样会导致用户的拍摄体验很差。

实现

takepicture是一个native方法,没有办法在中间过程进行优化。这时候正好看到了这篇文章,react-native的拍摄用的也是camera1,为了优化拍摄速度他提出了通过预览页面的回调数据,去生成拍照数据的思路,我们沿用他的思路进行处理。

通过camera1的onPreviewFrame回调,拿到预览的data数组并缓存。当用户点击拍照的时候,因为这个数组内容是Yuv格式的,通过android自带的YuvImage,将他转为jpg格式的bitmap,然后,将bitmap存到本地文件中并展示。

    void takePicture() {
        if (!isCameraOpened()) {
            throw new IllegalStateException(
                    "Camera is not ready. Call start() before takePicture().");
        }
        Camera.Size previewSize = mCameraParameters.getPreviewSize();
				// 获取Yuv格式的图片
        YuvImage image = new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        image.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, stream);
        Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
        try {
          stream.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
				// 处理图片的旋转问题
        Bitmap rotated;
        if (mCameraInfo.orientation == 0) {
          rotated = bmp;
        } else {
          Matrix matrix = new Matrix();
        matrix.setRotate(mCameraInfo.orientation);
        matrix.postScale(mCameraInfo.facing == FACING_BACK ? 1 : -1, 1);
        rotated = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, false);
        }
				// 回调拍摄成功的bitmap
        mCallback.onPictureTaken(rotated);
				bmp.recycle();
        rotated.recycle();
        }
    }

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
  // 缓存预览的数据
  this.data = data;
}

最终测试结果,拍照的时间在100ms以内