Android open source library using ZBar open source library to realize QR code function

In the project, Zxing has been used to realize the QR code function, but the recognition efficiency of ZXing is so low that in some extreme cases, the recognition effect is really unbearable. This is not necessarily an algorithm problem, but a big reason is Zxing Implemented using java. There is no other way but to try to use the ZBar open source library. This library is based on c/c++. It is well known that the recognition speed is much faster than ZXing!

Below is my complete compilation process of ZBar (refer to Yan Zhenjie's blog here ):

1. Download the source code

Go to ZBar's Github hosting homepage to download ZBar ;

Click on the Android directory on the Github hosting homepage of ZBar, and read the instructions below, telling us that libiconv is required to compile ZBar's Android SDK, so let's download libiconv first .

2. Compile libiconv

Compiling libiconv needs to be in the linux environment. I use the Cygwin client, but I can't compile it alive or dead. In the end, I still use the compilation provided by the reference blog ;

3. Compile zbar

  1. Put the libiconv compiled just now into the jni folder of our project.
  2. Unzip the Zbar you just downloaded, first put the folder where the Zbar header file is located zbar/includeinto the jni folder of our project.
  3. Put the interface file zbarjni.c of Zbar to java into the jni folder of our project, and zbrjni.c is under the zbar/javafolder.
  4. Put the folder where Zbar's core library files are located in zbar/zbarthe jni folder of our project.
  5. Android.mkCopy the , Applicaiton.mk, and , which config.hare needed when Zbar is compiled, to zbar\android\jnithe jni folder of our project.

At this point, the jni folder of our project looks like this: 
zbar

In theory, we can start compiling now, but because we changed the folder structure of zbar, we need to Android.mkmake changes, mainly to change the folder path and file path. The modified Android.mkcontent is as follows:

MY_LOCAL_PATH := $(call my-dir)

# libiconv
include $(CLEAR_VARS)
LOCAL_PATH := $(MY_LOCAL_PATH)
LOCAL_MODULE := libiconv
LOCAL_CFLAGS := \
    -Wno-multichar \
    -D_ANDROID \
    -DLIBDIR="c" \
    -DBUILDING_LIBICONV \
    -DBUILDING_LIBCHARSET \
    -DIN_LIBRARY

LOCAL_SRC_FILES := \
    libiconv-1.15/lib/iconv.c \
    libiconv-1.15/libcharset/lib/localcharset.c \
    libiconv-1.15/lib/relocatable.c

LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/libiconv-1.15/include \
    $(LOCAL_PATH)/libiconv-1.15/libcharset \
    $(LOCAL_PATH)/libiconv-1.15/libcharset/include

include $(BUILD_SHARED_LIBRARY)

LOCAL_LDLIBS := -llog -lcharset

# -----------------------------------------------------

# libzbar
include $(CLEAR_VARS)
LOCAL_PATH := $(MY_LOCAL_PATH)
LOCAL_MODULE := zbar
LOCAL_SRC_FILES := \
            zbarjni.c \
            zbar/img_scanner.c \
            zbar/decoder.c \
            zbar/image.c \
            zbar/symbol.c \
            zbar/convert.c \
            zbar/config.c \
            zbar/scanner.c \
            zbar/error.c \
            zbar/refcnt.c \
            zbar/video.c \
            zbar/video/null.c \
            zbar/decoder/code128.c \
            zbar/decoder/code39.c \
            zbar/decoder/code93.c \
            zbar/decoder/codabar.c \
            zbar/decoder/databar.c \
            zbar/decoder/ean.c \
            zbar/decoder/i25.c \
            zbar/decoder/qr_finder.c \
            zbar/qrcode/bch15_5.c \
            zbar/qrcode/binarize.c \
            zbar/qrcode/isaac.c \
            zbar/qrcode/qrdec.c \
            zbar/qrcode/qrdectxt.c \
            zbar/qrcode/rs.c \
            zbar/qrcode/util.c

LOCAL_C_INCLUDES := \
            $(LOCAL_PATH)/include \
            $(LOCAL_PATH)/zbar \
            $(LOCAL_PATH)/libiconv-1.15/include

LOCAL_SHARED_LIBRARIES := libiconv

include $(BUILD_SHARED_LIBRARY)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

Then Application.mkfill in the platform you want to compile, if you want to compile all:

APP_ABI := all
  • 1
  • 1

If you want to specify several platforms to compile, just write the platform names separated by spaces:

APP_ABI := armeabi armeabi-v7a x86 x86_64 mips mips_64 arm64_v8a
  • 1
  • 1

At this point, we use the command line to enter the parent directory of the jni folder of the project, and then execute ndk-buildthe compilation at this time.

Fourth, zbar Chinese garbled problem

1. Download the zbar source code at sourceforge and modify the file

zbar/qrcode/qrdectxt.c

 , about 62 lines, change the encoding standard ISO8859-1 to GBK or GB18030, as follows:

/*latin1_cd=iconv_open("UTF-8","ISO8859-1");*/
  latin1_cd=iconv_open("UTF-8","GB18030");

2. Continue to modify the above file zbar/qrcode/qrdectxt.c, about line 164, change the decoding order, and adjust the Chinese decoding to the first place as follows:

/*enc_list[0]=sjis_cd;
    enc_list[1]=latin1_cd;*/
    enc_list[0]=latin1_cd;
    enc_list[1]=sjis_cd;
After these two adjustments, the problem of Chinese garbled characters should be solved; (of course, after modifying the source code, remember to re-execute ndk-build to compile zbar).

3. Most of the Chinese garbled characters have been basically solved through Parts 1 and 2, but some Chinese characters are still garbled. For example, if the content of the QR code is "Guangdong 8888", the word "Guangdong" will be recognized as garbled characters;

This question refers to the blog . After identifying the QR code data, it is only necessary to determine whether the recognition result data is the Japanese code "Shift_JIS", if so, convert it to "utf-8" code, as follows:

try {
                String encodeResust = new String(qrCodeString.getBytes("Shift_JIS"), "utf-8");
                LogUtils.d(TAG + "--decodeBarcodeZbar--Convert 'Shift_JIS' encoding format to 'utf-8': " + encodeResust);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace ();
                LogUtils.e(TAG + "--decodeBarcodeZbar--The recognition result is not 'Shift_JIS' encoding format");
            }


5. Import the java code of zbar into the project

Copy the java files under the package and inside to the directory of your project. The approximate structure is as follows: zbar/Javanet.sourceforge.zbarjava
write picture description here

Pay attention to whether the name of the static library declared in the so library and the four java files of Image.java, ImageScanner.java, Symbol, java, SymbolSet.java needs to be modified.

因为我的so库名称是libzbar.so,所以静态库的声明代码需要改为:

System.loadLibrary("zbar");

六、Zbar调用

这里就不贴摄像头的调用和界面代码了,只贴一下调用Zbar识别二维码的代码:

 /**
     * 使用Zbar库识别二维码
     * @param imageData 图像数据(摄像头返回的)
     * @param width 图像的宽
     * @param height 图像的高
     * @param scanRect 扫描区域
     */
    public static String decodeBarcodeZbar(byte[] imageData, int width, int height, Rect scanRect){
        long start = System.currentTimeMillis();
        Image barcode = new Image(width, height, "Y800");
        barcode.setData(imageData);
        // 指定二维码在图片中的区域,也可以不指定,识别全图。
        if(null != scanRect) barcode.setCrop(scanRect.left, scanRect.top, scanRect.width(), scanRect.height());

        String qrCodeString = null;
        ImageScanner mImageScanner = new ImageScanner();

        int result = mImageScanner.scanImage(barcode);
        if (result != 0) {
            SymbolSet symSet = mImageScanner.getResults();
            for (Symbol sym : symSet)
                qrCodeString = sym.getData();
        }

        LogUtils.w(TAG + "--decodeBarcodeZbar: 总耗时:" + (System.currentTimeMillis() - start));

        if (!TextUtils.isEmpty(qrCodeString)) {
            // 成功识别二维码,qrCodeString就是数据。
            LogUtils.d(TAG + "--decodeBarcodeZbar--识别成功:" + qrCodeString);
            try {
                String encodeResust = new String(qrCodeString.getBytes("Shift_JIS"), "utf-8");
                LogUtils.d(TAG + "--decodeBarcodeZbar--将‘Shift_JIS’编码格式转成‘utf-8’:" + encodeResust);
                return encodeResust;
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                LogUtils.e(TAG + "--decodeBarcodeZbar--The recognition result is not 'Shift_JIS' encoding format");
                return qrCodeString;
            }
        }else{
            LogUtils.d(TAG + "--decodeBarcodeZbar--Recognition failed");
            return null;
        }
        
    }


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325988571&siteId=291194637