全面屏 android 自定义相机 显示拉伸处理

我们公司的相机是自定义的相机。在一些全面屏上有一些显示拉伸的问题。出现问题的手机有三星s8,华为mate10,并且系统是8.0的。我手机是s8,在升级8.0前确认是没有问题的,升级了8.0后拍照和扫描二维码出现了显示的图像变扁的问题。当时还以为是系统的bug。一看果然,刚升级8.0没几天,三星就由发布了一个8.0的补丁,里面的内容有修复相机bug的字样。当时还是比较开心的,以为跟新完就没事了,结果更新完后,没卵用。。。。。在打开微信的相机和扫一扫发现他们的没问题。就觉得他们应该处理过这个问题。

解决这个问题要先明白几个地方:

1. Camera.Params 的setPreviewSize方法和 setPictureSize方法

这俩个方法参数都是Size,并且这俩个size最好一致,不然就会有图像拉伸的问题。而这个size也不能自己想一个数来设置,必须获取系统支持的并且合适的值。查看系统支持的size的方法是:

Params.getSupportedPictureSizes()

Params.getSupportedPreviewSizes()

我的手机是s8他支持的对应的size如下:

05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface:  =============================================================================
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width4032   height:3024
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width4032   height:2268
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width3984   height:2988
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width3264   height:2448
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width3264   height:1836
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width3024   height:3024
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width2976   height:2976
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width2880   height:2160
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width2560   height:1920
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width2560   height:1440
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width2160   height:2160
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width2048   height:1152
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width1920   height:1080
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width1440   height:1080
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width1280   height:960
05-08 15:00:18.836 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width1280   height:720
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PictureSizes: width640   height:480
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface:  =============================================================================
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:1920    height:1080
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:1440    height:1080
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:1088    height:1088
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:1280    height:720
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:960    height:720
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:720    height:720
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:720    height:480
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:640    height:480
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:352    height:288
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:320    height:240
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: PreviewSizes: width:176    height:144
05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface:  =============================================================================

既然不能瞎写,哪我们怎么去找一个合适的size呢?这还要个问题要注意,返回的数据有可能是正序的也有可能是倒序的。为了方便处理我们要先对其进行排序。并且,因为默认摄像头方向是水平的,我们在使用的时候要旋转90度,所以这里的width实际上是高度,heigth实际上是宽度,下面给出选择方法:

  /**
     * 获取pictureSize的合适值
     * @param list      size集合
     * @param th        设置的最小宽度
     * @param rate      传入的宽高比
     * @return
     */
    public Camera.Size getPictureSize(List<Camera.Size> list, int th, float rate) {
        Collections.sort(list, sizeComparator);   //统一以升序的方式排列
        int i = 0;
        for (Camera.Size s : list) {
            if ((s.width > th) && equalRate(s, rate)) {        //合适参数的判断条件, 大于我们传入的最小高度且宽高比的差值不能超过0.2
                Log.i(TAG, "MakeSure Picture :w = " + s.width + " h = " + s.height);
                break;
            }
            i++;                                //拿到最合适的参数
        }
        if (i == list.size()) {                 //如果到最后也没有找到合适的,哪么就放宽条件去找
            return getBestSize(list, rate);
        } else {
            return list.get(i);                 //返回找到的合适size
        }
    }

    /**
     * 遍历所有的size,找到和传入的宽高比的差值最小的一个
     * @param list
     * @param rate
     * @return
     */
    private Camera.Size getBestSize(List<Camera.Size> list, float rate) {
        float previewDisparity = 100;
        int index = 0;
        for (int i = 0; i < list.size(); i++) {
            Camera.Size cur = list.get(i);
            float prop = (float) cur.width / (float) cur.height;
            if (Math.abs(rate - prop) < previewDisparity) {
                previewDisparity = Math.abs(rate - prop);
                index = i;
            }
        }
        return list.get(index);
    }


    private boolean equalRate(Camera.Size s, float rate) {
        float r = (float) (s.width) / (float) (s.height);
        return Math.abs(r - rate) <= 0.2;   //传入的宽高比和size的宽高比的差不能大于0.2,要尽量的和传入的宽高比相同
    }

    private class CameraSizeComparator implements Comparator<Camera.Size> {
        public int compare(Camera.Size lhs, Camera.Size rhs) {
            if (lhs.width == rhs.width) {
                return 0;
            } else if (lhs.width > rhs.width) {
                return 1;
            } else {
                return -1;
            }
        }

    }

获取previewSize的方法一样。

2.那么在显示的时候要保证pictureSize和previewSize尽量保证一样,然后相机的预览界面也要保证尽量和这俩个size一样。我获取的合适的pictureSize和previewSize如下:

05-08 15:00:18.837 8451-8574/com.example.wangxu.testcream I/CameraInterface: suitable:picture_width:1280  picture_height:720   preview_width:1280   preview_height:720

可以发现显示是一样的,那么我设置的预览界面有多大了?

05-08 15:49:23.349 28180-28180/com.example.wangxu.testcream I/JCameraView: screenSize: width:1665.0    height:2960.0

那么他们的比值了?

1280/720 = 1.7777

2960/1665 = 2.0

这。。。将宽高比1.7的的图片显示在宽高比2.0的布局里面,所以被拉伸了。所以我们要做的就是缩放布局,让他的宽高比也到1.7就好。这里就是缩放预览控件的方法:

 private void setSuitableParams() {
        if (screenProp > 1.8) { //屏幕的宽高比大于1.8的时候处理
            float previewProp = CameraInterface.getInstance().getPreviewProp();
            if (previewProp == 0 || mVideoView == null) {   //获取的size宽高比
                return;
            }
            int measuredHeight = mVideoView.getMeasuredHeight();
            int measuredWidth = mVideoView.getMeasuredWidth();
            float clacWidth = measuredHeight / previewProp;   //计算出要显示的预览界面的宽度。
            ViewGroup.LayoutParams layoutParams = mVideoView.getLayoutParams();
            if (layoutParams == null) {
                layoutParams = new ViewGroup.LayoutParams((int) clacWidth, measuredHeight);
            }
            if (clacWidth > 800 && Math.abs(clacWidth - measuredWidth) > clacWidth * 0.1F) {  //计算的宽度大于 800 并且和显示正常的布局的误差超过10%
                layoutParams.width = (int) clacWidth;
            }
            final ViewGroup.LayoutParams finalLayoutParams = layoutParams;
            mVideoView.post(new Runnable() {
                @Override
                public void run() {
                    if (mVideoView != null && finalLayoutParams != null) {
                        mVideoView.setLayoutParams(finalLayoutParams);
                    }
                }
            });
        }
    }
需要注意的是,因为我们将预览的布局进行了宽度的方大(全面屏是高度相对于宽度变大了),所以有部分宽度是在屏幕外面了,我们实际拍摄的图片的宽度大于预览界面上图片的宽度。


最后,为啥在8.0以下全面屏没事了。到底8.0对于相机做了啥,还不知道,如果有知道的小伙伴希望告知下。



猜你喜欢

转载自blog.csdn.net/u012674854/article/details/80239371
今日推荐