How to Write and Read QR Code with ZXing in Java

ZXing is an open-source, 1D/2D barcode image processing library implemented in Java. The supported barcode formats include UPC-A, UPC-E, EAN-8, Code 93, Code 128, QR Code, Data Matrix, Aztec, PDF 417, etc. Besides the Java version, developers can leverage other ported projects such as QZXing, zxing-cpp, zxing_cpp.rb, python-zxing and ZXing .NET to quickly make barcode reader or writer software. According to the visualization report of Google trends, QR code seems to be the most popular barcode format since 2009. In this post, I’d like to share how to use ZXing to create QR code writer and reader for both desktop Java applications and Android mobile apps.


zxing barcode test

Getting ZXing Source Code

The ZXing project has moved from Google Code to GitHub. To get the source code, use the  following git command line:

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

Linking ZXing to Projects

There are two ways to link ZXing:

  • Build the source code to a jar file, and then import it to Java projects.  If you want to use Android Studio instead of Eclipse, please read Time to Migrate Android Projects to Android Studio.
  • Directly import the ZXing source code to Java projects. In Eclipse, select Project Properties > Java Build Path > Source > Link Source, and specify the source folder location: <zxing>\core\src\main\java. If the folder location is incorrect, you will see many package errors in the console.
    link zxing source folder

Taking a Glimpse of ZXing Source Code

Before implementing QR code writer and reader, let’s take a look at the basic Java classes in ZXing barcode library.

In Eclipse, search for the text implements Writer.

zxing barcode writer
Here are the 1D/2D barcode writers. All barcode formats are defined in 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

}

The class MultiFormatWriter has covered all supported barcode writers. Instead of any specific bar code writer, we just need to use MultiFormatWriter with a specified barcode format.

@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);
  }

Similarly, we can search for implements Reader:

zxing barcode reader

The MultiFormatReader will also simplify the code work.

QR Code Writer and Reader for Windows, Mac and Linux

Since ZXing is implemented in Java, it is easy to create cross-platform QR writer and reader software for Windows, Mac and Linux. To operate image data in Java, we need to use the class BufferedImage.

Writing QR Code with QRCodeWriter

       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();
		}
	}

Reading QR Code with QRCodeReader

We need to use RGBLuminanceSource to wrap RGB data:

        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;
	}

QR Code Generator and Reader for Android

Comparing to the Java code of the desktop application, the only difference is the way of operating image bytes on Android. In Android SDK, there is no class named BufferedImage. Instead, we should use Bitmap.

Generating QR Code to ImageView on Android

    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();
    }

Reading QR Code from Android Camera Preview

The preview data type of Android camera is NV21. So We need to use PlanarYUVLuminanceSource to wrap it.

            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();
            }
  • kamal kannan

    how to read 1d barcodes using zxing? i am using zxing to read barcodes, it reads oonly QR codes.

  • Nadir SAHLLAL

    hello can anyone help me plz i want a to generate and read PDF417, plz write me the code, thx in advance

  • Alexi

    Width and height are initialized, the strange thing is that with QR everything works fine. I think I’ll use QR instead of Data Matrix. Thanks for help.

  • http://www.dynamsoft.com/ Xiao Ling

    Have you initialized the ImageView with width and height? If not, set width 180 and height 180 and then try it again.

  • Alexi

    When I use .getWidth () and .getHeight, I have this error;
    java.lang.IllegalArgumentException: width and height must be > 0.

  • http://www.dynamsoft.com/ Xiao Ling

    Did you locate the crashed line with the debugger? Why do you assign 180 to width and height? Are they same to the width and height of imageViewDataMatrix? Try as follows:
    int width = imageViewDataMatrix.getWidth();
    int height = imageViewDataMatrix.getHeight();
    //int width = 180;
    //int height = 180;

  • Alexi

    I used DataMatrixWriter before, but another error appeared: java.lang.IllegalArgumentException: Can’t find a symbol arrangement that matches the message. Data codewords: 1

    This is my code:

    public static void writeDataMatrix(String codeValue) {
    QRCodeWriter writer = new QRCodeWriter();
    DataMatrixWriter writerMatrix = new DataMatrixWriter();
    try {
    //int width = imageViewDataMatrix.getWidth();
    //int height = imageViewDataMatrix.getHeight();
    int width = 180;
    int height = 180;
    BitMatrix bitMatrix = writerMatrix.encode(codeValue, BarcodeFormat.DATA_MATRIX, 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);
    }
    }
    imageViewDataMatrix.setImageBitmap(bitmap);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

  • http://www.dynamsoft.com/ Xiao Ling

    If you want to generate DataMatrix, you should use DataMatrixWriter instead of QRCodeWriter: DataMatrixWriter writer = new DataMatrixWriter();
    BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.DATA_MATRIX, width, height);

  • Alexi

    I want to generate a Data Matrix code in Android, but the Zxing library just suport QR code. The problem is in this line:

    BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.DATA_MATRIX, width, height);

    The only way is;

    BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height);

    (sorry for my english)

  • http://www.dynamsoft.com/ Xiao Ling

    I don’t quite understand what your problem is. What have you done? What do you want to do? Can you share your code?

  • Alexi

    I have this error; “Can only encode QR_CODE, but got DATA_MATRIX”

    in Android Studio,

    What I can do?