ZXing读写二维码,桌面和手机的不同用法

jopen 9年前

虽然ZXing是用Java实现的Barcode开源库,但是并不代表桌面上实现的Barcode应用在手机上也可以直接使用。因为Android的Java接口有很多是不同的。这里分享下Java Barcode生成和读取的不同用法。

参考原文:How to Write and Read QR Code with ZXing in Java

作者:Desmond Shaw

翻译:yushulx

ZXing读写二维码,桌面和手机的不同用法

获取ZXing源码

之前ZXing是放在Google Code上的,现在已经全部移到了GitHub上。命令行获取:

git clone https://github.com/zxing/zxing

在工程中添加ZXing

工程中导入ZXing有两方方法:

  1. 把ZXing编译成jar包,导入到工程中使用。比如在Android Studio中可以新建一个module,把ZXing源码导入之后就可以build出一个jar包。

  2. 直接使用ZXing源码。在工程属性中选择Project Properties > Java Build Path > Source > Link Source。确定输入正确的folder名称,不然会出现大量的package错误。ZXing读写二维码,桌面和手机的不同用法

ZXing源码解析

要生成二维码,需要用到Writer类。搜索implements Writer可以看到所有ZXing支持的Barcode Writer。

ZXing读写二维码,桌面和手机的不同用法

这里包含了所有的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看到对应的类:

ZXing读写二维码,桌面和手机的不同用法

使用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