@sythos/js_barcode_universal 1.5.8 → 1.5.9
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 +17 -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
|
@@ -27,214 +27,299 @@
|
|
|
27
27
|
*
|
|
28
28
|
* Original work. No code from any other barcode implementation.
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
30
|
/** PDF417 high-level text, byte and numeric compaction. @module pdf417/compaction */
|
|
32
|
-
|
|
33
31
|
import { EncodeError, FormatError } from '../core/errors.js';
|
|
34
|
-
|
|
35
32
|
const ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ ';
|
|
36
33
|
const LOWER = 'abcdefghijklmnopqrstuvwxyz ';
|
|
37
34
|
const MIXED = '0123456789&\r\t,:#-.$/+%*=^';
|
|
38
35
|
const PUNCT = ';<>@[\\]_`~!\r\t,:\n-.$/"|*()?{}\'';
|
|
39
|
-
|
|
40
36
|
function packBase30(values) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
const out = [];
|
|
38
|
+
for (let i = 0; i < values.length; i += 2)
|
|
39
|
+
out.push(values[i] * 30 + (i + 1 < values.length ? values[i + 1] : 29));
|
|
40
|
+
return out;
|
|
44
41
|
}
|
|
45
|
-
|
|
46
42
|
/** Compact a value using the PDF417 Text Compaction alphabet. */
|
|
47
43
|
export function compactPdf417Text(value) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
44
|
+
if (typeof value !== 'string')
|
|
45
|
+
throw new EncodeError('PDF417 text: value must be a string');
|
|
46
|
+
const values = [];
|
|
47
|
+
let submode = 'alpha';
|
|
48
|
+
for (const character of value) {
|
|
49
|
+
const inAlpha = ALPHA.indexOf(character), inLower = LOWER.indexOf(character);
|
|
50
|
+
const inMixed = MIXED.indexOf(character), inPunct = PUNCT.indexOf(character);
|
|
51
|
+
if (submode === 'alpha') {
|
|
52
|
+
if (inAlpha >= 0)
|
|
53
|
+
values.push(inAlpha);
|
|
54
|
+
else if (inLower >= 0) {
|
|
55
|
+
values.push(27, inLower);
|
|
56
|
+
submode = 'lower';
|
|
57
|
+
}
|
|
58
|
+
else if (inMixed >= 0 || character === ' ') {
|
|
59
|
+
values.push(28, character === ' ' ? 26 : inMixed);
|
|
60
|
+
submode = 'mixed';
|
|
61
|
+
}
|
|
62
|
+
else if (inPunct >= 0)
|
|
63
|
+
values.push(29, inPunct);
|
|
64
|
+
else
|
|
65
|
+
throw new EncodeError(`PDF417 text: unsupported character ${JSON.stringify(character)}`);
|
|
66
|
+
}
|
|
67
|
+
else if (submode === 'lower') {
|
|
68
|
+
if (inLower >= 0)
|
|
69
|
+
values.push(inLower);
|
|
70
|
+
else if (inAlpha >= 0)
|
|
71
|
+
values.push(27, inAlpha);
|
|
72
|
+
else if (inMixed >= 0 || character === ' ') {
|
|
73
|
+
values.push(28, character === ' ' ? 26 : inMixed);
|
|
74
|
+
submode = 'mixed';
|
|
75
|
+
}
|
|
76
|
+
else if (inPunct >= 0)
|
|
77
|
+
values.push(29, inPunct);
|
|
78
|
+
else
|
|
79
|
+
throw new EncodeError(`PDF417 text: unsupported character ${JSON.stringify(character)}`);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
if (inMixed >= 0)
|
|
83
|
+
values.push(inMixed);
|
|
84
|
+
else if (character === ' ')
|
|
85
|
+
values.push(26);
|
|
86
|
+
else if (inAlpha >= 0) {
|
|
87
|
+
values.push(28);
|
|
88
|
+
submode = 'alpha';
|
|
89
|
+
values.push(inAlpha);
|
|
90
|
+
}
|
|
91
|
+
else if (inLower >= 0) {
|
|
92
|
+
values.push(27);
|
|
93
|
+
submode = 'lower';
|
|
94
|
+
values.push(inLower);
|
|
95
|
+
}
|
|
96
|
+
else if (inPunct >= 0)
|
|
97
|
+
values.push(29, inPunct);
|
|
98
|
+
else
|
|
99
|
+
throw new EncodeError(`PDF417 text: unsupported character ${JSON.stringify(character)}`);
|
|
100
|
+
}
|
|
73
101
|
}
|
|
74
|
-
|
|
75
|
-
return packBase30(values);
|
|
102
|
+
return packBase30(values);
|
|
76
103
|
}
|
|
77
|
-
|
|
78
104
|
function asBytes(value) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
105
|
+
if (value instanceof Uint8Array)
|
|
106
|
+
return value;
|
|
107
|
+
if (ArrayBuffer.isView(value))
|
|
108
|
+
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
109
|
+
if (typeof value === 'string')
|
|
110
|
+
return new TextEncoder().encode(value);
|
|
111
|
+
throw new EncodeError('PDF417 byte: value must be text or a byte array');
|
|
83
112
|
}
|
|
84
|
-
|
|
85
113
|
/** Compact bytes using latch 924 for exact six-byte blocks and 901 otherwise. */
|
|
86
114
|
export function compactPdf417Bytes(value) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
const bytes = asBytes(value);
|
|
116
|
+
const utf8 = typeof value === 'string' && /[^\x00-\x7f]/.test(value);
|
|
117
|
+
const out = utf8 ? [927, 26] : [];
|
|
118
|
+
out.push(bytes.length > 0 && bytes.length % 6 === 0 ? 924 : 901);
|
|
119
|
+
let at = 0;
|
|
120
|
+
while (at + 6 <= bytes.length) {
|
|
121
|
+
let number = 0n;
|
|
122
|
+
for (let i = 0; i < 6; i++)
|
|
123
|
+
number = (number << 8n) | BigInt(bytes[at++]);
|
|
124
|
+
const group = new Array(5);
|
|
125
|
+
for (let i = 4; i >= 0; i--) {
|
|
126
|
+
group[i] = Number(number % 900n);
|
|
127
|
+
number /= 900n;
|
|
128
|
+
}
|
|
129
|
+
out.push(...group);
|
|
130
|
+
}
|
|
131
|
+
while (at < bytes.length)
|
|
132
|
+
out.push(bytes[at++]);
|
|
133
|
+
return out;
|
|
101
134
|
}
|
|
102
|
-
|
|
103
135
|
/** Compact decimal digits using latch 902 and groups of at most 44 digits. */
|
|
104
136
|
export function compactPdf417Numeric(value) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
let
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
137
|
+
if (typeof value !== 'string' || !/^\d+$/.test(value))
|
|
138
|
+
throw new EncodeError('PDF417 numeric: value must contain decimal digits only');
|
|
139
|
+
const out = [902];
|
|
140
|
+
for (let at = 0; at < value.length; at += 44) {
|
|
141
|
+
let number = BigInt(`1${value.slice(at, at + 44)}`);
|
|
142
|
+
const group = [];
|
|
143
|
+
do {
|
|
144
|
+
group.unshift(Number(number % 900n));
|
|
145
|
+
number /= 900n;
|
|
146
|
+
} while (number > 0n);
|
|
147
|
+
out.push(...group);
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
114
150
|
}
|
|
115
|
-
|
|
116
151
|
/** Compact a single value, selecting text, numeric or byte mode. */
|
|
117
152
|
export function compactPdf417(value, options = {}) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
153
|
+
const mode = options.compaction ?? 'auto';
|
|
154
|
+
if (mode === 'text')
|
|
155
|
+
return compactPdf417Text(value);
|
|
156
|
+
if (mode === 'byte')
|
|
157
|
+
return compactPdf417Bytes(value);
|
|
158
|
+
if (mode === 'numeric')
|
|
159
|
+
return compactPdf417Numeric(value);
|
|
160
|
+
if (mode !== 'auto')
|
|
161
|
+
throw new EncodeError(`PDF417: unsupported compaction mode ${JSON.stringify(mode)}`);
|
|
162
|
+
if (typeof value === 'string' && /^\d{13,}$/.test(value))
|
|
163
|
+
return compactPdf417Numeric(value);
|
|
164
|
+
if (typeof value === 'string') {
|
|
165
|
+
try {
|
|
166
|
+
return compactPdf417Text(value);
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
if (!(error instanceof EncodeError))
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return compactPdf417Bytes(value);
|
|
128
174
|
}
|
|
129
|
-
|
|
130
175
|
function assertCodeword(codeword) {
|
|
131
|
-
|
|
176
|
+
if (!Number.isInteger(codeword) || codeword < 0 || codeword > 928)
|
|
177
|
+
throw new FormatError('PDF417: codeword is outside 0..928');
|
|
132
178
|
}
|
|
133
|
-
|
|
134
179
|
function decodeUtf8(bytes, eci) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
180
|
+
if (eci === 3)
|
|
181
|
+
return Array.from(bytes, (byte) => String.fromCharCode(byte)).join('');
|
|
182
|
+
if (eci !== 26)
|
|
183
|
+
throw new FormatError(`PDF417 ECI: unsupported assignment number ${eci}`);
|
|
184
|
+
try {
|
|
185
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(new Uint8Array(bytes));
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
throw new FormatError('PDF417 byte: invalid UTF-8 sequence');
|
|
189
|
+
}
|
|
139
190
|
}
|
|
140
|
-
|
|
141
191
|
function decodeByteSegment(codewords, at, eci, sixOnly = false) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
for (let
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
function decodeTextSegment(codewords, at, eci) {
|
|
166
|
-
let mode = 'alpha';
|
|
167
|
-
let output = '';
|
|
168
|
-
let shift = null;
|
|
169
|
-
let shiftedBytes = [];
|
|
170
|
-
const bytes = [];
|
|
171
|
-
const flushShiftedBytes = () => {
|
|
172
|
-
if (shiftedBytes.length) {
|
|
173
|
-
output += decodeUtf8(shiftedBytes, eci);
|
|
174
|
-
bytes.push(...shiftedBytes);
|
|
175
|
-
shiftedBytes = [];
|
|
192
|
+
const values = [];
|
|
193
|
+
while (at < codewords.length && codewords[at] < 900)
|
|
194
|
+
values.push(codewords[at++]);
|
|
195
|
+
if (sixOnly && values.length % 5)
|
|
196
|
+
throw new FormatError('PDF417 byte: 924 segment must contain complete six-byte groups');
|
|
197
|
+
const bytes = [];
|
|
198
|
+
// In 901 mode an encoder can use five terminal literal codewords. The
|
|
199
|
+
// unambiguous groups are therefore the ones followed by another codeword;
|
|
200
|
+
// 924 is available whenever a segment consists exclusively of six-byte groups.
|
|
201
|
+
const groupCount = sixOnly ? values.length / 5 : Math.max(0, Math.floor((values.length - 1) / 5));
|
|
202
|
+
for (let groupAt = 0; groupAt < groupCount * 5; groupAt += 5) {
|
|
203
|
+
let number = 0n;
|
|
204
|
+
for (let i = 0; i < 5; i++)
|
|
205
|
+
number = number * 900n + BigInt(values[groupAt + i]);
|
|
206
|
+
const group = new Uint8Array(6);
|
|
207
|
+
for (let i = 5; i >= 0; i--) {
|
|
208
|
+
group[i] = Number(number & 255n);
|
|
209
|
+
number >>= 8n;
|
|
210
|
+
}
|
|
211
|
+
if (number !== 0n)
|
|
212
|
+
throw new FormatError('PDF417 byte: base-900 group exceeds six bytes');
|
|
213
|
+
bytes.push(...group);
|
|
176
214
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
};
|
|
182
|
-
const process = (value) => {
|
|
183
|
-
if (shift) { emit(shift === 'alpha' ? ALPHA : PUNCT, value); shift = null; return; }
|
|
184
|
-
if (mode === 'alpha') {
|
|
185
|
-
if (value < 26) emit(ALPHA, value);
|
|
186
|
-
else if (value === 26) output += ' ';
|
|
187
|
-
else if (value === 27) mode = 'lower';
|
|
188
|
-
else if (value === 28) mode = 'mixed';
|
|
189
|
-
else if (value === 29) shift = 'punct';
|
|
190
|
-
} else if (mode === 'lower') {
|
|
191
|
-
if (value < 26) emit(LOWER, value);
|
|
192
|
-
else if (value === 26) output += ' ';
|
|
193
|
-
else if (value === 27) shift = 'alpha';
|
|
194
|
-
else if (value === 28) mode = 'mixed';
|
|
195
|
-
else if (value === 29) shift = 'punct';
|
|
196
|
-
} else if (mode === 'mixed') {
|
|
197
|
-
if (value < 25) emit(MIXED, value);
|
|
198
|
-
else if (value === 25) mode = 'punct';
|
|
199
|
-
else if (value === 26) output += ' ';
|
|
200
|
-
else if (value === 27) mode = 'lower';
|
|
201
|
-
else if (value === 28) mode = 'alpha';
|
|
202
|
-
else if (value === 29) shift = 'punct';
|
|
203
|
-
} else {
|
|
204
|
-
if (value < 29) emit(PUNCT, value);
|
|
205
|
-
else if (value === 29) mode = 'alpha';
|
|
215
|
+
for (let i = groupCount * 5; i < values.length; i++) {
|
|
216
|
+
if (values[i] > 255)
|
|
217
|
+
throw new FormatError('PDF417 byte: literal tail is outside 0..255');
|
|
218
|
+
bytes.push(values[i]);
|
|
206
219
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
220
|
+
return { at, text: decodeUtf8(bytes, eci), bytes: Uint8Array.from(bytes) };
|
|
221
|
+
}
|
|
222
|
+
function decodeTextSegment(codewords, at, eci) {
|
|
223
|
+
let mode = 'alpha';
|
|
224
|
+
let output = '';
|
|
225
|
+
let shift = null;
|
|
226
|
+
let shiftedBytes = [];
|
|
227
|
+
const bytes = [];
|
|
228
|
+
const flushShiftedBytes = () => {
|
|
229
|
+
if (shiftedBytes.length) {
|
|
230
|
+
output += decodeUtf8(shiftedBytes, eci);
|
|
231
|
+
bytes.push(...shiftedBytes);
|
|
232
|
+
shiftedBytes = [];
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
const emit = (alphabet, value) => {
|
|
236
|
+
if (value < 0 || value >= alphabet.length)
|
|
237
|
+
throw new FormatError('PDF417 text: invalid submode value');
|
|
238
|
+
output += alphabet[value];
|
|
239
|
+
};
|
|
240
|
+
const process = (value) => {
|
|
241
|
+
if (shift) {
|
|
242
|
+
emit(shift === 'alpha' ? ALPHA : PUNCT, value);
|
|
243
|
+
shift = null;
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (mode === 'alpha') {
|
|
247
|
+
if (value < 26)
|
|
248
|
+
emit(ALPHA, value);
|
|
249
|
+
else if (value === 26)
|
|
250
|
+
output += ' ';
|
|
251
|
+
else if (value === 27)
|
|
252
|
+
mode = 'lower';
|
|
253
|
+
else if (value === 28)
|
|
254
|
+
mode = 'mixed';
|
|
255
|
+
else if (value === 29)
|
|
256
|
+
shift = 'punct';
|
|
257
|
+
}
|
|
258
|
+
else if (mode === 'lower') {
|
|
259
|
+
if (value < 26)
|
|
260
|
+
emit(LOWER, value);
|
|
261
|
+
else if (value === 26)
|
|
262
|
+
output += ' ';
|
|
263
|
+
else if (value === 27)
|
|
264
|
+
shift = 'alpha';
|
|
265
|
+
else if (value === 28)
|
|
266
|
+
mode = 'mixed';
|
|
267
|
+
else if (value === 29)
|
|
268
|
+
shift = 'punct';
|
|
269
|
+
}
|
|
270
|
+
else if (mode === 'mixed') {
|
|
271
|
+
if (value < 25)
|
|
272
|
+
emit(MIXED, value);
|
|
273
|
+
else if (value === 25)
|
|
274
|
+
mode = 'punct';
|
|
275
|
+
else if (value === 26)
|
|
276
|
+
output += ' ';
|
|
277
|
+
else if (value === 27)
|
|
278
|
+
mode = 'lower';
|
|
279
|
+
else if (value === 28)
|
|
280
|
+
mode = 'alpha';
|
|
281
|
+
else if (value === 29)
|
|
282
|
+
shift = 'punct';
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
if (value < 29)
|
|
286
|
+
emit(PUNCT, value);
|
|
287
|
+
else if (value === 29)
|
|
288
|
+
mode = 'alpha';
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
while (at < codewords.length) {
|
|
292
|
+
const codeword = codewords[at];
|
|
293
|
+
if (codeword >= 900 && codeword !== 913)
|
|
294
|
+
break;
|
|
295
|
+
at++;
|
|
296
|
+
if (codeword === 913) {
|
|
297
|
+
if (at >= codewords.length || codewords[at] > 255)
|
|
298
|
+
throw new FormatError('PDF417 text: invalid byte shift');
|
|
299
|
+
shiftedBytes.push(codewords[at++]);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
flushShiftedBytes();
|
|
303
|
+
process(Math.floor(codeword / 30));
|
|
304
|
+
process(codeword % 30);
|
|
216
305
|
}
|
|
217
306
|
flushShiftedBytes();
|
|
218
|
-
|
|
219
|
-
process(codeword % 30);
|
|
220
|
-
}
|
|
221
|
-
flushShiftedBytes();
|
|
222
|
-
return { at, text: output, bytes: Uint8Array.from(bytes) };
|
|
307
|
+
return { at, text: output, bytes: Uint8Array.from(bytes) };
|
|
223
308
|
}
|
|
224
|
-
|
|
225
309
|
function decodeNumericSegment(codewords, at) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
310
|
+
let output = '';
|
|
311
|
+
while (at < codewords.length && codewords[at] < 900) {
|
|
312
|
+
const end = Math.min(at + 15, codewords.length);
|
|
313
|
+
let number = 0n;
|
|
314
|
+
for (; at < end && codewords[at] < 900; at++)
|
|
315
|
+
number = number * 900n + BigInt(codewords[at]);
|
|
316
|
+
const decimal = number.toString();
|
|
317
|
+
if (!decimal.startsWith('1'))
|
|
318
|
+
throw new FormatError('PDF417 numeric: missing leading sentinel');
|
|
319
|
+
output += decimal.slice(1);
|
|
320
|
+
}
|
|
321
|
+
return { at, text: output, bytes: new Uint8Array(0) };
|
|
236
322
|
}
|
|
237
|
-
|
|
238
323
|
/**
|
|
239
324
|
* Decode PDF417 compaction while preserving raw Byte Compaction and byte-shift
|
|
240
325
|
* payloads. Text and Numeric Compaction do not manufacture bytes: their text
|
|
@@ -242,57 +327,65 @@ function decodeNumericSegment(codewords, at) {
|
|
|
242
327
|
* modes that encode octets explicitly.
|
|
243
328
|
*/
|
|
244
329
|
export function decodePdf417CompactionDetailed(codewords) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
330
|
+
if (!Array.isArray(codewords) && !ArrayBuffer.isView(codewords))
|
|
331
|
+
throw new FormatError('PDF417: codewords must be an array');
|
|
332
|
+
for (const codeword of codewords)
|
|
333
|
+
assertCodeword(codeword);
|
|
334
|
+
let at = 0;
|
|
335
|
+
// ISO/IEC 8859-1 is the PDF417 default; UTF-8 is selected explicitly with ECI 26.
|
|
336
|
+
let eci = 3;
|
|
337
|
+
let output = '';
|
|
338
|
+
const bytes = [];
|
|
339
|
+
const segments = [];
|
|
340
|
+
while (at < codewords.length) {
|
|
341
|
+
const codeword = codewords[at];
|
|
342
|
+
if (codeword < 900 || codeword === 900 || codeword === 913) {
|
|
343
|
+
const start = at;
|
|
344
|
+
const latch = codeword === 900 ? codeword : null;
|
|
345
|
+
if (latch !== null)
|
|
346
|
+
at++;
|
|
347
|
+
const segment = decodeTextSegment(codewords, at, eci);
|
|
348
|
+
at = segment.at;
|
|
349
|
+
output += segment.text;
|
|
350
|
+
bytes.push(...segment.bytes);
|
|
351
|
+
if (segment.text.length || segment.bytes.length)
|
|
352
|
+
segments.push({ mode: 'text', text: segment.text, bytes: segment.bytes, eci, latch, codewordStart: start, codewordEnd: at });
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
const start = at;
|
|
356
|
+
at++;
|
|
357
|
+
if (codeword === 901) {
|
|
358
|
+
const segment = decodeByteSegment(codewords, at, eci);
|
|
359
|
+
at = segment.at;
|
|
360
|
+
output += segment.text;
|
|
361
|
+
bytes.push(...segment.bytes);
|
|
362
|
+
segments.push({ mode: 'byte', text: segment.text, bytes: segment.bytes, eci, latch: codeword, codewordStart: start, codewordEnd: at });
|
|
363
|
+
}
|
|
364
|
+
else if (codeword === 924) {
|
|
365
|
+
const segment = decodeByteSegment(codewords, at, eci, true);
|
|
366
|
+
at = segment.at;
|
|
367
|
+
output += segment.text;
|
|
368
|
+
bytes.push(...segment.bytes);
|
|
369
|
+
segments.push({ mode: 'byte', text: segment.text, bytes: segment.bytes, eci, latch: codeword, codewordStart: start, codewordEnd: at });
|
|
370
|
+
}
|
|
371
|
+
else if (codeword === 902) {
|
|
372
|
+
const segment = decodeNumericSegment(codewords, at);
|
|
373
|
+
at = segment.at;
|
|
374
|
+
output += segment.text;
|
|
375
|
+
segments.push({ mode: 'numeric', text: segment.text, bytes: segment.bytes, eci, latch: codeword, codewordStart: start, codewordEnd: at });
|
|
376
|
+
}
|
|
377
|
+
else if (codeword === 927) {
|
|
378
|
+
if (at >= codewords.length || codewords[at] > 899)
|
|
379
|
+
throw new FormatError('PDF417 ECI: missing assignment number');
|
|
380
|
+
eci = codewords[at++];
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
throw new FormatError(`PDF417: unsupported compaction codeword ${codeword}`);
|
|
384
|
+
}
|
|
290
385
|
}
|
|
291
|
-
|
|
292
|
-
return { text: output, bytes: Uint8Array.from(bytes), segments };
|
|
386
|
+
return { text: output, bytes: Uint8Array.from(bytes), segments };
|
|
293
387
|
}
|
|
294
|
-
|
|
295
388
|
/** Decode PDF417 Text, Byte, Numeric and UTF-8 ECI compaction segments in source order. */
|
|
296
389
|
export function decodePdf417Compaction(codewords) {
|
|
297
|
-
|
|
390
|
+
return decodePdf417CompactionDetailed(codewords).text;
|
|
298
391
|
}
|