很多手机app条形码应用都使用了ZXing和ZBar两个开源条形码SDK。那么从检测速度和检测率看哪个更出色呢?ZXing用Java实现,ZBar用C/C++实现,为了确保公平,这里用JNI封装ZBar,用Java写测试。

参考原文:How to Benchmark Barcode SDK Performance – ZXing vs ZBar

作者:Desmond Shaw

翻译:yushulx

SDK下载

ZXing Source code

https://github.com/zxing/zxing

ZBar Source Code

https://github.com/ZBar/ZBar

ZBar Windows Installer

http://sourceforge.net/projects/zbar/files/zbar/

如何使用Java解码TIFF文件

通过Java SDK中的ImageIO,我们可以解码很多图片格式,比如JPEG,PNG,BMP。但是TIFF是不支持的。实际使用的时候,经常会用到TIFF文件读取条形码。Oracle官方提供了Java Advanced Imaging (JAI)来支持TIFF。

JAI下载

照理说Oracle的官网是应该提供JAI的下载链接的。但是很奇怪的是打开之后都是404错误。在网上搜了一圈,找到了一个可用链接:http://www.java2s.com/Code/Jar/j/Downloadjaicore113jar.htm。使用的时候需要下载jai_codec-1.1.3.jar和jai_core-1.1.3.jar。这里是一个把TIFF读到int[]的例子:

