概述:
Android支持很多種相機功能, 我們可以在自己的APP中控制它, 比如圖片格式, 閃光模式, 焦點設置, 還有很多別的. 這裏會列出相機的常用功能並簡要地討論如何使用它們. 大多數相機功能可以訪問並且通過Camera.Parameters對象設置使用. 但是有一些重要的功能需要更加複雜的設置. 這些功能將在之後介紹. 包括: 測光和聚焦(Metering and focus areas), 人臉識別(Face detection),延時拍攝(Time lapse video).
Camera.Parameters:
下表是常用的相機功能, 按照引入的API級別排列.
功能 |
版本 |
描述 |
人臉識別(Face Detection) |
14 |
識別圖片中的人臉, 並對他們聚焦, 測光, 和白平衡. |
測光區域(Metering Areas) |
14 |
指定圖片中的一個或更多的區域用於計算白平衡. |
聚焦(Focus Areas) |
14 |
設置圖片中的一個或更多的區域用來做焦點. |
白平衡鎖定(White Balance Lock) |
14 |
啓動或者停止自動白平衡調整. |
曝光鎖定(Exposure Lock) |
14 |
啓動或者停止自動曝光調整. |
視頻快照(Video Snapshot) |
14 |
拍攝視頻的時候截個圖(幀抓取) |
延遲攝影 (Time Lapse Video) |
11 |
根據設置的延遲來錄製幀. |
多相機拍攝(Multiple Cameras) |
9 |
爲多於一個相機的設備提供支持. 包括前置和後置相機. |
對焦距離(Focus Distance) |
9 |
報告相機和焦點之間的距離. |
放大(Zoom) |
8 |
設置圖像放大. |
曝光補償(Exposure Compensation) |
8 |
增加或減少曝光等級. |
GPS數據(GPS Data) |
5 |
設置是否包括圖片的地理位置. |
白平衡(White Balance) |
5 |
設置白平衡模式, 它會影響照片的顏色值. |
對焦模式(Focus Mode) |
5 |
設置相機對焦的模式, 比如自動, 固定, 微距或者無窮大. |
場景模式(Scene Mode) |
5 |
爲特定類型的拍攝場景設置模式, 比如夜間, 海灘, 雪景或者燭光場景. |
JPEG質量(JPEG Quality) |
5 |
爲JPEG圖片設置壓縮等級, 它可以增加或者減少輸出的圖片文件的質量和大小. |
閃光模式(Flash Mode) |
5 |
開啓關閉閃光燈, 也可以使用自動模式. |
色彩效果(Color Effects) |
5 |
爲拍攝的圖片指定色彩效果, 比如黑白, 棕褐色色調或者底片. |
消除條紋(Anti-Banding) |
5 |
在JPEG壓縮的時候降低條紋的對比度, 變爲漸變色. |
圖片格式(Picture Format) |
1 |
爲圖片指定文件格式. |
圖片大小(Picture Size) |
1 |
爲保存的圖片指定像素尺寸. |
這些功能根據硬件差異和軟件實現並不會在所有的設備上都可以正常運行. 所以需要檢查功能的可用性.
檢查功能的可用性:
使用Android設備上的相機功能時首先要明白的是, 並不是所有的相機功能都可以在所有的設備上支持. 此外, 有些支持特殊功能的設備可能會有不同的可選功能. 因此, 開發策略由APP想要支持的功能決定.
我們可以通過獲取一個相機參數對象實例來檢查相機功能的可用性. 下面的代碼展示瞭如何獲得一個Camera.Parameters對象並檢查相機是否支持自動聚焦功能:
// get Camera parameters
Camera.Parameters
params = mCamera.getParameters();
List<String> focusModes
= params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))
{
// Autofocusmode is supported
}
我們可以對大部分的相機功能使用上面的方法. Camera.Parameters對象提供了getSupported…()方法, is…Supported()方法, getMax…()方法來確認一個功能是否被支持.
如果APP需要確定相機功能來實現某一功能, 我們可以將它們添加到manifest中. 當我們聲明使用某一個功能時, 比如閃光和自動聚焦, Google Play會限制APP安裝在那些不支持這些功能的設備上.
使用相機功能:
大多數相機功能可以被Camera.Parameters對象激活並控制. 想要獲取這個對象, 首先要獲取一個Camera對象實例, 調用getParameters()方法, 修改返回的參數對象, 並將它設置給相機對象, 栗子:
// get Camera parameters Camera.Parameters params = mCamera.getParameters(); // set the focus mode params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); // set Camera parameters mCamera.setParameters(params);
該套路幾乎可以用於所有的相機功能, 大部分參數可以在獲取了Camera對象後的任何時候修改. 參數的修改可以直接影響到用戶在預覽窗口看到的效果. 在軟件側, 參數修改可能要消耗幾幀的時間才能生效.
重要: 有些相機功能不能被隨意修改. 特別是修改相機預覽窗口的方向和尺寸, 修改這些參數需要先停止預覽, 然後再重啓預覽. 從Android4.0開始, 預覽方向可以不需要重啓修改.
測光和焦點區域:
在某些情況下拍攝自動對焦和測光可能不會產生預期的效果, 從Android4.0開始, 相機APP可以提供額外的控制, 它允許APP或者用戶可以指定圖片區域用來確定焦點或者亮度等級, 並傳遞這些值給硬件用於拍攝.
測光和聚焦區域工作起來跟其它的相機功能相似, 通過Camera.Parameters對象來控制. 下面的代碼展示了爲一個Camera實例設置兩個測光區域:
// Create an instance of Camera mCamera = getCameraInstance(); // set Camera parameters Camera.Parameters params = mCamera.getParameters(); if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>(); Rect areaRect1 = new Rect(-100, -100, 100, 100); // specify an area in center of image meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60% Rect areaRect2 = new Rect(800, -1000, 1000, -800); // specify an area in upper right of image meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40% params.setMeteringAreas(meteringAreas); } mCamera.setParameters(params);
Camera對象包含兩個數據參數: 一個Rect對象用來指定一個相機區域中的矩形區域和一個比重值, 它告訴相機該區域的重要級別, 應該給予什麼樣的測光或者聚焦.
Camera.Area對象中的矩形區域描述了一個2000x2000的單元格. 座標-1000,-1000表示相機圖片的左上角, 座標1000, 1000表示右下角, 如下圖:
紅線表示在相機預覽窗口中用Camera.Area指定的座標系統. 藍色的矩形表示333,333,667,667座標指示的形狀.
這個座標系的邊界總是對應於相機預覽中可見的圖像邊界, 並不隨着縮放級別而收縮或者擴展. 同樣, 通過Camera.setDisplayOrientation()方法旋轉圖像預覽系統也不會重新映射座標系統.
人臉識別:
對於包含人物的圖片, 面部通常都是圖中最重要的部分, 應該被着重照顧, 當拍照的時候聚焦和白平衡都應該用於面部. Android4.0 framework提供了用於識別面部和採用面部識別技術圖像設置的API.
注意, 當面部識別功能正在運行的時候, setWhiteBalance(String), setFocusAreas(List)和setMeteringAreas(List)方法不生效.
在相機APP中使用面部識別技術需要以下幾個典型的步驟:
l 檢查設備是否支持人臉識別.
l 創建人臉識別監聽器.
l 添加人臉識別監聽器到相機對象.
l 預覽後啓動人臉識別(在每個預覽重啓之後).
人臉識別功能並不是所有的設備都可以支持的, 我們可以用getMaxNumDetectedFaces()方法檢查該功能是否可用. 一個使用該方法的栗子將會在下面的startFaceDetection()方法的栗子中展示.
爲了得到通知和對人臉識別做出響應, 相機應用必須爲人臉識別事件設置一個監聽器. 想要完成這個功能, 必須創建一個監聽器類, 該類需要實現Camera.FaceDetectionListener接口, 栗子:
class MyFaceDetectionListener implements Camera.FaceDetectionListener { @Override public void onFaceDetection(Face[] faces, Camera camera) { if (faces.length > 0){ Log.d("FaceDetection", "face detected: "+ faces.length + " Face 1 Location X: " + faces[0].rect.centerX() + "Y: " + faces[0].rect.centerY() ); } } }
創建該類之後, 需要將它設置給APP的Camera對象, 栗子:
mCamera.setFaceDetectionListener(new MyFaceDetectionListener());
APP必須每次相機預覽啓動的時候(或者重啓)都要開啓人臉識別功能. 創建一個方法用於啓動人臉識別, 這樣就可以每次要的時候調用它了, 它是這樣的:
public void startFaceDetection(){ // Try starting Face Detection Camera.Parameters params = mCamera.getParameters(); // start face detection only *after* preview has started if (params.getMaxNumDetectedFaces() > 0){ // camera supports face detection, so can start it: mCamera.startFaceDetection(); } }
記得每次都要開啓. . .如果我們使用”創建一個預覽類”小節中的預覽類, 那麼需要添加startFaceDetection()方法到surfaceCreated()和surfaceChanged()方法中. 栗子:
public void surfaceCreated(SurfaceHolder holder) { try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // start face detection feature } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (mHolder.getSurface() == null){ // preview surface does not exist Log.d(TAG, "mHolder.getSurface() == null"); return; } try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: " + e.getMessage()); } try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); startFaceDetection(); // re-start face detection feature } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } }
注意: 記得在調用startPreview()方法之後調用這個方法. 不要嘗試在activity的onCreate()方法中啓動人臉識別, 因爲此時預覽不可用.
延時拍攝:
該功能允許用戶每隔幾秒或者幾分鐘創建視頻剪輯或圖片. 該功能使用MediaRecorder來拍攝. 想要使用MediaRecorder實現該功能, 必須配置recorder對象, 就好像錄製一個普通的視頻那樣, 設置每秒捕獲幀到一個較低的數目並使用一個時間間隔質量設置, 栗子:
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)); ... // Step 5.5: Set the video capture rate to a low number mMediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
這些設置必須作爲MediaRecorder較大的配置程序的一部分. 一個完整的配置代碼的栗子, 可以參考”配置MediaRecorder”. 一旦配置完成, 就好像啓動普通視頻那樣啓動視頻錄製即可.
總結:
自定義相機可以更加的充分的利用相機提供的功能, 詳情可以參考最上面的表格. 大部分的相機功能使用的流程是: 獲取Camera.Paramters參數, 設置該參數, 然後將其再設置回給Camera對象.
參考: https://developer.android.com/guide/topics/media/camera.html