Android Camera聚焦区域和测光区域的设置

   

先盗图一张(来自安卓官网),如图所示,无论屏幕是横屏竖屏,预览视图的中心点坐标一直都是(0,0),四个角的坐标也都固定如图所示,不会因为横竖屏而发生变化。从这张图可以看出:

        1:聚焦以及测光的坐标和手指触摸的屏幕真实坐标所选坐标系是不同的,它的值在(-1000,1000)之间变化。

        2:我们触摸到的是一个点,而聚焦及测光需要反馈给相机的是一个区域,所以就要以触摸点为中心来合理的选择一个区域。

    另外要提到的一点是,聚焦及测光是相对独立的两个参数,可以设置不同区域,不仅如此,测光还可以同时选择多个区域,通过权重来分配这些区域的测光比重。

    既然聚焦、测光与我们的手指在屏幕上的触摸点用的不是同一个坐标系,那就得通过一定方法来转化坐标,首先要做的是,给我们的预览VIEW设置onTouch事件,获取手指抬起时的坐标位置。之后将这个坐标按上图进行坐标系转换,并以转换后的坐标点为中心扩展一个合适的矩形区域,然后将这个区域传给对应的相机参数,返回给相机即可。核心代码如下(注意我的是固定竖屏,即AndroidManifest该页面方向设置为portrait,横屏时对于同一点获取到的点击坐标与此不同,但是聚焦以及测光的坐标横竖屏保持一致):

      

/**
     * 清除自动对焦
     */
    private static void clearCameraFocus() {
        camera.cancelAutoFocus();
        parameters = camera.getParameters();
        parameters.setFocusAreas(null);
        parameters.setMeteringAreas(null);
        try {
            camera.setParameters(parameters);
        } catch (Exception e) {
            Log.e(TAG, "failed to set parameters.\n" + e);
        }
    }
        Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1f);
        Rect meteringRect = calculateTapArea(event.getX(), event.getY(), 1f);
        // To start tap focus, should cancel auto focus first.
        List<Camera.Area> mFocusList = new ArrayList<>();
        mFocusList.add(new Camera.Area(focusRect, 1000));
        List<Camera.Area> mMeteringList = new ArrayList<>();
        mMeteringList.add(new Camera.Area(meteringRect, 1000));

        parameters = camera.getParameters();
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        // Setting new camera parameters to indicate focus area.
        if (parameters.getMaxNumFocusAreas() > 0) { // Check if it is safe to set focusArea.
            parameters.setFocusAreas(mFocusList);
        }
        if (parameters.getMaxNumMeteringAreas() > 0) { // Check if it is safe to set meteringArea.
            parameters.setMeteringAreas(mMeteringList);
        }

        camera.setParameters(parameters);
    private static Rect calculateTapArea(float x, float y, float coefficient) {
        int FOCUS_AREA_SIZE = 300;
//        //计算点击坐标点在新的坐标系中的位置
        Log.e(TAG, "focus position : " + x + " : " + y);
        int areaSize = Float.valueOf(FOCUS_AREA_SIZE * coefficient).intValue();
        int left = clamp(Float.valueOf((y / ScreenUtils.getScreenHeight()) * 2000 - 1000).intValue(), areaSize);
        int top = clamp(Float.valueOf(((ScreenUtils.getScreenWidth() - x) / ScreenUtils.getScreenWidth()) * 2000 - 1000).intValue(), areaSize);
        Log.d("CameraFocus", "measure width:" + previewSize.getWidth() + "  measure height:" + previewSize.getHeight());
        Log.d(TAG, "previewArea:" + left + "  " + top + " " + (left + areaSize) + " " + (top + areaSize));
        return new Rect(left, top, left + areaSize, top + areaSize);

    }
/**
     * 确保所选区域在合理范围内,不会超过边界值
     */
    private static int clamp(int touchCoordinateInCameraReper, int focusAreaSize) {
        int result;
        if (Math.abs(touchCoordinateInCameraReper) + focusAreaSize  > 1000) {
            if (touchCoordinateInCameraReper > 0) {
                    result = 1000 - focusAreaSize ;
            } else {
                result = -1000 + focusAreaSize ;
            }
        } else {
            result = touchCoordinateInCameraReper - focusAreaSize / 2;
        }
        return result;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值