ZXing讀寫二維碼,桌面和手機的不同用法
雖然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上。命令行獲取:
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:
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 這個類包涵了各種條形碼生成器:
@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
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。
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
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 。
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();
}來自:http://my.oschina.net/yushulx/blog/493961