ZXing讀寫二維碼,桌面和手機的不同用法

jopen 9年前發布 | 48K 次閱讀 條形碼/二維碼開發包 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源碼

之前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

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!