Camera.PreviewCallback 在 Camera2 中等效 API

Camera.PreviewCallback equivalent in Camera2 API

Camera2 中 Camera.PreviewCallback 从 API 21 是否有任何等效项,比映射到 SurfaceTexture 并拉动位图更好?我需要能够以 YUV 格式从相机中提取预览数据吗?

是的,使用ImageReaderclass。

使用格式 ImageFormat.YUV_420_888 和您想要的大小创建一个 ImageReader(确保您 select 您使用的相机设备支持的大小)。

然后使用 ImageReader.getSurface() 为 Surface 提供给 CameraDevice.createCaptureSession(),以及其他预览输出(如果有)。

最后,在您的重复捕获请求中,将 ImageReader 提供的表面添加为目标,然后再将其设置为捕获会话中的重复请求。

您可以从 Google 的 Camera2Basic 示例代码开始。

您需要将 ImageReader 的表面作为目标添加到预览捕获请求中:

//set up a CaptureRequest.Builder with the output Surface
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
mPreviewRequestBuilder.addTarget(mImageReader.getSurface());

之后,您可以在ImageReader.OnImageAvailableListener中检索图像:

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
    @Override
    public void onImageAvailable(ImageReader reader) {
        Image image = null;
        try {
            image = reader.acquireLatestImage();
            if (image != null) {
                ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                Bitmap bitmap = fromByteBuffer(buffer);
                image.close();
            }
        } catch (Exception e) {
            Log.w(LOG_TAG, e.getMessage());
        }
    }
};

要从 ByteBuffer 得到一个 Bitmap:

Bitmap fromByteBuffer(ByteBuffer buffer) {
    byte[] bytes = new byte[buffer.capacity()];
    buffer.get(bytes, 0, bytes.length);
    return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}