camera拍照预览界面图像拉伸处理,通过改变显示窗口大小来适配摄像头预览尺寸

1.前言
显示框口的控件:SurfaceView。
控件尺寸比例: 1:1(正方形的尺寸比较适合人脸识别)
显示窗口大小:非全屏
2.拉伸原因
camera预览尺寸是从厂商list读取的

Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();//获取预览的各种分辨率

获取最佳尺寸(google developer的源码)

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio;
    if (w > h) {
        targetRatio = (double) w / h;  /* w / h : 横向   h / w :竖向*/
    } else {
        targetRatio = (double) h / w;  /* w / h : 横向   h / w :竖向*/
    }
    if (sizes == null) return null;

    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    for (Camera.Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Camera.Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    Log.e(TAG, "finally choose size:optimalSize width=" + optimalSize.width + "   optimalSize height=" + optimalSize.height);
    return optimalSize;

}

完全是调用google的源码,并没有做改变。
那么如果,读取出来的list中,所有尺寸的宽高比都不满足我们的窗口会发生什么?
当然是预览界面的形变,比例不满足,则选出来的尺寸可能与我们预想的出入比较大,比如:
我们预览窗口的大小是:800×800,选择的camera预览尺寸是:1280×720,比窗口尺寸大则压缩,小则拉伸,来补满不足的像素点。
3.解决方案,动态改变窗口大小来适配camera预览尺寸。
还是以上述尺寸为例,正方形的预览窗口,在部分手机上没有获取到1:1的尺寸。
这时候需要调节一下自己的窗口比例,如果不希望与原来窗口大小的差异过大,则选择4:3比例(具体情况还需要根据自己的project来确定)。
800×800的窗口,调节后,为800×600

private boolean surfaceChanged = true;

定义一个全局变量来控制surfaceView是否需要调整,如果不需要则不用添加,但是要注意,这里会隐形调用surfaceChanged,如果在SurfaceView的重写方法中,有调用一下调整的方法,则必须要,否则会死循环。

double ratioSurface = (double) surfaceView.getWidth() / (double) surfaceView.getHeight();
double ratioCamera = (double) optionSize.width / (double) optionSize.height;
Log.v(TAG, "ratioSurface:" + ratioSurface + "    ratioCamera:" + ratioCamera);
if (surfaceChanged && ratioCamera != ratioSurface) {
   RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(600, 800);//这里根据自己的需要,是竖屏还是横屏,我们是竖屏,所以选择了宽高对换了一下。
   layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);//这一行是让控件在父控件完全居中
   surfaceView.setLayoutParams(layoutParams);
   surfaceChanged = false;
}

以上代码添加在什么位置呢?

 mCamera.setParameters(parameters);

在参数设置以前就可以。
4.可能遇到的问题
A.画面旋转:
这种情况下需要自己手动去调整摄像头

PS:由于这是在项目中解决问题时写的,就不方便上传源码了,不过源码估计可移植性不强。
感谢光临。

    原文作者:不会写代码的猴子
    原文地址: https://blog.csdn.net/mozushixin_1/article/details/93997938
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