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,感興趣的童鞋能夠去看一下。
以上

相關文章
相關標籤/搜索