使用 camera2 时获取当前缩放值

Get current zoom value when using camera2

使用 Legacy Camera API (android.hardware.Camera) 我可以使用下一行获取当前缩放级别

Camera.Parameters p = mCamera.getParameters();
int zoom = p.getZoomRatios().get(p.getZoom());

如何使用 Camera2 API (android.hardware.camera2)?

CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
...

我发现了解当前缩放的最简单方法实际上是在每次更改时跟踪它。

下一个缩放控制器可用于计算新缩放和获取当前缩放,这实际上只是传递给 .set() 方法的缓存值:

public final class Zoom
{
    private static final float DEFAULT_ZOOM_FACTOR = 1.0f;

    @NonNull
    private final Rect mCropRegion = new Rect();

    public final float maxZoom;

    private float mCurrentZoomFactor = Zoom.DEFAULT_ZOOM_FACTOR;

    @Nullable
    private final Rect mSensorSize;

    public final boolean hasSupport;

    public Zoom(@NonNull final CameraCharacteristics characteristics)
    {
        this.mSensorSize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);

        if (this.mSensorSize == null)
        {
            this.maxZoom = Zoom.DEFAULT_ZOOM_FACTOR;
            this.hasSupport = false;
            return;
        }

        final Float value = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);

        this.maxZoom = ((value == null) || (value < Zoom.DEFAULT_ZOOM_FACTOR))
                ? Zoom.DEFAULT_ZOOM_FACTOR
                : value;

        this.hasSupport = (Float.compare(this.maxZoom, Zoom.DEFAULT_ZOOM_FACTOR) > 0);
    }

    public void set(@NonNull final CaptureRequest.Builder builder, final float newZoom)
    {
        if (this.hasSupport == false)
        {
            return;
        }

        this.mCurrentZoomFactor = MathUtils.clamp(newZoom, Zoom.DEFAULT_ZOOM_FACTOR, this.maxZoom);

        final int centerX = this.mSensorSize.width() / 2;
        final int centerY = this.mSensorSize.height() / 2;
        final int deltaX  = (int)((0.5f * this.mSensorSize.width()) / this.mCurrentZoomFactor);
        final int deltaY  = (int)((0.5f * this.mSensorSize.height()) / this.mCurrentZoomFactor);

        this.mCropRegion.set(centerX - deltaX,
                centerY - deltaY,
                centerX + deltaX,
                centerY + deltaY);

        builder.set(CaptureRequest.SCALER_CROP_REGION, this.mCropRegion);
    }

    public float get()
    {
        return this.mCurrentZoomFactor;
    }
}

调用 zoom.set(...) 后,使用下一个代码段将新的缩放系数提交到活动相机会话中并使其生效。需要为活动预览会话完成,然后在拍摄照片时的捕获会话:

yourCameraSession.setRepeatingRequest(builder.build(), yourPreviewOrCaptureSessionCallback, yourCameraThreadHandler);