自定義相機那些坑之預覽介面適配及原理
0.思維導圖
1.問題的產生
當Activity的oritation設定為portrait時,前置/後置攝像頭預覽影象會逆時針旋轉90度展示,如圖:
2.問題產生的本質
相機影象資料來自影象感應器(物理器件)(Image Sensor),影象感應器再將資料輸出到預覽Window上時,影象感應器有一個讀取影象的方向,並且不會改變。這個讀取的方向通過CameraInfo的orientation可以獲取。現在的影象感應器硬體的讀取方向都是順時針90度,即讀取方向如下圖:
由此就會產生預覽方向逆時針旋轉90度。具體的產生過程如圖:
3.官方推薦的解決方案
public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) { android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraId, info); int rotation = activity.getWindowManager().getDefaultDisplay() .getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result); }
推薦的解決方案中:
(1)CameraInfo是例項化的相機類,其中orientation是相機(影象感應器)相對於自然座標系(即左上角座標系)的旋轉角度數.
(2)rotation是預覽window的旋轉的方向,當Activity的 screenOrientation="portrait"時,rotation=0,也就是沒有旋轉,當 screenOrientation="landscape"時,rotation=1。
(3)camera.setDisplayOrientation(int param)根據官方解釋就是圖片已經輸出後旋轉的度數。旋轉值可以是 0, 90, 180, and 270. (a)當開啟後置攝像頭,Window豎屏顯示時,預覽影象旋轉: result=(90-0+360)%360=90,順時針旋轉90度.
(b)當開啟後置攝像頭,Window橫屏顯示時,預覽影象旋轉: result=(90-90+360)%360=0,順時針旋轉0度.
(c)前置攝像頭有一些特殊情況,在下面會談到。
(d)param的引數官方解釋 @param degrees the angle that the picture will be rotated clockwise.Valid values are 0, 90, 180, and 270.
4.一些存在的問題
1、對於前後攝像頭,影象感應器輸出的方向是一致的,並不像部分部落格所說進行了映象。
2、CameraInfo中的facing欄位,無論是呼叫前置攝像頭還是後置攝像頭,facing均為0,即後置攝像頭值。如下圖各種機型返回值:
5.參考相關文件
騰訊Bugly: https://blog.csdn.net/Tencent_Bugly/article/details/53375311 http://hao.caibaojian.com/16047.html
Demo: https://github.com/xionglei12/camera-preview-demo.git