@sythos/js_barcode_universal 1.0.0 → 1.2.5
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 +16 -17
- package/NOTICE.md +24 -22
- package/README.md +137 -60
- package/bundle/sythos-barcode.esm.js +3380 -216
- package/bundle/sythos-barcode.js +3368 -216
- package/examples/create.html +2 -0
- package/examples/read.html +341 -341
- package/licenses/README.md +58 -29
- package/licenses/aztec-code.license +74 -0
- package/licenses/codabar.license +9 -9
- package/licenses/code-11.license +9 -9
- package/licenses/code-128.license +6 -6
- package/licenses/code-39.license +6 -6
- package/licenses/code-93.license +7 -7
- package/licenses/data-matrix.license +11 -11
- package/licenses/ean-13.license +6 -6
- package/licenses/ean-8.license +6 -6
- package/licenses/gs1-128.license +6 -6
- package/licenses/isbn.license +7 -7
- package/licenses/itf-14.license +6 -6
- package/licenses/itf.license +6 -6
- package/licenses/micropdf417.license +96 -0
- package/licenses/msi-plessey.license +7 -7
- package/licenses/pdf417.license +37 -0
- package/licenses/pharmacode.license +7 -7
- package/licenses/qr-code.license +6 -6
- package/licenses/upc-a.license +7 -7
- package/licenses/upc-e.license +6 -6
- package/package.json +13 -3
- package/src/aztec/decoder.js +317 -0
- package/src/aztec/detector.js +224 -0
- package/src/aztec/encoder.js +257 -0
- package/src/aztec/high-level.js +211 -0
- package/src/aztec/index.js +45 -0
- package/src/aztec/tables.js +210 -0
- package/src/core/galois-field.js +3 -0
- package/src/core/reed-solomon.js +64 -50
- package/src/datamatrix/decoder.js +262 -262
- package/src/datamatrix/detector.js +225 -225
- package/src/datamatrix/encoder.js +191 -191
- package/src/datamatrix/index.js +42 -42
- package/src/datamatrix/tables.js +123 -123
- package/src/index.js +113 -3
- package/src/micropdf417/compaction.js +116 -0
- package/src/micropdf417/decoder.js +183 -0
- package/src/micropdf417/detector.js +149 -0
- package/src/micropdf417/encoder.js +209 -0
- package/src/micropdf417/error-correction.js +55 -0
- package/src/micropdf417/index.js +49 -0
- package/src/micropdf417/tables.js +184 -0
- package/src/pdf417/compaction.js +298 -0
- package/src/pdf417/decoder.js +75 -0
- package/src/pdf417/detector.js +468 -0
- package/src/pdf417/encoder.js +91 -0
- package/src/pdf417/error-correction.js +47 -0
- package/src/pdf417/index.js +6 -0
- package/src/pdf417/tables.js +317 -0
package/src/datamatrix/tables.js
CHANGED
|
@@ -1,123 +1,123 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Sythos Barcode Suite
|
|
3
|
-
*
|
|
4
|
-
* MIT License
|
|
5
|
-
*
|
|
6
|
-
* Copyright (c) 2026 Sythos
|
|
7
|
-
*
|
|
8
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
10
|
-
* in the Software without restriction, including without limitation the rights
|
|
11
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
13
|
-
* furnished to do so, subject to the following conditions:
|
|
14
|
-
*
|
|
15
|
-
* The above copyright notice and this permission notice shall be included in all
|
|
16
|
-
* copies or substantial portions of the Software.
|
|
17
|
-
*
|
|
18
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
-
* SOFTWARE.
|
|
25
|
-
*
|
|
26
|
-
* SPDX-License-Identifier: MIT
|
|
27
|
-
*
|
|
28
|
-
* Original work. No code from any other barcode implementation.
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Data Matrix ECC 200 symbol parameters.
|
|
33
|
-
*
|
|
34
|
-
* Width and height include finder borders. `regionWidth` and `regionHeight`
|
|
35
|
-
* describe the usable modules inside one data region. The last three columns
|
|
36
|
-
* make the Reed-Solomon block split explicit instead of hiding the 144x144
|
|
37
|
-
* exception in encoder control flow.
|
|
38
|
-
*
|
|
39
|
-
* @module datamatrix/tables
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
function symbol(width, height, dataRegionWidth, dataRegionHeight, dataCodewords, errorCodewords, dataBlockLengths) {
|
|
43
|
-
const blockCount = dataBlockLengths.length;
|
|
44
|
-
return Object.freeze({
|
|
45
|
-
width, height, rows: height, columns: width,
|
|
46
|
-
// Region dimensions include their one-module finder border on each side;
|
|
47
|
-
// dataRegion* expose the inner placement lattice explicitly.
|
|
48
|
-
regionWidth: dataRegionWidth + 2, regionHeight: dataRegionHeight + 2,
|
|
49
|
-
dataRegionWidth, dataRegionHeight,
|
|
50
|
-
dataRegionRows: dataRegionHeight, dataRegionColumns: dataRegionWidth,
|
|
51
|
-
dataCodewords, errorCodewords, blockCount,
|
|
52
|
-
eccPerBlock: errorCodewords / blockCount,
|
|
53
|
-
dataBlockLengths: Object.freeze(dataBlockLengths),
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** Classic ISO/IEC 16022 ECC 200 symbols; DMRE is deliberately excluded. */
|
|
58
|
-
export const DATAMATRIX_SYMBOLS = Object.freeze([
|
|
59
|
-
symbol(10, 10, 8, 8, 3, 5, [3]),
|
|
60
|
-
symbol(12, 12, 10, 10, 5, 7, [5]),
|
|
61
|
-
symbol(14, 14, 12, 12, 8, 10, [8]),
|
|
62
|
-
symbol(16, 16, 14, 14, 12, 12, [12]),
|
|
63
|
-
symbol(18, 18, 16, 16, 18, 14, [18]),
|
|
64
|
-
symbol(20, 20, 18, 18, 22, 18, [22]),
|
|
65
|
-
symbol(22, 22, 20, 20, 30, 20, [30]),
|
|
66
|
-
symbol(24, 24, 22, 22, 36, 24, [36]),
|
|
67
|
-
symbol(26, 26, 24, 24, 44, 28, [44]),
|
|
68
|
-
symbol(32, 32, 14, 14, 62, 36, [62]),
|
|
69
|
-
symbol(36, 36, 16, 16, 86, 42, [86]),
|
|
70
|
-
symbol(40, 40, 18, 18, 114, 48, [114]),
|
|
71
|
-
symbol(44, 44, 20, 20, 144, 56, [144]),
|
|
72
|
-
symbol(48, 48, 22, 22, 174, 68, [174]),
|
|
73
|
-
symbol(52, 52, 24, 24, 204, 84, [102, 102]),
|
|
74
|
-
symbol(64, 64, 14, 14, 280, 112, [140, 140]),
|
|
75
|
-
symbol(72, 72, 16, 16, 368, 144, [92, 92, 92, 92]),
|
|
76
|
-
symbol(80, 80, 18, 18, 456, 192, [114, 114, 114, 114]),
|
|
77
|
-
symbol(88, 88, 20, 20, 576, 224, [144, 144, 144, 144]),
|
|
78
|
-
symbol(96, 96, 22, 22, 696, 272, [174, 174, 174, 174]),
|
|
79
|
-
symbol(104, 104, 24, 24, 816, 336, [136, 136, 136, 136, 136, 136]),
|
|
80
|
-
symbol(120, 120, 18, 18, 1050, 408, [175, 175, 175, 175, 175, 175]),
|
|
81
|
-
symbol(132, 132, 20, 20, 1304, 496, [163, 163, 163, 163, 163, 163, 163, 163]),
|
|
82
|
-
symbol(144, 144, 22, 22, 1558, 620, [156, 156, 156, 156, 156, 156, 156, 156, 155, 155]),
|
|
83
|
-
symbol(18, 8, 16, 6, 5, 7, [5]),
|
|
84
|
-
symbol(32, 8, 14, 6, 10, 11, [10]),
|
|
85
|
-
symbol(26, 12, 24, 10, 16, 14, [16]),
|
|
86
|
-
symbol(36, 12, 16, 10, 22, 18, [22]),
|
|
87
|
-
symbol(36, 16, 16, 14, 32, 24, [32]),
|
|
88
|
-
symbol(48, 16, 22, 14, 49, 28, [49]),
|
|
89
|
-
]);
|
|
90
|
-
|
|
91
|
-
/** Compatibility alias. */
|
|
92
|
-
export const SYMBOLS = DATAMATRIX_SYMBOLS;
|
|
93
|
-
|
|
94
|
-
/** Return the smallest permitted symbol that holds `count` data codewords. */
|
|
95
|
-
export function symbolForDataCodewords(count, shape = 'any') {
|
|
96
|
-
for (const s of DATAMATRIX_SYMBOLS) {
|
|
97
|
-
const rectangular = s.width !== s.height;
|
|
98
|
-
if ((shape === 'square' && rectangular) || (shape === 'rectangular' && !rectangular)) continue;
|
|
99
|
-
if (count <= s.dataCodewords) return s;
|
|
100
|
-
}
|
|
101
|
-
throw new RangeError(`Data Matrix: ${count} data codewords do not fit an ECC 200 ${shape} symbol`);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/** Check redundant geometry and block identities in the static table. */
|
|
105
|
-
export function validateDataMatrixTables() {
|
|
106
|
-
const issues = [];
|
|
107
|
-
for (const s of DATAMATRIX_SYMBOLS) {
|
|
108
|
-
const regionsX = s.width / s.regionWidth;
|
|
109
|
-
const regionsY = s.height / s.regionHeight;
|
|
110
|
-
if (!Number.isInteger(regionsX) || !Number.isInteger(regionsY)) issues.push(`${s.width}x${s.height}: non-integral regions`);
|
|
111
|
-
const modules = regionsX * regionsY * s.dataRegionWidth * s.dataRegionHeight;
|
|
112
|
-
// Annex F reserves four terminal modules on a few lattice dimensions.
|
|
113
|
-
// They are set to dark after codeword placement and do not carry data.
|
|
114
|
-
const unused = modules - (s.dataCodewords + s.errorCodewords) * 8;
|
|
115
|
-
if (unused !== 0 && unused !== 4) issues.push(`${s.width}x${s.height}: geometry/codeword mismatch`);
|
|
116
|
-
if (s.dataBlockLengths.reduce((a, b) => a + b, 0) !== s.dataCodewords) issues.push(`${s.width}x${s.height}: data block mismatch`);
|
|
117
|
-
if (s.eccPerBlock * s.blockCount !== s.errorCodewords) issues.push(`${s.width}x${s.height}: ecc block mismatch`);
|
|
118
|
-
}
|
|
119
|
-
return issues;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/** Compatibility alias. */
|
|
123
|
-
export const validateTables = validateDataMatrixTables;
|
|
1
|
+
/*!
|
|
2
|
+
* Sythos Barcode Suite
|
|
3
|
+
*
|
|
4
|
+
* MIT License
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2026 Sythos
|
|
7
|
+
*
|
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
* in the Software without restriction, including without limitation the rights
|
|
11
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
* furnished to do so, subject to the following conditions:
|
|
14
|
+
*
|
|
15
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
* copies or substantial portions of the Software.
|
|
17
|
+
*
|
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
* SOFTWARE.
|
|
25
|
+
*
|
|
26
|
+
* SPDX-License-Identifier: MIT
|
|
27
|
+
*
|
|
28
|
+
* Original work. No code from any other barcode implementation.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Data Matrix ECC 200 symbol parameters.
|
|
33
|
+
*
|
|
34
|
+
* Width and height include finder borders. `regionWidth` and `regionHeight`
|
|
35
|
+
* describe the usable modules inside one data region. The last three columns
|
|
36
|
+
* make the Reed-Solomon block split explicit instead of hiding the 144x144
|
|
37
|
+
* exception in encoder control flow.
|
|
38
|
+
*
|
|
39
|
+
* @module datamatrix/tables
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
function symbol(width, height, dataRegionWidth, dataRegionHeight, dataCodewords, errorCodewords, dataBlockLengths) {
|
|
43
|
+
const blockCount = dataBlockLengths.length;
|
|
44
|
+
return Object.freeze({
|
|
45
|
+
width, height, rows: height, columns: width,
|
|
46
|
+
// Region dimensions include their one-module finder border on each side;
|
|
47
|
+
// dataRegion* expose the inner placement lattice explicitly.
|
|
48
|
+
regionWidth: dataRegionWidth + 2, regionHeight: dataRegionHeight + 2,
|
|
49
|
+
dataRegionWidth, dataRegionHeight,
|
|
50
|
+
dataRegionRows: dataRegionHeight, dataRegionColumns: dataRegionWidth,
|
|
51
|
+
dataCodewords, errorCodewords, blockCount,
|
|
52
|
+
eccPerBlock: errorCodewords / blockCount,
|
|
53
|
+
dataBlockLengths: Object.freeze(dataBlockLengths),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Classic ISO/IEC 16022 ECC 200 symbols; DMRE is deliberately excluded. */
|
|
58
|
+
export const DATAMATRIX_SYMBOLS = Object.freeze([
|
|
59
|
+
symbol(10, 10, 8, 8, 3, 5, [3]),
|
|
60
|
+
symbol(12, 12, 10, 10, 5, 7, [5]),
|
|
61
|
+
symbol(14, 14, 12, 12, 8, 10, [8]),
|
|
62
|
+
symbol(16, 16, 14, 14, 12, 12, [12]),
|
|
63
|
+
symbol(18, 18, 16, 16, 18, 14, [18]),
|
|
64
|
+
symbol(20, 20, 18, 18, 22, 18, [22]),
|
|
65
|
+
symbol(22, 22, 20, 20, 30, 20, [30]),
|
|
66
|
+
symbol(24, 24, 22, 22, 36, 24, [36]),
|
|
67
|
+
symbol(26, 26, 24, 24, 44, 28, [44]),
|
|
68
|
+
symbol(32, 32, 14, 14, 62, 36, [62]),
|
|
69
|
+
symbol(36, 36, 16, 16, 86, 42, [86]),
|
|
70
|
+
symbol(40, 40, 18, 18, 114, 48, [114]),
|
|
71
|
+
symbol(44, 44, 20, 20, 144, 56, [144]),
|
|
72
|
+
symbol(48, 48, 22, 22, 174, 68, [174]),
|
|
73
|
+
symbol(52, 52, 24, 24, 204, 84, [102, 102]),
|
|
74
|
+
symbol(64, 64, 14, 14, 280, 112, [140, 140]),
|
|
75
|
+
symbol(72, 72, 16, 16, 368, 144, [92, 92, 92, 92]),
|
|
76
|
+
symbol(80, 80, 18, 18, 456, 192, [114, 114, 114, 114]),
|
|
77
|
+
symbol(88, 88, 20, 20, 576, 224, [144, 144, 144, 144]),
|
|
78
|
+
symbol(96, 96, 22, 22, 696, 272, [174, 174, 174, 174]),
|
|
79
|
+
symbol(104, 104, 24, 24, 816, 336, [136, 136, 136, 136, 136, 136]),
|
|
80
|
+
symbol(120, 120, 18, 18, 1050, 408, [175, 175, 175, 175, 175, 175]),
|
|
81
|
+
symbol(132, 132, 20, 20, 1304, 496, [163, 163, 163, 163, 163, 163, 163, 163]),
|
|
82
|
+
symbol(144, 144, 22, 22, 1558, 620, [156, 156, 156, 156, 156, 156, 156, 156, 155, 155]),
|
|
83
|
+
symbol(18, 8, 16, 6, 5, 7, [5]),
|
|
84
|
+
symbol(32, 8, 14, 6, 10, 11, [10]),
|
|
85
|
+
symbol(26, 12, 24, 10, 16, 14, [16]),
|
|
86
|
+
symbol(36, 12, 16, 10, 22, 18, [22]),
|
|
87
|
+
symbol(36, 16, 16, 14, 32, 24, [32]),
|
|
88
|
+
symbol(48, 16, 22, 14, 49, 28, [49]),
|
|
89
|
+
]);
|
|
90
|
+
|
|
91
|
+
/** Compatibility alias. */
|
|
92
|
+
export const SYMBOLS = DATAMATRIX_SYMBOLS;
|
|
93
|
+
|
|
94
|
+
/** Return the smallest permitted symbol that holds `count` data codewords. */
|
|
95
|
+
export function symbolForDataCodewords(count, shape = 'any') {
|
|
96
|
+
for (const s of DATAMATRIX_SYMBOLS) {
|
|
97
|
+
const rectangular = s.width !== s.height;
|
|
98
|
+
if ((shape === 'square' && rectangular) || (shape === 'rectangular' && !rectangular)) continue;
|
|
99
|
+
if (count <= s.dataCodewords) return s;
|
|
100
|
+
}
|
|
101
|
+
throw new RangeError(`Data Matrix: ${count} data codewords do not fit an ECC 200 ${shape} symbol`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Check redundant geometry and block identities in the static table. */
|
|
105
|
+
export function validateDataMatrixTables() {
|
|
106
|
+
const issues = [];
|
|
107
|
+
for (const s of DATAMATRIX_SYMBOLS) {
|
|
108
|
+
const regionsX = s.width / s.regionWidth;
|
|
109
|
+
const regionsY = s.height / s.regionHeight;
|
|
110
|
+
if (!Number.isInteger(regionsX) || !Number.isInteger(regionsY)) issues.push(`${s.width}x${s.height}: non-integral regions`);
|
|
111
|
+
const modules = regionsX * regionsY * s.dataRegionWidth * s.dataRegionHeight;
|
|
112
|
+
// Annex F reserves four terminal modules on a few lattice dimensions.
|
|
113
|
+
// They are set to dark after codeword placement and do not carry data.
|
|
114
|
+
const unused = modules - (s.dataCodewords + s.errorCodewords) * 8;
|
|
115
|
+
if (unused !== 0 && unused !== 4) issues.push(`${s.width}x${s.height}: geometry/codeword mismatch`);
|
|
116
|
+
if (s.dataBlockLengths.reduce((a, b) => a + b, 0) !== s.dataCodewords) issues.push(`${s.width}x${s.height}: data block mismatch`);
|
|
117
|
+
if (s.eccPerBlock * s.blockCount !== s.errorCodewords) issues.push(`${s.width}x${s.height}: ecc block mismatch`);
|
|
118
|
+
}
|
|
119
|
+
return issues;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Compatibility alias. */
|
|
123
|
+
export const validateTables = validateDataMatrixTables;
|
package/src/index.js
CHANGED
|
@@ -53,6 +53,9 @@ import { ONED_FORMATS } from './oned/index.js';
|
|
|
53
53
|
import { decodeOneD } from './oned/reader.js';
|
|
54
54
|
import * as datamatrix from './datamatrix/index.js';
|
|
55
55
|
import * as qr from './qr/index.js';
|
|
56
|
+
import * as aztec from './aztec/index.js';
|
|
57
|
+
import * as pdf417 from './pdf417/index.js';
|
|
58
|
+
import * as micropdf417 from './micropdf417/index.js';
|
|
56
59
|
|
|
57
60
|
export { BitMatrix };
|
|
58
61
|
export {
|
|
@@ -70,6 +73,11 @@ export { encodeQR, decodeQR, detectQR, detectAndDecodeQR } from './qr/index.js';
|
|
|
70
73
|
export {
|
|
71
74
|
encodeDataMatrix, decodeDataMatrix, detectDataMatrix, detectAndDecodeDataMatrix,
|
|
72
75
|
} from './datamatrix/index.js';
|
|
76
|
+
export { encodeAztec, decodeAztec, detectAztec, detectAndDecodeAztec } from './aztec/index.js';
|
|
77
|
+
export { encodePDF417, decodePDF417, detectPDF417, detectAndDecodePDF417 } from './pdf417/index.js';
|
|
78
|
+
export {
|
|
79
|
+
encodeMicroPDF417, decodeMicroPDF417, detectMicroPDF417, detectAndDecodeMicroPDF417,
|
|
80
|
+
} from './micropdf417/index.js';
|
|
73
81
|
|
|
74
82
|
/**
|
|
75
83
|
* @typedef {object} FormatInfo
|
|
@@ -95,6 +103,16 @@ const qrCanDecode = qrPresent &&
|
|
|
95
103
|
typeof qr.detectAndDecodeQR === 'function' && qr.QR_CAN_DECODE !== false;
|
|
96
104
|
const dataMatrixCanEncode = typeof datamatrix.encodeDataMatrix === 'function';
|
|
97
105
|
const dataMatrixCanDecode = typeof datamatrix.detectAndDecodeDataMatrix === 'function';
|
|
106
|
+
const aztecCanEncode = typeof aztec.encodeAztec === 'function';
|
|
107
|
+
const aztecCanDecode = typeof aztec.detectAndDecodeAztec === 'function';
|
|
108
|
+
const pdf417CanEncode = typeof pdf417.encodePDF417 === 'function';
|
|
109
|
+
// The matrix decoder is complete, but automatic image localization is still
|
|
110
|
+
// limited to clean module-aligned symbols or an application-supplied
|
|
111
|
+
// quadrilateral. Keep the generic scanner capability opt-in until a
|
|
112
|
+
// perspective/noise corpus is passed.
|
|
113
|
+
const pdf417CanDecode = typeof pdf417.detectAndDecodePDF417 === 'function';
|
|
114
|
+
const microPdf417CanEncode = typeof micropdf417.encodeMicroPDF417 === 'function';
|
|
115
|
+
const microPdf417CanDecode = typeof micropdf417.detectAndDecodeMicroPDF417 === 'function';
|
|
98
116
|
|
|
99
117
|
/**
|
|
100
118
|
* Every format this build supports.
|
|
@@ -129,6 +147,27 @@ export function listFormats() {
|
|
|
129
147
|
canRead: dataMatrixCanDecode,
|
|
130
148
|
kind: /** @type {'2D'} */ ('2D'),
|
|
131
149
|
});
|
|
150
|
+
formats.push({
|
|
151
|
+
id: 'aztec',
|
|
152
|
+
label: 'Aztec Code',
|
|
153
|
+
canWrite: aztecCanEncode,
|
|
154
|
+
canRead: aztecCanDecode,
|
|
155
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
156
|
+
});
|
|
157
|
+
formats.push({
|
|
158
|
+
id: 'pdf417',
|
|
159
|
+
label: 'PDF417',
|
|
160
|
+
canWrite: pdf417CanEncode,
|
|
161
|
+
canRead: pdf417CanDecode,
|
|
162
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
163
|
+
});
|
|
164
|
+
formats.push({
|
|
165
|
+
id: 'micropdf417',
|
|
166
|
+
label: 'MicroPDF417',
|
|
167
|
+
canWrite: microPdf417CanEncode,
|
|
168
|
+
canRead: microPdf417CanDecode,
|
|
169
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
170
|
+
});
|
|
132
171
|
|
|
133
172
|
return formats;
|
|
134
173
|
}
|
|
@@ -149,6 +188,16 @@ export function listFormats() {
|
|
|
149
188
|
* @param {boolean} [options.checkDigit] Append a check digit, where optional.
|
|
150
189
|
* @param {boolean} [options.fullAscii] Code 39 extended encoding.
|
|
151
190
|
* @param {boolean} [options.gs1] Emit a leading FNC1.
|
|
191
|
+
* @param {number} [options.layers] Aztec layer count; automatic if omitted.
|
|
192
|
+
* @param {boolean} [options.compact] Force an Aztec Compact or Full symbol.
|
|
193
|
+
* @param {number} [options.eccPercent] Requested Aztec error-correction percentage.
|
|
194
|
+
* @param {number} [options.eccLevel] PDF417 error-correction level, 0-8.
|
|
195
|
+
* @param {number} [options.columns] PDF417 columns, 1-30.
|
|
196
|
+
* @param {number} [options.rows] PDF417 rows, 3-90.
|
|
197
|
+
* @param {number} [options.rowHeight] PDF417 row height in modules.
|
|
198
|
+
* @param {'auto'|'text'|'byte'|'numeric'} [options.compaction] PDF417 compaction mode.
|
|
199
|
+
* @param {number} [options.eci] MicroPDF417 byte-compaction ECI assignment (3 or 26).
|
|
200
|
+
* @param {number} [options.aspectRatio] Preferred MicroPDF417 symbol aspect ratio.
|
|
152
201
|
* @returns {BitMatrix}
|
|
153
202
|
*/
|
|
154
203
|
export function encode(text, options = {}) {
|
|
@@ -161,10 +210,19 @@ export function encode(text, options = {}) {
|
|
|
161
210
|
if (format === 'datamatrix' || format === 'data-matrix') {
|
|
162
211
|
return datamatrix.encodeDataMatrix(value, options);
|
|
163
212
|
}
|
|
213
|
+
if (format === 'aztec' || format === 'aztec-code') {
|
|
214
|
+
return aztec.encodeAztec(value, options);
|
|
215
|
+
}
|
|
216
|
+
if (format === 'pdf417' || format === 'pdf-417') {
|
|
217
|
+
return pdf417.encodePDF417(value, options);
|
|
218
|
+
}
|
|
219
|
+
if (format === 'micropdf417' || format === 'micro-pdf417' || format === 'micro-pdf-417') {
|
|
220
|
+
return micropdf417.encodeMicroPDF417(value, options);
|
|
221
|
+
}
|
|
164
222
|
|
|
165
223
|
const entry = ONED_FORMATS[format];
|
|
166
224
|
if (!entry) {
|
|
167
|
-
const known = [...Object.keys(ONED_FORMATS), 'qr', 'datamatrix'].join(', ');
|
|
225
|
+
const known = [...Object.keys(ONED_FORMATS), 'qr', 'datamatrix', 'aztec', 'pdf417', 'micropdf417'].join(', ');
|
|
168
226
|
throw new EncodeError(`Unknown format "${format}". Known formats: ${known}`);
|
|
169
227
|
}
|
|
170
228
|
return entry.encode(value, options);
|
|
@@ -174,9 +232,19 @@ export function encode(text, options = {}) {
|
|
|
174
232
|
* @typedef {object} DecodeResult
|
|
175
233
|
* @property {string} text
|
|
176
234
|
* @property {string} format
|
|
177
|
-
* @property {Uint8Array} [bytes] Raw payload, before text decoding.
|
|
235
|
+
* @property {Uint8Array} [bytes] Raw octets exposed by byte-oriented payload modes, before text decoding.
|
|
236
|
+
* @property {{mode: 'text'|'byte'|'numeric', text: string, bytes: Uint8Array, eci: number, latch: number|null, codewordStart: number, codewordEnd: number}[]} [segments] PDF417 compaction segments in source order.
|
|
178
237
|
* @property {number} [version] QR version.
|
|
179
238
|
* @property {string} [ecc] QR error-correction level.
|
|
239
|
+
* @property {number} [layers] Aztec layer count.
|
|
240
|
+
* @property {boolean} [compact] Whether an Aztec symbol is Compact.
|
|
241
|
+
* @property {number} [corrections] Reed–Solomon corrections applied by an Aztec decode.
|
|
242
|
+
* @property {number} [rows] PDF417 row count.
|
|
243
|
+
* @property {number} [columns] PDF417 column count.
|
|
244
|
+
* @property {number} [eccLevel] PDF417 error-correction level.
|
|
245
|
+
* @property {number} [rowHeight] PDF417 row height in modules.
|
|
246
|
+
* @property {number} [variant] MicroPDF417 predefined variant number.
|
|
247
|
+
* @property {number} [eccCodewords] MicroPDF417 fixed error-correction codewords.
|
|
180
248
|
*/
|
|
181
249
|
|
|
182
250
|
/**
|
|
@@ -198,6 +266,9 @@ export function decode(image, options = {}) {
|
|
|
198
266
|
const want = formats ? new Set(formats.map((f) => f.toLowerCase())) : null;
|
|
199
267
|
const wantQR = !want || want.has('qr') || want.has('qrcode');
|
|
200
268
|
const wantDataMatrix = !want || want.has('datamatrix') || want.has('data-matrix');
|
|
269
|
+
const wantAztec = !want || want.has('aztec') || want.has('aztec-code');
|
|
270
|
+
const wantPDF417 = !want || want.has('pdf417') || want.has('pdf-417');
|
|
271
|
+
const wantMicroPDF417 = !want || want.has('micropdf417') || want.has('micro-pdf417') || want.has('micro-pdf-417');
|
|
201
272
|
const wantOneD = !want || [...want].some((f) => f in ONED_FORMATS);
|
|
202
273
|
|
|
203
274
|
const source = LuminanceSource.fromImageData(image);
|
|
@@ -235,6 +306,45 @@ export function decode(image, options = {}) {
|
|
|
235
306
|
}
|
|
236
307
|
}
|
|
237
308
|
|
|
309
|
+
if (wantAztec && aztecCanDecode) {
|
|
310
|
+
// The central bull's-eye is a small, high-contrast target. Hybrid
|
|
311
|
+
// thresholding can flatten it on clean rendered symbols, so mirror the
|
|
312
|
+
// Data Matrix global fallback in auto mode.
|
|
313
|
+
const aztecBits = binarizer === 'auto' ? [bits, binarize(pass, 'global')] : [bits];
|
|
314
|
+
for (const candidateBits of aztecBits) {
|
|
315
|
+
try {
|
|
316
|
+
const found = aztec.detectAndDecodeAztec(candidateBits);
|
|
317
|
+
if (found) { results.push({ ...found, format: 'aztec' }); break; }
|
|
318
|
+
} catch {
|
|
319
|
+
/* no Aztec code with this threshold */
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (wantPDF417 && pdf417CanDecode) {
|
|
325
|
+
try {
|
|
326
|
+
const found = pdf417.detectAndDecodePDF417(bits);
|
|
327
|
+
if (found) results.push({ ...found, format: 'pdf417' });
|
|
328
|
+
} catch {
|
|
329
|
+
/* no PDF417 in this pass */
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (wantMicroPDF417 && microPdf417CanDecode) {
|
|
334
|
+
// MicroPDF417 detection measures runs across the whole raster. Hybrid
|
|
335
|
+
// thresholding can alter uniform modules near local-window boundaries,
|
|
336
|
+
// so retry the global threshold in auto mode as for the other 2D codes.
|
|
337
|
+
const microPdf417Bits = binarizer === 'auto' ? [bits, binarize(pass, 'global')] : [bits];
|
|
338
|
+
for (const candidateBits of microPdf417Bits) {
|
|
339
|
+
try {
|
|
340
|
+
const found = micropdf417.detectAndDecodeMicroPDF417(candidateBits);
|
|
341
|
+
if (found) { results.push({ ...found, format: 'micropdf417' }); break; }
|
|
342
|
+
} catch {
|
|
343
|
+
/* no MicroPDF417 with this threshold */
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
238
348
|
if (wantOneD) {
|
|
239
349
|
const oneDFormats = want ? [...want].filter((f) => f in ONED_FORMATS) : null;
|
|
240
350
|
for (const found of decodeOneD(bits, { formats: oneDFormats, tryHarder })) {
|
|
@@ -269,4 +379,4 @@ export function decodeStrict(image, options) {
|
|
|
269
379
|
}
|
|
270
380
|
|
|
271
381
|
/** Library version, matching package.json. */
|
|
272
|
-
export const VERSION = '1.
|
|
382
|
+
export const VERSION = '1.2.5';
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Sythos Barcode Suite
|
|
3
|
+
*
|
|
4
|
+
* MIT License
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2026 Sythos
|
|
7
|
+
*
|
|
8
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
* in the Software without restriction, including without limitation the rights
|
|
11
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
* furnished to do so, subject to the following conditions:
|
|
14
|
+
*
|
|
15
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
* copies or substantial portions of the Software.
|
|
17
|
+
*
|
|
18
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
* SOFTWARE.
|
|
25
|
+
*
|
|
26
|
+
* SPDX-License-Identifier: MIT
|
|
27
|
+
*
|
|
28
|
+
* Original work. No code from any other barcode implementation.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/** MicroPDF417 high-level compaction adapter. @module micropdf417/compaction */
|
|
32
|
+
|
|
33
|
+
import { EncodeError } from '../core/errors.js';
|
|
34
|
+
import {
|
|
35
|
+
compactPdf417Bytes,
|
|
36
|
+
compactPdf417Numeric,
|
|
37
|
+
compactPdf417Text,
|
|
38
|
+
} from '../pdf417/compaction.js';
|
|
39
|
+
|
|
40
|
+
function byteLength(value) {
|
|
41
|
+
if (value instanceof Uint8Array) return value.byteLength;
|
|
42
|
+
if (ArrayBuffer.isView(value)) return value.byteLength;
|
|
43
|
+
return -1;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function assertNotEmpty(value) {
|
|
47
|
+
if ((typeof value === 'string' && value.length === 0) || byteLength(value) === 0) {
|
|
48
|
+
throw new EncodeError('MicroPDF417: value must not be empty');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function latin1Bytes(value) {
|
|
53
|
+
if (typeof value !== 'string') return value;
|
|
54
|
+
const bytes = [];
|
|
55
|
+
for (const character of value) {
|
|
56
|
+
const codePoint = character.codePointAt(0);
|
|
57
|
+
if (codePoint > 255) {
|
|
58
|
+
throw new EncodeError('MicroPDF417 ECI 3: string contains a character outside ISO-8859-1');
|
|
59
|
+
}
|
|
60
|
+
bytes.push(codePoint);
|
|
61
|
+
}
|
|
62
|
+
return Uint8Array.from(bytes);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function compactByte(value, eci) {
|
|
66
|
+
if (eci === undefined) return compactPdf417Bytes(value);
|
|
67
|
+
if (eci === 3) return compactPdf417Bytes(latin1Bytes(value));
|
|
68
|
+
if (eci === 26) {
|
|
69
|
+
if (typeof value !== 'string') {
|
|
70
|
+
throw new EncodeError('MicroPDF417 ECI 26: value must be a string so UTF-8 validity is known');
|
|
71
|
+
}
|
|
72
|
+
const encoded = compactPdf417Bytes(value);
|
|
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');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Compact one MicroPDF417 value.
|
|
80
|
+
*
|
|
81
|
+
* Unlike PDF417, MicroPDF417 starts in Byte Compaction. Text therefore needs
|
|
82
|
+
* an explicit 900 latch. Byte compaction always emits 901 or 924 so its start
|
|
83
|
+
* state is unambiguous, including when an ECI designator precedes it.
|
|
84
|
+
*/
|
|
85
|
+
export function compactMicroPDF417(value, options = {}) {
|
|
86
|
+
assertNotEmpty(value);
|
|
87
|
+
const mode = options.compaction ?? 'auto';
|
|
88
|
+
const eci = options.eci;
|
|
89
|
+
if (eci !== undefined && eci !== 3 && eci !== 26) {
|
|
90
|
+
throw new EncodeError('MicroPDF417: supported ECI assignment numbers are 3 and 26');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (mode === 'text') {
|
|
94
|
+
if (eci !== undefined) throw new EncodeError('MicroPDF417: explicit ECI is supported only with byte compaction');
|
|
95
|
+
return [900, ...compactPdf417Text(value)];
|
|
96
|
+
}
|
|
97
|
+
if (mode === 'numeric') {
|
|
98
|
+
if (eci !== undefined) throw new EncodeError('MicroPDF417: explicit ECI is supported only with byte compaction');
|
|
99
|
+
return compactPdf417Numeric(value);
|
|
100
|
+
}
|
|
101
|
+
if (mode === 'byte') return compactByte(value, eci);
|
|
102
|
+
if (mode !== 'auto') {
|
|
103
|
+
throw new EncodeError(`MicroPDF417: unsupported compaction mode ${JSON.stringify(mode)}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (eci !== undefined) return compactByte(value, eci);
|
|
107
|
+
if (typeof value === 'string' && /^\d{13,}$/.test(value)) return compactPdf417Numeric(value);
|
|
108
|
+
if (typeof value === 'string') {
|
|
109
|
+
try {
|
|
110
|
+
return [900, ...compactPdf417Text(value)];
|
|
111
|
+
} catch (error) {
|
|
112
|
+
if (!(error instanceof EncodeError)) throw error;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return compactPdf417Bytes(value);
|
|
116
|
+
}
|