Android相机开发中遇到的坑(注意事项)

Android相机开发中遇到的坑(注意事项)

相机预览界面方向的设定

在默认情况下有些相机用户看到的预览界面和真实世界的情况是颠倒的,所以我们需要设定预览界面的方向,如下所示:

    public static int getDisplayRotation(Activity activity) {
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        switch (rotation) {
            case Surface.ROTATION_0:
                return 0;
            case Surface.ROTATION_90:
                return 90;
            case Surface.ROTATION_180:
                return 180;
            case Surface.ROTATION_270:
                return 270;
        }
        return 0;
    }
    public static int getDisplayOrientation(int degrees, int cameraId) {
        // See android.hardware.Camera.setDisplayOrientation for
        // documentation.
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        return result;
    }

最后设定预览界面的方向

mDisplayRotation = CameraUtils.getDisplayRotation(mActivity);
mDisplayOrientation = CameraUtils.getDisplayOrientation(mDisplayRotation, mCameraId);
mCameraDevice.setDisplayOrientation(mDisplayOrientation);

相片方向的设定

由于得到的相片和我们用户使用手机的方向有关,例如用户竖着拍照,那么得到的应该也是竖着的图片,所以我们监听手机方向的变化。如下

private MyOrientationEventListener mOrientationListener;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mOrientationListener = new MyOrientationEventListener(this);

    }

    @Override
    public void onPause() {
        mOrientationListener.disable();
        super.onPause();
    }


    @Override
    public void onResume() {
        mOrientationListener.enable();
        super.onResume();
    }

    private class MyOrientationEventListener
            extends OrientationEventListener {
        public MyOrientationEventListener(Context context) {
            super(context);
        }

        @Override
        public void onOrientationChanged(int orientation) {
            // We keep the last known orientation. So if the user first orient
            // the camera then point the camera to floor or sky, we still have
            // the correct orientation.
            if (orientation == ORIENTATION_UNKNOWN) return;
            KSLog2.KSLog().d("onOrientationChanged = " + orientation);

        }
    }

通过上面的方法我们就可以监听手机的方向,然后我们通过公式来计算在当前手机的方向下应该设定手机真正的方向(0,90,180,270)这几种方向的一种,如下所示:

    // Orientation hysteresis amount used in rounding, in degrees
    public static final int ORIENTATION_HYSTERESIS = 5;
    public static int roundOrientation(int orientation, int orientationHistory) {
        boolean changeOrientation = false;
        if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) {
            changeOrientation = true;
        } else {
            int dist = Math.abs(orientation - orientationHistory);
            dist = Math.min( dist, 360 - dist );
            changeOrientation = ( dist >= 45 + ORIENTATION_HYSTERESIS );
        }
        if (changeOrientation) {
            return ((orientation + 45) / 90 * 90) % 360;
        }
        return orientationHistory;
    }

得到手机真正的方向后,我们就可以计算图片的方向了。如下所以

    /**
     *  获取照片的方向
     * @param cameraId 摄像头ID
     * @param orientation 手机方向
     * @return
     */
    public static int getJpegRotation(int cameraId, int orientation) {
        // See android.hardware.Camera.Parameters.setRotation for
        // documentation.
        int rotation = 0;
        if (orientation != OrientationEventListener.ORIENTATION_UNKNOWN) {
            Camera.CameraInfo info = CameraHolder.instance().getCameraInfo()[cameraId];
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                rotation = (info.orientation - orientation + 360) % 360;
            } else {  // back-facing camera
                rotation = (info.orientation + orientation) % 360;
            }
        }
        return rotation;
    }

最后设定图片的方向

// Set rotation and gps data.
            mJpegRotation = CameraUtils.getJpegRotation(mCameraId, mOrientation);
            mParameters.setRotation(mJpegRotation);
            mParameters.set("rotation", mJpegRotation);
            mCameraDevice.setParameters(mParameters);

预览界面的大小设定

在设定预览界面的时候我们不能任意设定预览界面的大小(会出现异常同时也有可能出现在其他手机不兼容的情况),所以我们应该先查询系统支持的大小,然后通过计算得到最适合的预览界面。如下所示:

    public static Camera.Size getOptimalPreviewSize(Activity activity, List<Camera.Size> sizes) {
        if (sizes == null) return null;
        DeviceInfoUtils.ScreenInfo screenInfo = DeviceInfoUtils.getScreenInfo(activity);
        //这里得到的是surfaceView的长宽比,你们可以根据自己需要计算自己相机surfaceView的长宽比
        final double targetRatio = (screenInfo.width * 1.0f) / (screenInfo.height - activity.getResources().getDimensionPixelOffset(R.dimen.doc_scan_camera_bottom_bar_height));
        Camera.Size optimalSize = null;
        double minRatioDiff = Double.MAX_VALUE;
        double ratio = 0;
        for (Camera.Size size : sizes) {
            if (size.height > size.width) {
                ratio = ((double) (size.width)) / ((double) size.height);
            } else {
                ratio = ((double) (size.height)) / ((double) size.width);
            }
            double temp = Math.abs(targetRatio - ratio);
            if (temp < minRatioDiff && Math.min(size.height, size.width) >= screenInfo.width) {
                optimalSize = size;
                minRatioDiff = temp;
            }
        }
        KSLog2.KSLog().d("preview size width = " + optimalSize.width + " height = " + optimalSize.height + " minRatioDiff= " + minRatioDiff);
        return optimalSize;
    }

设定预览界面的大小

    // Set a preview size that is closest to the viewfinder height and has
        // the right aspect ratio.
        List<Camera.Size> sizes = mParameters.getSupportedPreviewSizes();
        Camera.Size optimalSize = CameraUtils.getOptimalPreviewSize(mActivity, sizes);
        Camera.Size original = mParameters.getPreviewSize();
        if (!original.equals(optimalSize)) {
            mParameters.setPreviewSize(optimalSize.width, optimalSize.height);
        }

总结

在开发相机中需要设定很多参数,其中很多参数都需要查询系统是否支持,然后再去设定系统支持设定中的某一种,例如:图片输出的大小、对焦方式、曝光模式等等,不然容易出现崩溃或者兼容性问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值