最近公司要求在原有的项目中添加一个扫码登录的功能,在调试好相机之后,发现相机返回到Surfaceview页面上的预览图片,与我们现实中物品的比例并不相同,在一块正方形的Surfaceview中,预览界面的物品,也都会被压缩成正方形比例。为解决这一问题,经过在网上的不断的查找,找到一篇很实用的博客。android Camera预览界面拉伸问题解决_雨幕青山的博客-CSDN博客

问题原因分析:

在手机上看到的预览页面被拉伸或是被压缩,是由于surfaceview的宽高比例和camera preview的宽高比例不一样才会产生这样的效果,所以我们得出结论,要想surfaceview的页面保持正常,就需要surfaceview的尺寸比例跟预览的尺寸比例相同。

解决方式:

因为我们的项目是基于开源的ZXing 项目,来实现相机扫描的,所以需要修改ZXing中的代码。

在相机参数设置步骤中,有两个方法的调用,一个是初始化相机参数initFromCameraParameters和设置相机参数的方法setDesiredCameraParameters

  /*** Opens the camera driver and initializes the hardware parameters.** @param holder The surface object which the camera will draw preview frames*               into.* @throws IOException Indicates the camera driver failed to open.*/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);// FIXME// SharedPreferences prefs =// PreferenceManager.getDefaultSharedPreferences(context);// �Ƿ�ʹ��ǰ��// if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false))// {// FlashlightManager.enableFlashlight();// }FlashlightManager.enableFlashlight();}}

在setDesiredCameraParameters方法中有一段代码,是设置相机预览界面的分辨率的。

parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);

而cameraResolution的参数是从initFromCameraParameters()中获取的

    /*** Reads, one time, values from the camera that are needed by the app.*/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);}

所以我们改变cameraResolution就可以改变预览的分辨率,在上述代码中,我们可以看出cameraResolution的值是通过getOptimalPreviewSize(parameters, screenResolution)获取的。所以修改getOptimalPreviewSize方法

private static Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {String previewSizeValueString = parameters.get("preview-size-values");// saw this on Xperiaif (previewSizeValueString == null) {previewSizeValueString = parameters.get("preview-size-value");}Point cameraResolution = null;if (previewSizeValueString != null) {Log.d(TAG, "preview-size-values parameter: " + previewSizeValueString);
//            cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();//获取所有支持的camera尺寸cameraResolution = getOptimalPreviewSize(true, sizeList, screenResolution.x, screenResolution.y);//获取一个最为适配的屏幕尺寸}if (cameraResolution == null) {// Ensure that the camera resolution is a multiple of 8, as the screen may not be.cameraResolution = new Point((screenResolution.x >> 3) << 3,(screenResolution.y >> 3) << 3);}return cameraResolution;}

在上述代码中与源代码不同的是,修改了一行代码,将

cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);

修改为

List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
cameraResolution = getOptimalPreviewSize(true, sizeList, screenResolution.x, screenResolution.y);

然后根据getOptimalPreviewSize,通过对比得到与宽高比最接近的预览尺度

    /*** 通过对比得到与宽高比最接近的预览尺寸(如果有相同尺寸,优先选择)** @param isPortrait 是否竖屏* @param surfaceWidth 需要被进行对比的原宽* @param surfaceHeight 需要被进行对比的原高* @param preSizeList 需要对比的预览尺寸列表* @return 得到与原宽高比例最接近的尺寸*/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;}//先查找preview中是否存在与surfaceview相同宽高的尺寸for(Camera.Size size : preSizeList){if((size.width == reqTmpWidth) && (size.height == reqTmpHeight)){return new Point(size.width, size.height);}}// 得到与传入的宽高比最接近的sizefloat 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);}

