1. 程式人生 > >Android二維碼掃描開發(一):實現思路與原理

Android二維碼掃描開發(一):實現思路與原理

【 回覆“ 1024 ”,送你一個特別推送 】

現在二維碼已經非常普及了,那麼二維碼的掃描與處理也成為了Android開發中的一個必要技能。網上有很多關於Android中二維碼處理的帖子,大都是在講開源框架zxing用法,然後貼貼程式碼就完了,並沒有一個系統的分析和原理解析。其中涉及到的Camera的操作和YUV影象處理,也大都沒有詳細的介紹。所以我自己寫了這篇文章,把Android二維碼的開發來從頭捋一下。

本例介面如下圖所示,程式碼連結在文章最下方。

二維碼處理流程分為幾個步驟:

  1. 初始化相機,設定一些相機引數; 

  2. 繫結SurfaceView,在SurfaceView上顯示預覽影象; 

  3. 獲取相機的一幀影象; 

  4. 對影象進行一定的預處理,只保留亮度資訊,成為灰度影象;

  5. 對灰度影象進行二維碼解析,解析成功進入下一步,不成功回到第③步; 

  6. 返回解析結果並退出。

流程圖如下圖所示:

一、初始化相機

相機使用的是android.hardware.Camera這個類,在Android 5.0之後,推薦使用更強大的android.hardware.Camera2這個類,為了相容更低版本Android系統,我們在這裡仍然使用Camera類來實現。

Camera可以通過setDisplayOrientation()方法設定預覽影象的方向,旋轉度數只能是0、90、180、270中的一個,根據需求,本例中設定為90度。

Camera還可以通過Camera.Parameters類設定預覽影象的解析度,但是隻能在氣可支援的解析度中選擇一個,不能隨便設定,我們需要根據螢幕大小,在其中選出一個最佳的預覽影象解析度,太大浪費資源,太小會顯示不清楚,具體選擇方法,在程式碼中有,這裡就不細述了。

Camera可以通過setPreviewFormat()方法來設定預覽影象的資料格式,推薦選擇的有ImageFormat.NV21和ImageFormat.YV12,預設是NV21。NV21屬於YUV影象,和RGB影象有所不同,YUV影象在下一篇會有詳細介紹。

注意在使用Camera時,需要在AndroidManifest.xml裡宣告一些許可權:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.camera.flash" />

二、繫結SurfaceView

在SurfaceView建立好後,通過Camera類的setPreviewDisplay()方法,將SurfaceHolder傳入Camera。

呼叫Camera的startPreview()方法,Camera捕捉到的影象就會顯示到SurfaceView上了。

三、獲取一幀影象

呼叫Camera的setOneShotPreviewCallback(PreviewCallback cb)方法,可以請求獲取一幀影象,獲取到影象後,會呼叫PreviewCallback的onPreviewFrame(byte[] data, Camera camera)方法,其中的data引數就是影象的YUV資料了。

四、影象預處理

根據二維碼的原理,我們只需要影象的亮度資訊來進行二維碼解析,所以我們要把獲取到的彩色影象轉換為灰度影象。YUV影象轉換為灰度影象的方法,以及RGB影象轉換為灰度影象的方法,在後續文章中會有介紹,這裡只說原理,具體實現就不再贅述。

五、二維碼解析

在這裡,二維碼解析使用的是google的zxing開源框架,把上一步處理後的灰度影象,封裝為zxing的LuminanceSource,再封裝為zxing的BinaryBitmap,然後就可以進行二維碼解析了。

值得一提的是,利用zxing解析二維碼是耗時操作,為避免ANR,需要寫到子執行緒中來處理。

具體程式碼在這裡就不貼了,後續章節中將會對zxing的使用及LuminanceSource的處理做詳細解答。

六、解析結果

本例中,除了返回解析到的字串之外,還對LuminanceSource增加了一個renderCroppedGreyScaleBitmap()方法,用來生成處理好的灰度影象Bitmap。

二維碼掃描的大致流程和原理就敘述到這裡了,下一篇將會對YUV影象進行詳細的介紹。

原始碼地址: https://github.com/xushanmeng/QRCodeScannerDemo