Generate QR codes (Java)

Generate QR codes (Java)

Overview

A QR code (Quick Response code) is a type of a barcode invented in 1994 by the Japanese automotive company Denso Wave. In this article, we’ll get a basic information about QR codes in general and will learn how to generate QR codes in a Java application.

Nowadays, QR codes are widely used in various applications:

  • to store a link to a web resource (restaurant menu, historical place description, etc.)
  • to store a link to a social network profile
  • to store a product tracking identifier
  • to join a Wi-Fi network
  • others

Here is how QR codes look like:

Generate QR codes

QR codes have a fixed structure:

  • positioning detection markers (located at three corners)
  • alignment markings
  • timing pattern (define the size of the data matrix)
  • version information
  • format information (error tolerance and data mask pattern)
  • data and error correction keys
  • quiet zone (to distinguish the QR Code from its surroundings)

What about the amount of data to be stored in QR codes, they can store for example ~4Kb of alphanumeric characters.

Generate QR codes

There are various libraries to generate QR codes. In this tutorial, we’ll explore ZXing library.

First of all, let’s add the following Maven dependencies:

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.3.0</version>
</dependency>
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.3.0</version>
</dependency>

Now let’s create a service that takes an input string and generates a QR code containing this string. There will be two return type options:

  • BufferedImage instance (e.g. to save as a physical file)
  • Base64 string (e.g. to use as src attribute of an img HTML tag)
package com.keepcodeclean.qrcode;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.util.EnumMap;
import java.util.Map;
import java.util.logging.Logger;

public class QrCodeUtil {
    private static final Logger LOG = Logger.getLogger(QrCodeUtil.class.getName());

    private static final String BASE64_PREFIX = "data:image/png;base64,";
    private static final int DEFAULT_QR_CODE_WIDTH = 200;
    private static final int DEFAULT_QR_CODE_HEIGHT = 200;
    private static final int QR_CODE_WHITESPACE_MARGIN = 2;
    private static final String DEFAULT_IMAGE_FORMAT = "png";
    private static final String UTF_8_CHARSET = "UTF-8";

    public static BufferedImage toQrCode(final String input,
                                         final int width,
                                         final int height) {
        final QRCodeWriter barcodeWriter = new QRCodeWriter();
        try {
            final Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
            hints.put(EncodeHintType.CHARACTER_SET, UTF_8_CHARSET);
            hints.put(EncodeHintType.MARGIN, QR_CODE_WHITESPACE_MARGIN);

            final BitMatrix bitMatrix = barcodeWriter.encode(input, BarcodeFormat.QR_CODE, width, height, hints);
            return MatrixToImageWriter.toBufferedImage(bitMatrix);
        } catch (Exception e) {
            LOG.severe("Could not generate a QR code.");
            throw new RuntimeException(e);
        }
    }
    
    public static String toBase64QrCode(final String input,
                                        final int width,
                                        final int height) {
        try {
            final BufferedImage bufferedImage = toQrCode(input, width, height);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, DEFAULT_IMAGE_FORMAT, outputStream);

            return BASE64_PREFIX + new String(Base64.getEncoder().encode(outputStream.toByteArray()));
        } catch (Exception e) {
            LOG.severe("Could not generate a QR code.");
            throw new RuntimeException(e);
        }
    }

    public static String toBase64QrCode(final String input) {
        return toBase64QrCode(input, DEFAULT_QR_CODE_WIDTH, DEFAULT_QR_CODE_HEIGHT);
    }

    public static BufferedImage toQrCode(final String input) {
        return toQrCode(input, DEFAULT_QR_CODE_WIDTH, DEFAULT_QR_CODE_HEIGHT);
    }
}

Now we can test this functionality. Let’s call toQrCode(String input) method passing “https://keepcodeclean.com” as input and save it to a file (e.g. using ImageIO.write method).

File outputfile = new File("qrCode.jpg");
ImageIO.write(toQrCode("https://keepcodeclean.com"), "jpg", outputfile);

Here is the result which you can easily validate by a QR code scanner.

Generate QR codes

If you want to embed the image into a web page, just call toBase64QrCode(String input) method and put the resulting string into src attribute of an img tag (<img src=”<base64qrcode>” />).

Leave a Reply

Your email address will not be published. Required fields are marked *