Camera2挖坑日记---如何解决预览画面变形

原文地址请点击 原创文章,转载请联系做者java

一梦觉来三十载,休休。空为梅花白了头android

概述

Camera2是目前Android相机开发最新的API,旧版本的Camera已经被废弃了。
通常状况下,Camera2的使用是将图像发送到SurfaceView或者TextureView【经过SurfaceTexture】来预览。使用JPEG或者Raw sensor格式的ImageReader来捕获JPEG图像或RAW缓冲区。【注1】
今天主要是记录一下, 在使用Camera2API开发Android相机过程当中,解决预览画面变形的问题。
另,本文所记录的状况,都是竖屏状况的设备。
题主参考Google方法给出的Demo,自定义了TextureView,能够自动适配宽高,支持全屏展现。代码地址AutoFitTextureViewgit

效果

如下的画面基本上处于同一角度拍摄所得github

  • 变形的画面
    bash

  • 正常的小画面,以宽为基准计算高度。ide

  • 正常全屏画面,高度铺满屏幕,画面被拉近。函数

解决

++在解决方案上,主要参考了Google官方给出的Demo。Camera2VideoFragment++。
Camera2的使用上,我使用了TextureView做为预览画面的承载。为何不使用SurfaceView呢?由于SurfaceView是基于Window层面的View,有不少View的属性都用不了,使用起来比较麻烦。
Camera2API会返回一系列能够用于输出到SurfaceTexture的Size集合。--++TextureView显示原理便是使用SurfaceTexture构建的Surface++ post

如图:
以题主手上的Oppo r15为例,总共会返回13个能够用做输出的size
须要注意的是,若是以竖屏为例,这里的宽高是反过来的
在获得可用的size集合后,根据实际开发状况选择合适的PreviewSize便可ui

正常小画面展现

选定了一个合适的PreviewSize以后,只须要适配TextureView的宽高便可。小画面以宽为基准,须要根据屏幕宽度来计算相应的高度便可。这一部分的代码,在官方Demo里已经至关详细。其实很简单,就是自电影AutoFitTextureView里的onMeasure函数里,从新设定宽高。google

override fun onMeasure(....){
    if (width < ((height * ratioWidth) / ratioHeight)) {
            // 控件自己的宽小于根据比例计算来得宽,则使用控件自己的宽
        setMeasuredDimension(width, (width * ratioHeight) / ratioWidth)
    } else {
        setMeasuredDimension((height * ratioWidth) / ratioHeight, height)
    }
}
复制代码

其中ratioWidth、ratioHeight便是PreviewSize

全屏展现

全屏展现预览画面,则须要使用TextureView的另外一个函数——setTransform。这个函数是给Textureview设置一个Transform,用于改变TextureView的画面。By,双指缩放时可使用这个函数。
全屏展现时,TextureView的宽高铺满整个屏幕,相应的咱们只须要改变一下Transform便可,此时高度不变,可是要将画面的宽度放大。放大的倍数即为屏幕的高度除以小画面时计算得来的高度比例便可。
仍是在onMeasure函数内:

override fun onmeasure(...){
    val w = resources.displayMetrics.widthPixels
    val h = resources.displayMetrics.heightPixels
    setMeasuredDimension(w, h)
    fullScreenTransform.reset()
    fullScreenTransform.set(defTransform)
    // 宽拉伸,高不变
    fullScreenTransform.postScale(h.toFloat() /ratioHeight,
                    1f, w * 0.5f, h * 0.5f)
    setTransform(fullScreenTransform)
}
复制代码

其中fullScreenTransform即为TextureView最初始的Transform

自定义TextureView

题主将AutoFitTextureView从新封装了一下,对外提供了全屏展现的开关函数。地址在这里AutoFitTextureView,感兴趣的童鞋能够去看一下。
以上

相关文章
相关标签/搜索