?
1
2
3
4
File file = new File(fileName);
RenderedImage tiff = JAI.create("tiffload", fileName);
BufferedImage image = PlanarImage.wrapRenderedImage(tiff).getAsBufferedImage();
int[] pixels = image.getRGB(00, image.getWidth(), image.getHeight(), null0, image.getWidth();

使用ZXing读取图片中的多个条形码

ZXing中的MultiFormatReader是用来读取一个条形码的,要读取多个条形码,需要把它放到GenericMultipleBarcodeReader中:

?
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
RGBLuminanceSource source = new RGBLuminanceSource(image.getWidth(),
        image.getHeight(), pixels);
bitmap = new BinaryBitmap(new HybridBinarizer(source));
  
Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
hints.put(DecodeHintType.TRY_HARDER, null);
Collection<BarcodeFormat> formats = new ArrayList<>();
formats.add(BarcodeFormat.QR_CODE);
formats.add(BarcodeFormat.CODABAR);
formats.add(BarcodeFormat.CODE_39);
formats.add(BarcodeFormat.CODE_93);
formats.add(BarcodeFormat.CODE_128);
formats.add(BarcodeFormat.EAN_8);
formats.add(BarcodeFormat.EAN_13);
formats.add(BarcodeFormat.ITF);
formats.add(BarcodeFormat.UPC_A);
formats.add(BarcodeFormat.UPC_E);
formats.add(BarcodeFormat.UPC_EAN_EXTENSION);
  
hints.put(DecodeHintType.POSSIBLE_FORMATS, formats);
MultiFormatReader reader = new MultiFormatReader(); 
  
// read multi barcodes
GenericMultipleBarcodeReader multiReader = new GenericMultipleBarcodeReader(
        reader);
try {
    Result[] results = multiReader.decodeMultiple(bitmap, hints);
    System.out.println(ZXING + TIME_COST
            + ((System.nanoTime() - start) / 1000000) + MS);
    if (results != null) {
        for (Result result : results) {
            System.out.println(ZXING + TYPE + result.getBarcodeFormat() + VALUE + result.getText());
        }
    }
catch (NotFoundException e) {
    e.printStackTrace();
    return;
}

ZBar JNI

要用JNI封装ZBar,最简单的方法就是参考自带的例子scan_image.cpp。把main函数改成JNI的接口就行了,在底层获取数据之后返回给Java层:

?
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <iostream>
#include <Magick++.h>
#include <zbar.h>
#include <jni.h>
#define STR(s) #s
  
using namespace std;
using namespace zbar;
  
#ifndef DEBUG
#define DEBUG(...) printf(__VA_ARGS__)
#endif
  
extern "C" {
    JNIEXPORT jobjectArray JNICALL Java_com_dynamsoft_zbar_ZBarReader_decode(JNIEnv *env, jobject obj, jstring fileName);
}
  
JNIEXPORT jobjectArray JNICALL Java_com_dynamsoft_zbar_ZBarReader_decode(JNIEnv *env, jobject obj, jstring fileName)
{
    const char *pszFileName = env->GetStringUTFChars(fileName, 0);
  
#ifdef MAGICK_HOME
    // http://www.imagemagick.org/Magick++/
    //    under Windows it is necessary to initialize the ImageMagick
    //    library prior to using the Magick++ library
    Magick::InitializeMagick(MAGICK_HOME);
#endif
  
    // create a reader
    ImageScanner scanner;
  
    // configure the reader
    scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
  
    // obtain image data
    Magick::Image magick(pszFileName);  // read an image file
    int width = magick.columns();   // extract dimensions
    int height = magick.rows();
    Magick::Blob blob;              // extract the raw data
    magick.modifyImage();
    magick.write(&blob, "GRAY"8);
    const void *raw = blob.data();
  
    // wrap image data
    Image image(width, height, "Y800", raw, width * height);
  
    // scan the image for barcodes
    int n = scanner.scan(image);
  
    // find java class
    jclass clsZBarResult = env->FindClass("com/dynamsoft/zbar/ZBarResult");
    // create java array
    int data_length = 0;
    for (Image::SymbolIterator symbol = image.symbol_begin();
        symbol != image.symbol_end();
        ++symbol) {
        ++data_length;
    }
  
    jobjectArray clsZBarResultArray = env->NewObjectArray(data_length, clsZBarResult, 0);
    int iIndex = 0;
  
    // extract results
    for (Image::SymbolIterator symbol = image.symbol_begin();
        symbol != image.symbol_end();
        ++symbol) {
        // do something useful with results
        //cout << "ZBR Type: " << symbol->get_type_name()
        //  << ", Value \"" << symbol->get_data() << '"' << endl;
  
        // save result to java array
        jmethodID init = env->GetMethodID(clsZBarResult, "<init>""()V");
        jobject clsZBarResultObj = env->NewObject(clsZBarResult, init);
        jfieldID jType = env->GetFieldID(clsZBarResult, "mType""Ljava/lang/String;");
        jfieldID jValue = env->GetFieldID(clsZBarResult, "mValue""Ljava/lang/String;");
        env->SetObjectField(clsZBarResultObj, jType, env->NewStringUTF(symbol->get_type_name().c_str()));
        env->SetObjectField(clsZBarResultObj, jValue, env->NewStringUTF(symbol->get_data().c_str()));
        env->SetObjectArrayElement(clsZBarResultArray, iIndex, clsZBarResultObj);
        ++iIndex;       
    }
  
    // clean up
    image.set_data(NULL, 0);
  
    // release string
    env->ReleaseStringUTFChars(fileName, pszFileName);
  
    return clsZBarResultArray;
}

这里你会需要用到ImageMagick x86版本,下载地址:http://www.imagemagick.org/script/binary-releases.php。

相关的Java类如下:

ZBarReader.java

?
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
package com.dynamsoft.zbar;
  
import com.dynamsoft.utils.BaseReader;
  
public class ZBarReader extends BaseReader {
  
    static {
        System.loadLibrary("zbarjni");
    }
  
    public void testZBar(String fileName) {
        long start = System.nanoTime();
        ZBarReader reader =  new ZBarReader();
        ZBarResult[] results = (ZBarResult[])reader.decode(fileName);
        System.out.println(ZBAR + TIME_COST
                + ((System.nanoTime() - start) / 1000000) + MS);
  
        if (results != null && results.length > 0) {
            mCount += 1;
            for (ZBarResult result : results) {
                System.out.println(ZBAR + TYPE + result.mType + VALUE + result.mValue);
            }
        }
    }
  
    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return super.getCount();
    }
  
    public native Object[] decode(String fileName);
}

ZBarResult.java

?
1
2
3
4
5
6
package com.dynamsoft.zbar;
  
public class ZBarResult {
    public String mType;
    public String mValue;
}

性能PK

找一些数据集来测试。多条形码测试可以使用Dynamsoft的测试数据https://github.com/Dynamsoft/Dynamsoft-Barcode-Reader/tree/master/Images,单条形码可以使用ZXing的数据https://github.com/zxing/zxing/tree/master/core/src/test/resources。这里用ZXing的二维码数据https://github.com/zxing/zxing/tree/master/core/src/test/resources/blackbox/qrcode-1来做一个测试对比,结果如下:

?
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
F:\resources\blackbox\qrcode-1\1.png
  
ZXI Time cost: 122ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 33ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\10.png
  
ZXI Time cost: 66ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 28ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\11.png
  
ZXI Time cost: 53ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 29ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\12.png
  
ZXI Time cost: 71ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 29ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\13.png
  
ZXI Time cost: 84ms
  
ZXI Type: QR_CODE, value: http://google.com/gwt/n?u=bluenile.com
  
ZBA Time cost: 27ms
  
ZBA Type: QR-Code, value: http://google.com/gwt/n?u=bluenile.com
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\14.png
  
com.google.zxing.NotFoundException
  
ZBA Time cost: 32ms
  
ZBA Type: QR-Code, value: http://google.com/gwt/n?u=bluenile.com
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\15.png
  
ZXI Time cost: 90ms
  
ZXI Type: QR_CODE, value: http://google.com/gwt/n?u=bluenile.com
  
ZBA Time cost: 34ms
  
ZBA Type: QR-Code, value: http://google.com/gwt/n?u=bluenile.com
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\16.png
  
ZXI Time cost: 77ms
  
ZXI Type: QR_CODE, value: Sean Owen
  
srowen@google.com
  
917-364-2918
  
http://awesome-thoughts.com
  
ZBA Time cost: 35ms
  
ZBA Type: QR-Code, value: Sean Owen
  
srowen@google.com
  
917-364-2918
  
http://awesome-thoughts.com
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\17.png
  
ZXI Time cost: 82ms
  
ZXI Type: QR_CODE, value: Sean Owen
  
srowen@google.com
  
917-364-2918
  
http://awesome-thoughts.com
  
ZBA Time cost: 32ms
  
ZBA Type: QR-Code, value: Sean Owen
  
srowen@google.com
  
917-364-2918
  
http://awesome-thoughts.com
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\18.png
  
ZXI Time cost: 80ms
  
ZXI Type: QR_CODE, value: Sean Owen
  
srowen@google.com
  
917-364-2918
  
http://awesome-thoughts.com
  
ZBA Time cost: 35ms
  
ZBA Type: QR-Code, value: Sean Owen
  
srowen@google.com
  
917-364-2918
  
http://awesome-thoughts.com
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\19.png
  
ZXI Time cost: 64ms
  
ZXI Type: QR_CODE, value: Sean Owen
  
srowen@google.com
  
917-364-2918
  
http://awesome-thoughts.com
  
ZBA Time cost: 28ms
  
ZBA Type: QR-Code, value: Sean Owen
  
srowen@google.com
  
917-364-2918
  
http://awesome-thoughts.com
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\2.png
  
ZXI Time cost: 61ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 28ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\20.png
  
ZXI Time cost: 55ms
  
ZXI Type: QR_CODE, value: Sean Owen
  
srowen@google.com
  
917-364-2918
  
http://awesome-thoughts.com
  
ZBA Time cost: 30ms
  
ZBA Type: QR-Code, value: Sean Owen
  
srowen@google.com
  
917-364-2918
  
http://awesome-thoughts.com
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\3.png
  
ZXI Time cost: 56ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 29ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\4.png
  
ZXI Time cost: 70ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 28ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\5.png
  
ZXI Time cost: 64ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 28ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\6.png
  
ZXI Time cost: 56ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 28ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\7.png
  
ZXI Time cost: 73ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 30ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\8.png
  
ZXI Time cost: 55ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 27ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
       F:\resources\blackbox\qrcode-1\9.png
  
ZXI Time cost: 55ms
  
ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
ZBA Time cost: 27ms
  
ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;
  
-------------------------------------------------------------------------------------
  
ZXI passed: 19
  
ZBA passed: 20

结果发现,ZBar的二维码解码速度居然比ZXing快很多!感兴趣的同学可以去测试下别的数据。

源码

https://github.com/Dynamsoft/Dynamsoft-Barcode-Reader/tree/master/samples/Java

ZXing vs ZBar: 开源条形码SDK性能PK相关推荐

  1. ZXing是一个开源Java类库用于解析多种格式的条形码和二维码

    ZXing是一个开源Java类库用于解析多种格式的条形码和二维码 2014年05月07日 17:30:37 shine4j 阅读数 5677 blog迁移至:http://www.micmiu.com ...

  2. c语言编程图片识别条形码,基于Zbar的条形码图像识别算法的制作方法

    本发明涉及条形码识别技术领域,特别是涉及一种基于Zbar的条形码图像识别算法. 背景技术: 条形码是将宽度不等的多个黑条和空白,按一定的编码规则排列,用以表达一组信息的图形标识符.随着科技的迅速发展, ...

  3. 表格存储的Java SDK性能优化经验

    原文发布于阿里云论坛,在圈子内重发. 问题背景 用户通过Java SDK来访问表格存储,在SDK内部也是有开销的,在高并发的场景下这些开销尤其突出.如果SDK的性能很差,用户为了达到更高的QPS,可能 ...

  4. 英伟达推出新款“煤气灶”Titan RTX,售价近2万,并开源PhysX SDK

    晓查 郭一璞 安妮 乾明 发自 凹非寺 量子位 出品 | 公众号 QbitAI 刚刚,英伟达发布Titan RTX. 和传言一样,Titan RTX配备72 颗Turing RT核心.4608颗CUD ...

  5. Zxing与 Zbar生成二维码最简单的实现方式

    Zxing与 Zbar生成二维码最简单的实现方式 导入依赖 implementation 'cn.bingoogolapple:bga-qrcode-zbar:1.2.1' 或者 implementa ...

  6. Java与Node.js性能PK

    原文链接:www.tandemseven.com/b... 如果你打开浏览器,搜索"Java与Node.js哪个更快",你会发现大部分答案声称Node.js更快,也有一些人持相反意 ...

  7. ML之xgboostGBM:基于xgboostGBM算法对HiggsBoson数据集(Kaggle竞赛)训练(两模型性能PK)实现二分类预测

    ML之xgboost&GBM:基于xgboost&GBM算法对HiggsBoson数据集(Kaggle竞赛)训练(两模型性能PK)实现二分类预测 目录 输出结果 设计思路 核心代码 输 ...

  8. CITAHub 社区成员开源 CITA SDK Python 组件

    CITAHub 社区成员有大家科技,在不断推进区块链内核 CITA 研究的同时,正式开源了 CITA SDK Python.这是开源区块链内核 CITA 收到的第一个社区成员贡献的 SDK 组件. 作 ...

  9. android epub 开源,EPUB SDK

    问题:Neat EPUB SDK 有哪些优点? 回答:目前市面上的EPUB SDK一般分为两种,一种是免费的开源项目,一种是低价的SDK. 开源EPUB SDK,目前几乎都是疏于维护的状态,要么更新缓 ...

最新文章

  1. 皮一皮:打完疫苗千万别睡太死...
  2. MySQL第4天:MySQL的架构介绍之修改数据库编码格式
  3. 042_JDK的Map接口
  4. 数据扩张:数据的杠杆作用
  5. linux安装tf-gpu注意事项
  6. StringBuilder与String互转
  7. 基因分子生物学~DNA与蛋白质模板
  8. MapReduce运行机制-Map阶段
  9. 返回局部变量或临时变量的地址_值传递和地址返回两者在堆区(Heap)应用的三种易错点...
  10. python实现组合问题_python3 最基本且简单的实现组合设计模式
  11. Spring Cloud Sleuth 原理简介和使用
  12. 机器学习2/100天-简单线性回归
  13. iOS设计模式 - 单例
  14. 2018考研信工所二室
  15. 高通X12平台XO信号干扰灵敏度的解决方案
  16. python3+selenium实现126邮箱登陆 _修改个人设置(未封装)
  17. arcmap fishnet 经纬度
  18. Tableau 2020.2版本如何做环形图
  19. win10任务栏图标两个以上不显示缩略图且不显示桌面预览解决方案
  20. fzu2198 快来快来数一数

热门文章

  1. CSK与KCF算法推导(二)
  2. sm4 的s盒_商密算法SM2、SM3、SM4的用途和原理
  3. js调用扫描仪(Web Twain Scan)-兼容Chrome、Edge、360、Firefox、IE、钉钉、企业微信等
  4. 安超OS为企业数字化转型构建坚实的云基座
  5. CSS:精灵图 字体图标
  6. Python - 在定义函数时,为什么默认参数不能放在必选参数前面?
  7. 编写python代码获取4k高清壁纸
  8. Codeforces 844A
  9. 使用NTS理解细粒度图像分类
  10. 激光雷达SLAM方法汇总 | 自动驾驶和移动机器人领域