在运行时更改 Android Camera 2 的 Flash 设置
Changing Flash setting of Android Camera 2 at runtime
基本上,我想做的是通过在应用程序中单击按钮来更改 CONTROL_AE_MODE。用户可以使用自动闪光(ON_AUTO_FLASH),打开(ON_ALWAYS_FLASH)或关闭(CONTROL_AE_MODE_OFF)。
第818行,他们设置了一次闪光灯:
// Use the same AE and AF modes as the preview.
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
setAutoFlash(captureBuilder);
// Orientation
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
CameraCaptureSession.CaptureCallback CaptureCallback
= new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
showToast("Saved: " + mFile);
Log.d(TAG, mFile.toString());
unlockFocus();
}
};
mCaptureSession.stopRepeating();
mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
然后在第 840 行构建 CaptureSession。
有没有办法在预览完成后更改CONTROL_AE_MODE?
我尝试重新制作会话,效果还不错:
if(flashMode == CameraView.CAMERA_FLASH_ON){
Log.e("CAMERA 2", "FLASH ON");
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
}else if(flashMode == CameraView.CAMERA_FLASH_OFF){
Log.e("CAMERA 2", "FLASH OFF");
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
}else if(flashMode == CameraView.CAMERA_FLASH_AUTO){
Log.e("CAMERA 2", "FLASH AUTO");
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
}
mFlashMode = flashMode;
if (mCameraCaptureSession != null) {
mCameraCaptureSession.close();
mCameraCaptureSession = null;
}
createCameraPreviewSession();
出于某种原因,CONTROL_AE_MODE_OFF 会使整个预览变黑。
我尝试在文档中查找更新方法,但没有找到任何内容。
非常感谢任何教程或文档。
我不知道为什么你的预览会变黑,但你不需要手动关闭捕获会话。来自 .close()
方法的文档:
Using createCaptureSession(List , CameraCaptureSession.StateCallback,
Handler)
directly without closing is the recommended approach for
quickly switching to a new session, since unchanged target outputs can
be reused more efficiently.
因此您可以重用现有的 CaptureRequest.Builder,设置更改后的值,构建新的 PreviewRequest 并使用这个新请求启动新会话,如下所示:
try {
// Change some capture settings
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
// Build new request (we can't just edit existing one, as it is immutable)
mPreviewRequest = mPreviewRequestBuilder.build();
// Set new repeating request with our changed one
mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
它会快得多(几乎没有任何可见的预览冻结)。
您想要的是禁用闪光灯,而不是 auto-exposure (AE),因此您想使用 CONTROL_AE_MODE_ON
而不是 CONTROL_AE_MODE_OFF
。
如documentation所述:
CONTROL_AE_MODE_ON
The camera device's autoexposure routine is active, with no flash control.
如 @cyborg86pl 所述,切换闪光灯模式时不应切换 CONTROL_AE_MODE
。相反,您可以在 FLASH_MODE
之间切换。这是我的案例的一个工作示例:
when (currentFlashState) {
FlashState.AUTO -> {
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)
}
FlashState.ON -> {
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
previewRequestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH)
}
FlashState.OFF -> {
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
previewRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF)
}
}
previewRequest = previewRequestBuilder.build()
captureSession.setRepeatingRequest(previewRequest, captureCallback, backgroundHandler)
基本上,我想做的是通过在应用程序中单击按钮来更改 CONTROL_AE_MODE。用户可以使用自动闪光(ON_AUTO_FLASH),打开(ON_ALWAYS_FLASH)或关闭(CONTROL_AE_MODE_OFF)。
第818行,他们设置了一次闪光灯:
// Use the same AE and AF modes as the preview.
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
setAutoFlash(captureBuilder);
// Orientation
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
CameraCaptureSession.CaptureCallback CaptureCallback
= new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
showToast("Saved: " + mFile);
Log.d(TAG, mFile.toString());
unlockFocus();
}
};
mCaptureSession.stopRepeating();
mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
然后在第 840 行构建 CaptureSession。
有没有办法在预览完成后更改CONTROL_AE_MODE?
我尝试重新制作会话,效果还不错:
if(flashMode == CameraView.CAMERA_FLASH_ON){
Log.e("CAMERA 2", "FLASH ON");
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
}else if(flashMode == CameraView.CAMERA_FLASH_OFF){
Log.e("CAMERA 2", "FLASH OFF");
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
}else if(flashMode == CameraView.CAMERA_FLASH_AUTO){
Log.e("CAMERA 2", "FLASH AUTO");
mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
}
mFlashMode = flashMode;
if (mCameraCaptureSession != null) {
mCameraCaptureSession.close();
mCameraCaptureSession = null;
}
createCameraPreviewSession();
出于某种原因,CONTROL_AE_MODE_OFF 会使整个预览变黑。 我尝试在文档中查找更新方法,但没有找到任何内容。
非常感谢任何教程或文档。
我不知道为什么你的预览会变黑,但你不需要手动关闭捕获会话。来自 .close()
方法的文档:
Using
createCaptureSession(List , CameraCaptureSession.StateCallback, Handler)
directly without closing is the recommended approach for quickly switching to a new session, since unchanged target outputs can be reused more efficiently.
因此您可以重用现有的 CaptureRequest.Builder,设置更改后的值,构建新的 PreviewRequest 并使用这个新请求启动新会话,如下所示:
try {
// Change some capture settings
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
// Build new request (we can't just edit existing one, as it is immutable)
mPreviewRequest = mPreviewRequestBuilder.build();
// Set new repeating request with our changed one
mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
它会快得多(几乎没有任何可见的预览冻结)。
您想要的是禁用闪光灯,而不是 auto-exposure (AE),因此您想使用 CONTROL_AE_MODE_ON
而不是 CONTROL_AE_MODE_OFF
。
如documentation所述:
CONTROL_AE_MODE_ON
The camera device's autoexposure routine is active, with no flash control.
如 @cyborg86pl 所述,切换闪光灯模式时不应切换 CONTROL_AE_MODE
。相反,您可以在 FLASH_MODE
之间切换。这是我的案例的一个工作示例:
when (currentFlashState) {
FlashState.AUTO -> {
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)
}
FlashState.ON -> {
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
previewRequestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH)
}
FlashState.OFF -> {
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
previewRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF)
}
}
previewRequest = previewRequestBuilder.build()
captureSession.setRepeatingRequest(previewRequest, captureCallback, backgroundHandler)