1.概述
本文將仿照此前博文Android NDK Camera2小結的方式,來記錄Camera1的使用。
Camera1僅爲Java實現(不必糾結於此,Native實現...JNI反調...你懂的~且性能差別不大)。
本文的講解基於UML Component圖,描述Camera1核心對象及API的調用生成關係。如縮略圖不清晰,可點擊放大。
Component圖中,模塊爲函數,節點爲對象。橫向(左或右)箭頭爲資源釋放操作調用。調用過程與順序/時機無關。
其中綠色模塊爲Camera對象成員方法,黃色爲Camera類靜態方法。
粉色爲Camera.Parameters對象成員方法。
紅色爲自定義方法,需要自行實現。
Component圖未包含所有接口,僅爲Camera1預覽模式的簡單實現。
2.Camera1的使用
相比於Camera2的複雜架構,Camera1(android.hardware.Camera)十分簡單,僅爲一個類文件。因此,操作也即爲簡便。
遵循以下步驟便可完成預覽。
2.1獲取Camera數量
使用靜態方法Camera.getNumberOfCameras,獲取camera數量num。Camera ID範圍爲【0,num-1】。
int cameraCount = Camera.getNumberOfCameras();
2.2獲取CameraInfo
以Camera ID作爲傳參,調用靜態方法Camera.getCameraInfo,獲取對應CameraInfo。CameraInfo僅包括三項,Facing(鏡頭方向,前置/後置),orientation(鏡頭旋轉角度)和canDisableShutterSound(是否支持取消快門聲音)。
通常通過CameraInfo,來確定要使用的Camera。
for (int i = 0; i < cameraCount; i++) {
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
Camera.getCameraInfo(i, cameraInfo);
}
2.3開啓Camera
以Camera ID作爲傳參,調用靜態方法Camera.open即可打開設備,該方法將返回一個Camera對象。但打開設備,並不代表能夠看到畫面。仍需要後續操作,來完成預覽。包括設置Camera.Parameters,以及畫布(surface View)。若需要使用圖片數據,則需要設置Callback接口。
Camera camera = Camera.open(cameraId);
2.4設置Camera配置參數
獲取Camera對象後,調用成員方法getParameters,可以獲取Camera.Parameters。Camera.Parameters中包含的信息,要遠多於CameraInfo。在獲取Camera.Parameters後,可以調用成員方法getSupportedXXXX來獲取相應的數據。例如分辨率,預覽格式等。
對於分辨率,可以調用Camera.Parameters成員方法getSupportedPreviewSizes,獲取List<Camera.Size>。設置則是調用Camera.Parameters成員方法setPreviewSize。
Camera.Parameters params = camera.getParameters();
List<Camera.Size> supportSizes = params.getSupportedPreviewSizes();
...
mParams.setPreviewSize(width, height);
對於預覽格式,可以調用Camera.Parameters成員方法getSupportedPreviewFormats,獲取List<Integer>。設置則是調用setPreviewFormat。由於前端爲視頻流,因此,通常使用PixelFormat.YCbCr_420_SP。
parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP);
當然,還有其它一些參數可以設置,例如曝光補償(可參照關於Android Camera的曝光補償),焦距(可參照關於Android Camera變焦)等。
List<Integer> zoomRatios =parameters.getZoomRatios();
int MAX_ZOOM = mParams.getMaxZoom();
int tMaxExposure=parameters.getMaxExposureCompensation();
int tMinExposure=parameters.getMinExposureCompensation();
...
mParams.setZoom(currentZoom);
parameters.setExposureCompensation(mExposureCompensationRate);
在設置完Camera.Parameters子項後,需要將其回填給Camera,需要調用Camera成員方法setParameters。
mCamera.setParameters(mParams);
2.5設置預覽界面
surface view爲Camera的畫布,僅需將其SurfaceHolder作爲傳參,調用Camera的成員方法setPreviewDisplay即可完成預覽界面設置。
SurfaceHolder holder;
...
mCamera.setPreviewDisplay(holder);
2.6預覽畫面矯正
通過用Camera的成員方法setDisplayOrientation調設置畫面的矯正角度,使得畫面以自然0度顯示在畫布上。通常使用角度爲0,90,180,270。關於android設備的角度問題,將另闢博文描述。
mCamera.setDisplayOrientation(90);
2.7設置previewCallback
如果想獲取圖像數據,則需要通過調用Camera的成員方法setPreviewCallback添加Callback方法。默認返回爲YCbCr_420_SP格式的數據。
PreviewCallback mpreview = new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
}
};
mCamera.setPreviewCallback(mpreview);
public interface PreviewCallback
{
/**
* Called as preview frames are displayed. This callback is invoked
* on the event thread {@link #open(int)} was called from.
*
* <p>If using the {@link android.graphics.ImageFormat#YV12} format,
* refer to the equations in {@link Camera.Parameters#setPreviewFormat}
* for the arrangement of the pixel data in the preview callback
* buffers.
*
* @param data the contents of the preview frame in the format defined
* by {@link android.graphics.ImageFormat}, which can be queried
* with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
* If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}
* is never called, the default will be the YCbCr_420_SP
* (NV21) format.
* @param camera the Camera service object.
*/
void onPreviewFrame(byte[] data, Camera camera);
};
2.8啓動預覽
完成相關設置後,僅需調用Camera成員方法startPreview即可。
mCamera.startPreview();
2.9停止預覽
調用Camera成員方法stopPreview即可。
mCamera.stopPreview()
2.10關閉相機
調用Camera成員方法release即可。
mCamera.release();
3.結束語
Android Camera2 Java實現始於andorid 5.0, Native 實現則開始於android7.0(API level24)。
到目前爲止,5.0以上系統市場佔有率爲85%,7.0以上系統僅爲37%,因此,Camera2不足以適配所有Android 設備。
所以,Camera1雖然最終將被替代,但仍有存在價值。Camera1僅爲單個類,沒有Camera2複雜的結構,並且java實現還是相對簡單實用。在不考慮被遺棄的情況,Camera1還是更爲通用。