为了更易于理解,将几个答案结合起来。因为@VP的答案虽然技术上很清晰,但如果是您第一次从Camera转移到Camera2,可能难以理解:
使用https://github.com/googlesamples/android-Camera2Basic作为起点,修改以下内容:
在createCameraPreviewSession()
中从mImageReader
初始化一个新的Surface
。
Surface mImageSurface = mImageReader.getSurface()
将新的表面作为输出目标添加到您的
CaptureRequest.Builder
变量中。使用Camera2Basic示例,该变量将是
mPreviewRequestBuilder
。
mPreviewRequestBuilder.addTarget(mImageSurface)
这是带有新换行符的代码片段(请查看我的@AngeloS评论):
private void createCameraPreviewSession() {
try {
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Surface surface = new Surface(texture);
Surface mImageSurface = mImageReader.getSurface();
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(mImageSurface);
mPreviewRequestBuilder.addTarget(surface);
...
接下来,在setUpCameraOutputs()
中,当您初始化ImageReader
时,请将格式从ImageFormat.JPEG
更改为ImageFormat.YUV_420_888
。(另外,我建议您降低预览大小以获得更流畅的操作 - 这是Camera2的一个不错的功能)
mImageReader = ImageReader.newInstance(largest.getWidth() / 16, largest.getHeight() / 16, ImageFormat.YUV_420_888, 2);
最后,在您的ImageReader.OnImageAvailableListener
的onImageAvailable()
方法中,请务必使用@Kamala的建议,因为如果不关闭预览,预览将在几帧后停止。
@Override
public void onImageAvailable(ImageReader reader) {
Log.d(TAG, "I'm an image frame!");
Image image = reader.acquireNextImage();
...
if (image != null)
image.close();
}
setOnImageAvailableListener
在捕获图像时获取新图像。为了绘制图像,我创建了一个OpenGL表面,它呈现纹理和一个着色器,将YUV_420_888
转换为RGB
。 - buboonImageAvailable(...)
中读取并关闭图像。即使您不使用图像,监听器也不能是空的,您需要读取它(例如使用reader.acquireNextImage()
)。 - bubo