@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
|
@@ -27,54 +27,48 @@
|
|
|
27
27
|
*
|
|
28
28
|
* Original work. No code from any other barcode implementation.
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
30
|
/** MicroPDF417 high-level compaction adapter. @module micropdf417/compaction */
|
|
32
|
-
|
|
33
31
|
import { EncodeError } from '../core/errors.js';
|
|
34
|
-
import {
|
|
35
|
-
compactPdf417Bytes,
|
|
36
|
-
compactPdf417Numeric,
|
|
37
|
-
compactPdf417Text,
|
|
38
|
-
} from '../pdf417/compaction.js';
|
|
39
|
-
|
|
32
|
+
import { compactPdf417Bytes, compactPdf417Numeric, compactPdf417Text, } from '../pdf417/compaction.js';
|
|
40
33
|
function byteLength(value) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
if (value instanceof Uint8Array)
|
|
35
|
+
return value.byteLength;
|
|
36
|
+
if (ArrayBuffer.isView(value))
|
|
37
|
+
return value.byteLength;
|
|
38
|
+
return -1;
|
|
44
39
|
}
|
|
45
|
-
|
|
46
40
|
function assertNotEmpty(value) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
if ((typeof value === 'string' && value.length === 0) || byteLength(value) === 0) {
|
|
42
|
+
throw new EncodeError('MicroPDF417: value must not be empty');
|
|
43
|
+
}
|
|
50
44
|
}
|
|
51
|
-
|
|
52
45
|
function latin1Bytes(value) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
if (typeof value !== 'string')
|
|
47
|
+
return value;
|
|
48
|
+
const bytes = [];
|
|
49
|
+
for (const character of value) {
|
|
50
|
+
const codePoint = character.codePointAt(0);
|
|
51
|
+
if (codePoint > 255) {
|
|
52
|
+
throw new EncodeError('MicroPDF417 ECI 3: string contains a character outside ISO-8859-1');
|
|
53
|
+
}
|
|
54
|
+
bytes.push(codePoint);
|
|
59
55
|
}
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
return Uint8Array.from(bytes);
|
|
56
|
+
return Uint8Array.from(bytes);
|
|
63
57
|
}
|
|
64
|
-
|
|
65
58
|
function compactByte(value, eci) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
59
|
+
if (eci === undefined)
|
|
60
|
+
return compactPdf417Bytes(value);
|
|
61
|
+
if (eci === 3)
|
|
62
|
+
return compactPdf417Bytes(latin1Bytes(value));
|
|
63
|
+
if (eci === 26) {
|
|
64
|
+
if (typeof value !== 'string') {
|
|
65
|
+
throw new EncodeError('MicroPDF417 ECI 26: value must be a string so UTF-8 validity is known');
|
|
66
|
+
}
|
|
67
|
+
const encoded = compactPdf417Bytes(value);
|
|
68
|
+
return encoded[0] === 927 && encoded[1] === 26 ? encoded : [927, 26, ...encoded];
|
|
71
69
|
}
|
|
72
|
-
|
|
73
|
-
return encoded[0] === 927 && encoded[1] === 26 ? encoded : [927, 26, ...encoded];
|
|
74
|
-
}
|
|
75
|
-
throw new EncodeError('MicroPDF417: supported ECI assignment numbers are 3 and 26');
|
|
70
|
+
throw new EncodeError('MicroPDF417: supported ECI assignment numbers are 3 and 26');
|
|
76
71
|
}
|
|
77
|
-
|
|
78
72
|
/**
|
|
79
73
|
* Compact one MicroPDF417 value.
|
|
80
74
|
*
|
|
@@ -83,34 +77,39 @@ function compactByte(value, eci) {
|
|
|
83
77
|
* state is unambiguous, including when an ECI designator precedes it.
|
|
84
78
|
*/
|
|
85
79
|
export function compactMicroPDF417(value, options = {}) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
80
|
+
assertNotEmpty(value);
|
|
81
|
+
const mode = options.compaction ?? 'auto';
|
|
82
|
+
const eci = options.eci;
|
|
83
|
+
if (eci !== undefined && eci !== 3 && eci !== 26) {
|
|
84
|
+
throw new EncodeError('MicroPDF417: supported ECI assignment numbers are 3 and 26');
|
|
85
|
+
}
|
|
86
|
+
if (mode === 'text') {
|
|
87
|
+
if (eci !== undefined)
|
|
88
|
+
throw new EncodeError('MicroPDF417: explicit ECI is supported only with byte compaction');
|
|
89
|
+
return [900, ...compactPdf417Text(value)];
|
|
90
|
+
}
|
|
91
|
+
if (mode === 'numeric') {
|
|
92
|
+
if (eci !== undefined)
|
|
93
|
+
throw new EncodeError('MicroPDF417: explicit ECI is supported only with byte compaction');
|
|
94
|
+
return compactPdf417Numeric(value);
|
|
95
|
+
}
|
|
96
|
+
if (mode === 'byte')
|
|
97
|
+
return compactByte(value, eci);
|
|
98
|
+
if (mode !== 'auto') {
|
|
99
|
+
throw new EncodeError(`MicroPDF417: unsupported compaction mode ${JSON.stringify(mode)}`);
|
|
100
|
+
}
|
|
101
|
+
if (eci !== undefined)
|
|
102
|
+
return compactByte(value, eci);
|
|
103
|
+
if (typeof value === 'string' && /^\d{13,}$/.test(value))
|
|
104
|
+
return compactPdf417Numeric(value);
|
|
105
|
+
if (typeof value === 'string') {
|
|
106
|
+
try {
|
|
107
|
+
return [900, ...compactPdf417Text(value)];
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (!(error instanceof EncodeError))
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
113
|
}
|
|
114
|
-
|
|
115
|
-
return compactPdf417Bytes(value);
|
|
114
|
+
return compactPdf417Bytes(value);
|
|
116
115
|
}
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
*
|
|
28
28
|
* Original work. No code from any other barcode implementation.
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
30
|
/**
|
|
32
31
|
* Direct-module MicroPDF417 decoder.
|
|
33
32
|
*
|
|
@@ -38,125 +37,123 @@
|
|
|
38
37
|
*
|
|
39
38
|
* @module micropdf417/decoder
|
|
40
39
|
*/
|
|
41
|
-
|
|
42
40
|
import { FormatError } from '../core/errors.js';
|
|
43
41
|
import { decodePdf417CompactionDetailed } from '../pdf417/compaction.js';
|
|
44
42
|
import { pdf417CodewordForPattern } from '../pdf417/tables.js';
|
|
45
43
|
import { microPdf417CorrectErrors } from './error-correction.js';
|
|
46
|
-
import {
|
|
47
|
-
MICROPDF417_VARIANTS,
|
|
48
|
-
microPdf417RapSequence,
|
|
49
|
-
microPdf417RowAddress,
|
|
50
|
-
microPdf417VariantByNumber,
|
|
51
|
-
} from './tables.js';
|
|
52
|
-
|
|
44
|
+
import { MICROPDF417_VARIANTS, microPdf417RapSequence, microPdf417RowAddress, microPdf417VariantByNumber, } from './tables.js';
|
|
53
45
|
function symbolWidth(columns) {
|
|
54
|
-
|
|
46
|
+
return 21 + columns * 17 + (columns > 2 ? 10 : 0);
|
|
55
47
|
}
|
|
56
|
-
|
|
57
48
|
function bits(matrix, y, x, width) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
49
|
+
let value = 0;
|
|
50
|
+
for (let i = 0; i < width; i++)
|
|
51
|
+
value = (value << 1) | (matrix.get(x + i, y) ? 1 : 0);
|
|
52
|
+
return value;
|
|
61
53
|
}
|
|
62
|
-
|
|
63
54
|
function widthsToBits(widths) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
55
|
+
let dark = true;
|
|
56
|
+
let out = '';
|
|
57
|
+
for (const digit of widths) {
|
|
58
|
+
out += (dark ? '1' : '0').repeat(digit.charCodeAt(0) - 48);
|
|
59
|
+
dark = !dark;
|
|
60
|
+
}
|
|
61
|
+
return out;
|
|
71
62
|
}
|
|
72
|
-
|
|
73
63
|
function hasExpectedBits(matrix, y, x, sequence) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
const expected = widthsToBits(sequence);
|
|
65
|
+
for (let i = 0; i < expected.length; i++) {
|
|
66
|
+
if ((matrix.get(x + i, y) ? '1' : '0') !== expected[i])
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
79
70
|
}
|
|
80
|
-
|
|
81
71
|
function centralRapAfter(entry, column) {
|
|
82
|
-
|
|
83
|
-
|
|
72
|
+
return (entry.columns === 3 && column === 0) ||
|
|
73
|
+
(entry.columns === 4 && column === 1);
|
|
84
74
|
}
|
|
85
|
-
|
|
86
75
|
/** Return true when all address patterns for this format candidate agree. */
|
|
87
76
|
function hasValidRowAddresses(matrix, entry, rowHeight) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
77
|
+
for (let row = 0; row < entry.rows; row++) {
|
|
78
|
+
const y = row * rowHeight;
|
|
79
|
+
const address = microPdf417RowAddress(entry, row);
|
|
80
|
+
let x = 0;
|
|
81
|
+
if (!hasExpectedBits(matrix, y, x, microPdf417RapSequence(address.left, 'side')))
|
|
82
|
+
return false;
|
|
83
|
+
x += 10;
|
|
84
|
+
for (let column = 0; column < entry.columns; column++) {
|
|
85
|
+
x += 17;
|
|
86
|
+
if (centralRapAfter(entry, column)) {
|
|
87
|
+
if (address.center === null ||
|
|
88
|
+
!hasExpectedBits(matrix, y, x, microPdf417RapSequence(address.center, 'center')))
|
|
89
|
+
return false;
|
|
90
|
+
x += 10;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (!hasExpectedBits(matrix, y, x, microPdf417RapSequence(address.right, 'side')))
|
|
94
|
+
return false;
|
|
99
95
|
x += 10;
|
|
100
|
-
|
|
96
|
+
if (!matrix.get(x, y) || x + 1 !== matrix.width)
|
|
97
|
+
return false;
|
|
101
98
|
}
|
|
102
|
-
|
|
103
|
-
x += 10;
|
|
104
|
-
if (!matrix.get(x, y) || x + 1 !== matrix.width) return false;
|
|
105
|
-
}
|
|
106
|
-
return true;
|
|
99
|
+
return true;
|
|
107
100
|
}
|
|
108
|
-
|
|
109
101
|
function candidateFormats(matrix, options) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
102
|
+
const metadataHeight = matrix.micropdf417?.rowHeight;
|
|
103
|
+
const requestedHeight = options.rowHeight ?? metadataHeight;
|
|
104
|
+
if (requestedHeight !== undefined && (!Number.isInteger(requestedHeight) || requestedHeight < 1)) {
|
|
105
|
+
throw new FormatError('MicroPDF417: rowHeight must be a positive integer');
|
|
106
|
+
}
|
|
107
|
+
const requestedVariant = options.variant === undefined ? null : microPdf417VariantByNumber(options.variant);
|
|
108
|
+
const pool = requestedVariant ? [requestedVariant] : MICROPDF417_VARIANTS;
|
|
109
|
+
const candidates = [];
|
|
110
|
+
for (const entry of pool) {
|
|
111
|
+
if (matrix.width !== symbolWidth(entry.columns))
|
|
112
|
+
continue;
|
|
113
|
+
if (matrix.height % entry.rows)
|
|
114
|
+
continue;
|
|
115
|
+
const rowHeight = matrix.height / entry.rows;
|
|
116
|
+
if (requestedHeight !== undefined && rowHeight !== requestedHeight)
|
|
117
|
+
continue;
|
|
118
|
+
if (hasValidRowAddresses(matrix, entry, rowHeight))
|
|
119
|
+
candidates.push({ entry, rowHeight });
|
|
120
|
+
}
|
|
121
|
+
return candidates;
|
|
126
122
|
}
|
|
127
|
-
|
|
128
123
|
function resolveFormat(matrix, options) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
124
|
+
if (!matrix?.width || !matrix?.height || typeof matrix.get !== 'function') {
|
|
125
|
+
throw new FormatError('MicroPDF417: matrix with width, height and get() is required');
|
|
126
|
+
}
|
|
127
|
+
const candidates = candidateFormats(matrix, options);
|
|
128
|
+
if (!candidates.length)
|
|
129
|
+
throw new FormatError('MicroPDF417: no variant matches matrix geometry and row-address patterns');
|
|
130
|
+
if (candidates.length > 1)
|
|
131
|
+
throw new FormatError('MicroPDF417: row-address patterns do not identify a unique variant');
|
|
132
|
+
return candidates[0];
|
|
136
133
|
}
|
|
137
|
-
|
|
138
134
|
function readCodewords(matrix, entry, rowHeight) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
135
|
+
const codewords = [];
|
|
136
|
+
const erasures = [];
|
|
137
|
+
for (let row = 0; row < entry.rows; row++) {
|
|
138
|
+
const y = row * rowHeight;
|
|
139
|
+
const address = microPdf417RowAddress(entry, row);
|
|
140
|
+
let x = 10;
|
|
141
|
+
for (let column = 0; column < entry.columns; column++) {
|
|
142
|
+
const decoded = pdf417CodewordForPattern(bits(matrix, y, x, 17));
|
|
143
|
+
if (!decoded || decoded.cluster !== address.cluster) {
|
|
144
|
+
erasures.push(codewords.length);
|
|
145
|
+
codewords.push(0);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
codewords.push(decoded.codeword);
|
|
149
|
+
}
|
|
150
|
+
x += 17;
|
|
151
|
+
if (centralRapAfter(entry, column))
|
|
152
|
+
x += 10;
|
|
153
|
+
}
|
|
155
154
|
}
|
|
156
|
-
|
|
157
|
-
return { codewords, erasures };
|
|
155
|
+
return { codewords, erasures };
|
|
158
156
|
}
|
|
159
|
-
|
|
160
157
|
/**
|
|
161
158
|
* Decode a sampled MicroPDF417 matrix.
|
|
162
159
|
*
|
|
@@ -165,19 +162,19 @@ function readCodewords(matrix, entry, rowHeight) {
|
|
|
165
162
|
* payload. This avoids relying on non-symbol metadata for payload length.
|
|
166
163
|
*/
|
|
167
164
|
export function decodeMicroPDF417(matrix, options = {}) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
165
|
+
const { entry, rowHeight } = resolveFormat(matrix, options);
|
|
166
|
+
const { codewords, erasures } = readCodewords(matrix, entry, rowHeight);
|
|
167
|
+
const corrections = microPdf417CorrectErrors(codewords, entry, erasures);
|
|
168
|
+
const data = codewords.slice(0, entry.dataCodewords);
|
|
169
|
+
const decoded = decodePdf417CompactionDetailed(data);
|
|
170
|
+
return {
|
|
171
|
+
...decoded,
|
|
172
|
+
codewords,
|
|
173
|
+
rows: entry.rows,
|
|
174
|
+
columns: entry.columns,
|
|
175
|
+
variant: entry.id,
|
|
176
|
+
eccCodewords: entry.eccCodewords,
|
|
177
|
+
rowHeight,
|
|
178
|
+
corrections,
|
|
179
|
+
};
|
|
183
180
|
}
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
*
|
|
28
28
|
* Original work. No code from any other barcode implementation.
|
|
29
29
|
*/
|
|
30
|
-
|
|
31
30
|
/**
|
|
32
31
|
* Axis-aligned MicroPDF417 raster detection.
|
|
33
32
|
*
|
|
@@ -42,71 +41,74 @@
|
|
|
42
41
|
*
|
|
43
42
|
* @module micropdf417/detector
|
|
44
43
|
*/
|
|
45
|
-
|
|
46
44
|
import { BitMatrix } from '../core/bit-matrix.js';
|
|
47
45
|
import { decodeMicroPDF417 } from './decoder.js';
|
|
48
|
-
|
|
49
46
|
/** @typedef {{x:number, y:number}} Point */
|
|
50
|
-
|
|
51
47
|
// Each row has two 10-module side RAPs, a final separator, and 17 modules for
|
|
52
48
|
// each data column. Three and four columns also contain one central RAP.
|
|
53
49
|
function symbolWidth(columns) { return 21 + columns * 17 + (columns > 2 ? 10 : 0); }
|
|
54
50
|
const WIDTHS = [1, 2, 3, 4].map(symbolWidth);
|
|
55
|
-
|
|
56
51
|
function rotateClockwise(source) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
const rotated = new BitMatrix(source.height, source.width);
|
|
53
|
+
for (let y = 0; y < source.height; y++)
|
|
54
|
+
for (let x = 0; x < source.width; x++) {
|
|
55
|
+
if (source.get(x, y))
|
|
56
|
+
rotated.set(source.height - 1 - y, x);
|
|
57
|
+
}
|
|
58
|
+
return rotated;
|
|
62
59
|
}
|
|
63
|
-
|
|
64
60
|
function integerScale(width, modules) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
if (width % modules)
|
|
62
|
+
return 0;
|
|
63
|
+
const scale = width / modules;
|
|
64
|
+
return Number.isInteger(scale) && scale > 0 ? scale : 0;
|
|
68
65
|
}
|
|
69
|
-
|
|
70
66
|
/** Collapse exact integer scale blocks using a majority vote. */
|
|
71
67
|
function sampleRaster(image, bounds, modulesWide, scale) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
let
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
68
|
+
const modulesHigh = bounds.height / scale;
|
|
69
|
+
if (!Number.isInteger(modulesHigh) || modulesHigh < 1)
|
|
70
|
+
return null;
|
|
71
|
+
const matrix = new BitMatrix(modulesWide, modulesHigh);
|
|
72
|
+
for (let y = 0; y < modulesHigh; y++)
|
|
73
|
+
for (let x = 0; x < modulesWide; x++) {
|
|
74
|
+
let dark = 0;
|
|
75
|
+
for (let py = 0; py < scale; py++)
|
|
76
|
+
for (let px = 0; px < scale; px++) {
|
|
77
|
+
if (image.get(bounds.x + x * scale + px, bounds.y + y * scale + py))
|
|
78
|
+
dark++;
|
|
79
|
+
}
|
|
80
|
+
if (dark * 2 >= scale * scale)
|
|
81
|
+
matrix.set(x, y);
|
|
82
|
+
}
|
|
83
|
+
return matrix;
|
|
83
84
|
}
|
|
84
|
-
|
|
85
85
|
function rectangle(bounds) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
return [
|
|
87
|
+
{ x: bounds.x, y: bounds.y },
|
|
88
|
+
{ x: bounds.x + bounds.width, y: bounds.y },
|
|
89
|
+
{ x: bounds.x + bounds.width, y: bounds.y + bounds.height },
|
|
90
|
+
{ x: bounds.x, y: bounds.y + bounds.height },
|
|
91
|
+
];
|
|
92
92
|
}
|
|
93
|
-
|
|
94
93
|
function detectAxisAligned(image, options) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
94
|
+
const bounds = image.getBounds();
|
|
95
|
+
if (!bounds)
|
|
96
|
+
return null;
|
|
97
|
+
for (const width of WIDTHS) {
|
|
98
|
+
const scale = integerScale(bounds.width, width);
|
|
99
|
+
if (!scale || bounds.height % scale)
|
|
100
|
+
continue;
|
|
101
|
+
const matrix = sampleRaster(image, bounds, width, scale);
|
|
102
|
+
if (!matrix)
|
|
103
|
+
continue;
|
|
104
|
+
try {
|
|
105
|
+
const decoded = decodeMicroPDF417(matrix, options);
|
|
106
|
+
return { matrix, corners: rectangle(bounds), moduleSize: scale, ...decoded };
|
|
107
|
+
}
|
|
108
|
+
catch { /* The RAP sequence is not a MicroPDF417 symbol of this width. */ }
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
108
111
|
}
|
|
109
|
-
|
|
110
112
|
/**
|
|
111
113
|
* Detect and decode one clean, binarized MicroPDF417 raster.
|
|
112
114
|
*
|
|
@@ -121,29 +123,30 @@ function detectAxisAligned(image, options) {
|
|
|
121
123
|
* @returns {(ReturnType<typeof decodeMicroPDF417> & {matrix: BitMatrix, corners: Point[], moduleSize: number, rotation: number}) | null}
|
|
122
124
|
*/
|
|
123
125
|
export function detectMicroPDF417(binaryImage, options = {}) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
126
|
+
if (!binaryImage?.width || !binaryImage?.height || typeof binaryImage.get !== 'function')
|
|
127
|
+
return null;
|
|
128
|
+
let oriented = binaryImage;
|
|
129
|
+
let toOriginal = (point) => ({ x: point.x, y: point.y });
|
|
130
|
+
for (let turns = 0; turns < 4; turns++) {
|
|
131
|
+
const found = detectAxisAligned(oriented, options);
|
|
132
|
+
// Search rotates clockwise to normalize the input. Public rotation has the
|
|
133
|
+
// opposite meaning: it describes how the input itself was rotated.
|
|
134
|
+
if (found)
|
|
135
|
+
return {
|
|
136
|
+
...found,
|
|
137
|
+
rotation: (360 - turns * 90) % 360,
|
|
138
|
+
corners: found.corners.map(toOriginal),
|
|
139
|
+
};
|
|
140
|
+
const previous = oriented;
|
|
141
|
+
const previousToOriginal = toOriginal;
|
|
142
|
+
oriented = rotateClockwise(previous);
|
|
143
|
+
// Boundary coordinates (rather than just pixel centres) are transformed
|
|
144
|
+
// here, so callers can draw the returned rectangle directly on the input.
|
|
145
|
+
toOriginal = (point) => previousToOriginal({ x: point.y, y: previous.height - point.x });
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
144
148
|
}
|
|
145
|
-
|
|
146
149
|
/** Alias kept symmetric with the other 2D readers. */
|
|
147
150
|
export function detectAndDecodeMicroPDF417(binaryImage, options = {}) {
|
|
148
|
-
|
|
151
|
+
return detectMicroPDF417(binaryImage, options);
|
|
149
152
|
}
|