最近开发一款自定义相机采集照片的demo,花了一个上午开发了一个在测试机上功能正常的apk连同测试机一起交付(需求方反馈没有Android设备),然而晚上被喊去说是在华为畅玩某型号上预览会变形,拍到的图片边界都移位了,只要加个班处理一下机型适配的问题。根据开发经验,防止预览图像变形的终极奥义就是保持照相机硬件支持的某个size(每个特定的手机都有其支持的camera分辨率)、屏幕宽高比、界面上SurfaceView的宽高比尽量一致,同时保持拍照图与预览图分辨率一致,拍出来的照片就和预览看到的相同。

  下面给出实现代码:

  

    private fun getOptimalPreviewSize(sizes: List<Camera.Size>?, w: Int, h: Int): Camera.Size? {
val ASPECT_TOLERANCE = 0.1
val targetRatio = h.toDouble() / w if (sizes == null) return null var optimalSize: Camera.Size? = null
var minDiff = java.lang.Double.MAX_VALUE for (size in sizes) {
val ratio = size.width.toDouble() / size.height
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size
minDiff = Math.abs(size.height - h).toDouble()
}
} if (optimalSize == null) {
minDiff = java.lang.Double.MAX_VALUE
for (size in sizes) {
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size
minDiff = Math.abs(size.height - h).toDouble()
}
}
}
return optimalSize
}

其中第一个参数sizes是camera支持的预览size列表,第二个是View的宽,第三个是View的高,由于我这里的surfaceview是全屏的,所以传入的宽和高可以是屏幕的宽和高

下面给出完整代码:

    override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_camera)
screenWidth = ScreenUtil.getWindowWidth(this)
screenHeight = ScreenUtil.getWindowHeigh(this)
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK)
surface.holder.addCallback(this)
} override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
camera?.setPreviewDisplay(holder)
camera?.startPreview()
} override fun surfaceDestroyed(holder: SurfaceHolder?) {
} override fun surfaceCreated(holder: SurfaceHolder?) {
if (camera == null) {
camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK)
}
val parameters = camera?.parameters
var sizes = parameters!!.supportedPreviewSizes
var preSize = getOptimalPreviewSize(sizes, screenWidth, screenHeight)
parameters.setPreviewSize(preSize!!.width, preSize.height)
//重新给定surfaceView宽高
surface.resize(preSize.width, preSize.height)
if (parameters.supportedFocusModes!!.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
parameters.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO
}
parameters.sceneMode = Camera.Parameters.SCENE_MODE_AUTO
//保持picturesize与presize一致
parameters.setPictureSize(preSize.width, preSize.height)
parameters.previewFormat = ImageFormat.NV21
camera?.parameters = parameters
camera?.setPreviewDisplay(holder)
camera?.startPreview()
} private fun getOptimalPreviewSize(sizes: List<Camera.Size>?, w: Int, h: Int): Camera.Size? {
val ASPECT_TOLERANCE = 0.1
val targetRatio = h.toDouble() / w if (sizes == null) return null var optimalSize: Camera.Size? = null
var minDiff = java.lang.Double.MAX_VALUE for (size in sizes) {
val ratio = size.width.toDouble() / size.height
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size
minDiff = Math.abs(size.height - h).toDouble()
}
} if (optimalSize == null) {
minDiff = java.lang.Double.MAX_VALUE
for (size in sizes) {
if (Math.abs(size.height - h) < minDiff) {
optimalSize = size
minDiff = Math.abs(size.height - h).toDouble()
}
}
}
return optimalSize
} override fun onWindowFocusChanged(hasFocus: Boolean) {
val decorView = this@CameraActivity.window.decorView
decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
} override fun onPause() {
super.onPause()
camera?.stopPreview()
} override fun onDestroy() {
super.onDestroy()
camera?.setPreviewCallback(null)
camera?.release()
}

