2021SC@SDUSC Zxing开源代码(十二)Aztec二维码(一)
2021SC@SDUSC目录前言:本篇博客简单介绍了Aztec相关知识,以及编码步骤过程。Aztec Code是1995年,由Hand HeldProducts公司的Dr. Andrew Longacre设计。它是一种高容量的二维条形码格式。它可以对ASCII和扩展ASCII码进行编码。当使用最高容量和25%的纠错级别的時候,Aztec可以对3000个字符或者3750个数字进行编码。Aztec的矩
2021SC@SDUSC
目录
前言:本篇博客简单介绍了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) + '>';
}
}
参考文献
更多推荐
所有评论(0)