Camera.PreviewCallback equivalent in Camera2 API

2019-03-12 15:14发布

问题:

Is there any equivalent for Camera.PreviewCallback in Camera2 from API 21,better than mapping to a SurfaceTexture and pulling a Bitmap ? I need to be able to pull preview data off of the camera as YUV?

回答1:

You can start from the Camera2Basic sample code from Google.

You need to add the surface of the ImageReader as a target to the preview capture request:

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

After that, you can retrieve the image in the 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());
        }
    }
};

To get a Bitmap from the ByteBuffer:

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


回答2:

Yes, use the ImageReader class.

Create an ImageReader using the format ImageFormat.YUV_420_888 and your desired size (make sure you select a size that's supported by the camera device you're using).

Then use ImageReader.getSurface() for a Surface to provide to CameraDevice.createCaptureSession(), along with your other preview outputs, if any.

Finally, in your repeating capture request, add the ImageReader provided surface as a target before setting it as the repeating request in your capture session.