Jetpack-CameraX 實踐

參看文章??跳轉(zhuǎn)

關(guān)于 CameraX ,建議看看 Google I/O 大會上的??視頻記錄

DEMO??使用 OpenGL 黑白濾鏡渲染
? ? ? ? ? ? ?CameraX小試牛刀,實現(xiàn)二維碼掃描

Android Camera開發(fā)中的尺寸和方向問題

Android Camera模型及API接口演變

對于一個簡單能用的 Camera 應(yīng)用來說,關(guān)注兩個方面:預(yù)覽和拍攝。

而預(yù)覽和拍攝的圖像都受到分辨率、方向的影響。Camera 最必備的功能就是能針對預(yù)覽和拍攝提供兩套分辨率,因此就得區(qū)分場景去設(shè)置。

對于拍攝還好說一點,要獲得最好的圖像質(zhì)量,就選擇同比例中分辨率最大的吧。

而預(yù)覽的圖像最終要呈現(xiàn)到 Android 的 Surface 上,因此選擇分辨率的時候要考慮 Surface 的寬高比例,不要出現(xiàn)比例不匹配導(dǎo)致圖像拉伸的現(xiàn)象。

另外,如果要做美顏、濾鏡類的應(yīng)用,就要把 Camera 預(yù)覽的圖像放到 OpenGL 渲染的線程上去,然后由 OpenGL 去做圖像相關(guān)的操作,也就沒 Camera 什么事了。等到拍攝圖片時,可以由 OpenGL 去獲取圖像內(nèi)容,也可以由 Camera 獲得圖像內(nèi)容,然后經(jīng)過 OpenGL 做離屏處理~~~

至于 Camera 開發(fā)的其他功能,比如對焦、曝光、白平衡、HDR 等操作,不一定所有的 Camera 都能夠支持,而且也可以在上面的基礎(chǔ)上當(dāng)做 Camera 的一個 feature 去拓展開發(fā),并不算難事,這也是一個 Camera 開發(fā)工程師進階所要掌握的內(nèi)容~~

CameraX 開發(fā)實踐

CameraX 目前的版本是?1.0.0-alpha01?,在使用時要添加如下的依賴:

// CameraX

def camerax_version="1.0.0-alpha01"

implementation"androidx.camera:camera-core:${camerax_version}"

implementation"androidx.camera:camera-camera2:${camerax_version}"

CameraX 向后兼容到 Android 5.0(API Level 21),并且它是基于 Camera 2.0 的 API 進行封裝的,解決了市面上絕大部分手機的兼容性問題~~~

相比 Camera 2.0 復(fù)雜的調(diào)用流程,CameraX 就簡化很多,只關(guān)心我們需要的內(nèi)容就好了,不像前者得自己維護 CameraSession 會話等狀態(tài),并且 CameraX 和 Jetpack 主打的 Lifecycle 綁定在一起了,什么時候該打開相機,什么時候該釋放相機,都交給 Lifecycle 生命周期去管理吧

上手 CameraX 主要關(guān)注三個方面:

圖像預(yù)覽(Image Preview)

圖像分析(Image analysis)

圖像拍攝(Image capture)

1.? 預(yù)覽

不管是 預(yù)覽 還是 圖像分析、圖像拍攝,CameraX 都是通過一個建造者模式來構(gòu)建參數(shù) Config 類,再由 Config 類創(chuàng)建預(yù)覽、分析器、拍攝的類,并在綁定生命周期時將它們傳過去。

//? Apply declared configs to CameraX using the same lifecycle owner

CameraX.bindToLifecycle(lifecycleOwner:this,preview,imageCapture,imageAnalyzer)

既可以綁定 Activity 的 Lifecycle,也可以綁定 Fragment 的。

當(dāng)需要解除綁定時:

// Unbinds all use cases from the lifecycle and removes them from CameraX.

CameraX.unbindAll()

CameraX 預(yù)覽的參數(shù)配置

提供我們的目標(biāo)參數(shù),由 CameraX 去判斷當(dāng)前 Camera 是否支持,并選擇最符合的。


通過建造者模式創(chuàng)建?Preview?對象,并且一定要給 Preview 對象設(shè)置?OnPreviewOutputUpdateListener?接口回調(diào)。

相機預(yù)覽的圖像流是通過 SurfaceTexture 來返回的,而在項目例子中,是通過把 TextureView 的 SurfaceTexture 替換成 CameraX 返回的 SurfaceTexture,這樣實現(xiàn)了 TextureView 控件顯示 Camera 預(yù)覽內(nèi)容。

另外,還需要考慮到設(shè)備的選擇方向,當(dāng)設(shè)備橫屏變?yōu)樨Q屏了,TextureView 也要相應(yīng)的做旋轉(zhuǎn)。


TextureView 旋轉(zhuǎn)的設(shè)置同樣在?OnPreviewOutputUpdateListener?接口中去完成。

2.??圖像分析

在?bindToLifecycle?方法中,imageAnalyzer?參數(shù)并不是必需的。

ImageAnalysis?可以幫助我們做一些圖像質(zhì)量的分析,需要我們?nèi)崿F(xiàn)?ImageAnalysis.Analyzer?接口的?analyze?方法。


在圖像分析器的相關(guān)配置中,有個?ImageReaderMode?和?ImageQueueDepth?的設(shè)置。

ImageQueueDepth 會指定相機管線中圖像的個數(shù),提高 ImageQueueDepth 的數(shù)量會對相機的性能和內(nèi)存的使用造成影響

其中,ImageReaderMode 有兩種模式:

ACQUIRE_LATEST_IMAGE

該模式下,獲得圖像隊列中最新的圖片,并且會清空隊列已有的舊的圖像。

ACQUIRE_NEXT_IMAGE

該模式下,獲得下一張圖像。

在圖像分析的?analyze?方法中,能通過 ImageProxy 類拿到一些圖像信息,并基于這些信息做分析。

3.??拍攝

拍攝同樣有一個 Config 參數(shù)構(gòu)建者類,而且設(shè)定的參數(shù)和預(yù)覽相差不大,也是圖像寬高比例、旋轉(zhuǎn)方向、分辨率,除此之外還有閃光燈等配置項。


在圖像拍攝的相關(guān)配置中,也有個?CaptureMode?的設(shè)置。

它有兩種選項:

MIN_LATENCY? ? 該模式下,拍攝速度會相對快一點,但圖像質(zhì)量會打折扣

MAX_QUALITY? ? 該模式下,拍攝速度會慢一點,但圖像質(zhì)量好

4.? OpenGL 渲染

以上是關(guān)于 CameraX 的簡單應(yīng)用方面的內(nèi)容,更關(guān)心的是如何用 CameraX 去做 OpenGL 渲染實現(xiàn)美顏。濾鏡等效果。

還記得在圖像預(yù)覽 Preview 的 setOnPreviewOutputUpdateListener 方法中,會返回一個?SurfaceTexture?,相機的圖像流就是通過它返回的。

那么要實現(xiàn) OpenGL 線程的渲染,首先就要基于 EGL 去創(chuàng)建 OpenGL 繪制環(huán)境,然后利用 SurfaceTexture 的?attachToGLContext?方法,將 SurfaceTexture 添加到 OpenGL 線程去。

attachToGLContext 的參數(shù)是一個紋理 ID ,這個紋理就必須是 OES 類型的紋理。

然后再把這紋理 ID 繪制到 OpenGL 對應(yīng)的 Surface 上,這可以看成是兩個不同的線程在允許,一個 Camera 預(yù)覽線程,一個 OpenGL 繪制線程。( 具體可參考? 上文 DEMO? )

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容