Camera2简要说明
在Google 推出Android 5.0的时候, Android Camera API 版本升级到了API2(android.hardware.camera2),大幅提高了Android系统拍照的功能,还能支持RAW照片输出,允许程序调整相机的对焦模式、曝光模式、快门等
源码地址
https://github.com/WuKaik/QuickCamera.git
需要了解camera2的几个重要类
- CameraManager: 管理设备上的所有摄像头设备,主要是获取摄像头列表和打开指定的摄像头
- CameraCharacteristics:摄像头特性,该对象通过CameraManager来获取,用于描述特定摄像头所支持的各种特性
- CameraDevice: 具体的摄像头设备,主要是创建CaptureSession和CaptureRequest
- CameraCaptureSession: 相机捕获会话,主要是处理拍照和预览,需要预览、拍照时,都需要先通过该类的实例创建 Session
- CaptureRequest.Builder:负责生成CameraRequest对象
- CaptureRequest: 通过CaptureRequest.Builder.build()后得到的一次捕获请求,用于描述捕获图片的各种参数设置,比如对焦模式、曝光模式……
使用简要说明
- 获取CameraManager
- 调用CameraManager.getCameraCharacteristics()方法得到CameraCharacteristics
- 调用CameraManager.open()方法在回调中得到CameraDevice
- 通过CameraDevice.createCaptureRequest()得到CaptureRequest.Builder,构建CaptureRequest对象
- 通过CameraDevice.createCaptureSession() 在回调中获取CameraCaptureSession
- 通过 CameraCaptureSession发送CaptureRequest, capture表示只发一次请求, setRepeatingRequest表示不断发送请求.
- 在ImageReader.OnImageAvailableListener回调中获取拍照数据
主要代码截图
/**
* 开始预览
* 使用TextureView显示相机预览数据
* Camera2的预览和拍照数据都是使用CameraCaptureSession会话来请求的
*/
private void startPreview() {
SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
//设置TextureView缓冲区大小
surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
//获取Surface显示数据
Surface surface = new Surface(surfaceTexture);
try {
//设置捕获请求为预览(还有其它,如拍照、录像)
mCaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
//可以通过这个set(key,value)方法,设置曝光啊,自动聚焦等参数!!
//mCaptureBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
//获取ImageReader(ImageFormat不要使用jpeg,预览会出现卡顿)
mReader = ImageReader.newInstance(mPreviewSize.getWidth(), mPreviewSize.getHeight(), ImageFormat.YUV_420_888, 2);
//设置有图像数据流时监听
mReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader reader) {
//需要调用acquireLatestImage()和close(),不然会卡顿
Image image = reader.acquireLatestImage();
//将这帧数据转成字节数组,类似于Camera1的PreviewCallback回调的预览帧数据
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
//Log.d(TAG, "onImageAvailable: data size"+data.length);
image.close();
}
}, mHandler);
//设置预览界面为数据的显示
mCaptureBuilder.addTarget(surface);
mCaptureBuilder.addTarget(mReader.getSurface());
//创建相机捕获会话
mCameraDevice.createCaptureSession(Arrays.asList(surface, mReader.getSurface()), mCaptureStateCallback, mHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private CameraCaptureSession.StateCallback mCaptureStateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
//创建捕获请求
mCaptureRequest = mCaptureBuilder.build();
mCameraSession = session;
try {
//设置反复捕获数据的请求,这样预览界面就会一直有数据显示
mCameraSession.setRepeatingRequest(mCaptureRequest, null, mHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
}
};