@sythos/js_barcode_universal 1.5.8 → 1.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -4
- package/NOTICE.md +2 -2
- package/README.md +61 -13
- package/bundle/sythos-barcode.esm.js +11658 -11244
- package/bundle/sythos-barcode.js +11658 -11244
- package/package.json +10 -3
- package/src/index.d.ts +1 -1
- package/src/index.js +508 -516
- package/src/js/aztec/decoder.js +208 -199
- package/src/js/aztec/detector.js +153 -126
- package/src/js/aztec/encoder.js +172 -153
- package/src/js/aztec/high-level.js +106 -101
- package/src/js/aztec/index.js +1 -12
- package/src/js/aztec/tables.js +106 -120
- package/src/js/aztecrune/decoder.js +76 -85
- package/src/js/aztecrune/detector.js +107 -93
- package/src/js/aztecrune/encoder.js +50 -68
- package/src/js/aztecrune/index.js +1 -16
- package/src/js/aztecrune/tables.js +59 -54
- package/src/js/compactpdf417/decoder.js +69 -74
- package/src/js/compactpdf417/detector.js +74 -75
- package/src/js/compactpdf417/encoder.js +68 -81
- package/src/js/compactpdf417/index.js +1 -13
- package/src/js/compactpdf417/tables.js +71 -80
- package/src/js/core/bit-buffer.js +106 -122
- package/src/js/core/bit-matrix.js +196 -194
- package/src/js/core/errors.js +13 -15
- package/src/js/core/galois-field.js +119 -133
- package/src/js/core/index.js +2 -19
- package/src/js/core/reed-solomon.js +195 -204
- package/src/js/databar/codec.js +93 -108
- package/src/js/databar/decoder.js +149 -140
- package/src/js/databar/encoder.js +47 -55
- package/src/js/databar/gs1.js +122 -123
- package/src/js/databar/index.js +4 -36
- package/src/js/databar/patterns.js +81 -85
- package/src/js/databar/tables.js +51 -52
- package/src/js/datamatrix/decoder.js +216 -182
- package/src/js/datamatrix/detector.js +161 -132
- package/src/js/datamatrix/encoder.js +192 -133
- package/src/js/datamatrix/index.js +1 -9
- package/src/js/datamatrix/tables.js +68 -69
- package/src/js/frameqr/decoder.js +102 -125
- package/src/js/frameqr/detector.js +101 -94
- package/src/js/frameqr/encoder.js +67 -80
- package/src/js/frameqr/index.js +1 -10
- package/src/js/frameqr/tables.js +145 -163
- package/src/js/image/binarizer.js +146 -162
- package/src/js/image/grid-sampler.js +63 -79
- package/src/js/image/index.js +0 -2
- package/src/js/image/luminance.js +129 -140
- package/src/js/image/perspective.js +112 -149
- package/src/js/micropdf417/compaction.js +64 -65
- package/src/js/micropdf417/decoder.js +106 -109
- package/src/js/micropdf417/detector.js +73 -70
- package/src/js/micropdf417/encoder.js +129 -154
- package/src/js/micropdf417/error-correction.js +6 -11
- package/src/js/micropdf417/index.js +2 -16
- package/src/js/micropdf417/tables.js +112 -99
- package/src/js/microqr/decoder.js +177 -182
- package/src/js/microqr/detector.js +240 -256
- package/src/js/microqr/encoder.js +239 -194
- package/src/js/microqr/index.js +0 -2
- package/src/js/microqr/tables.js +208 -200
- package/src/js/oned/addons.js +167 -191
- package/src/js/oned/index.js +27 -58
- package/src/js/oned/patterns.js +194 -213
- package/src/js/oned/reader.js +1003 -984
- package/src/js/oned/writers.js +411 -466
- package/src/js/pdf417/compaction.js +315 -222
- package/src/js/pdf417/decoder.js +71 -36
- package/src/js/pdf417/detector.js +377 -361
- package/src/js/pdf417/encoder.js +57 -46
- package/src/js/pdf417/error-correction.js +5 -8
- package/src/js/pdf417/tables.js +248 -250
- package/src/js/qr/decoder.js +311 -347
- package/src/js/qr/detector.js +378 -395
- package/src/js/qr/encoder.js +514 -599
- package/src/js/qr/index.js +0 -2
- package/src/js/qr/tables.js +375 -422
- package/src/js/render/image-data.js +57 -62
- package/src/js/render/index.js +21 -23
- package/src/js/render/options.js +82 -90
- package/src/js/render/png.js +144 -169
- package/src/js/render/svg.js +41 -44
- package/src/js/render/webgl.js +103 -109
- package/src/js/render/webgpu.js +205 -217
- package/src/js/rmqr/decoder.js +161 -53
- package/src/js/rmqr/detector.js +73 -41
- package/src/js/rmqr/encoder.js +253 -104
- package/src/js/rmqr/index.js +1 -5
- package/src/js/rmqr/tables.js +108 -85
- package/src/ts/aztec/decoder.ts +317 -0
- package/src/ts/aztec/detector.ts +224 -0
- package/src/ts/aztec/encoder.ts +257 -0
- package/src/ts/aztec/high-level.ts +211 -0
- package/src/ts/aztec/index.ts +45 -0
- package/src/ts/aztec/tables.ts +210 -0
- package/src/ts/aztecrune/decoder.ts +155 -0
- package/src/ts/aztecrune/detector.ts +166 -0
- package/src/ts/aztecrune/encoder.ts +121 -0
- package/src/ts/aztecrune/index.ts +49 -0
- package/src/ts/aztecrune/tables.ts +137 -0
- package/src/ts/compactpdf417/decoder.ts +128 -0
- package/src/ts/compactpdf417/detector.ts +139 -0
- package/src/ts/compactpdf417/encoder.ts +140 -0
- package/src/ts/compactpdf417/index.ts +17 -0
- package/src/ts/compactpdf417/tables.ts +173 -0
- package/src/ts/core/bit-buffer.ts +174 -0
- package/src/ts/core/bit-matrix.ts +241 -0
- package/src/ts/core/errors.ts +61 -0
- package/src/ts/core/galois-field.ts +207 -0
- package/src/ts/core/index.ts +56 -0
- package/src/ts/core/reed-solomon.ts +327 -0
- package/src/ts/databar/codec.ts +181 -0
- package/src/ts/databar/decoder.ts +215 -0
- package/src/ts/databar/encoder.ts +96 -0
- package/src/ts/databar/gs1.ts +177 -0
- package/src/ts/databar/index.ts +68 -0
- package/src/ts/databar/patterns.ts +143 -0
- package/src/ts/databar/tables.ts +124 -0
- package/src/ts/datamatrix/decoder.ts +262 -0
- package/src/ts/datamatrix/detector.ts +225 -0
- package/src/ts/datamatrix/encoder.ts +191 -0
- package/src/ts/datamatrix/index.ts +42 -0
- package/src/ts/datamatrix/tables.ts +123 -0
- package/src/ts/frameqr/decoder.ts +239 -0
- package/src/ts/frameqr/detector.ts +192 -0
- package/src/ts/frameqr/encoder.ts +156 -0
- package/src/ts/frameqr/index.ts +42 -0
- package/src/ts/frameqr/tables.ts +270 -0
- package/src/ts/image/binarizer.ts +270 -0
- package/src/ts/image/grid-sampler.ts +164 -0
- package/src/ts/image/index.ts +40 -0
- package/src/ts/image/luminance.ts +196 -0
- package/src/ts/image/perspective.ts +195 -0
- package/src/ts/index.d.ts +1 -1
- package/src/ts/index.ts +790 -0
- package/src/ts/micropdf417/compaction.ts +116 -0
- package/src/ts/micropdf417/decoder.ts +183 -0
- package/src/ts/micropdf417/detector.ts +149 -0
- package/src/ts/micropdf417/encoder.ts +209 -0
- package/src/ts/micropdf417/error-correction.ts +55 -0
- package/src/ts/micropdf417/index.ts +49 -0
- package/src/ts/micropdf417/tables.ts +184 -0
- package/src/ts/microqr/decoder.ts +245 -0
- package/src/ts/microqr/detector.ts +355 -0
- package/src/ts/microqr/encoder.ts +269 -0
- package/src/ts/microqr/index.ts +36 -0
- package/src/ts/microqr/tables.ts +316 -0
- package/src/ts/oned/addons.ts +420 -0
- package/src/ts/oned/index.ts +106 -0
- package/src/ts/oned/patterns.ts +384 -0
- package/src/ts/oned/reader.ts +1364 -0
- package/src/ts/oned/writers.ts +746 -0
- package/src/ts/pdf417/compaction.ts +298 -0
- package/src/ts/pdf417/decoder.ts +75 -0
- package/src/ts/pdf417/detector.ts +468 -0
- package/src/ts/pdf417/encoder.ts +91 -0
- package/src/ts/pdf417/error-correction.ts +47 -0
- package/src/ts/pdf417/index.ts +6 -0
- package/src/ts/pdf417/tables.ts +317 -0
- package/src/ts/qr/decoder.ts +575 -0
- package/src/ts/qr/detector.ts +630 -0
- package/src/ts/qr/encoder.ts +958 -0
- package/src/ts/qr/index.ts +44 -0
- package/src/ts/qr/tables.ts +737 -0
- package/src/ts/render/image-data.ts +125 -0
- package/src/ts/render/index.ts +130 -0
- package/src/ts/render/options.ts +160 -0
- package/src/ts/render/png.ts +295 -0
- package/src/ts/render/svg.ts +120 -0
- package/src/ts/render/webgl.ts +206 -0
- package/src/ts/render/webgpu.ts +369 -0
- package/src/ts/rmqr/decoder.ts +101 -0
- package/src/ts/rmqr/detector.ts +90 -0
- package/src/ts/rmqr/encoder.ts +172 -0
- package/src/ts/rmqr/index.ts +37 -0
- package/src/ts/rmqr/tables.ts +154 -0
package/src/js/aztec/decoder.js
CHANGED
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
*
|
|
28
28
|
* Original work. No code from any other barcode implementation.
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
30
|
/**
|
|
32
31
|
* Decoder for a sampled Aztec symbol.
|
|
33
32
|
*
|
|
@@ -44,40 +43,32 @@
|
|
|
44
43
|
*
|
|
45
44
|
* @module aztec/decoder
|
|
46
45
|
*/
|
|
47
|
-
|
|
48
46
|
import { FormatError } from '../core/errors.js';
|
|
49
47
|
import { rsDecode } from '../core/reed-solomon.js';
|
|
50
|
-
import {
|
|
51
|
-
aztecLayer as aztecSymbolForLayers,
|
|
52
|
-
wordSizeForLayers as aztecWordSizeForLayers,
|
|
53
|
-
fieldForLayers as aztecFieldForLayers,
|
|
54
|
-
fieldForWordSize,
|
|
55
|
-
aztecSymbolSize as aztecMatrixSize,
|
|
56
|
-
} from './tables.js';
|
|
57
|
-
|
|
48
|
+
import { aztecLayer as aztecSymbolForLayers, wordSizeForLayers as aztecWordSizeForLayers, fieldForLayers as aztecFieldForLayers, fieldForWordSize, aztecSymbolSize as aztecMatrixSize, } from './tables.js';
|
|
58
49
|
const UPPER = ['CTRL_PS', ' ', ...'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'CTRL_LL', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS'];
|
|
59
50
|
const LOWER = ['CTRL_PS', ' ', ...'abcdefghijklmnopqrstuvwxyz', 'CTRL_US', 'CTRL_ML', 'CTRL_DL', 'CTRL_BS'];
|
|
60
51
|
const MIXED = [
|
|
61
|
-
|
|
62
|
-
|
|
52
|
+
'CTRL_PS', ' ', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\b', '\t', '\n', '\x0b', '\f', '\r', '\x1b',
|
|
53
|
+
'\x1c', '\x1d', '\x1e', '\x1f', '@', '\\', '^', '_', '`', '|', '~', '\x7f', 'CTRL_LL', 'CTRL_UL', 'CTRL_PL', 'CTRL_BS',
|
|
63
54
|
];
|
|
64
55
|
const PUNCT = ['FLG(n)', '\r', '\r\n', '. ', ', ', ': ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', ']', '{', '}', 'CTRL_UL'];
|
|
65
56
|
const DIGIT = ['CTRL_PS', ' ', ...'0123456789', ',', '.', 'CTRL_UL'];
|
|
66
57
|
const TABLES = { UPPER, LOWER, MIXED, PUNCT, DIGIT };
|
|
67
|
-
|
|
68
58
|
/** @param {boolean[]} bits @param {number} offset @param {number} count */
|
|
69
59
|
function readBits(bits, offset, count) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
60
|
+
if (offset + count > bits.length)
|
|
61
|
+
throw new FormatError('Aztec: truncated high-level stream');
|
|
62
|
+
let value = 0;
|
|
63
|
+
for (let i = 0; i < count; i++)
|
|
64
|
+
value = (value << 1) | (bits[offset + i] ? 1 : 0);
|
|
65
|
+
return value;
|
|
74
66
|
}
|
|
75
|
-
|
|
76
67
|
/** @param {number} value @param {number} count @param {boolean[]} out */
|
|
77
68
|
function appendBits(value, count, out) {
|
|
78
|
-
|
|
69
|
+
for (let i = count - 1; i >= 0; i--)
|
|
70
|
+
out.push(((value >>> i) & 1) !== 0);
|
|
79
71
|
}
|
|
80
|
-
|
|
81
72
|
/**
|
|
82
73
|
* Decode an Aztec high-level bit stream to its exact byte payload.
|
|
83
74
|
*
|
|
@@ -89,91 +80,98 @@ function appendBits(value, count, out) {
|
|
|
89
80
|
* @returns {Uint8Array}
|
|
90
81
|
*/
|
|
91
82
|
export function decodeHighLevelBits(bits) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const size = shift === 'DIGIT' ? 4 : 5;
|
|
117
|
-
if (offset + size > bits.length) break; // trailing pad after unstuffing
|
|
118
|
-
const code = readBits(bits, offset, size);
|
|
119
|
-
offset += size;
|
|
120
|
-
const table = TABLES[shift];
|
|
121
|
-
const token = table[code];
|
|
122
|
-
if (token === undefined) throw new FormatError(`Aztec: invalid ${shift} code ${code}`);
|
|
123
|
-
|
|
124
|
-
if (token === 'FLG(n)') {
|
|
125
|
-
if (offset + 3 > bits.length) throw new FormatError('Aztec: truncated FLG(n)');
|
|
126
|
-
const count = readBits(bits, offset, 3);
|
|
127
|
-
offset += 3;
|
|
128
|
-
if (count === 0) output.push(0x1d); // FNC1 / GS
|
|
129
|
-
else if (count <= 6) {
|
|
130
|
-
// ECI assignment number, encoded as count decimal digits. It changes
|
|
131
|
-
// interpretation, not the wire bytes, so consume it without output.
|
|
132
|
-
for (let i = 0; i < count; i++) {
|
|
133
|
-
if (offset + 4 > bits.length) throw new FormatError('Aztec: truncated ECI');
|
|
134
|
-
const digit = readBits(bits, offset, 4);
|
|
135
|
-
offset += 4;
|
|
136
|
-
if (digit < 2 || digit > 11) throw new FormatError('Aztec: invalid ECI digit');
|
|
83
|
+
const output = [];
|
|
84
|
+
let latch = 'UPPER';
|
|
85
|
+
let shift = 'UPPER';
|
|
86
|
+
let offset = 0;
|
|
87
|
+
while (offset < bits.length) {
|
|
88
|
+
if (shift === 'BINARY') {
|
|
89
|
+
if (offset + 5 > bits.length)
|
|
90
|
+
break; // legal trailing pad
|
|
91
|
+
let length = readBits(bits, offset, 5);
|
|
92
|
+
offset += 5;
|
|
93
|
+
if (length === 0) {
|
|
94
|
+
if (offset + 11 > bits.length)
|
|
95
|
+
throw new FormatError('Aztec: truncated Binary Shift length');
|
|
96
|
+
length = readBits(bits, offset, 11) + 31;
|
|
97
|
+
offset += 11;
|
|
98
|
+
}
|
|
99
|
+
if (offset + length * 8 > bits.length)
|
|
100
|
+
throw new FormatError('Aztec: truncated Binary Shift data');
|
|
101
|
+
for (let i = 0; i < length; i++) {
|
|
102
|
+
output.push(readBits(bits, offset, 8));
|
|
103
|
+
offset += 8;
|
|
104
|
+
}
|
|
105
|
+
shift = latch;
|
|
106
|
+
continue;
|
|
137
107
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
108
|
+
const size = shift === 'DIGIT' ? 4 : 5;
|
|
109
|
+
if (offset + size > bits.length)
|
|
110
|
+
break; // trailing pad after unstuffing
|
|
111
|
+
const code = readBits(bits, offset, size);
|
|
112
|
+
offset += size;
|
|
113
|
+
const table = TABLES[shift];
|
|
114
|
+
const token = table[code];
|
|
115
|
+
if (token === undefined)
|
|
116
|
+
throw new FormatError(`Aztec: invalid ${shift} code ${code}`);
|
|
117
|
+
if (token === 'FLG(n)') {
|
|
118
|
+
if (offset + 3 > bits.length)
|
|
119
|
+
throw new FormatError('Aztec: truncated FLG(n)');
|
|
120
|
+
const count = readBits(bits, offset, 3);
|
|
121
|
+
offset += 3;
|
|
122
|
+
if (count === 0)
|
|
123
|
+
output.push(0x1d); // FNC1 / GS
|
|
124
|
+
else if (count <= 6) {
|
|
125
|
+
// ECI assignment number, encoded as count decimal digits. It changes
|
|
126
|
+
// interpretation, not the wire bytes, so consume it without output.
|
|
127
|
+
for (let i = 0; i < count; i++) {
|
|
128
|
+
if (offset + 4 > bits.length)
|
|
129
|
+
throw new FormatError('Aztec: truncated ECI');
|
|
130
|
+
const digit = readBits(bits, offset, 4);
|
|
131
|
+
offset += 4;
|
|
132
|
+
if (digit < 2 || digit > 11)
|
|
133
|
+
throw new FormatError('Aztec: invalid ECI digit');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
throw new FormatError(`Aztec: unsupported FLG(${count})`);
|
|
138
|
+
}
|
|
139
|
+
shift = latch;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (token.startsWith('CTRL_')) {
|
|
143
|
+
const targetCode = token.slice(5, -1);
|
|
144
|
+
const latchMode = token.endsWith('L');
|
|
145
|
+
const target = ({ P: 'PUNCT', L: 'LOWER', M: 'MIXED', D: 'DIGIT', U: 'UPPER', B: 'BINARY' })[targetCode];
|
|
146
|
+
if (!target)
|
|
147
|
+
throw new FormatError(`Aztec: invalid control ${token}`);
|
|
148
|
+
shift = target;
|
|
149
|
+
if (latchMode)
|
|
150
|
+
latch = shift;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
for (let i = 0; i < token.length; i++)
|
|
154
|
+
output.push(token.charCodeAt(i));
|
|
155
|
+
shift = latch;
|
|
153
156
|
}
|
|
154
|
-
|
|
155
|
-
for (let i = 0; i < token.length; i++) output.push(token.charCodeAt(i));
|
|
156
|
-
shift = latch;
|
|
157
|
-
}
|
|
158
|
-
return Uint8Array.from(output);
|
|
157
|
+
return Uint8Array.from(output);
|
|
159
158
|
}
|
|
160
|
-
|
|
161
159
|
/** @param {boolean} compact @param {number} layers */
|
|
162
160
|
function alignmentMap(compact, layers) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
161
|
+
const baseSize = (compact ? 11 : 14) + layers * 4;
|
|
162
|
+
if (compact)
|
|
163
|
+
return Array.from({ length: baseSize }, (_, i) => i);
|
|
164
|
+
const size = aztecMatrixSize(layers, false);
|
|
165
|
+
const map = new Array(baseSize);
|
|
166
|
+
const baseCenter = baseSize >> 1;
|
|
167
|
+
const center = size >> 1;
|
|
168
|
+
for (let i = 0; i < baseCenter; i++) {
|
|
169
|
+
const offset = i + Math.floor(i / 15);
|
|
170
|
+
map[baseCenter - i - 1] = center - offset - 1;
|
|
171
|
+
map[baseCenter + i] = center + offset + 1;
|
|
172
|
+
}
|
|
173
|
+
return map;
|
|
175
174
|
}
|
|
176
|
-
|
|
177
175
|
/**
|
|
178
176
|
* Read the four sides of the parameter message. The order mirrors the
|
|
179
177
|
* clockwise write order and is independent of the data spiral.
|
|
@@ -183,42 +181,42 @@ function alignmentMap(compact, layers) {
|
|
|
183
181
|
* @returns {boolean[]}
|
|
184
182
|
*/
|
|
185
183
|
function readModeBits(matrix, compact) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
(
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
184
|
+
const center = matrix.width >> 1;
|
|
185
|
+
const side = compact ? 7 : 10;
|
|
186
|
+
const offset = compact ? 5 : 7;
|
|
187
|
+
// Full symbols skip the reference grid line through the bull's-eye. This
|
|
188
|
+
// exact sequence is also used by drawModeMessage() in encoder.js.
|
|
189
|
+
const positions = Array.from({ length: side }, (_, i) => compact ? center - 3 + i : center - 5 + i + Math.floor(i / 5));
|
|
190
|
+
const bits = [];
|
|
191
|
+
for (let i = 0; i < side; i++)
|
|
192
|
+
bits.push(matrix.get(positions[i], center - offset));
|
|
193
|
+
for (let i = 0; i < side; i++)
|
|
194
|
+
bits.push(matrix.get(center + offset, positions[i]));
|
|
195
|
+
for (let i = 0; i < side; i++)
|
|
196
|
+
bits.push(matrix.get(positions[side - 1 - i], center + offset));
|
|
197
|
+
for (let i = 0; i < side; i++)
|
|
198
|
+
bits.push(matrix.get(center - offset, positions[side - 1 - i]));
|
|
199
|
+
return bits;
|
|
201
200
|
}
|
|
202
|
-
|
|
203
201
|
/** @param {boolean[]} bits @param {boolean} compact */
|
|
204
202
|
function decodeModeMessage(bits, compact) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
203
|
+
const total = compact ? 7 : 10;
|
|
204
|
+
const dataWords = compact ? 2 : 4;
|
|
205
|
+
const words = new Array(total);
|
|
206
|
+
for (let i = 0; i < total; i++)
|
|
207
|
+
words[i] = readBits(bits, i * 4, 4);
|
|
208
|
+
const corrections = rsDecode(words, total - dataWords, fieldForWordSize(4), 1);
|
|
209
|
+
let data = 0;
|
|
210
|
+
for (let i = 0; i < dataWords; i++)
|
|
211
|
+
data = (data << 4) | words[i];
|
|
212
|
+
const layers = compact ? (data >>> 6) + 1 : (data >>> 11) + 1;
|
|
213
|
+
const dataCodewords = compact ? (data & 0x3f) + 1 : (data & 0x7ff) + 1;
|
|
214
|
+
return { layers, dataCodewords, corrections };
|
|
215
215
|
}
|
|
216
|
-
|
|
217
216
|
/** @param {boolean} compact @param {number} layers */
|
|
218
217
|
function totalBitsInLayers(compact, layers) {
|
|
219
|
-
|
|
218
|
+
return ((compact ? 88 : 112) + 16 * layers) * layers;
|
|
220
219
|
}
|
|
221
|
-
|
|
222
220
|
/**
|
|
223
221
|
* Extract raw, stuffed codeword bits in logical ring order.
|
|
224
222
|
* @param {import('../core/bit-matrix.js').BitMatrix} matrix
|
|
@@ -226,55 +224,61 @@ function totalBitsInLayers(compact, layers) {
|
|
|
226
224
|
* @returns {boolean[]}
|
|
227
225
|
*/
|
|
228
226
|
function extractBits(matrix, compact, layers) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
227
|
+
const baseSize = (compact ? 11 : 14) + layers * 4;
|
|
228
|
+
const map = alignmentMap(compact, layers);
|
|
229
|
+
const raw = new Array(totalBitsInLayers(compact, layers));
|
|
230
|
+
let offset = 0;
|
|
231
|
+
for (let layer = 0; layer < layers; layer++) {
|
|
232
|
+
const rowSize = (layers - layer) * 4 + (compact ? 9 : 12);
|
|
233
|
+
for (let j = 0; j < rowSize; j++) {
|
|
234
|
+
const col = j * 2;
|
|
235
|
+
for (let k = 0; k < 2; k++) {
|
|
236
|
+
raw[offset + col + k] = matrix.get(map[layer * 2 + k], map[layer * 2 + j]);
|
|
237
|
+
raw[offset + rowSize * 2 + col + k] = matrix.get(map[layer * 2 + j], map[baseSize - 1 - layer * 2 - k]);
|
|
238
|
+
raw[offset + rowSize * 4 + col + k] = matrix.get(map[baseSize - 1 - layer * 2 - k], map[baseSize - 1 - layer * 2 - j]);
|
|
239
|
+
raw[offset + rowSize * 6 + col + k] = matrix.get(map[baseSize - 1 - layer * 2 - j], map[layer * 2 + k]);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
offset += rowSize * 8;
|
|
243
243
|
}
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
return raw;
|
|
244
|
+
return raw;
|
|
247
245
|
}
|
|
248
|
-
|
|
249
246
|
/** @param {boolean[]} raw @param {number} layers @param {number} dataCodewords */
|
|
250
247
|
function correctAndUnstuff(raw, layers, dataCodewords) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
248
|
+
const wordSize = aztecWordSizeForLayers(layers);
|
|
249
|
+
const totalWords = Math.floor(raw.length / wordSize);
|
|
250
|
+
if (dataCodewords <= 0 || dataCodewords > totalWords)
|
|
251
|
+
throw new FormatError('Aztec: invalid data word count');
|
|
252
|
+
const start = raw.length % wordSize;
|
|
253
|
+
const words = new Array(totalWords);
|
|
254
|
+
for (let i = 0; i < totalWords; i++)
|
|
255
|
+
words[i] = readBits(raw, start + i * wordSize, wordSize);
|
|
256
|
+
const corrections = rsDecode(words, totalWords - dataCodewords, aztecFieldForLayers(layers), 1);
|
|
257
|
+
const mask = (1 << wordSize) - 1;
|
|
258
|
+
const corrected = [];
|
|
259
|
+
for (let i = 0; i < dataCodewords; i++) {
|
|
260
|
+
const word = words[i];
|
|
261
|
+
if (word === 0 || word === mask)
|
|
262
|
+
throw new FormatError('Aztec: invalid stuffed codeword');
|
|
263
|
+
if (word === 1 || word === mask - 1) {
|
|
264
|
+
for (let j = 0; j < wordSize - 1; j++)
|
|
265
|
+
corrected.push(word === mask - 1);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
appendBits(word, wordSize, corrected);
|
|
269
|
+
}
|
|
267
270
|
}
|
|
268
|
-
|
|
269
|
-
return { bits: corrected, corrections };
|
|
271
|
+
return { bits: corrected, corrections };
|
|
270
272
|
}
|
|
271
|
-
|
|
272
273
|
/** @param {Uint8Array} bytes */
|
|
273
274
|
function bytesToText(bytes) {
|
|
274
|
-
|
|
275
|
-
|
|
275
|
+
try {
|
|
276
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
return new TextDecoder('latin1').decode(bytes);
|
|
280
|
+
}
|
|
276
281
|
}
|
|
277
|
-
|
|
278
282
|
/**
|
|
279
283
|
* Decode a square Aztec symbol with one bit per module and no quiet zone.
|
|
280
284
|
* The matrix must already be oriented with the mode message at the top.
|
|
@@ -283,35 +287,40 @@ function bytesToText(bytes) {
|
|
|
283
287
|
* @returns {{text: string, bytes: Uint8Array, compact: boolean, layers: number, corrections: number, eccPercent: number}}
|
|
284
288
|
*/
|
|
285
289
|
export function decodeAztec(matrix) {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
290
|
+
if (!matrix || matrix.width !== matrix.height)
|
|
291
|
+
throw new FormatError('Aztec: expected a square BitMatrix');
|
|
292
|
+
let compact;
|
|
293
|
+
let mode;
|
|
294
|
+
// Compact and full dimensions are disjoint; trying both also makes malformed
|
|
295
|
+
// candidate handling deterministic for the future image detector.
|
|
296
|
+
for (const candidate of [true, false]) {
|
|
297
|
+
try {
|
|
298
|
+
const value = decodeModeMessage(readModeBits(matrix, candidate), candidate);
|
|
299
|
+
if (value.layers < 1 || value.layers > (candidate ? 4 : 32))
|
|
300
|
+
continue;
|
|
301
|
+
if (aztecMatrixSize(value.layers, candidate) !== matrix.width)
|
|
302
|
+
continue;
|
|
303
|
+
compact = candidate;
|
|
304
|
+
mode = value;
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
catch { /* Try the other family. */ }
|
|
308
|
+
}
|
|
309
|
+
if (compact === undefined || !mode)
|
|
310
|
+
throw new FormatError('Aztec: invalid mode message or dimensions');
|
|
311
|
+
// Ensure the declared layer data agrees with the table module, so a future
|
|
312
|
+
// tables refactor cannot silently make decoder capacity calculations stale.
|
|
313
|
+
aztecSymbolForLayers(mode.layers, compact);
|
|
314
|
+
const raw = extractBits(matrix, compact, mode.layers);
|
|
315
|
+
const payload = correctAndUnstuff(raw, mode.layers, mode.dataCodewords);
|
|
316
|
+
const bytes = decodeHighLevelBits(payload.bits);
|
|
317
|
+
const totalWords = Math.floor(raw.length / aztecWordSizeForLayers(mode.layers));
|
|
318
|
+
return {
|
|
319
|
+
text: bytesToText(bytes),
|
|
320
|
+
bytes,
|
|
321
|
+
compact,
|
|
322
|
+
layers: mode.layers,
|
|
323
|
+
corrections: mode.corrections + payload.corrections,
|
|
324
|
+
eccPercent: Math.round(((totalWords - mode.dataCodewords) * 100) / totalWords),
|
|
325
|
+
};
|
|
317
326
|
}
|