Android相机预览页面被压缩和拉伸问题相关推荐

  1. android 预览和拍照成像方向不一致,Android相机预览方向深入探究

    原标题:Android相机预览方向深入探究 今日快讯 9月7日,北京市交通委召集各区管理部门和15家共享自行车企业负责人,听取共享自行车投放和管理的意见建议,研究决定并下发通知,暂停在本市新增投放共享 ...

  2. Android相机预览设置适配及显示方式

    Android相机的部分工作原理. 预览流程 相机预览是Android Camera最常用的功能之一,它是很多功能重要的输入,例如扫码.AR等. 一般而言,相机预览的整体流程,可以通过下图表示: 其中 ...

  3. Android相机预览方向

    以前对Camera了解的不是太深入,最近有需求把人脸识别 集成到项目,必然会与Camera打交道,遇到一些坑,与大家分享一下. 一.预览方向   Camera.CameraInfo info = ne ...

  4. Android 相机预览 横屏竖屏 -- 显示

    相机在设备上处于固定位置,无论设备是否 是手机.平板电脑或计算机.当设备方向更改时, 相机方向更改.常见的布局显示比率是 4:3. 对于前置摄像头,图像缓冲区逆时针旋转(从 传感器的自然方向) 对于后 ...

  5. Android 相机方向传感,Nexus 5x反向横向传感器修复在Android相机预览...

    我是Android开发中的新手,所以如果我的问题很简单,我会提前道歉.在我的应用程序的一部分,我需要我的后置摄像头的实时预览,所以我创建了一个自定义类,扩展SurfaceView并实现SurfaceH ...

  6. 2022-07-21 Android 相机预览数据转Bitmap优化

    背景 在Android开发中我们有时候会需要拿到相机预览数据转成bitmap自己做处理. 常用方式 在Android API中提供了 一套转换方式: private Bitmap convertBit ...

  7. Android相机预览,指定区域显示预览框,在区域内出现人脸进行人脸识别,并抓拍人脸照片存在本地,CameraX,虹软人脸识别

    效果图: 第一种是使用camerax进行预览,android camerax预览官方文档,主要通过imageAnalysis,抓帧进行图片处理,然后通过android自带的图片人脸识别FaceDete ...

  8. android相机预览拍照功能实现

    代码目录结构 LAUNCHER activity:CameraActivity : onCreate()方法中创建Camera工具类CameraHelper的实例并初始化: mCameraHelper ...

  9. CameraView Android 相机预览控件

    Github地址:https://github.com/google/cameraview 该控件为Google开源,非官方,只为了开发人员轻松集成Camera功能. 混淆: 发布release版本时 ...

最新文章

  1. 案例 | 杭州佰勤医疗器械:智办事助力企业组织数字化转型
  2. 【阿里云OSS】OSS概述
  3. cnsul linux环境后台启动_Redis安装和配置(Windows和Linux)
  4. 园区交换网络和路由网络综合设计,测试完工啦
  5. 计算机应用基础18春在线作业1答案,东师计算机应用基础-18春在线作业1.docx
  6. 为什么很多企业都喜欢鹅厂出来的产品经理?
  7. NAT网络映射设置:允许局域网用户访问VMWare内linux的SSH
  8. Unity3D实习生面试题总结-图形学相关
  9. Atitit. Ati IDE 开发平台的第一版规划
  10. Access数据库的模糊查询
  11. 发那科机器人编程软件fanuc roboguide授权补丁_工业机器人离线编程与应用:ROBOGUIDE V8.3版本的工程文件创建...
  12. 计算机网络科研项目申请书,科研项目申请书范文例.doc
  13. 中国个人企业征信体系介绍
  14. 医疗物联网七大应用场景案例解析
  15. idea复制代码空格报错
  16. 滴滴2018秋招编程题
  17. python运维小工具_Python实现跨平台运维小神器
  18. Kvaser Android驱动程序已经在许多应用程序中得到了成功的应用
  19. 中国原盐产业发展现状分析,原盐主要应用于化工行业「图」
  20. 神经网络计算也称神经网络或神经计算

热门文章

  1. 【Python】股票价格与交易量分析代码
  2. 阅读笔记 |《上帝掷骰子吗:量子物理史话》曹天元
  3. (附源码)计算机毕业设计SSM旅游推广系统
  4. 云计算基础概念——Iaas、PaaS、SaaS
  5. 设置谷歌浏览器安全级别
  6. 五个了解自己天赋优势的分析工具(一)霍兰德兴趣测试
  7. Redis 内存分析神器
  8. 模式识别算法之2--感知器(感知机)算法
  9. VOS客户端动态黑名单功能配置详解
  10. Cathy学习Java——GUI与正则表达式