问题现象
项目中的扫一扫界面打开以后,扫描二维码的界面显示的二维码被拉伸,图片如下:
问题原因
通常,拍照预览页面的视图拉伸主要与下面两个因素有关:
- Surfaceview的大小
- Camera中的Preview的大小
如果手机surfaceview大小为比例为16:9,而预览尺寸大小为比例为4:3,从上面的二维码可以看到明显的拉伸。正因为surfaceview的宽高比例跟camera preview的宽高比例不一样才会产生这样的效果。如果surfaceview尺寸比例跟预览尺寸比例相同,那便不会产生变形。由此可以得出结论:
- 1.手机surfaceview与默认的camera preview的宽高比不一致
- 2.camera preview的宽高比设置不正确
解决方法
然后道长翻找ZXing的代码(具体版本可能非常老了),找到如下一段代码:
public void openDriver(SurfaceHolder holder) throws IOException {
if (camera == null) {
camera = Camera.open();
if (camera == null) {
throw new IOException();
}
camera.setPreviewDisplay(holder);
if (!initialized) {
initialized = true;
configManager.initFromCameraParameters(camera);
}
configManager.setDesiredCameraParameters(camera);
FlashlightManager.enableFlashlight();
}
}
其中有两个方法调用,一个是初始化相机参数的initFromCameraParameters()和设置相机参数的setDesiredCameraParameters()。然后我发现在设置相机参数的方法中已经设置对应的parameters,setDesiredCameraParameters()代码如下:
void setDesiredCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
Log.d(TAG, "Setting preview size: " + cameraResolution);
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
setFlash(parameters);
setZoom(parameters);
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
}
在上面的代码中,这一行代码便是设置相机预览界面的分辨率的。
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
然后在初始化相机参数的方法initFromCameraParameters()中获取了cameraResolution这个参数的值,代码如下:
void initFromCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
previewFormat = parameters.getPreviewFormat();
previewFormatString = parameters.get("preview-format");
Log.d(TAG, "Default preview format: " + previewFormat + '/' + previewFormatString);
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
screenResolution = new Point(display.getWidth(), display.getHeight());
Log.d(TAG, "Screen resolution: " + screenResolution);
cameraResolution = getCameraResolution(parameters, screenResolution);
Log.d(TAG, "Camera resolution: " + screenResolution);
}
然后把上面代码中getCameraResolution()方法改为了网上以为老哥的方法,代码如下:
private static Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {
String previewSizeValueString = parameters.get("preview-size-values");
if (previewSizeValueString == null) {
previewSizeValueString = parameters.get("preview-size-value");
}
Point cameraResolution = null;
if (previewSizeValueString != null) {
Log.d(TAG, "preview-size-values parameter: " + previewSizeValueString);
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
cameraResolution = getOptimalPreviewSize(true, sizeList, screenResolution.x, screenResolution.y);
}
if (cameraResolution == null) {
cameraResolution = new Point(
(screenResolution.x >> 3) << 3,
(screenResolution.y >> 3) << 3);
}
return cameraResolution;
}
public static Point getOptimalPreviewSize(boolean isPortrait, List<Camera.Size> preSizeList, int surfaceWidth, int surfaceHeight) {
int reqTmpWidth;
int reqTmpHeight;
if (isPortrait) {
reqTmpWidth = surfaceHeight;
reqTmpHeight = surfaceWidth;
} else {
reqTmpWidth = surfaceWidth;
reqTmpHeight = surfaceHeight;
}
for(Camera.Size size : preSizeList){
if((size.width == reqTmpWidth) && (size.height == reqTmpHeight)){
return new Point(size.width, size.height);
}
}
float reqRatio = ((float) reqTmpWidth) / reqTmpHeight;
float curRatio, deltaRatio;
float deltaRatioMin = Float.MAX_VALUE;
Camera.Size retSize = null;
for (Camera.Size size : preSizeList) {
curRatio = ((float) size.width) / size.height;
deltaRatio = Math.abs(reqRatio - curRatio);
if (deltaRatio < deltaRatioMin) {
deltaRatioMin = deltaRatio;
retSize = size;
}
}
return new Point(retSize.width, retSize.height);
}
到此,道长已经解决了Camera预览界面拉伸的问题,希望这篇博客对你有所帮助。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)