Camera2实现相机缩放实现

前言

首先看这篇文章之前,要搞懂Captrue的重复模式的基本概念,才会比较好入手。

关键代码

其实相机的缩放最主要的代码并不多,说白了也就是三行代码。

float maxZoom = mCameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
Rect rect = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
mPreviewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomRect);

第一行代码是获取相机设备最大能聚焦的数值,第二行代码是获取相机显示捕获光线的区域,简单来说就是自定义相机的预览画面大小。而第三行这是最核心的代码,第一条与第二条代码都是为了求出zoomRect而服务使用的。zoomRect代表的是缩放后的显示捕获光线的区域。我们只要求出zoomRect便能实现缩放功能。

代码实现

首先我们观察自己手机的相机,采取的是监听触摸两指的缩放进行焦距的调整,我们可以模仿其做一个,首先我们可以监听一下触摸事件。我采用的是fragment,直接在createview上进行监听。

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView: success");
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_take_photo, container, false);
        initView(view);
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                if (event.getPointerCount() == 2) {
                    //表示检测到两个触摸点的时候,执行操作
                    switch (event.getAction() & MotionEvent.ACTION_MASK) {
                        case MotionEvent.ACTION_POINTER_DOWN:
                            //按下的时候,记录原本的位置
                            float x = event.getX(0) - event.getX(1);
                            float y = event.getY(0) - event.getY(1);
                            oldlength = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
                            break;
                        case MotionEvent.ACTION_MOVE:
                            //移动的时候
                            float newx = event.getX(0) - event.getX(1);
                            float newy = event.getY(0) - event.getY(1);
                            double newlength = Math.sqrt(Math.pow(newx, 2) + Math.pow(newy, 2));
                            System.out.println("对比一下");
                            System.out.println(oldlength+":"+newlength);

                            if (newlength >= oldlength) {
                                //放大操作
                                previewZoom(true);
                            } else {
                                //缩小操作
                                previewZoom(false);
                            }
                            break;
                    }
                }
                return true;
            }
        });
        textureView.setSurfaceTextureListener(textureListener);
        //动态授权
        getPermission();
        isCreated = true;
        return view;
    }

上述代码主要是实现了监听作用,具体的缩放操作还是在previewZoom方法中进行实现。

private final int MAX_ZOOM = 100; // 放大的最大值,用于计算每次放大/缩小操作改变的大小
private int mZoom = 0; // 缩放
private float mStepWidth; // 每次改变的宽度大小
private float mStepHeight; // 每次改变的高度大小

// 每次切换摄像头计算一次就行,结果缓存到成员变量中
private void initZoomParameter() {
    Rect rect = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
    Log.d(TAG, "sensor_info_active_array_size: " + rect);
    // max_digital_zoom 表示 active_rect 除以 crop_rect 的最大值
    float max_digital_zoom = mCameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
    Log.d(TAG, "max_digital_zoom: " + max_digital_zoom);
    // crop_rect的最小宽高
    float minWidth = rect.width() / max_digital_zoom;
    float minHeight = rect.height() / max_digital_zoom;
    // 因为缩放时两边都要变化,所以要除以2
    mStepWidth = (rect.width() - minWidth) / MAX_ZOOM / 2;
    mStepHeight = (rect.height() - minHeight) / MAX_ZOOM / 2;
}

public void handleZoom(boolean isZoomIn) {
    if (mCameraDevice == null || mCameraCharacteristics == null || mPreviewRequestBuilder == null) {
        return;
    }
    if (isZoomIn && mZoom < MAX_ZOOM) { // 放大
        mZoom++;
    } else if (mZoom > 0) { // 缩小
        mZoom--;
    }
    Log.v(TAG, "handleZoom: mZoom: " + mZoom);
    Rect rect = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
    int cropW = (int) (mStepWidth * mZoom);
    int cropH = (int) (mStepHeight * mZoom);
    Rect zoomRect = new Rect(rect.left + cropW, rect.top + cropH, rect.right - cropW, rect.bottom - cropH);
    Log.d(TAG, "zoomRect: " + zoomRect);
    mPreviewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoomRect);
    startPreview(); // 需要重新 start preview 才能生效
}

接下来我将对代码中的一些点进行一个讲解。我们在缩放之前还需要计算出每次缩放的步长,而 initZoomParameter方法很明显就是实现这个功能的。可能大部分对最后计算mStepWidth、mStepHeight存在疑问,为什么要减去最小的宽高,为什么要除以2,这些其实画出画的话会好理解很多。

 其他的应该没有什么特别难理解的了,实现的过程牢记重复模式的一些点便可以实现。同样的道理,实现录像缩放,拍照缩放便可以解决。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值