Java 使用Camera2 API的相机变焦设置

Java 使用Camera2 API的相机变焦设置,java,android,android-camera2,Java,Android,Android Camera2,我正在尝试使用新的Camera2 API访问相机设置并应用变焦。 在旧的不推荐使用的Camera API中,代码如下所示: Camera.Parameters parameters = mCamera.getParameters(); parameters.setZoom(zoomValue); mCamera.setParameters(parameters); 考虑到CameraManager,我们如何实现同样的目标 是用来打开相机的吗 CameraManager.openCamera(c

我正在尝试使用新的Camera2 API访问相机设置并应用变焦。 在旧的不推荐使用的Camera API中,代码如下所示:

Camera.Parameters parameters = mCamera.getParameters();
parameters.setZoom(zoomValue);
mCamera.setParameters(parameters);
考虑到CameraManager,我们如何实现同样的目标 是用来打开相机的吗

CameraManager.openCamera(cameraId, stateCallback, backgroundHandler);

使用下一个代码。使用目标调用setZoom,以便在需要时使用预览或图片装订生成器

使用maxZoom获取用户界面计算缩放范围的阈值。 缩放范围将始终在默认缩放系数最大缩放之间

调用setZoom后,要激活新的缩放,您仍然需要通过重复请求将其发送到当前缩放

用于计算新缩放因子的代码段:

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

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

    public final float maxZoom;

    @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 setZoom(@NonNull final CaptureRequest.Builder builder, final float zoom)
    {
        if (this.hasSupport == false)
        {
            return;
        }

        final float newZoom = MathUtils.clamp(zoom, 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()) / newZoom);
        final int deltaY  = (int)((0.5f * this.mSensorSize.height()) / newZoom);

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

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

使用下一个代码。使用目标调用setZoom,以便在需要时使用预览或图片装订生成器

使用maxZoom获取用户界面计算缩放范围的阈值。 缩放范围将始终在默认缩放系数最大缩放之间

调用setZoom后,要激活新的缩放,您仍然需要通过重复请求将其发送到当前缩放

用于计算新缩放因子的代码段:

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

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

    public final float maxZoom;

    @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 setZoom(@NonNull final CaptureRequest.Builder builder, final float zoom)
    {
        if (this.hasSupport == false)
        {
            return;
        }

        final float newZoom = MathUtils.clamp(zoom, 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()) / newZoom);
        final int deltaY  = (int)((0.5f * this.mSensorSize.height()) / newZoom);

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

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

因为PerraCollabs@已经提到了如何使用api,所以我将尝试解释范式转换

在camera1 API中,缩放是一种简单的中心裁剪缩放,如下所示:

正如您所看到的,api只是简单地裁剪到帧的中心,并将结果缩放到屏幕上。Android就是这样定义应用程序和供应商HALAPI的。供应商HAL只需获取缩放级别并自行计算裁剪值,而android框架只需将缩放值传递给摄像头HAL

在Camera2 api中,这更灵活,因为您可以裁剪帧的任何部分,然后进行缩放。因此,基本上使用camera2 api是可能的:

观察内部矩形如何不居中。这无法使用camera1 api完成


虽然这对应用程序开发人员来说是一个很好的灵活性,但我认为android也可以为camera2 CaptureRequest中的直接用例提供camera1等效密钥。

既然PerraCollabs@已经提到了如何使用api,我将试着解释范式转换

在camera1 API中,缩放是一种简单的中心裁剪缩放,如下所示:

正如您所看到的,api只是简单地裁剪到帧的中心,并将结果缩放到屏幕上。Android就是这样定义应用程序和供应商HALAPI的。供应商HAL只需获取缩放级别并自行计算裁剪值,而android框架只需将缩放值传递给摄像头HAL

在Camera2 api中,这更灵活,因为您可以裁剪帧的任何部分,然后进行缩放。因此,基本上使用camera2 api是可能的:

观察内部矩形如何不居中。这无法使用camera1 api完成


虽然这对应用程序开发人员来说是一个很好的灵活性,但我认为android也可以为camera2 CaptureRequest中的直接用例提供camera1等效密钥。

这很好,但如果我理解正确,没有一种直接的方法可以访问相机上的缩放规格并在不操纵视图的情况下进行更改。对于camera2,范例不同,这不是视图操纵,而是更改缩放的直接方法。在旧的API中,setZoom只是一个易于使用的方法,内部可能也在做类似的事情。感谢您的澄清,您确定
characteristics.get(CameraCharacteristics.SCALER\u AVAILABLE\u MAX\u DIGITAL\u ZOOM)
可以为空吗?文档中没有这样的信息,所以我认为它不能为null…@user25,characteristics.get方法返回值可以为null,请检查源代码。因此,无论特定请求是否可以返回null,您都有两个选项:1)检查可为null,2)或添加lint ignore语句以停止null lint警告。随你。如果你可以接受空警告,那么就不需要在这个特定的标志中检查空。这很好,但如果我理解正确,没有直接的方法可以访问相机上的缩放规格并在不操纵视图的情况下更改它。对于camera2,范例是不同的,这不是视图操纵,而是更改缩放的直接方法。在旧的API中,setZoom只是一个易于使用的方法,内部可能也在做类似的事情。感谢您的澄清,您确定
characteristics.get(CameraCharacteristics.SCALER\u AVAILABLE\u MAX\u DIGITAL\u ZOOM)
可以为空吗?文档中没有这样的信息,所以我认为它不能为null…@user25,characteristics.get方法返回值可以为null,请检查源代码。因此,无论特定请求是否可以返回null,您都有两个选项:1)检查可为null,2)或添加lint ignore语句以停止null lint警告。随你。如果您可以接受空警告,则不需要检查此特定标志中的空。