虽然ZXing是用Java实现的Barcode开源库,但是并不代表桌面上实现的Barcode应用在手机上也可以直接使用。因为Android的Java接口有很多是不同的。这里分享下Java Barcode生成和读取的不同用法。
参考原文:How to Write and Read QR Code with ZXing in Java
作者:Desmond Shaw
翻译:yushulx
获取ZXing源码
之前ZXing是放在Google Code上的,现在已经全部移到了GitHub上。命令行获取:
1
|
git clone https:
//github
.com
/zxing/zxing
|
在工程中添加ZXing
工程中导入ZXing有两方方法:
-
把ZXing编译成jar包,导入到工程中使用。比如在Android Studio中可以新建一个module,把ZXing源码导入之后就可以build出一个jar包。
-
直接使用ZXing源码。在工程属性中选择Project Properties > Java Build Path > Source > Link Source。确定输入正确的folder名称,不然会出现大量的package错误。
ZXing源码解析
要生成二维码,需要用到Writer类。搜索implements Writer可以看到所有ZXing支持的Barcode Writer。
这里包含了所有的1D/2D条形码。ZXing支持的条形码类型可以查询BarcodeFormat.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
|
public
enum
BarcodeFormat {
/** Aztec 2D barcode format. */
AZTEC,
/** CODABAR 1D format. */
CODABAR,
/** Code 39 1D format. */
CODE_39,
/** Code 93 1D format. */
CODE_93,
/** Code 128 1D format. */
CODE_128,
/** Data Matrix 2D barcode format. */
DATA_MATRIX,
/** EAN-8 1D format. */
EAN_8,
/** EAN-13 1D format. */
EAN_13,
/** ITF (Interleaved Two of Five) 1D format. */
ITF,
/** MaxiCode 2D barcode format. */
MAXICODE,
/** PDF417 format. */
PDF_417,
/** QR Code 2D barcode format. */
QR_CODE,
/** RSS 14 */
RSS_14,
/** RSS EXPANDED */
RSS_EXPANDED,
/** UPC-A 1D format. */
UPC_A,
/** UPC-E 1D format. */
UPC_E,
/** UPC/EAN extension format. Not a stand-alone format. */
UPC_EAN_EXTENSION
}
|
MultiFormatWriter 这个类包涵了各种条形码生成器:
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
|
@Override
public
BitMatrix encode(String contents,
BarcodeFormat format,
int
width,
int
height,
Map<EncodeHintType,?> hints)
throws
WriterException {
Writer writer;
switch
(format) {
case
EAN_8:
writer =
new
EAN8Writer();
break
;
case
EAN_13:
writer =
new
EAN13Writer();
break
;
case
UPC_A:
writer =
new
UPCAWriter();
break
;
case
QR_CODE:
writer =
new
QRCodeWriter();
break
;
case
CODE_39:
writer =
new
Code39Writer();
break
;
case
CODE_128:
writer =
new
Code128Writer();
break
;
case
ITF:
writer =
new
ITFWriter();
break
;
case
PDF_417:
writer =
new
PDF417Writer();
break
;
case
CODABAR:
writer =
new
CodaBarWriter();
break
;
case
DATA_MATRIX:
writer =
new
DataMatrixWriter();
break
;
case
AZTEC:
writer =
new
AztecWriter();
break
;
default
:
throw
new
IllegalArgumentException(
"No encoder available for format "
+ format);
}
return
writer.encode(contents, format, width, height, hints);
}
|
同样的,可以搜索implements Reader看到对应的类:
使用MultiFormatReader可以简化代码。
Windows, Mac和Linux上二维码的生成和读取
使用Java创建桌面Barcode应用,需要用到BufferedImage来操作图像。
Java QRCode Writer
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
|
public
static
void
writeQRCode() {
QRCodeWriter writer =
new
QRCodeWriter();
int
width =
256
, height =
256
;
BufferedImage image =
new
BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// create an empty image
int
white =
255
<<
16
|
255
<<
8
|
255
;
int
black =
0
;
try
{
BitMatrix bitMatrix = writer.encode(
"http://www.codepool.biz/zxing-write-read-qrcode.html"
, BarcodeFormat.QR_CODE, width, height);
for
(
int
i =
0
; i < width; i++) {
for
(
int
j =
0
; j < height; j++) {
image.setRGB(i, j, bitMatrix.get(i, j) ? black : white);
// set pixel one by one
}
}
try
{
ImageIO.write(image,
"jpg"
,
new
File(
"dynamsoftbarcode.jpg"
));
// save QR image to disk
}
catch
(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
catch
(WriterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
|
Java QRCode Reader
在读取图像数据的时候,需要使用RGBLuminanceSource来封装数据RGB。
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
|
public
static
String readQRCode(String fileName) {
File file =
new
File(fileName);
BufferedImage image =
null
;
BinaryBitmap bitmap =
null
;
Result result =
null
;
try
{
image = ImageIO.read(file);
int
[] pixels = image.getRGB(
0
,
0
, image.getWidth(), image.getHeight(),
null
,
0
, image.getWidth());
RGBLuminanceSource source =
new
RGBLuminanceSource(image.getWidth(), image.getHeight(), pixels);
bitmap =
new
BinaryBitmap(
new
HybridBinarizer(source));
}
catch
(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if
(bitmap ==
null
)
return
null
;
QRCodeReader reader =
new
QRCodeReader();
try
{
result = reader.decode(bitmap);
return
result.getText();
}
catch
(NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch
(ChecksumException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch
(FormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return
null
;
}
|
Android上二维码的生成和读取
在Android平台上,BufferedImage是不存在的。取而代之的是Bitmap。
Android QRCode Writer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
QRCodeWriter writer =
new
QRCodeWriter();
try
{
int
width = mImageView.getWidth();
int
height = mImageView.getHeight();
BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
for
(
int
i =
0
; i < width; i++) {
for
(
int
j =
0
; j < height; j++) {
bitmap.setPixel(i, j, bitMatrix.get(i, j) ? Color.BLACK: Color.WHITE);
}
}
mImageView.setImageBitmap(bitmap);
}
catch
(WriterException e) {
e.printStackTrace();
}
|
Android QRCode Reader
从camera预览进来的数据是NV21格式的,所以在封装数据的时候需要使用PlanarYUVLuminanceSource 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
MultiFormatReader reader =
new
MultiFormatReader();
LuminanceSource source =
new
PlanarYUVLuminanceSource(yuvData, dataWidth, dataHeight, left, top, width, height,
false
);
BinaryBitmap bitmap =
new
BinaryBitmap(
new
HybridBinarizer(source));
Result result;
try
{
result = reader.decode(bitmap);
if
(result !=
null
) {
mDialog.setTitle(
"Result"
);
mDialog.setMessage(result.getText());
mDialog.show();
}
}
catch
(NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
|