在生活中常常可以看到條碼(Barcode)的存在,無論是商品結帳時在收銀台使用的EAN條碼、書籍使用的ISBN條碼,還是在最近因行動裝置的流行也跟著帶動起來的QR Code,這些條碼都可以讓我們的生活更便利,傳遞資訊的速度更快,省下許多使用鍵盤打字的時間。大多數的Android裝置,都有配備相機(Camera)功能,因此可以直接使用Android的相機功能來拍攝出條碼的樣子,再使用一些影像處理的演算法來解析出條碼的內容。在Android上最常用來辨識條碼影像的工具,應該是使用純Java語言的zxing開源專案,因為不需要動用到C/C++層的Native Code,所以應用起來十分容易。但是使用Java的話,就會有效能不好的缺點,因此,這篇文章將提供另一個選擇,也就是使用以C語言為基礎的zBar來完成條碼辨識。
zBar
zBar可以支援的條碼有EAN-8、EAN-13、UPC-E、UPC-A、ISBN-10、ISBN-13、Interleaved 2 of 5(交錯式25條碼)、DataBar、DataBar Expanded、Codabar、Code 39、Code 93、Code 128、PDF417、QR Code。開源專案網址如下:
官方已經有提供編譯好的Android SDK,可以直接下載下來,將.so檔和.jar檔案加入Android專案中的「libs」資料夾即可使用。只是如果直接這樣用的話,可能會遭遇到很多問題,最常見的就是文字亂碼的問題,亂碼問題與zBar預設的字元編碼以及使用到的libiconv版本有關。因此建議如果要使用zBar的話,還是自己使用JNI和Android NDK來編譯出最新的版本吧!
編譯zBar For Android
編譯環境:Linux Mint 17 MATE
取得zBar
zBar的原始碼可以直接在zBar的SourceForge上取得。只是要注意的是,最好不要使用官方打包好、正式發佈的zBar版本,版本可能過舊,能夠解析的條碼種類也會比較少。所以建議將zBar目前最新的專案資料夾整個打包下載回來。
取得libiconv
zBar可以使用libiconv來協助進行編碼的預測與轉換,libiconv的開源專案網址如下:
加入JNI支援至Android 專案
在編譯zBar For Android時,會使用到JNI,所以要讓Android專案能支援JNI。如果您還不知道怎麼樣加入JNI至Android專案中,可以參考這篇文章:
將zBar和libiconv原始碼放置於Android專案下
把剛才下載下來的zBar和libiconv原始碼目錄放置在Android的專案下,為了要讓.mk設定檔能直接套用,需分別命名成「zbarSDK-master」和「libiconv」。
加入Android.mk和Application.mk至JNI目錄
在官方的zBar專案中有這兩個檔案可以在「android/jni」目錄下找到,但是編譯時Android.mk檔案內的路徑還要另外設置,於是筆者稍微將它修改了一下。下載網址:
配置libiconv
將終端機的工作目錄移動到libiconv目錄下,執行以下指令來配置libiconv的編譯設定:
使用ndk-build來編譯
將終端機下的工作目錄移動到Android專案的目錄下,執行以下指令使用Android NDK開始編譯libiconv和zbar。
編譯成功的話可以看到以下畫面:
並且可以在「libs」目錄中找到編譯出來的.so檔案。
然而,現實總是不會如此順利。如果編譯過程有問題發生,請繼續按照以下方式修改。
找不到langinfo.h
編譯時若是出現localcharset.c找不到langinfo.h的訊息,如下圖:
要修改libiconv目錄下,「libcharset」目錄裡的「config.h」檔案,將「HAVE_LANGINFO_CODESET」這個巨集設為「0」。
「c」變數沒有宣告
編譯時若是出現localcharset.c中「'c' undeclared」的訊息,如下圖:
要修改libiconv目錄下,「libcharset/lib」目錄裡的「localcharset.c」檔案,在發生未宣告「c」錯誤的那行程式碼前,加上「int c;」宣告出「c」變數即可。
編譯成功,但在執行時,libiconv.so的「__ctype_get_mb_cur_max」會出錯
這似乎是NDK的BUG,在stdlib.h內有宣告出__ctype_get_mb_cur_max函數,但是卻沒有去實作它。如果出現這個問題,不建議直接修改NDK,要到libiconv目錄下,修改「libcharset/lib」目錄裡的「localcharset.c」檔案,在檔案最下面加上以下程式碼即可。
size_t __ctype_get_mb_cur_max(void){
return 1;
}
使用zBar For Android
編譯出zBar的.so檔之後,要如何在Android SDK下使用呢?還要透過JNI嗎?不用,我們其實已經在Android.mk檔配置中將JNI的程式編譯進.so檔中了,因此只要在Android SDK的Java程式中讀入.so函式庫,並宣告出Native的方法,即可使用zBar的功能。這部份的程式在zBar目錄下的「java」目錄中可以找到,只要將程式碼加到Android專案中的「src」目錄下就可以使用。
至於用法的話,就參考一下zBar目錄下的「android」目錄裡的範例吧!
解決zBar讀取QR Code會有亂碼的問題
讀取QR Code會有亂碼並不是zBar的問題,而是QR Code並沒有統一的字元編碼方式,許多人常會使用內碼來產生QR Code,如果在讀取QR Code時不知道當初這個QR Code是以何種方式編碼字元的話,那就沒辦法正常地將字元解碼還原。zBar能夠做到的,最多只是「猜」這個QR Code是用什麼編碼而已。如果要控制zBar猜QR Code編碼的方式的話,可以修改zBar目錄下「zbar/qrcode」中的「qrdectxt.c」檔案。
enc_list陣列的大小和順序,就是猜測編碼的種類數量和猜測順序。修改一下,讓它能符合自己的需求吧!