在 Camera2 中切换闪光灯 API
Switch flash in Camera2 API
我的问题是当我在不同的闪光灯模式之间切换然后想要捕获图像时,我的 captureBuilder 不会设置所选的闪光灯模式。它只在我关闭并重新打开相机时有效。
我以https://github.com/googlesamples/android-Camera2Basic为起点。
我的方法:
private void captureStillPicture() {
try {
final Activity activity = (Activity) context;
if (null == activity || null == mCameraDevice) {
return;
}
// This is the CaptureRequest.Builder that we use to take a picture.
CaptureRequest.Builder captureBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(mImageReader.getSurface());
// Use the same AE and AF modes as the preview.
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
setCurrentFlash(captureBuilder);
// Orientation
int rotation = activity.getWindowManager()
.getDefaultDisplay()
.getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
CameraCaptureSession.CaptureCallback captureCallback =
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(context, "image captured", Toast.LENGTH_SHORT)
.show();
unlockFocus();
}
};
mCaptureSession.stopRepeating();
mCaptureSession.capture(captureBuilder.build(), captureCallback, null);
} catch (CameraAccessException e) {
Log.e(this.getClass()
.getSimpleName(), e.getMessage(), e);
}
这是 setCurrentFlash 方法:
private void setCurrentFlash(CaptureRequest.Builder requestBuilder) {
if (mFlashSupported) {
switch (flashMode.name()) {
case FLASH_AUTO:
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
break;
case FLASH_ON:
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
break;
case FLASH_OFF:
requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
break;
default:
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
break;
}
}
知道为什么构建器在捕获之前没有正确设置闪光灯吗?
***** 编辑 *****
通过像 Eddy Talvala 建议的那样调用 runPrecaptureSequence() 时将 flash 设置为 previewRequestBuilder 解决了问题
private void runPrecaptureSequence() {
try {
// This is how to tell the camera to trigger.
setCurrentFlash(previewRequestBuilder);
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
// Tell #mCaptureCallback to wait for the precapture sequence to be set.
state = STATE_WAITING_PRECAPTURE;
captureSession.capture(previewRequestBuilder.build(), mCaptureCallback, backgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
您也想更新预览请求中的 Flash 模式;通常,当您触发预捕获序列(AE_PRECAPTURE_TRIGGER)时,相机设备想知道您想要的闪光模式,以便它知道是否应该打开预捕获闪光灯,它需要确定最终的闪光灯功率。
通常的事件顺序是:
- 将预览闪光模式设置为所需模式
- 等待用户按下快门按钮
- 发出带有预捕获触发器集的单个预览请求(但保持重复预览请求)。
- 等待 AE_STATE_PRECAPTURE 停止成为捕获结果中的 AE 状态
- 发出最终捕获请求(保持相同的闪光模式)
- 在您的 ImageReader 中获取最终的 JPEG
(这忽略了确保焦点良好,这通常是在 before/in 开始预捕获序列的同时完成的)
我的问题是当我在不同的闪光灯模式之间切换然后想要捕获图像时,我的 captureBuilder 不会设置所选的闪光灯模式。它只在我关闭并重新打开相机时有效。
我以https://github.com/googlesamples/android-Camera2Basic为起点。
我的方法:
private void captureStillPicture() {
try {
final Activity activity = (Activity) context;
if (null == activity || null == mCameraDevice) {
return;
}
// This is the CaptureRequest.Builder that we use to take a picture.
CaptureRequest.Builder captureBuilder =
mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(mImageReader.getSurface());
// Use the same AE and AF modes as the preview.
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
setCurrentFlash(captureBuilder);
// Orientation
int rotation = activity.getWindowManager()
.getDefaultDisplay()
.getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
CameraCaptureSession.CaptureCallback captureCallback =
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Toast.makeText(context, "image captured", Toast.LENGTH_SHORT)
.show();
unlockFocus();
}
};
mCaptureSession.stopRepeating();
mCaptureSession.capture(captureBuilder.build(), captureCallback, null);
} catch (CameraAccessException e) {
Log.e(this.getClass()
.getSimpleName(), e.getMessage(), e);
}
这是 setCurrentFlash 方法:
private void setCurrentFlash(CaptureRequest.Builder requestBuilder) {
if (mFlashSupported) {
switch (flashMode.name()) {
case FLASH_AUTO:
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
break;
case FLASH_ON:
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
break;
case FLASH_OFF:
requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
break;
default:
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
break;
}
}
知道为什么构建器在捕获之前没有正确设置闪光灯吗?
***** 编辑 *****
通过像 Eddy Talvala 建议的那样调用 runPrecaptureSequence() 时将 flash 设置为 previewRequestBuilder 解决了问题
private void runPrecaptureSequence() {
try {
// This is how to tell the camera to trigger.
setCurrentFlash(previewRequestBuilder);
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
// Tell #mCaptureCallback to wait for the precapture sequence to be set.
state = STATE_WAITING_PRECAPTURE;
captureSession.capture(previewRequestBuilder.build(), mCaptureCallback, backgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
您也想更新预览请求中的 Flash 模式;通常,当您触发预捕获序列(AE_PRECAPTURE_TRIGGER)时,相机设备想知道您想要的闪光模式,以便它知道是否应该打开预捕获闪光灯,它需要确定最终的闪光灯功率。
通常的事件顺序是:
- 将预览闪光模式设置为所需模式
- 等待用户按下快门按钮
- 发出带有预捕获触发器集的单个预览请求(但保持重复预览请求)。
- 等待 AE_STATE_PRECAPTURE 停止成为捕获结果中的 AE 状态
- 发出最终捕获请求(保持相同的闪光模式)
- 在您的 ImageReader 中获取最终的 JPEG
(这忽略了确保焦点良好,这通常是在 before/in 开始预捕获序列的同时完成的)