在相机2上使用闪光灯拍照,可以在“闪光”之后显示图像(即没有闪光灯)

时间:2015-11-24 13:25:34

标签: android android-camera camera2

我的代码基于来自Google Camera2-Basic的示例,并且添加了Flash始终支持。但看起来照片是在闪光灯发生后立即拍摄的。即使闪光灯被触发,我(几乎)总是得到非闪光的照片。

修改后的预览请求构建器:

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);

我还将此控制模式添加到captureStillPicture()

captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);

并修改了process()开关:

       case STATE_WAITING_PRECAPTURE: {
          // CONTROL_AE_STATE can be null on some devices
          Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
          Log.i(TAG, "aeState = " + aeState);
          if (aeState == null ||
              aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
              aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED ||
              aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
            mState = STATE_WAITING_NON_PRECAPTURE;
          }
          break;
        }

1 个答案:

答案 0 :(得分:0)

我在Nexus 5上遇到了同样的问题。我通过检查CaptureResult.FLASH_STATE来解决这个问题,如果它等于CaptureResult.FLASH_STATE_FIRED则立即触发捕获。基本上,如果闪光灯闪光,那么无论你处于什么状态,你都需要在那里进行捕捉,因为它只会发射一次。如果自动对焦/曝光等在这一点上没有正确收敛,那么你无能为力。

你可以在onCaptureCompleted开头检查一下:

if(mFlashAvailable && mWaitingForFlash)
{
     Integer flashState = result.get(CaptureResult.FLASH_STATE);
     if(flashState != null && flashState==CaptureResult.FLASH_STATE_FIRED)
     {
         mWaitingForFlash = false;

         // do the capture...
         mState = STATE_PICTURE_TAKEN;
         captureStillPicture();

         return;  // don't call process()
     }
}
打开相机时,

mFlashAvailable是从CameraCharacteristics设置的:

mFlashAvailable = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);

mWaitingForFlash只是您在启动预捕获时可以设置的标记,因此您不会捕获多个帧。但是,在您的特定情况下,这可能不是必需的。

如果您在问题中描述,那将在状态收敛之前(即照片在闪光之后)闪光灯闪光时进行处理。然而,当闪光灯开始播放时你也需要处理这种情况(我从未见过这种情况实际发生但是以防万一)。您可以通过在将mExpectingFlash = true;设置为CONTROL_AE_MODE时设置CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH这样的标记,并且如果它是真的则不捕获通常的方式(因为您将在检测到闪光灯时捕获)相反)。如果您使用aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED,则可以在获得CONTROL_AE_MODE_ON_AUTO_FLASH时设置此标记。作为一个安全网,我有一个超时,所以我不会等待一个永远不会出现的闪光灯,如果检测到CONTROL_AE_STATE_FLASH_REQUIRED但是闪光灯没有闪光。

如果捕获多个帧,则可以在检测到闪光灯闪光时读取时间戳,如下所示:

 long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);

然后将其与onImageAvailable

中图像的时间戳进行交叉检查
 Image image = reader.acquireLatestImage();
 if (image != null)
 {
     long timestamp = image.getTimestamp();
     // ....
 }