你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

2021SC@SDUSC Zxing开源代码(十二)Aztec二维码(一)

2021/12/1 10:47:01

2021SC@SDUSC

目录

  • 一、Aztec二维码简介
    • 1.1 简介
    • 1.2 Aztec码的结构
    • 1.3 编码步骤
    • 1.4 字符集
  • 二、AztecWriter
  • 三、AztecCode
  • 四、Token
    • 4.1 SimpleToken
    • 4.2 BinaryShiftToken
  • 参考文献


前言:本篇博客简单介绍了Aztec相关知识,以及编码步骤过程。


一、Aztec二维码简介

1.1 简介

Aztec码也称阿兹特克码,是一种回形嵌套式的二维条码,可以对多达3000个字符进行编码。由于Aztec码的名称源自中心图案与阿兹特克金字塔相似,因此不需要边缘留白(静区),Aztec码比其他矩阵条码使用更少的空间。

Aztec Code是1995年,由Hand HeldProducts公司的Dr. Andrew Longacre设计。它是一种高容量的二维条形码格式。它可以对ASCII和扩展ASCII码进行编码。当使用最高容量和25%的纠错级别的時候,Aztec可以对3000个字符或者3750个数字进行编码。

Aztec的矩阵大小在15 * 15和151 * 151之间变化。每个最小单位非黑即白。它独特的位于正中的模式识别标志和安置算法使Aztec看起来像个旋涡一样。

Aztec打印解决方案允许用户选择大小和纠错级别。一共有36中不同的格式供选择,此外还有19种纠错级别可供选择,默认纠错级别是5级23%。高纠错级别意味着更少的数据容量和更小的误码机会。

1.2 Aztec码的结构

该种符号构筑在方形网格上,其中心有一个“牛眼”图案用以该码,数据围绕该牛眼图案做同心方形环状编码。中心的“牛眼”为99或1313像素,并在周围的一行像素编码基本编码参数,产生一个1111或1515的核心。而数据以层,每个层包含2环像素,总像素形成1515、1919、23*23等。

核心的边角存在方向标记,以支持图案被旋转或镜像时读取代码。解码从有三个像素的边角开始,然后顺时针到两个像素、一个像素、零个像素的边角。在中心的核心编码载有尺寸信息,所以不需要其他一些条码所需要的空白“静区”来标记代码边缘。
在这里插入图片描述

1.3 编码步骤

1.将源消息转换为字符串比特

2.计算必要的符号大小和模式消息,用以决定Reed-Solomon码字大小

3.对消息比特补足为Reed-Solomon码字

4.消息填充到码字边界

5.追加检查码字

6.围绕核心以螺旋形式排列完整信息

1.4 字符集

所有8位的值都可编码,另外加上两个转义代码

默认情况下,0-127的码遵循ANSI*3.4(ASCII)解释,128-255遵循ISO 8859-1:Latin AIphabet No.1解释,这对应ECI 000003。

二、AztecWriter

与QR码和DM码类似,我们先来分析一下编码类AztecWriter。
它继承自父类Writer,并重写了encode方法:

@Override
  public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map<EncodeHintType,?> hints) {
    Charset charset = null; // 默认情况下,不要添加任何ECI代码
    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);
  }

除此之外,还有一个静态encode方法。

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) {
      // 写入条形码此行的内容
      for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
        if (input.get(inputX, inputY)) {
          output.setRegion(outputX, outputY, multiple, multiple);
        }
      }
    }
    return output;
  }

三、AztecCode

AztecCode类用来表示Aztec二维码,上面AztecWriter有调用它。
此类就是一个简单的构造类,有以下五个成员变量:

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

分别表示:
compact:如果是紧凑型而不是全模式为真,反之为假;
size:大小(以像素为单位,宽度和高度)
layers:级别数
codeWords:数据码字的数目
matrix:二维码符号图像

四、Token

Token是一个抽象类,SimpleToken和BinaryShiftToken都继承自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对于普通字而言的。

final class SimpleToken extends Token {
  private final short value;  // 指示值
  private final short bitCount;  // 位计数

  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是与二进制有关的。

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)) {
        // 在第一个字符前加一个头,当总字节码<=62时,在第31个字符前加一个头
        bitArray.appendBits(31, 5);  // 二进制移位
        if (bsbc > 62) {
          bitArray.appendBits(bsbc - 31, 16);
        } else if (i == 0) {
          // 1<=二进制移位字节码<=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) + '>';
  }

}

参考文献

有关Aztec码详解