2021SC@SDUSC
目录
- 一、BarcodeMatrix
- 二、BarcodeRow
- 三、Compaction
- 四、Dimensions
- 五、PDF417ErrorCorrection
- 六、PDF417HighLevelEncoder
前言:本篇博客继续介绍PDF417二维码的编码步骤过程。
一、BarcodeMatrix
BarcodeMatrix类以易于访问的格式保存条形码的所有信息。
包括以下四个成员变量,分别表示二维码相应的矩阵、当前行、二维码的高和宽。
private final BarcodeRow[] matrix;
private int currentRow;
private final int height;
private final int width;
其构造函数为:
height和width分别为矩阵的高度(行)和宽度(列)。
BarcodeMatrix(int height, int width) {
matrix = new BarcodeRow[height];
//将数组初始化为正确的宽度
for (int i = 0, matrixLength = matrix.length; i < matrixLength; i++) {
matrix[i] = new BarcodeRow((width + 4) * 17 + 1);
}
this.width = width * 17;
this.height = height;
this.currentRow = -1;
}
二、BarcodeRow
BarcodeRow类用来创建条形码的行。
其成员变量有:
private final byte[] row;
private int currentLocation;
主要方法有:
其中,x表示在条中的位置;black为一个布尔值,如果条为黑色,则为真;如果条为白色,则为假;width表示条宽为多少个点。
set(int x, boolean black) 方法用来设置栏中的特定位置;addBar(boolean black, int width) 用来添加条。
private void set(int x, boolean black) {
row[x] = (byte) (black ? 1 : 0);
}
void addBar(boolean black, int width) {
for (int ii = 0; ii < width; ii++) {
set(currentLocation++, black);
}
}
getScaledRow(int scale)方法用于缩放行,scale 表示缩放图像的大小,必须大于或等于1;此函数返回缩放的行。
byte[] getScaledRow(int scale) {
byte[] output = new byte[row.length * scale];
for (int i = 0; i < output.length; i++) {
output[i] = row[i / scale];
}
return output;
}
三、Compaction
Compaction类是一个枚举类,用来表示可能的PDF417条码压缩类型。
一共有四种类型: AUTO、TEXT、BYTE、NUMERIC
public enum Compaction {
AUTO,
TEXT,
BYTE,
NUMERIC
}
四、Dimensions
Dimensions是数据对象,用于指定PDF417条形码的最小行数和最大列数。
四个成员变量分别表示最小列数、最大列数、最小行数、最大行数。
public final class Dimensions {
private final int minCols;
private final int maxCols;
private final int minRows;
private final int maxRows;
public Dimensions(int minCols, int maxCols, int minRows, int maxRows) {
this.minCols = minCols;
this.maxCols = maxCols;
this.minRows = minRows;
this.maxRows = maxRows;
}
public int getMinCols() {return minCols;}
public int getMaxCols() {return maxCols;}
public int getMinRows() {return minRows;}
public int getMaxRows() {return maxRows;}
}
五、PDF417ErrorCorrection
PDF417ErrorCorrection类为PDF417的纠错码,遵循ISO/IEC 15438:2001(E)第4.10章所述算法。
getErrorCorrectionCodewordCount(int errorCorrectionLevel) 用来确定指定纠错级别的纠错码字数。
errorCorrectionLevel 为错误更正级别(0-8);
函数返回为纠错而生成的码字数。
static int getErrorCorrectionCodewordCount(int errorCorrectionLevel) {
if (errorCorrectionLevel < 0 || errorCorrectionLevel > 8) {
throw new IllegalArgumentException("Error correction level must be between 0 and 8!");
}
return 1 << (errorCorrectionLevel + 1);
}
getRecommendedMinimumErrorCorrectionLevel(int n)函数返回ISO/IEC 15438:2001(E)附录E中所述的建议最小错误纠正水平。
n 为数据码字的数量。
static int getRecommendedMinimumErrorCorrectionLevel(int n) throws WriterException {
if (n <= 0) {
throw new IllegalArgumentException("n must be > 0");
}
if (n <= 40) {return 2;}
if (n <= 160) {return 3;}
if (n <= 320) {return 4;}
if (n <= 863) {return 5;}
throw new WriterException("No recommendation possible");
}
generateErrorCorrection(CharSequence dataCodewords, int errorCorrectionLevel)函数根据ISO/IEC 15438:2001(E)中的4.10生成纠错码字。
dataCodewords 为数据码字数据码字;errorCorrectionLevel 为错误更正级别(0-8)。
static String generateErrorCorrection(CharSequence dataCodewords, int errorCorrectionLevel) {
int k = getErrorCorrectionCodewordCount(errorCorrectionLevel);
char[] e = new char[k];
int sld = dataCodewords.length();
for (int i = 0; i < sld; i++) {
int t1 = (dataCodewords.charAt(i) + e[e.length - 1]) % 929;
int t2;
int t3;
for (int j = k - 1; j >= 1; j--) {
t2 = (t1 * EC_COEFFICIENTS[errorCorrectionLevel][j]) % 929;
t3 = 929 - t2;
e[j] = (char) ((e[j - 1] + t3) % 929);
}
t2 = (t1 * EC_COEFFICIENTS[errorCorrectionLevel][0]) % 929;
t3 = 929 - t2;
e[0] = (char) (t3 % 929);
}
StringBuilder sb = new StringBuilder(k);
for (int j = k - 1; j >= 0; j--) {
if (e[j] != 0) {
e[j] = (char) (929 - e[j]);
}
sb.append(e[j]);
}
return sb.toString();
}
六、PDF417HighLevelEncoder
PDF417HighLevelEncoder类为PDF417的高级编码器。
含有多个成员变量。
成员变量 | 取值 | 说明 |
---|---|---|
TEXT_COMPACTION | 0 | 文本压缩代码 |
BYTE_COMPACTION | 1 | 字节压缩代码 |
NUMERIC_COMPACTION | 2 | 数字压缩代码 |
SUBMODE_ALPHA | 0 | 文本压缩子模式Alpha |
SUBMODE_LOWER | 1 | 文本压缩子模式下 |
SUBMODE_MIXED | 2 | 文本压缩子模式混合 |
SUBMODE_PUNCTUATION | 3 | 文本压缩子模式标点符号 |
LATCH_TO_TEXT | 900 | 模式锁存到文本压缩模式 |
LATCH_TO_BYTE_PADDED | 901 | 模式锁存到字节压缩模式(字符数不是6的倍数) |
LATCH_TO_NUMERIC | 902 | 模式锁存到数字压缩模式 |
SHIFT_TO_BYTE | 913 | 模式转换为字节压缩模式 |
LATCH_TO_BYTE | 924 | 模式锁存到字节压缩模式(字符数为6的倍数) |
ECI_USER_DEFINED | 925 | 用户定义扩展信道解释(ECI)的标识符 |
ECI_GENERAL_PURPOSE | 926 | 通用ECO格式的标识符 |
ECI_CHARSET | 927 | 代码页字符集的ECI标识符 |
TEXT_MIXED_RAW | — | 文本压缩混合子模式的原始代码表 |
TEXT_PUNCTUATION_RAW | — | 文本压缩的原始代码表:标点子模式 |
成员函数为:
成员函数 | 说明 |
---|---|
encodeHighLevel(String msg, Compaction compaction, Charset encoding) | 使用ISO/IEC 15438:2001(E)附录P中描述的算法对PDF417消息执行高级编码。如果已选择字节压缩,则仅使用字节压缩。返回编码消息(字符值范围从0到928) |
encodeText(CharSequence msg, int startpos,int count,StringBuilder sb, int initialSubmode) | 使用文本压缩对部分信息进行编码。返回此方法结束时的文本子模式 |
encodeBinary(byte[] bytes, int startpos,int count,int startmode,StringBuilder sb) | 使用字节压缩对部分信息进行编码。Unicode字符将使用cp437代码页转换为二进制。返回接收编码的码字。 |
determineConsecutiveDigitCount(CharSequence msg, int startpos) | 确定可使用数字压缩编码的连续字符数。返回请求的字符数。 |
determineConsecutiveTextCount(CharSequence msg, int startpos) | 确定可使用文本压缩编码的连续字符数。返回请求的字符数。 |
determineConsecutiveBinaryCount(String msg, int startpos, Charset encoding) | 确定可使用二进制压缩编码的连续字符数。返回请求的字符数。 |