实现特点
- 实现自动对焦
- 选择性正常触发闪光灯flash
- 复用CaptureRequest.Builder, 参数完全一致
- 拍照注意事项讲解
- 代码片段详解
流程
- 按照常规方式打开预览
- 设置好相应的全局变量:
CameraDevice的cameraDevice
CameraCaptureSession的mPreviewSession
CaptureRequest.Builder的captureRequestBuilder
ImageReader的imageReader
等 - 定义一个类似takePicture()的开始拍照方法
- 自动对焦 对焦, 直接开始拍照, 调用类似captureStillPicture()的方法
- 自动对焦
// 设置自动对焦模式
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
- 拍摄前, 如果需要闪光的, 需要设置
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
上面这条语句会触发闪光的开启动作
- 添加拍摄图片的输出
captureRequestBuilder.addTarget(mImageReader.getSurface());
- 设置当前的拍摄意图
captureRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CameraMetadata.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
这条设置页会影响到闪光的正常开启. 如果不需要闪光灯的话, 设置了也没事.
- 设置图片的方向
因为物理相机的镜头方向可能和手机的朝向不一致(手机倒着拿), 所以设置这个是确保拍摄出来的图片永远是正向的
int sensorOrientation = mCameraCharacteristics.get(
CameraCharacteristics.SENSOR_ORIENTATION);
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION,
(sensorOrientation +
mDisplayOrientation * (mFacing == Constants.FACING_FRONT ? 1 : -1) +
360) % 360);
- 停止画面预览
mPreviewSession.stopRepeating();
也可以不调用这条, 不停止画面. 不过这样会出现闪光灯闪烁2次的问题.
- 开始拍照
mPreviewSession.capture(captureRequestBuilder.build(),
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
//移除输出到ImageReader, 不移除的话,会造成拍照停不下来的问题
captureRequestBuilder.removeTarget(imageReader.getSurface());
//恢复相机预提为预览
captureRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CameraMetadata.CONTROL_CAPTURE_INTENT_PREVIEW);
try {
//不加这句话, 闪光灯无法正常工作, 如果不适用闪光等, 可以不加
mPreviewSession.capture(mPreviewRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}, null);
- 完整部分代码
/**拍照*/
private void takePicture()
{
try
{
if (cameraDevice == null)
{
return;
}
// 创建拍照请求
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
// 设置自动对焦模式
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
// 将imageReader的surface设为目标
captureRequestBuilder.addTarget(imageReader.getSurface());
// 获取设备方向
int rotation = getWindowManager().getDefaultDisplay().getRotation();
// 根据设备方向计算设置照片的方向
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION
, ORIENTATIONS.get(rotation));
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 5);
// 停止连续取景
mPreviewSession.stopRepeating();
mPreviewSession.abortCaptures();
//拍照
CaptureRequest captureRequest = captureRequestBuilder.build();
//设置拍照监听
mPreviewSession.capture(captureRequest,captureCallback, null);
}
catch (CameraAccessException e)
{
e.printStackTrace();
}
}