天天看點

android 設定橫豎屏_Android 開發中關于攝像頭方向的了解

「code小生」一個專注 Android 領域的技術平台

公衆号回複 Android 加入我的安卓技術群

作者:tsia連結:https://www.jianshu.com/p/c362c6de0e23聲明:本文來自

tsia

投稿,轉發等請聯系原作者授權

安卓開發中經常有需要使用攝像頭的應用場景,對于初次接觸的同學攝像頭的方向是一個比較難弄清楚的概念,開發時很容易處理不當,本文将詳述該部分内容幫助了解。

一、攝像頭捕獲的圖像

先看一個簡單的場景,打開手機的後置攝像頭拍攝,攝像頭捕獲的圖像幀資料可通過Camera.PreviewCallback回調中擷取,也就是攝像頭的輸出資料,

這裡我們先忽略螢幕上的預覽,隻關注攝像頭的輸出。如果把它儲存為圖檔或直接顯示出來,可以看到圖像和原始畫面相比逆時針旋轉了90度。

android 設定橫豎屏_Android 開發中關于攝像頭方向的了解

而我們如果同樣使用iPhone手機拍攝,輸出的結果是一個正向的圖檔。

二、攝像頭的正向

為什麼輸出的圖像相比原始畫面旋轉了90度?因為裝置的攝像頭存在一個“正向角度”,什麼是攝像頭的正向?

通俗一點講,裝置相當于人的身體,眼睛相當于攝像頭,眼睛把接收到的畫面回報給大腦處理,相當于攝像頭把接收到的資料給應用程式處理。人眼能判斷出我們頭頂向上的方向是我們視覺上的正向,而後置攝像頭判斷的正向并不是手機實體螢幕向上的方向,而是實體螢幕右側的方向。我們想象一下,如果人眼是這個攝像頭,它認為右側才是我們的視覺正向,那我們看到的東西是不是都是旋轉90度的?這樣就比較好了解了。

android 設定橫豎屏_Android 開發中關于攝像頭方向的了解

上圖是手機在豎直和水準方向攝像頭“看”到的畫面。

固定裝置,指定的攝像頭,正向角度固定的(0/90/180/270),和螢幕旋轉、橫豎屏切換無關,一般都在螢幕的右側(但不排除某些廠商修改成别的)。

這個角度在代碼中可通過Camera.CameraInfo的orientation擷取,官方文檔也有解釋:

The orientation of the camera image. The value is the angle that the camera image needs to be rotated clockwise so it shows correctly on the display in its natural orientation. It should be 0, 90, 180, or 270.

For example, suppose a device has a naturally tall screen. The back-facing camera sensor is mounted in landscape. You are looking at the screen. If the top side of the camera sensor is aligned with the right edge of the screen in natural orientation, the value should be 90. If the top side of a front-facing camera sensor is aligned with the right of the screen, the value should be 270.

意思就是輸出的圖檔需要順時針旋轉多少度,才能在自然方向上正确顯示。這裡的自然方向就是以标題欄左上角為原點的螢幕渲染坐标系,圖檔旋轉後,把它放到渲染坐标系中,能和原始畫面一樣正常顯示。

android 設定橫豎屏_Android 開發中關于攝像頭方向的了解

上圖紅點代表了圖檔的坐标原點,藍點則代表螢幕渲染坐标的原點。隻有做了旋轉處理,渲染到螢幕上的預覽圖像才是正确的(和原始畫面一樣),而這個旋轉的角度,就是orientation的值。

注意,正向始終在實體螢幕的右側(想象音量鍵那邊有一個正向箭頭),orientation就等于從攝像頭的角度(想象成人眼)看,從實體裝置的正上方向(想象聽筒位置有個箭頭),需要順時針旋轉多少度才能到正向的箭頭。是以,根據這個想象一下前後攝像頭的差別,這個值後置攝像頭是90,前置攝像頭是270。

iPhone的攝像頭正向就是實體裝置的正上方,對應的正向角度是0,是以輸出的圖像是正向的。

三、如何正确地預覽圖像

其實不預覽應用程式也能正确擷取到攝像頭的輸入,但是一般應用打開攝像頭後都會在螢幕上顯示目前拍攝到的畫面,這是使用者的基本的使用體驗。正确的預覽圖像就是讓攝像頭輸出的圖像能夠正确的在螢幕上顯示給使用者。

如上節所述,攝像頭采集到的圖像按照orientation旋轉和渲染坐标系對齊即可,這樣就能正确顯示圖像了。不過這是在螢幕方向鎖定的情況下,就是渲染坐标系始終在實體螢幕的左上方。

如果我們打開了裝置陀螺儀(鎖屏),螢幕可以在四個方向上切換,對應渲染的坐标原點(藍點)會在實體螢幕的四個角上切換。

切換方向的角度可以通過

android 設定橫豎屏_Android 開發中關于攝像頭方向的了解

螢幕切換的角度值

這個角度可以了解為,以實體裝置左上角為原點的渲染坐标系(聽筒左邊的角點),需要順時針旋轉多少度,才能變成目前的渲染坐标系。打開陀螺儀後,無論手機怎麼旋轉,目前的渲染坐标系永遠以絕對左上角為原點(視覺左上方角點)。這個角度恰好和實體旋轉的角度相反。

我們隻要根據目前的切換角度+攝像頭正向角度正确地設定顯示角度就行了,官方文檔也有現成的适配代碼,詳見setDisplayOrientation。

注意,setDisplayOrientation隻會對預覽顯示的圖像有影響,并不會影響onPreviewFrame回調的資料。

如果還不了解這段代碼的意思,看下這張圖就明白了:

android 設定橫豎屏_Android 開發中關于攝像頭方向的了解

藍點是渲染的坐标原點,紅點是輸出圖檔的原點。每一次旋轉圖檔的原點就會變換到絕對位置的左上角,setDisplayOrientation要設定的值就是圖像要順時針旋轉的角度,使圖檔能在渲染坐标系中正确顯示。從圖中也能看出來,它就是第二列的箭頭需要順時針旋轉到第一列箭頭的角度。

推薦閱讀

Android開發之自定義相機、相冊趟坑之旅

釘釘自動拍照打卡 App 的實作

android 設定橫豎屏_Android 開發中關于攝像頭方向的了解