2021SC@SDUSC Zxing open source code Aztec QR code

2021SC@SDUSC

This blog briefly introduces the relevant knowledge of Aztec and the coding steps and processes.

1, Introduction to Aztec QR code

1.1 INTRODUCTION

Aztec code, also known as Aztec code, is a loop nested two-dimensional bar code, which can encode up to 3000 characters. Because the name of Aztec code comes from the central pattern, which is similar to Aztec pyramid, there is no need to leave blank (static area) on the edge, and Aztec code uses less space than other matrix barcodes.

Aztec Code was designed by Dr. Andrew Longacre of hand held products in 1995. It is a high-capacity two-dimensional bar code format. It can encode ASCII and extended ASCII codes. Aztec can encode 3000 characters or 3750 numbers when using the maximum capacity and 25% error correction level.

The matrix size of Aztec varies between 15 * 15 and 151 * 151. Each smallest unit is either black or white. Its unique pattern recognition mark and placement algorithm in the middle make Aztec look like a vortex.

Aztec printing solution allows users to select size and error correction level. There are 36 different formats to choose from. In addition, there are 19 error correction levels to choose from. The default error correction level is 5 levels 23%. High error correction level means less data capacity and less bit error opportunities.

1.2 structure of Aztec code

The symbol is constructed on a square grid, with an "ox eye" pattern in the center for the code, and the data is encoded in a concentric square ring around the ox eye pattern. The "bull eye" in the center is 99 or 1313 pixels, and the basic coding parameters are encoded in the surrounding row of pixels to produce a 1111 or 1515 core. The data is divided into layers, each layer contains 2 rings of pixels, and the total pixels form 1515, 1919, 23 * 23, etc.

There are direction marks at the corners of the core to support reading the code when the pattern is rotated or mirrored. Decoding starts from the corner with three pixels, and then clockwise to the corner with two pixels, one pixel and zero pixels. The core code in the center contains size information, so there is no need for the blank "static area" required by other barcodes to mark the edge of the code.

1.3 coding steps

1. Convert the source message to string bits

2. Calculate the necessary symbol size and mode message to determine the Reed Solomon codeword size

3. Supplement the message bits with Reed Solomon codewords

4. Message filling to codeword boundary

5. Add check code word

6. Arrange complete information in a spiral around the core

1.4 character set

All 8-bit values can be encoded, plus two escape codes

By default, codes 0-127 follow ANSI*3.4 (ASCII) interpretation, and 128-255 follow ISO 8859-1: Latin AIphabet No.1 interpretation, which corresponds to ECI 00000 3.

2, AztecWriter

Similar to QR code and DM code, let's first analyze the coding class AztecWriter.
It inherits from the parent class Writer and rewrites the encode method:

@Override
  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map<EncodeHintType,?> hints) {
    Charset charset = null; // By default, do not add any ECI codes
    int eccPercent = Encoder.DEFAULT_EC_PERCENT;
    int layers = Encoder.DEFAULT_AZTEC_LAYERS;
    if (hints != null) {
      if (hints.containsKey(EncodeHintType.CHARACTER_SET)) {
        charset = Charset.forName(hints.get(EncodeHintType.CHARACTER_SET).toString());
      }
      if (hints.containsKey(EncodeHintType.ERROR_CORRECTION)) {
        eccPercent = Integer.parseInt(hints.get(EncodeHintType.ERROR_CORRECTION).toString());
      }
      if (hints.containsKey(EncodeHintType.AZTEC_LAYERS)) {
        layers = Integer.parseInt(hints.get(EncodeHintType.AZTEC_LAYERS).toString());
      }
    }
    return encode(contents, format, width, height, charset, eccPercent, layers);
  }

In addition, there is a static encode method.

