我会解释我的情况。 我正在尝试做一个应用程序,其中每5秒钟拍摄一张图像,一张没有闪光灯,然后在5秒钟后拍摄一张闪光灯,每次重复此操作。所以它将需要一个没有闪光灯,一个闪光灯,一个没有闪光灯,一个闪光灯...无限。
案例是,我的代码可以在某些设备中执行此操作,但相同的代码在其他设备中无法正常工作。即:
如何做到这一点,我尝试过的所有设备都是Camera2 API的LEGACY硬件支持级别。
这是我的代码中的一些重要方法(由于char限制,我无法发布所有代码)。我从Google示例开始:
此setAutoFlash执行上述操作。
private void setAutoFlash(CaptureRequest.Builder requestBuilder) {
if (mFlashSupported) {
if(phototaken) {
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
}else{
requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
}
}
}
另一个适用于某些设备和bq aquaris e5,但不会在bq aquaris x5 plus中闪光。
private void setAutoFlash(CaptureRequest.Builder requestBuilder) {
if (mFlashSupported) {
if(phototaken) {
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
}else{
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
}
}
}
我的captureStillPicture
private void captureStillPicture() {
try {
final Activity activity = getActivity();
if (null == activity || null == mCameraDevice) {
return;
}
// This is the CaptureRequest.Builder that we use to take a picture.
final 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);
setAutoFlash(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) {
showToast("Saved: " + mFile);
Log.d(TAG, mFile.toString());
unlockFocus();
}
};
mCaptureSession.stopRepeating();
mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
phototaken = !phototaken;
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
问题是,我做错了什么,所以它不适用于所有设备?任何帮助都会很棒。
答案 0 :(得分:4)
闪光灯有两个级别的控制 - 手动,并由自动曝光程序控制。你现在正在将它们混合在一起。
如果您想手动触发闪光灯,则需要将AE_MODE设置为AE_MODE_OFF或AE_MODE_ON;不是任何闪存模式。然后,对于给定的请求,FLASH_MODE将控制闪光灯是处于割炬模式,关闭还是闪光一次。
由于您始终将AE_MODE保留在其中一种FLASH状态,因此您对FLASH_MODE所做的操作无关紧要,除非某些特定设备出现错误。
如果你想保证每张照片中的闪光灯闪光,你需要使用AE_MODE_ON_ALWAYS_FLASH作为强制闪光照片,你需要使用AE_MODE_ON来拍摄无闪光的照片;请勿触摸FLASH_MODE。 现在,使用AUTO_FLASH,无论是否发射闪光灯,设备都能正常运行,因此您会看到不同设备和照明条件下的不同行为 - 有些会触发,有些会不会发生。
你没有做的另一件关键事情是运行预捕获序列;这对于闪光照片至关重要,因为它允许设备发出预闪,以确定正确的闪光灯功率,对焦和白平衡。
要运行预捕获,请根据需要设置AE_MODE,然后将AE_PRECAPTURE_TRIGGER设置为START以进行一个请求。这会将AE_STATE转换为PRECAPTURE,并且它会在那里保留一定数量的帧;一旦AE_STATE不再是PRECAPTURE,您就可以发出实际的图像捕获请求。确保始终保持AE_MODE一致。
示例应用Camera2Basic实现了预捕获序列,所以看看那里;它也有一些优化,如果场景不够暗,不需要闪光灯,可以跳过预捕,但是因为你想强制闪光,这与你无关。