Camera 预览变形问题解决的更多相关文章

  1. opencv-android笔记1:android studio 2.3 + opencv-android-sdk 实现 camera预览

    Android studio环境配置不再赘述,可以参照我的其他博客. Android应用程序开发环境搭建:http://blog.csdn.net/ja33son/article/details/61 ...

  2. Android Camera 预览图像被拉伸变形的解决方法【转】

    问题描述: 预览图像被拉伸变形 问题原因: 由于预览图像大小跟SurfaceView 大小不一致引起 解决方法: 获取系统支持的所有预览尺寸[getSupportedPictureSizes],然后再 ...

  3. 圆形Camera预览实现

    需求 最近有个需求要求界面上使用圆形相机预览进行面部检测 , 具体需求如下图 关于Camera之前接触得比较多 , 主要就是通过SurfaceView显示预览视图 , 因此需要展示圆形预览界面, 只需 ...

  4. Android手势识别 Camera 预览界面上显示文字 布局注意事项(merge布局)

    通常在Surfaceview作为预览视频帧的载体,有时需在上面显示提示文字.曾经我弄的都好好的.今天忽然发现叠加的TextView不管咋弄都出不来文字了,跟Surfaceview一起放在FrameLa ...

  5. vue富文本编辑,编辑自动预览,单个图片上传不能预览的问题解决:

    //预览<div class="htmlViewBox"> <p v-html="activity_html_defaultMsg" v-sh ...

  6. android camera 摄像头预览画面变形

    问题:最近在处理一下camera的问题,发现在竖屏时预览图像会变形,而横屏时正常.但有的手机则是横竖屏都会变形. 结果:解决了预览变形的问题,同时支持前后摄像头,预览无变形,拍照生成的jpg照片方向正 ...

  7. 玩转Android Camera开发(四):预览界面四周暗中间亮,仅仅拍摄矩形区域图片(附完整源代码)

    杂家前文曾写过一篇关于仅仅拍摄特定区域图片的demo.仅仅是比較简陋.在坐标的换算上不是非常严谨,并且没有完毕预览界面四周暗中间亮的效果,深以为憾.今天把这个补齐了. 在上代码之前首先交代下,这里面存 ...

  8. Android开发实践:掌握Camera的预览方向和拍照方向

    http://ticktick.blog.51cto.com/823160/1592267?utm_source=tuicool&utm_medium=referral Android的Cam ...

  9. OV5640全景模式预览倒180度,拍照正常的问题

    此方法基本上适用于所有android平台上全景模式预览倒180度,拍照正常的问题. 首先说明的是,影响camera方向的有三个地方,分别是系统方向,内核camera方向和驱动镜像.全景模式预览只跟系统 ...

随机推荐

  1. 通过IP获取所在城市

    <script type="text/javascript"> var map = new BMap.Map("allmap"); var poin ...

  2. php模块组成

    php总共有三个模块:内核.ZEND引擎.扩展. 内核是用来处理请求.文件流.错误处理等操作的: ZEND引擎是将源文件转换成机器语言,然后在虚拟机上运行: 扩展层是一组函数.类库和流,php使用它们 ...

  3. service redis does not support chkconfig 的解决办法

    问题解决办法如下: 必须把下面两行注释放在/etc/init.d/redis文件靠前的注释中(加入以下注释): # chkconfig: # description: Redis is a persi ...

  4. hibernate核心配置

    # hibernate核心配置 注意:  - hibernate.cfg.xml默认放在src目录下(这样可以自动加载该文件) - 必须配置的参数:   * 数据库的四大参数和方言  - 可选配置的参 ...

  5. linux 内核大牛-谢宝友

    http://blog.chinaunix.net/uid/25845340.html 谢宝友:毕业于四川省税务学校税收专业,现供职于中兴通讯操作系统团队,对操作系统内核有较强的兴趣.专职于操作系统内 ...

  6. Nginx HTTP负载均衡/反向代理的相关参数测试

    原文地址:http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/03/15/1984976.html 测试目的 (1)弄清楚HTTP Upstr ...

  7. 使用 NSPropertyListSerialization 持久化字典与数组

    NSPropertyListSerialization The NSPropertyListSerialization class provides methods that convert prop ...

  8. DWZ验证表单规则一览

    <form onsubmit="return validateCallback(this)" class="pageForm" action=" ...

  9. [Mongo] 解决mongoose不支持条件操作符 $gt$gte:$lte$ne $in $all $not

    reference : http://blog.sina.com.cn/s/blog_4df23d840100u25x.html 找到mongoose的安装目录 /usr/local/lib/node ...

  10. 【BZOJ】【2730】【HNOI2012】矿场搭建

    Tarjan求BCC/割点 然而似乎我一开始抄的白书的板子哪里抄错了?还是本身哪里不对……(可能是不适用于这道题?因为这题要求求出每个BCC的大小..? 膜拜了ydc的写法= = 其实两次dfs也并没 ...