private static BitMatrix encode(String contents, BarcodeFormat format,
                                  int width, int height,
                                  Charset charset, int eccPercent, int layers) {
    if (format != BarcodeFormat.AZTEC) {
      throw new IllegalArgumentException("Can only encode AZTEC, but got " + format);
    }
    AztecCode aztec = Encoder.encode(contents, eccPercent, layers, charset);
    return renderResult(aztec, width, height);
  }

  private static BitMatrix renderResult(AztecCode code, int width, int height) {
    BitMatrix input = code.getMatrix();
    if (input == null) {
      throw new IllegalStateException();
    }
    int inputWidth = input.getWidth();
    int inputHeight = input.getHeight();
    int outputWidth = Math.max(width, inputWidth);
    int outputHeight = Math.max(height, inputHeight);

    int multiple = Math.min(outputWidth / inputWidth, outputHeight / inputHeight);
    int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
    int topPadding = (outputHeight - (inputHeight * multiple)) / 2;

    BitMatrix output = new BitMatrix(outputWidth, outputHeight);

    for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
      // Write the contents of this line of barcode
      for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
        if (input.get(inputX, inputY)) {
          output.setRegion(outputX, outputY, multiple, multiple);
        }
      }
    }
    return output;
  }

3, Aztecode

AztecCode class is used to represent Aztec QR code, which is called by AztecWriter above.
This class is a simple constructor class with the following five member variables:

  private boolean compact;
  private int size;
  private int layers;
  private int codeWords;
  private BitMatrix matrix;

Respectively means:
Compact: true if it is compact instead of full mode, and false otherwise;
Size: size (in pixels, width and height)
layers: number of levels
codeWords: number of data codeWords
matrix: QR code symbol image

4, Token

Token is an abstract class. Both SimpleToken and BinaryShiftToken inherit from token.

abstract class Token {

  static final Token EMPTY = new SimpleToken(null, 0, 0);
  private final Token previous;

  Token(Token previous) {
    this.previous = previous;
  }
  
  final Token getPrevious() {
    return previous;
  }
  
  final Token add(int value, int bitCount) {
    return new SimpleToken(this, value, bitCount);
   }
   
  final Token addBinaryShift(int start, int byteCount) {
    return new BinaryShiftToken(this, start, byteCount);
  }
  
  abstract void appendTo(BitArray bitArray, byte[] text);
}

4.1 SimpleToken

SimpleToken is for ordinary words.

final class SimpleToken extends Token {
  private final short value;  // Indicated value
  private final short bitCount;  // Bit count

  SimpleToken(Token previous, int value, int bitCount) {
    super(previous);
    this.value = (short) value;
    this.bitCount = (short) bitCount;
  }

  @Override
  void appendTo(BitArray bitArray, byte[] text) {
    bitArray.appendBits(value, bitCount);
  }

  @Override
  public String toString() {
    int value = this.value & ((1 << bitCount) - 1);
    value |= 1 << bitCount;
    return '<' + Integer.toBinaryString(value | (1 << bitCount)).substring(1) + '>';
  }

}

4.2 BinaryShiftToken

BinaryShiftToken is binary related.

final class BinaryShiftToken extends Token {

  private final int binaryShiftStart;
  private final int binaryShiftByteCount;

  BinaryShiftToken(Token previous,
                   int binaryShiftStart,
                   int binaryShiftByteCount) {
    super(previous);
    this.binaryShiftStart = binaryShiftStart;
    this.binaryShiftByteCount = binaryShiftByteCount;
  }

  @Override
  public void appendTo(BitArray bitArray, byte[] text) {
    int bsbc = binaryShiftByteCount;
    for (int i = 0; i < bsbc; i++) {
      if (i == 0 || (i == 31 && bsbc <= 62)) {
        // Add a header before the first character. When the total bytecode is < = 62, add a header before the 31st character
        bitArray.appendBits(31, 5);  // Binary shift
        if (bsbc > 62) {
          bitArray.appendBits(bsbc - 31, 16);
        } else if (i == 0) {
          // 1 < = binary shift bytecode < = 62
          bitArray.appendBits(Math.min(bsbc, 31), 5);
        } else {
          // 32<=binaryShiftCount<=62,i==31
          bitArray.appendBits(bsbc - 31, 5);
        }
      }
      bitArray.appendBits(text[binaryShiftStart + i], 8);
    }
  }

  @Override
  public String toString() {
    return "<" + binaryShiftStart + "::" + (binaryShiftStart + binaryShiftByteCount - 1) + '>';
  }

}

reference

Detailed explanation of Aztec code

Keywords: Java

Added by ZibingsCoder on Wed, 01 Dec 2021 05:12:03 +0200