標籤:
雖然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();}
ZXing讀寫二維碼,案頭和手機的不同用法