android--相機開發----我的相機我做主
因為要模仿一個iphone的遊戲,昨天開始學習android的相機應用。
在android中應用相機功能,一般有兩種:一種是直接呼叫系統相機,一種自己寫的相機。
我將分別演示兩種方式的使用:
第一種:是使用Intent跳轉到系統相機,action為:android.media.action.STILL_IMAGE_CAMERA
關鍵程式碼:
例子:CameraTest_2.java
想要測試的,可以直接新建一個專案,並且把主activity的程式碼換成上面的,然後執行,我測試了一下,上面這個程式碼並不
需要許可權,畢竟只是呼叫系統自帶的程式。
當然網上還有一些其他相關的呼叫方法,只要設定對了action,那麼系統就會呼叫系統自帶的相機.
第二種:
(1)首先我們要自己建立一個照相,必須考慮用什麼控制元件顯示照相機中的預覽效果,顯然android已經幫我們做好了選擇,那就是
SurfaceView,而控制SurfaceView則需要一個surfaceHolder,他是系統提供的一個用來設定surfaceView的一個物件,而它通過surfaceView.getHolder()這個方法來獲得。而Camera提供一個setPreviewDisplay(SurfaceHolder)的方法來連線
surfaceHolder,並通過他來控制surfaceView,而我們則使用android的Camera類提供了startPreview()和stopPreview()來開啟和關閉預覽.
關係如下:
Camera -- -->SurfaceHolder------>SurfaceView.
(2)知道怎麼預覽,當然也要知道怎麼開啟相機.Camera.open()這是個靜態方法,如果相機沒有別人用著,則會返回一個 相機引用,如果被人用著,則會丟擲異常。很奇怪的是,這個方法,不能隨便放,如放在構造方法或者onCreate()方法中,都會照成沒有預覽效果.
(3)
SurfaceHolder.Callback,這是個holder用來顯示surfaceView 資料的介面,他分別必須實現3個方法
surfaceCreated()這個方法是surface 被建立後呼叫的
surfaceChanged()這個方法是當surfaceView發生改變後呼叫的
surfaceDestroyed()這個是當surfaceView銷燬時呼叫的.
surfaceHolde通過addCallBack()方法將響應的介面繫結到他身上.
surfaceHolder還必須設定一個setType()方法,檢視api的時候,發現這個方法已經過時,但是沒有寫,又會報錯。。各種奇怪。
(4)
我用以上知識寫了一個MySurfaceView類,他繼承於SurfaceView,並在裡面實現了照相機的預覽功能.這個我覺得最簡單的照相機預覽程式碼:
MySurfaceView.java
CameraTest_3.java
而且必須給應用新增許可權:<uses-permission android:name="android.permission.CAMERA"></uses-permission>
(5)能夠預覽了,接下來就是拍照了,拍照用到了一個camera.tackPiture()這個方法,這個方法,有三個引數分別是
ShutterCallBack shutter,PictureCallBack raw,PictureCallBack jpeg.
下面是對他們的實現
當開始拍照時,會依次呼叫shutter的onShutter()方法,raw的onPictureTaken方法,jpeg的onPictureTaken方法.
三個引數的作用是shutter--拍照瞬間呼叫,raw--獲得沒有壓縮過的圖片資料,jpeg---返回jpeg的圖片資料
當你不需要對照片進行處理,可以直接用null代替.
注意,當呼叫camera.takePiture方法後,camera關閉了預覽,這時需要呼叫startPreview()來重新開啟預覽。
我用以上知識,加到上面的那個例子,就形成了下面的程式碼:
MySurfaceView.java
CameraTest_3.java
這樣就是實現了拍照的功能,那麼怎樣要圖片儲存呢?那麼這是就需要在那個引數中的jpeg的
方法裡面進行處理了,那個方法的data引數,就是相片的資料。
我們通過BitmapFactory.decodeByteArray(data, 0, data.length)來獲得圖片並通過io處理,將圖片儲存到想要儲存的位置
下面這段程式碼,是將照片儲存到/sdcard/wjh.jpg;並把一些沒有用到的程式碼全部刪掉,剩下一些必須的程式碼
MySurfaceView.java
CameraTest_3.java跟上面的一樣
注意,這是必須新增在sd卡上寫資料的許可權
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
(7)能夠拍照了,這下子要考慮如何讓圖片更好看了,這顯然是專業人士的強項,但是我們在程式上,也可以做一些處理,
向上面的那些,因為我直接把surfaceView當做整體佈局,就可能出現螢幕被拉開了,不是很好看,所以這時,就可以不要把
surfaceView弄成整體佈局,把他弄到到一個佈局管理器,在設定相關的引數.
這是需要注意的是有些引數不能隨便亂設,
如以下程式碼:Camera.Parameters parames = myCamera.getParameters();//獲得引數物件
parames.setPictureFormat(PixelFormat.JPEG);//設定圖片格式
parames.setPreviewSize(640,480);//這裡面的引數只能是幾個特定的引數,否則會報錯.(176*144,320*240,352*288,480*360,640*480)
myCamera.setParameters(parames);
還有自動對焦,當然有些手機沒有這個功能,自動對焦是通過autoFocus()這個方法呼叫一個自動對焦的介面,並在裡面進行處理。
注意,這個方法必須在startPreview()和stopPreview()中間。
AutoFocusCallback是自動對焦的介面,實現它必須實現public void onAutoFocus(boolean success, Camera camera)這個方法,
所以我們可以將拍照方法放在這裡面,然後對焦後再進行拍攝。。效果會好很多。
注意自動對焦需要新增<uses-feature android:name="android.hardware.camera.autofocus" />
下面我叫直接把上面的使用例子直接寫出。
CameraTest_4.java
<textarea cols="50" rows="15" name="code" class="java">import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.app.Activity; import android.content.pm.ActivityInfo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.PictureCallback; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.view.SurfaceHolder.Callback; import android.view.View.OnClickListener; public class CameraTest_4 extends Activity implements Callback, OnClickListener, AutoFocusCallback{ SurfaceView mySurfaceView;//surfaceView宣告 SurfaceHolder holder;//surfaceHolder宣告 Camera myCamera;//相機宣告 String filePath="/sdcard/wjh.jpg";//照片儲存路徑 boolean isClicked = false;//是否點選標識 //建立jpeg圖片回撥資料物件 PictureCallback jpeg = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // TODO Auto-generated method stub try {// 獲得圖片 Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length); File file = new File(filePath); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);//將圖片壓縮到流中 bos.flush();//輸出 bos.close();//關閉 }catch(Exception e) { e.printStackTrace(); } } }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);//無標題 //設定拍攝方向 this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); setContentView(R.layout.main); //獲得控制元件 mySurfaceView = (SurfaceView)findViewById(R.id.surfaceView1); //獲得控制程式碼 holder = mySurfaceView.getHolder(); //新增回撥 holder.addCallback(this); //設定型別 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //設定監聽 mySurfaceView.setOnClickListener(this); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub //設定引數並開始預覽 Camera.Parameters params = myCamera.getParameters(); params.setPictureFormat(PixelFormat.JPEG); params.setPreviewSize(640,480); myCamera.setParameters(params); myCamera.startPreview(); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub //開啟相機 if(myCamera == null) { myCamera = Camera.open(); try { myCamera.setPreviewDisplay(holder); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub //關閉預覽並釋放資源 myCamera.stopPreview(); myCamera.release(); myCamera = null; } @Override public void onClick(View v) { // TODO Auto-generated method stub if(!isClicked) { myCamera.autoFocus(this);//自動對焦 isClicked = true; }else { myCamera.startPreview();//開啟預覽 isClicked = false; } } @Override public void onAutoFocus(boolean success, Camera camera) { // TODO Auto-generated method stub if(success) { //設定引數,並拍照 Camera.Parameters params = myCamera.getParameters(); params.setPictureFormat(PixelFormat.JPEG); params.setPreviewSize(640,480); myCamera.setParameters(params); myCamera.takePicture(null, null, jpeg); } } }</textarea>
main.xml
AndroidManifest.xml
<textarea cols="50" rows="15" name="code" class="xhtml"><?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wjh.camera" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="7" /> <uses-permission android:name="android.permission.CAMERA"></uses-permission> <uses-feature android:name="android.hardware.camera.autofocus" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".CameraTest_4" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest></textarea>
相關文章
- 相機連不上關我上位機什麼事啊?
- 我的AI學習歷程(一):瞭解相機AI
- 我與快取的相愛相殺快取
- Restcloud ETL 我的演算法我做主RESTCloud演算法
- 【Flutter高階玩法- Flow 】我的位置我做主Flutter
- 組長問我幾天能開發一個人見人愛的百萬量級Android相機,我是這樣回答的...Android
- 智慧相機與工業相機的區別
- CameraX:Android 相機庫開發實踐Android
- 我與Linux的相識之旅Linux
- 相聲小品我幫您
- win10找不到相機怎麼辦_Win10電腦出現“我們找不到你的相機”如何解決Win10
- 相機360
- 老闆說相機APP實現美團功能!聽完我哭了。。。。。。。APP
- HarmonyOS開發例項:【相機和媒體庫】
- 1, 單相電機及單相調速電機
- 相機成像原理
- iOS 上的相機捕捉iOS
- 相機成像相關知識總結
- 散爆、青瓷相繼被“招安”,投資方:您看,我還有機會嗎?
- 移動機器人相機模型:從相機移動到二維影像機器人模型
- TOF相機簡介
- 拇指相機 比較
- 支付寶“手機網站支付”開發的相關文件和工具網站
- ps/lr如何為一個型號相機的raw使用其他相機的預設
- [轉發]淺談我在職場中與人相處的技巧
- 化身“監工”的AI,我們該如何相處?AI
- 盤點與我們日常相關的小程式
- three.js學習3_相機相關JS
- win10不能開啟相機怎麼解決 windows10無法開啟相機處理方法Win10Windows
- 我的javascript心跳機JavaScript
- Camera開發系列之二 相機資料回撥處理
- Halcon單相機標定
- OSG開發筆記(三十二):深入理解相機視口、製作支援與主檢視同步變換旋轉的相機HUD筆記
- iOS 14將隱私分享權還給使用者,我的資料我做主?iOS
- 敏捷開發相關敏捷
- Three.js開發指南(9):建立動畫和移動相機JS動畫
- Android開發在Activity外申請許可權呼叫相機開啟相簿Android
- 新一代Web安全治理體系讓“我的地盤我做主”不再只是夢Web