1. 程式人生 > >android實現自定義相機效果

android實現自定義相機效果

樓主在進行android開發時用到了自定義攝像頭拍照並將所拍攝的照片轉化成二進位制流輸出這一功能(當然程式裡也附帶將圖片儲存在sd卡里的功能),花了好多天的時間查了很多資料最後終於把它給搞出來了。。。

來~~~直接上圖~~~


首先先搞出界面佈局來


佈局定製出來是這樣的:


這裡的佈局其實挺簡單的,只有一個Framelayout和一個Button按鈕

Framelayout用於顯示相機,Button按鈕新增OnClickListene用於獲取影象。

然後我們再看活動是如何建立的:

上程式碼:


我們來看一下活動中程式碼的執行順序:

onCreate方法裡活動首先呼叫getCameraInstance裡的方法getCamera()來獲取一個相機物件

當然getCameraInstance類是自己建立的一個類,下面是它裡面的程式碼:

這裡的程式碼就比較簡單了,定義一個camera c,初始化為null。然後嘗試開啟攝像頭,注意這裡的c.open(1)

引數為“1”的含義為開啟前攝像頭,如果想開啟後攝像頭為c.open(0)或者直接省略引數。如果開啟成功則返回camera物件,失敗則丟擲異常。

~~~

再接著看活動,定義一個mCamera用於接收呼叫getCamera()返回的相機物件。

將得到的camera作為引數傳遞給相機預覽物件,顯示當前相機裡的影象。

當然這個相機預覽類也是自己寫的:附程式碼


<textarea name="code" class="c++" readonly="readonly" style="width: 619px; height: 410px;">package myfinalcamera.caicai.com.myfinalcamera; import android.content.Context; import android.hardware.Camera; import android.util.Log; import android.view.SurfaceView; import android.view.SurfaceHolder; import java.io.IOException; /** * Created by caicai on 2017/5/5. */ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback,Camera.AutoFocusCallback { private Camera mCamera; private SurfaceHolder mHolder; private static final String TAG=&quot;CameraPreview&quot;; private static final String TAGDRAW=&quot;Draw&quot;; public CameraPreview(Context context,Camera camera) { super(context); mCamera=camera; mHolder=getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } @Override public void surfaceCreated(SurfaceHolder holder) { try { mCamera.setPreviewDisplay(holder); mCamera.setDisplayOrientation(90); /* 設定一下preview的大小 */ Camera.Parameters parameters=mCamera.getParameters(); parameters.setPreviewSize(640,480); parameters.setPictureSize(640,480); parameters.setJpegQuality(100); mCamera.setParameters(parameters); mCamera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if(mHolder.getSurface()==null){ return; } try { mCamera.stopPreview(); }catch (Exception e){ } try { mCamera.setPreviewDisplay(mHolder); mCamera.setDisplayOrientation(90); Camera.Parameters parameters=mCamera.getParameters(); parameters.setPreviewSize(320,240); parameters.setPictureSize(320,240); parameters.setJpegQuality(100); mCamera.setParameters(parameters); mCamera.startPreview(); }catch (Exception e){ Log.d(TAG, &quot;Errorstarting camera preview: &quot; + e.getMessage()); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { mCamera.stopPreview();//停止預覽 mCamera.release();//釋放相機資源 mCamera = null; holder = null; } @Override public void onAutoFocus(boolean success, Camera Camera) { if (success) { Log.i(TAG, &quot;onAutoFocus success=&quot;+success); } } } </textarea>

CameraPreview繼承自SurfaceView實現了SurfaceHolder.Callback和Camera.AutoFocusCallback介面。SurfaceView允許其他執行緒(非UI執行緒)多次繪製圖形,即可在其介面上顯示當前相機捕獲的影象。

~~~

接著活動繼續往下講:

獲得mpreview相機預覽物件後,定義一個FrameLayout佈局物件preview指向佈局裡的camera_preview,preview呼叫addView將相機預覽檢視新增到FramLayout佈局裡。這樣就可以再佈局裡的camera_preview裡顯示了。

~~~

camera_preview裡已經能顯示了,再就是實現點選按鈕實現拍照功能了

定義一個Buttou物件captureButton指向佈局檔案的button_capture_button按鈕,為capture_button新增點選事件,當點選按鈕時呼叫takePicture(save.shutter,save.row,save.jpeg)方法,第一個引數為快門,第二個引數為原資料,第三個引數為jpeg格式的資料,前兩個我們可以不管直接在save類裡實例化一個CameraCallback物件和PictureCallback物件裡面的程式碼不需要改動,需要改的是第三個引數,因為要涉及到照片的儲存和生成二進位制流輸出。這裡又涉及到一個自定義類。


下面只看第三個引數呼叫的程式碼,這裡定義了一個Bitmap物件bm和緩衝輸出流物件bom,接著用bm接收拍照生成的data資料。定義圖片的儲存路徑和名稱,呼叫自己寫的生成圖片儲存路徑和名稱的方法:


返回圖片儲存路徑後,將資料以jpeg的形式儲存到指定路徑中去。在儲存結束後我還用Log.i(TAG,new String(data));在控制檯輸出了一下照片的字串型別資料。程式碼的最後就是清空緩衝區關閉緩衝輸出流物件等。

最後別忘了在AndroidManifest.xml裡將新增許可權,在模擬器或真機上執行時,也要允許程式在相應的模擬器或真機上有相應的許可權。