Camera2 api问题触发闪光/没有闪光图像

时间:2017-03-28 12:21:22

标签: android camera2 camera-flash

我会解释我的情况。 我正在尝试做一个应用程序,其中每5秒钟拍摄一张图像,一张没有闪光灯,然后在5秒钟后拍摄一张闪光灯,每次重复此操作。所以它将需要一个没有闪光灯,一个闪光灯,一个没有闪光灯,一个闪光灯...无限。

案例是,我的代码可以在某些设备中执行此操作,但相同的代码在其他设备中无法正常工作。即:

  • BQ Aquaris X5 Plus :无闪光图像正确,但闪光图像只是白色。
  • BQ Aquaris E5 :不会闪光。

如何做到这一点,我尝试过的所有设备都是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();
        }
}

问题是,我做错了什么,所以它不适用于所有设备?任何帮助都会很棒。

1 个答案:

答案 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实现了预捕获序列,所以看看那里;它也有一些优化,如果场景不够暗,不需要闪光灯,可以跳过预捕,但是因为你想强制闪光,这与你无关。