实现特点
- 实现自动对焦
- 选择性正常触发闪光灯flash
- 复用CaptureRequest.Builder, 参数完全一致
- 拍照注意事项讲解
- 代码片段详解
流程
- 按照常规方式打开预览
- 设置好相应的全局变量:
CameraDevice的cameraDevice
CameraCaptureSession的mPreviewSession
CaptureRequest.Builder的captureRequestBuilder
ImageReader的imageReader
等 - 定义一个类似takePicture()的开始拍照方法
- 自动对焦 对焦, 直接开始拍照, 调用类似captureStillPicture()的方法
- 自动对焦
1 2 3 | // 设置自动对焦模式 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); |
- 拍摄前, 如果需要闪光的, 需要设置
1 | captureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START); |
上面这条语句会触发闪光的开启动作
- 添加拍摄图片的输出
1 | captureRequestBuilder.addTarget(mImageReader.getSurface()); |
- 设置当前的拍摄意图
1 | captureRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CameraMetadata.CONTROL_CAPTURE_INTENT_STILL_CAPTURE); |
这条设置页会影响到闪光的正常开启. 如果不需要闪光灯的话, 设置了也没事.
- 设置图片的方向
因为物理相机的镜头方向可能和手机的朝向不一致(手机倒着拿), 所以设置这个是确保拍摄出来的图片永远是正向的
1 2 3 4 5 6 | int sensorOrientation = mCameraCharacteristics.get( CameraCharacteristics.SENSOR_ORIENTATION); captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, (sensorOrientation + mDisplayOrientation * (mFacing == Constants.FACING_FRONT ? 1 : -1) + 360) % 360); |
- 停止画面预览
1 | mPreviewSession.stopRepeating(); |
也可以不调用这条, 不停止画面. 不过这样会出现闪光灯闪烁2次的问题.
- 开始拍照
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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); |
- 完整部分代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /**拍照*/ 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(); } } |