@sythos/js_barcode_universal 1.5.7 → 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 +50 -37
- package/bundle/sythos-barcode.esm.js +12051 -11484
- package/bundle/sythos-barcode.js +12051 -11484
- package/package.json +52 -45
- package/src/index.d.ts +363 -0
- package/src/index.js +573 -428
- package/src/js/aztec/decoder.js +326 -0
- package/src/js/aztec/detector.js +251 -0
- package/src/js/aztec/encoder.js +276 -0
- package/src/js/aztec/high-level.js +216 -0
- package/src/js/aztec/index.js +34 -0
- package/src/js/aztec/tables.js +196 -0
- package/src/js/aztecrune/decoder.js +146 -0
- package/src/js/aztecrune/detector.js +180 -0
- package/src/js/aztecrune/encoder.js +103 -0
- package/src/js/aztecrune/index.js +34 -0
- package/src/js/aztecrune/tables.js +142 -0
- package/src/js/compactpdf417/decoder.js +123 -0
- package/src/js/compactpdf417/detector.js +138 -0
- package/src/js/compactpdf417/encoder.js +127 -0
- package/src/js/compactpdf417/index.js +5 -0
- package/src/js/compactpdf417/tables.js +164 -0
- package/src/js/core/bit-buffer.js +158 -0
- package/src/js/core/bit-matrix.js +243 -0
- package/src/js/core/errors.js +59 -0
- package/src/js/core/galois-field.js +193 -0
- package/src/js/core/index.js +39 -0
- package/src/js/core/reed-solomon.js +318 -0
- package/src/js/databar/codec.js +166 -0
- package/src/js/databar/decoder.js +224 -0
- package/src/js/databar/encoder.js +88 -0
- package/src/js/databar/gs1.js +176 -0
- package/src/js/databar/index.js +36 -0
- package/src/js/databar/patterns.js +139 -0
- package/src/js/databar/tables.js +123 -0
- package/src/js/datamatrix/decoder.js +296 -0
- package/src/js/datamatrix/detector.js +254 -0
- package/src/js/datamatrix/encoder.js +250 -0
- package/src/js/datamatrix/index.js +34 -0
- package/src/js/datamatrix/tables.js +122 -0
- package/src/js/frameqr/decoder.js +216 -0
- package/src/js/frameqr/detector.js +199 -0
- package/src/js/frameqr/encoder.js +143 -0
- package/src/js/frameqr/index.js +33 -0
- package/src/js/frameqr/tables.js +252 -0
- package/src/js/image/binarizer.js +254 -0
- package/src/js/image/grid-sampler.js +148 -0
- package/src/js/image/index.js +38 -0
- package/src/js/image/luminance.js +185 -0
- package/src/js/image/perspective.js +158 -0
- package/src/js/micropdf417/compaction.js +115 -0
- package/src/js/micropdf417/decoder.js +180 -0
- package/src/js/micropdf417/detector.js +152 -0
- package/src/js/micropdf417/encoder.js +184 -0
- package/src/js/micropdf417/error-correction.js +50 -0
- package/src/js/micropdf417/index.js +35 -0
- package/src/js/micropdf417/tables.js +197 -0
- package/src/js/microqr/decoder.js +240 -0
- package/src/js/microqr/detector.js +339 -0
- package/src/js/microqr/encoder.js +314 -0
- package/src/js/microqr/index.js +34 -0
- package/src/js/microqr/tables.js +324 -0
- package/src/js/oned/addons.js +396 -0
- package/src/js/oned/index.js +75 -0
- package/src/js/oned/patterns.js +365 -0
- package/src/js/oned/reader.js +1383 -0
- package/src/js/oned/writers.js +691 -0
- package/src/js/pdf417/compaction.js +391 -0
- package/src/js/pdf417/decoder.js +110 -0
- package/src/js/pdf417/detector.js +484 -0
- package/src/js/pdf417/encoder.js +102 -0
- package/src/js/pdf417/error-correction.js +44 -0
- package/src/{pdf417 → js/pdf417}/index.js +0 -5
- package/src/js/pdf417/tables.js +315 -0
- package/src/js/qr/decoder.js +539 -0
- package/src/js/qr/detector.js +613 -0
- package/src/js/qr/encoder.js +873 -0
- package/src/js/qr/index.js +42 -0
- package/src/js/qr/tables.js +690 -0
- package/src/js/render/image-data.js +120 -0
- package/src/js/render/index.js +128 -0
- package/src/js/render/options.js +152 -0
- package/src/js/render/png.js +270 -0
- package/src/js/render/svg.js +117 -0
- package/src/js/render/webgl.js +200 -0
- package/src/js/render/webgpu.js +357 -0
- package/src/js/rmqr/decoder.js +209 -0
- package/src/js/rmqr/detector.js +122 -0
- package/src/js/rmqr/encoder.js +321 -0
- package/src/js/rmqr/index.js +33 -0
- package/src/js/rmqr/tables.js +177 -0
- package/src/{aztec/decoder.js → ts/aztec/decoder.ts} +0 -1
- package/{typings → src/ts}/aztec/detector.d.ts +2 -2
- package/src/{aztec/detector.js → ts/aztec/detector.ts} +0 -1
- package/src/{aztec/encoder.js → ts/aztec/encoder.ts} +0 -1
- package/src/{aztec/high-level.js → ts/aztec/high-level.ts} +0 -1
- package/src/{aztec/index.js → ts/aztec/index.ts} +0 -1
- package/src/{aztec/tables.js → ts/aztec/tables.ts} +0 -1
- package/src/{aztecrune/decoder.js → ts/aztecrune/decoder.ts} +0 -1
- package/src/{aztecrune/detector.js → ts/aztecrune/detector.ts} +0 -1
- package/src/{aztecrune/encoder.js → ts/aztecrune/encoder.ts} +0 -1
- package/src/{aztecrune/index.js → ts/aztecrune/index.ts} +0 -1
- package/src/{aztecrune/tables.js → ts/aztecrune/tables.ts} +0 -1
- package/src/{compactpdf417/decoder.js → ts/compactpdf417/decoder.ts} +0 -1
- package/src/{compactpdf417/detector.js → ts/compactpdf417/detector.ts} +0 -1
- package/src/{compactpdf417/encoder.js → ts/compactpdf417/encoder.ts} +0 -1
- package/src/{compactpdf417/index.js → ts/compactpdf417/index.ts} +0 -5
- package/src/{compactpdf417/tables.js → ts/compactpdf417/tables.ts} +0 -1
- package/src/{core/bit-buffer.js → ts/core/bit-buffer.ts} +0 -1
- package/src/{core/bit-matrix.js → ts/core/bit-matrix.ts} +0 -1
- package/src/{core/errors.js → ts/core/errors.ts} +0 -1
- package/src/{core/galois-field.js → ts/core/galois-field.ts} +0 -1
- package/src/{core/index.js → ts/core/index.ts} +0 -1
- package/src/{core/reed-solomon.js → ts/core/reed-solomon.ts} +0 -1
- package/src/{databar/codec.js → ts/databar/codec.ts} +0 -1
- package/src/{databar/decoder.js → ts/databar/decoder.ts} +0 -1
- package/src/{databar/encoder.js → ts/databar/encoder.ts} +0 -1
- package/src/{databar/gs1.js → ts/databar/gs1.ts} +0 -1
- package/src/{databar/index.js → ts/databar/index.ts} +0 -1
- package/src/{databar/patterns.js → ts/databar/patterns.ts} +0 -1
- package/src/{databar/tables.js → ts/databar/tables.ts} +0 -1
- package/src/{datamatrix/decoder.js → ts/datamatrix/decoder.ts} +0 -1
- package/{typings → src/ts}/datamatrix/detector.d.ts +2 -2
- package/src/{datamatrix/detector.js → ts/datamatrix/detector.ts} +0 -1
- package/src/{datamatrix/encoder.js → ts/datamatrix/encoder.ts} +0 -1
- package/src/{datamatrix/index.js → ts/datamatrix/index.ts} +0 -1
- package/src/{datamatrix/tables.js → ts/datamatrix/tables.ts} +0 -1
- package/src/{frameqr/decoder.js → ts/frameqr/decoder.ts} +15 -16
- package/src/{frameqr/detector.js → ts/frameqr/detector.ts} +2 -3
- package/src/{frameqr/encoder.js → ts/frameqr/encoder.ts} +7 -8
- package/src/{frameqr/index.js → ts/frameqr/index.ts} +0 -1
- package/src/{frameqr/tables.js → ts/frameqr/tables.ts} +10 -11
- package/src/{image/binarizer.js → ts/image/binarizer.ts} +0 -1
- package/src/{image/grid-sampler.js → ts/image/grid-sampler.ts} +0 -1
- package/src/{image/index.js → ts/image/index.ts} +0 -1
- package/src/{image/luminance.js → ts/image/luminance.ts} +0 -1
- package/src/{image/perspective.js → ts/image/perspective.ts} +0 -1
- package/{typings → src/ts}/index.d.ts +3 -3
- package/src/ts/index.ts +790 -0
- package/src/{micropdf417/compaction.js → ts/micropdf417/compaction.ts} +0 -1
- package/src/{micropdf417/decoder.js → ts/micropdf417/decoder.ts} +0 -1
- package/src/{micropdf417/detector.js → ts/micropdf417/detector.ts} +0 -1
- package/src/{micropdf417/encoder.js → ts/micropdf417/encoder.ts} +0 -1
- package/src/{micropdf417/error-correction.js → ts/micropdf417/error-correction.ts} +0 -1
- package/src/{micropdf417/index.js → ts/micropdf417/index.ts} +0 -1
- package/src/{micropdf417/tables.js → ts/micropdf417/tables.ts} +0 -1
- package/src/{microqr/decoder.js → ts/microqr/decoder.ts} +0 -1
- package/src/{microqr/detector.js → ts/microqr/detector.ts} +0 -1
- package/src/{microqr/encoder.js → ts/microqr/encoder.ts} +0 -1
- package/src/{microqr/index.js → ts/microqr/index.ts} +0 -1
- package/src/{microqr/tables.js → ts/microqr/tables.ts} +0 -1
- package/src/{oned/addons.js → ts/oned/addons.ts} +0 -1
- package/src/{oned/index.js → ts/oned/index.ts} +0 -1
- package/src/{oned/patterns.js → ts/oned/patterns.ts} +0 -1
- package/src/{oned/reader.js → ts/oned/reader.ts} +0 -1
- package/src/{oned/writers.js → ts/oned/writers.ts} +0 -1
- package/src/{pdf417/compaction.js → ts/pdf417/compaction.ts} +0 -1
- package/src/{pdf417/decoder.js → ts/pdf417/decoder.ts} +0 -1
- package/src/{pdf417/detector.js → ts/pdf417/detector.ts} +0 -1
- package/src/{pdf417/encoder.js → ts/pdf417/encoder.ts} +0 -1
- package/src/{pdf417/error-correction.js → ts/pdf417/error-correction.ts} +0 -1
- package/src/ts/pdf417/index.ts +6 -0
- package/src/{pdf417/tables.js → ts/pdf417/tables.ts} +0 -1
- package/src/{qr/decoder.js → ts/qr/decoder.ts} +0 -1
- package/src/{qr/detector.js → ts/qr/detector.ts} +0 -1
- package/src/{qr/encoder.js → ts/qr/encoder.ts} +0 -1
- package/src/{qr/index.js → ts/qr/index.ts} +0 -1
- package/src/{qr/tables.js → ts/qr/tables.ts} +0 -1
- package/src/{render/image-data.js → ts/render/image-data.ts} +0 -1
- package/src/{render/index.js → ts/render/index.ts} +0 -1
- package/src/{render/options.js → ts/render/options.ts} +0 -1
- package/src/{render/png.js → ts/render/png.ts} +0 -1
- package/src/{render/svg.js → ts/render/svg.ts} +0 -1
- package/src/{render/webgl.js → ts/render/webgl.ts} +0 -1
- package/src/{render/webgpu.js → ts/render/webgpu.ts} +0 -1
- package/src/{rmqr/decoder.js → ts/rmqr/decoder.ts} +0 -1
- package/src/{rmqr/detector.js → ts/rmqr/detector.ts} +0 -1
- package/src/{rmqr/encoder.js → ts/rmqr/encoder.ts} +0 -1
- package/src/{rmqr/index.js → ts/rmqr/index.ts} +0 -1
- package/src/{rmqr/tables.js → ts/rmqr/tables.ts} +0 -1
- /package/{typings → src/ts}/aztec/decoder.d.ts +0 -0
- /package/{typings → src/ts}/aztec/encoder.d.ts +0 -0
- /package/{typings → src/ts}/aztec/high-level.d.ts +0 -0
- /package/{typings → src/ts}/aztec/index.d.ts +0 -0
- /package/{typings → src/ts}/aztec/tables.d.ts +0 -0
- /package/{typings → src/ts}/aztecrune/decoder.d.ts +0 -0
- /package/{typings → src/ts}/aztecrune/detector.d.ts +0 -0
- /package/{typings → src/ts}/aztecrune/encoder.d.ts +0 -0
- /package/{typings → src/ts}/aztecrune/index.d.ts +0 -0
- /package/{typings → src/ts}/aztecrune/tables.d.ts +0 -0
- /package/{typings → src/ts}/bundle/sythos-barcode.d.ts +0 -0
- /package/{typings → src/ts}/bundle/sythos-barcode.esm.d.ts +0 -0
- /package/{typings → src/ts}/compactpdf417/decoder.d.ts +0 -0
- /package/{typings → src/ts}/compactpdf417/detector.d.ts +0 -0
- /package/{typings → src/ts}/compactpdf417/encoder.d.ts +0 -0
- /package/{typings → src/ts}/compactpdf417/index.d.ts +0 -0
- /package/{typings → src/ts}/compactpdf417/tables.d.ts +0 -0
- /package/{typings → src/ts}/core/bit-buffer.d.ts +0 -0
- /package/{typings → src/ts}/core/bit-matrix.d.ts +0 -0
- /package/{typings → src/ts}/core/errors.d.ts +0 -0
- /package/{typings → src/ts}/core/galois-field.d.ts +0 -0
- /package/{typings → src/ts}/core/index.d.ts +0 -0
- /package/{typings → src/ts}/core/reed-solomon.d.ts +0 -0
- /package/{typings → src/ts}/databar/codec.d.ts +0 -0
- /package/{typings → src/ts}/databar/decoder.d.ts +0 -0
- /package/{typings → src/ts}/databar/encoder.d.ts +0 -0
- /package/{typings → src/ts}/databar/gs1.d.ts +0 -0
- /package/{typings → src/ts}/databar/index.d.ts +0 -0
- /package/{typings → src/ts}/databar/patterns.d.ts +0 -0
- /package/{typings → src/ts}/databar/tables.d.ts +0 -0
- /package/{typings → src/ts}/datamatrix/decoder.d.ts +0 -0
- /package/{typings → src/ts}/datamatrix/encoder.d.ts +0 -0
- /package/{typings → src/ts}/datamatrix/index.d.ts +0 -0
- /package/{typings → src/ts}/datamatrix/tables.d.ts +0 -0
- /package/{typings → src/ts}/frameqr/decoder.d.ts +0 -0
- /package/{typings → src/ts}/frameqr/detector.d.ts +0 -0
- /package/{typings → src/ts}/frameqr/encoder.d.ts +0 -0
- /package/{typings → src/ts}/frameqr/index.d.ts +0 -0
- /package/{typings → src/ts}/frameqr/tables.d.ts +0 -0
- /package/{typings → src/ts}/image/binarizer.d.ts +0 -0
- /package/{typings → src/ts}/image/grid-sampler.d.ts +0 -0
- /package/{typings → src/ts}/image/index.d.ts +0 -0
- /package/{typings → src/ts}/image/luminance.d.ts +0 -0
- /package/{typings → src/ts}/image/perspective.d.ts +0 -0
- /package/{typings → src/ts}/micropdf417/compaction.d.ts +0 -0
- /package/{typings → src/ts}/micropdf417/decoder.d.ts +0 -0
- /package/{typings → src/ts}/micropdf417/detector.d.ts +0 -0
- /package/{typings → src/ts}/micropdf417/encoder.d.ts +0 -0
- /package/{typings → src/ts}/micropdf417/error-correction.d.ts +0 -0
- /package/{typings → src/ts}/micropdf417/index.d.ts +0 -0
- /package/{typings → src/ts}/micropdf417/tables.d.ts +0 -0
- /package/{typings → src/ts}/microqr/decoder.d.ts +0 -0
- /package/{typings → src/ts}/microqr/detector.d.ts +0 -0
- /package/{typings → src/ts}/microqr/encoder.d.ts +0 -0
- /package/{typings → src/ts}/microqr/index.d.ts +0 -0
- /package/{typings → src/ts}/microqr/tables.d.ts +0 -0
- /package/{typings → src/ts}/oned/addons.d.ts +0 -0
- /package/{typings → src/ts}/oned/index.d.ts +0 -0
- /package/{typings → src/ts}/oned/patterns.d.ts +0 -0
- /package/{typings → src/ts}/oned/reader.d.ts +0 -0
- /package/{typings → src/ts}/oned/writers.d.ts +0 -0
- /package/{typings → src/ts}/pdf417/compaction.d.ts +0 -0
- /package/{typings → src/ts}/pdf417/decoder.d.ts +0 -0
- /package/{typings → src/ts}/pdf417/detector.d.ts +0 -0
- /package/{typings → src/ts}/pdf417/encoder.d.ts +0 -0
- /package/{typings → src/ts}/pdf417/error-correction.d.ts +0 -0
- /package/{typings → src/ts}/pdf417/index.d.ts +0 -0
- /package/{typings → src/ts}/pdf417/tables.d.ts +0 -0
- /package/{typings → src/ts}/qr/decoder.d.ts +0 -0
- /package/{typings → src/ts}/qr/detector.d.ts +0 -0
- /package/{typings → src/ts}/qr/encoder.d.ts +0 -0
- /package/{typings → src/ts}/qr/index.d.ts +0 -0
- /package/{typings → src/ts}/qr/tables.d.ts +0 -0
- /package/{typings → src/ts}/render/image-data.d.ts +0 -0
- /package/{typings → src/ts}/render/index.d.ts +0 -0
- /package/{typings → src/ts}/render/options.d.ts +0 -0
- /package/{typings → src/ts}/render/png.d.ts +0 -0
- /package/{typings → src/ts}/render/svg.d.ts +0 -0
- /package/{typings → src/ts}/render/webgl.d.ts +0 -0
- /package/{typings → src/ts}/render/webgpu.d.ts +0 -0
- /package/{typings → src/ts}/rmqr/decoder.d.ts +0 -0
- /package/{typings → src/ts}/rmqr/detector.d.ts +0 -0
- /package/{typings → src/ts}/rmqr/encoder.d.ts +0 -0
- /package/{typings → src/ts}/rmqr/index.d.ts +0 -0
- /package/{typings → src/ts}/rmqr/tables.d.ts +0 -0
package/src/index.js
CHANGED
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
*
|
|
29
29
|
* Original work. No code from any other barcode implementation.
|
|
30
30
|
*/
|
|
31
|
-
|
|
32
31
|
/**
|
|
33
32
|
* Sythos Barcode Suite — public API.
|
|
34
33
|
*
|
|
@@ -45,57 +44,46 @@
|
|
|
45
44
|
*
|
|
46
45
|
* @module @sythos/js_barcode_universal
|
|
47
46
|
*/
|
|
48
|
-
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
54
|
-
import
|
|
55
|
-
import * as
|
|
56
|
-
import * as
|
|
57
|
-
import * as
|
|
58
|
-
import * as
|
|
59
|
-
import * as
|
|
60
|
-
import * as
|
|
61
|
-
import * as
|
|
62
|
-
import * as
|
|
63
|
-
import * as
|
|
64
|
-
import * as
|
|
65
|
-
import * as databar from './databar/index.js';
|
|
66
|
-
|
|
47
|
+
import { BitMatrix } from './js/core/bit-matrix.js';
|
|
48
|
+
import { EncodeError, NotFoundError } from './js/core/errors.js';
|
|
49
|
+
import { LuminanceSource } from './js/image/luminance.js';
|
|
50
|
+
import { binarize } from './js/image/binarizer.js';
|
|
51
|
+
import { ONED_FORMATS } from './js/oned/index.js';
|
|
52
|
+
import { decodeOneD } from './js/oned/reader.js';
|
|
53
|
+
import * as datamatrix from './js/datamatrix/index.js';
|
|
54
|
+
import * as qr from './js/qr/index.js';
|
|
55
|
+
import * as aztec from './js/aztec/index.js';
|
|
56
|
+
import * as pdf417 from './js/pdf417/index.js';
|
|
57
|
+
import * as micropdf417 from './js/micropdf417/index.js';
|
|
58
|
+
import * as microqr from './js/microqr/index.js';
|
|
59
|
+
import * as rmqr from './js/rmqr/index.js';
|
|
60
|
+
import * as frameqr from './js/frameqr/index.js';
|
|
61
|
+
import * as aztecRune from './js/aztecrune/index.js';
|
|
62
|
+
import * as compactPdf417 from './js/compactpdf417/index.js';
|
|
63
|
+
import * as databar from './js/databar/index.js';
|
|
67
64
|
export { BitMatrix };
|
|
68
|
-
export {
|
|
69
|
-
|
|
70
|
-
} from './
|
|
71
|
-
export
|
|
72
|
-
export {
|
|
73
|
-
export
|
|
74
|
-
export {
|
|
75
|
-
export {
|
|
76
|
-
export {
|
|
77
|
-
export {
|
|
78
|
-
export {
|
|
79
|
-
export {
|
|
80
|
-
export
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
export
|
|
86
|
-
export
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
export
|
|
90
|
-
export {
|
|
91
|
-
encodeMicroPDF417, decodeMicroPDF417, detectMicroPDF417, detectAndDecodeMicroPDF417,
|
|
92
|
-
} from './micropdf417/index.js';
|
|
93
|
-
export { encodeMicroQR, decodeMicroQR, detectMicroQR, detectAndDecodeMicroQR } from './microqr/index.js';
|
|
94
|
-
export { encodeRMQR, decodeRMQR, detectRMQR, detectAndDecodeRMQR } from './rmqr/index.js';
|
|
95
|
-
export {
|
|
96
|
-
encodeFrameQR, decodeFrameQR, detectFrameQR, detectAndDecodeFrameQR,
|
|
97
|
-
} from './frameqr/index.js';
|
|
98
|
-
|
|
65
|
+
export { BarcodeError, EncodeError, NotFoundError, FormatError, ChecksumError, } from './js/core/errors.js';
|
|
66
|
+
export { LuminanceSource } from './js/image/luminance.js';
|
|
67
|
+
export { binarize, binarizeGlobal, binarizeHybrid } from './js/image/binarizer.js';
|
|
68
|
+
export * from './js/oned/index.js';
|
|
69
|
+
export { toSVG, toSVGDataURI } from './js/render/svg.js';
|
|
70
|
+
export { toImageData, toCanvas } from './js/render/image-data.js';
|
|
71
|
+
export { toPNG, toPNGDataURI } from './js/render/png.js';
|
|
72
|
+
export { renderToCanvasAuto, isWebGL2Available } from './js/render/index.js';
|
|
73
|
+
export { renderToCanvasAutoAsync, isWebGPUAvailable } from './js/render/index.js';
|
|
74
|
+
export { encodeQR, decodeQR, detectQR, detectAndDecodeQR } from './js/qr/index.js';
|
|
75
|
+
export { encodeDataMatrix, decodeDataMatrix, detectDataMatrix, detectAndDecodeDataMatrix, } from './js/datamatrix/index.js';
|
|
76
|
+
export { encodeAztec, decodeAztec, detectAztec, detectAndDecodeAztec } from './js/aztec/index.js';
|
|
77
|
+
export * from './js/aztecrune/index.js';
|
|
78
|
+
export { encodePDF417, decodePDF417, detectPDF417, detectAndDecodePDF417 } from './js/pdf417/index.js';
|
|
79
|
+
export * from './js/compactpdf417/index.js';
|
|
80
|
+
// DataBar exports include both the verified GTIN/data layer and the
|
|
81
|
+
// Omnidirectional/Truncated physical image path.
|
|
82
|
+
export * from './js/databar/index.js';
|
|
83
|
+
export { encodeMicroPDF417, decodeMicroPDF417, detectMicroPDF417, detectAndDecodeMicroPDF417, } from './js/micropdf417/index.js';
|
|
84
|
+
export { encodeMicroQR, decodeMicroQR, detectMicroQR, detectAndDecodeMicroQR } from './js/microqr/index.js';
|
|
85
|
+
export { encodeRMQR, decodeRMQR, detectRMQR, detectAndDecodeRMQR } from './js/rmqr/index.js';
|
|
86
|
+
export { encodeFrameQR, decodeFrameQR, detectFrameQR, detectAndDecodeFrameQR, } from './js/frameqr/index.js';
|
|
99
87
|
/**
|
|
100
88
|
* @typedef {object} FormatInfo
|
|
101
89
|
* @property {string} id
|
|
@@ -105,7 +93,6 @@ export {
|
|
|
105
93
|
* @property {'1D' | '2D'} kind
|
|
106
94
|
* @property {'supplement'} [role]
|
|
107
95
|
*/
|
|
108
|
-
|
|
109
96
|
// Writing and reading a format are separate capabilities that can land at
|
|
110
97
|
// different times, so they are reported separately rather than collapsed into
|
|
111
98
|
// one "supported" flag that would be wrong in one direction or the other.
|
|
@@ -116,9 +103,9 @@ export {
|
|
|
116
103
|
// value.
|
|
117
104
|
const qrPresent = qr.QR_PLACEHOLDER !== true;
|
|
118
105
|
const qrCanEncode = qrPresent &&
|
|
119
|
-
|
|
106
|
+
typeof qr.encodeQR === 'function' && qr.QR_CAN_ENCODE !== false;
|
|
120
107
|
const qrCanDecode = qrPresent &&
|
|
121
|
-
|
|
108
|
+
typeof qr.detectAndDecodeQR === 'function' && qr.QR_CAN_DECODE !== false;
|
|
122
109
|
const dataMatrixCanEncode = typeof datamatrix.encodeDataMatrix === 'function';
|
|
123
110
|
const dataMatrixCanDecode = typeof datamatrix.detectAndDecodeDataMatrix === 'function';
|
|
124
111
|
const aztecCanEncode = typeof aztec.encodeAztec === 'function';
|
|
@@ -143,7 +130,6 @@ const compactPdf417CanEncode = typeof compactPdf417.encodeCompactPDF417 === 'fun
|
|
|
143
130
|
const compactPdf417CanDecode = typeof compactPdf417.detectAndDecodeCompactPDF417 === 'function';
|
|
144
131
|
const dataBarCanEncode = typeof databar.encodeDataBar14 === 'function';
|
|
145
132
|
const dataBarCanDecode = typeof databar.decodeDataBar14Scanline === 'function';
|
|
146
|
-
|
|
147
133
|
/**
|
|
148
134
|
* Every format this build supports.
|
|
149
135
|
*
|
|
@@ -155,96 +141,93 @@ const dataBarCanDecode = typeof databar.decodeDataBar14Scanline === 'function';
|
|
|
155
141
|
* @returns {FormatInfo[]}
|
|
156
142
|
*/
|
|
157
143
|
export function listFormats() {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
return formats;
|
|
144
|
+
const formats = Object.entries(ONED_FORMATS).map(([id, info]) => ({
|
|
145
|
+
id,
|
|
146
|
+
label: info.label,
|
|
147
|
+
canWrite: true,
|
|
148
|
+
canRead: info.readable,
|
|
149
|
+
kind: /** @type {'1D'} */ ('1D'),
|
|
150
|
+
...(info.role ? { role: info.role } : {}),
|
|
151
|
+
}));
|
|
152
|
+
formats.push({
|
|
153
|
+
id: 'qr',
|
|
154
|
+
label: 'QR Code',
|
|
155
|
+
canWrite: qrCanEncode,
|
|
156
|
+
canRead: qrCanDecode,
|
|
157
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
158
|
+
});
|
|
159
|
+
formats.push({
|
|
160
|
+
id: 'datamatrix',
|
|
161
|
+
label: 'Data Matrix ECC 200',
|
|
162
|
+
canWrite: dataMatrixCanEncode,
|
|
163
|
+
canRead: dataMatrixCanDecode,
|
|
164
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
165
|
+
});
|
|
166
|
+
formats.push({
|
|
167
|
+
id: 'aztec',
|
|
168
|
+
label: 'Aztec Code',
|
|
169
|
+
canWrite: aztecCanEncode,
|
|
170
|
+
canRead: aztecCanDecode,
|
|
171
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
172
|
+
});
|
|
173
|
+
formats.push({
|
|
174
|
+
id: 'aztecrune',
|
|
175
|
+
label: 'Aztec Rune',
|
|
176
|
+
canWrite: aztecRuneCanEncode,
|
|
177
|
+
canRead: aztecRuneCanDecode,
|
|
178
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
179
|
+
});
|
|
180
|
+
formats.push({
|
|
181
|
+
id: 'pdf417',
|
|
182
|
+
label: 'PDF417',
|
|
183
|
+
canWrite: pdf417CanEncode,
|
|
184
|
+
canRead: pdf417CanDecode,
|
|
185
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
186
|
+
});
|
|
187
|
+
formats.push({
|
|
188
|
+
id: 'compactpdf417',
|
|
189
|
+
label: 'Compact PDF417',
|
|
190
|
+
canWrite: compactPdf417CanEncode,
|
|
191
|
+
canRead: compactPdf417CanDecode,
|
|
192
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
193
|
+
});
|
|
194
|
+
formats.push({
|
|
195
|
+
id: 'micropdf417',
|
|
196
|
+
label: 'MicroPDF417',
|
|
197
|
+
canWrite: microPdf417CanEncode,
|
|
198
|
+
canRead: microPdf417CanDecode,
|
|
199
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
200
|
+
});
|
|
201
|
+
formats.push({
|
|
202
|
+
id: 'microqr',
|
|
203
|
+
label: 'Micro QR Code',
|
|
204
|
+
canWrite: microQrCanEncode,
|
|
205
|
+
canRead: microQrCanDecode,
|
|
206
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
207
|
+
});
|
|
208
|
+
formats.push({
|
|
209
|
+
id: 'rmqr',
|
|
210
|
+
label: 'rMQR Code',
|
|
211
|
+
canWrite: rmqrCanEncode,
|
|
212
|
+
canRead: rmqrCanDecode,
|
|
213
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
214
|
+
});
|
|
215
|
+
formats.push({
|
|
216
|
+
id: 'frameqr',
|
|
217
|
+
label: 'Sythos Canvas QR profile',
|
|
218
|
+
canWrite: frameQrCanEncode,
|
|
219
|
+
canRead: frameQrCanDecode,
|
|
220
|
+
kind: /** @type {'2D'} */ ('2D'),
|
|
221
|
+
});
|
|
222
|
+
formats.push({
|
|
223
|
+
id: 'gs1databar14',
|
|
224
|
+
label: 'GS1 DataBar Omnidirectional / Truncated',
|
|
225
|
+
canWrite: dataBarCanEncode,
|
|
226
|
+
canRead: dataBarCanDecode,
|
|
227
|
+
kind: /** @type {'1D'} */ ('1D'),
|
|
228
|
+
});
|
|
229
|
+
return formats;
|
|
246
230
|
}
|
|
247
|
-
|
|
248
231
|
/**
|
|
249
232
|
* Encode a payload into a barcode matrix.
|
|
250
233
|
*
|
|
@@ -271,7 +254,7 @@ export function listFormats() {
|
|
|
271
254
|
* @param {'auto'|'text'|'byte'|'numeric'} [options.compaction] PDF417 compaction mode.
|
|
272
255
|
* @param {number} [options.eci] MicroPDF417 byte-compaction ECI assignment (3 or 26).
|
|
273
256
|
* @param {number} [options.aspectRatio] Preferred MicroPDF417 symbol aspect ratio.
|
|
274
|
-
* @param {object} [options.canvas]
|
|
257
|
+
* @param {object} [options.canvas] Sythos Canvas QR artwork reservation.
|
|
275
258
|
* @param {'square'|'circle'|'diamond'} [options.canvas.shape] Canvas shape.
|
|
276
259
|
* @param {number} [options.canvas.size] Odd canvas size in QR modules.
|
|
277
260
|
* @param {number} [options.canvas.width] Canvas width in QR modules.
|
|
@@ -282,51 +265,48 @@ export function listFormats() {
|
|
|
282
265
|
* @returns {BitMatrix}
|
|
283
266
|
*/
|
|
284
267
|
export function encode(text, options = {}) {
|
|
285
|
-
|
|
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
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
return entry.encode(value, options);
|
|
268
|
+
const format = String(options.format ?? 'qr').toLowerCase();
|
|
269
|
+
const value = typeof text === 'number' ? String(text) : text;
|
|
270
|
+
if (format === 'qr' || format === 'qrcode') {
|
|
271
|
+
return qr.encodeQR(value, options);
|
|
272
|
+
}
|
|
273
|
+
if (format === 'datamatrix' || format === 'data-matrix') {
|
|
274
|
+
return datamatrix.encodeDataMatrix(value, options);
|
|
275
|
+
}
|
|
276
|
+
if (format === 'aztec' || format === 'aztec-code') {
|
|
277
|
+
return aztec.encodeAztec(value, options);
|
|
278
|
+
}
|
|
279
|
+
if (format === 'aztecrune' || format === 'aztec-rune' || format === 'rune') {
|
|
280
|
+
return aztecRune.encodeAztecRune(value, options);
|
|
281
|
+
}
|
|
282
|
+
if (format === 'pdf417' || format === 'pdf-417') {
|
|
283
|
+
return pdf417.encodePDF417(value, options);
|
|
284
|
+
}
|
|
285
|
+
if (format === 'compactpdf417' || format === 'compact-pdf417' || format === 'compact-pdf-417') {
|
|
286
|
+
return compactPdf417.encodeCompactPDF417(value, options);
|
|
287
|
+
}
|
|
288
|
+
if (format === 'micropdf417' || format === 'micro-pdf417' || format === 'micro-pdf-417') {
|
|
289
|
+
return micropdf417.encodeMicroPDF417(value, options);
|
|
290
|
+
}
|
|
291
|
+
if (format === 'microqr' || format === 'micro-qr') {
|
|
292
|
+
return microqr.encodeMicroQR(value, options);
|
|
293
|
+
}
|
|
294
|
+
if (format === 'rmqr' || format === 'r-mqr' || format === 'rectangular-micro-qr') {
|
|
295
|
+
return rmqr.encodeRMQR(value, options);
|
|
296
|
+
}
|
|
297
|
+
if (format === 'frameqr' || format === 'frame-qr' || format === 'canvas-qr') {
|
|
298
|
+
return frameqr.encodeFrameQR(value, options);
|
|
299
|
+
}
|
|
300
|
+
if (format === 'gs1databar14' || format === 'gs1-databar14' || format === 'databar') {
|
|
301
|
+
return databar.encodeDataBar14(value, options);
|
|
302
|
+
}
|
|
303
|
+
const entry = ONED_FORMATS[format];
|
|
304
|
+
if (!entry) {
|
|
305
|
+
const known = [...Object.keys(ONED_FORMATS), 'qr', 'datamatrix', 'aztec', 'aztecrune', 'pdf417', 'compactpdf417', 'micropdf417', 'microqr', 'rmqr', 'frameqr', 'gs1databar14'].join(', ');
|
|
306
|
+
throw new EncodeError(`Unknown format "${format}". Known formats: ${known}`);
|
|
307
|
+
}
|
|
308
|
+
return entry.encode(value, options);
|
|
328
309
|
}
|
|
329
|
-
|
|
330
310
|
/**
|
|
331
311
|
* @typedef {object} DecodeResult
|
|
332
312
|
* @property {string} text
|
|
@@ -344,13 +324,13 @@ export function encode(text, options = {}) {
|
|
|
344
324
|
* @property {number} [rowHeight] PDF417 row height in modules.
|
|
345
325
|
* @property {number} [variant] MicroPDF417 predefined variant number.
|
|
346
326
|
* @property {number} [eccCodewords] MicroPDF417 fixed error-correction codewords.
|
|
347
|
-
* @property {string} [profile]
|
|
327
|
+
* @property {string} [profile] Sythos Canvas QR profile identifier.
|
|
348
328
|
* @property {boolean} [certified] Whether the profile is certified by its originator.
|
|
349
|
-
* @property {object} [canvas] Canvas reservation metadata for the
|
|
329
|
+
* @property {object} [canvas] Canvas reservation metadata for the Sythos profile.
|
|
350
330
|
* @property {{format:'ean2'|'ean5', text:string, parity:string, checksum?:number}} [addon] Attached EAN/UPC supplement.
|
|
351
331
|
* @property {number} [confidence] Camera-profile confidence from 0 to 1.
|
|
352
332
|
* @property {{x:number,y:number,width:number,height:number}} [bounds] Camera-profile bounds in the scanned orientation.
|
|
353
|
-
* @property {0|90|180|270} [rotation] Camera-profile orientation in degrees.
|
|
333
|
+
* @property {0|45|90|135|180|225|270|315} [rotation] Camera-profile orientation in degrees.
|
|
354
334
|
* @property {{quietZone:boolean,checksum:boolean|null,rows:number|null,consistency:number|null}} [quality] Camera-profile validation evidence.
|
|
355
335
|
* @property {boolean} [gs1] Whether the physical symbol is classified as GS1.
|
|
356
336
|
* @property {string} [symbologyIdentifier] GS1 symbology identifier.
|
|
@@ -359,7 +339,6 @@ export function encode(text, options = {}) {
|
|
|
359
339
|
* @property {string} [gtin] GS1 DataBar GTIN-14 payload.
|
|
360
340
|
* @property {boolean} [linkage] GS1 DataBar linkage flag.
|
|
361
341
|
*/
|
|
362
|
-
|
|
363
342
|
/**
|
|
364
343
|
* Find and decode every barcode in an image.
|
|
365
344
|
*
|
|
@@ -372,254 +351,420 @@ export function encode(text, options = {}) {
|
|
|
372
351
|
* @param {string[]} [options.formats] Restrict to these format ids.
|
|
373
352
|
* @param {boolean} [options.tryHarder] Retry inverted and rotated. Default true.
|
|
374
353
|
* @param {'global'|'hybrid'|'auto'} [options.binarizer]
|
|
375
|
-
* @param {'camera'} [options.profile] Opt-in strict camera profile for validated
|
|
376
|
-
* @param {object} [options.frameqr]
|
|
354
|
+
* @param {'camera'} [options.profile] Opt-in strict camera profile for validated reads.
|
|
355
|
+
* @param {object} [options.frameqr] Sythos Canvas QR detector options when
|
|
377
356
|
* the profile marker is not preserved through image rendering.
|
|
378
357
|
* @returns {DecodeResult[]}
|
|
379
358
|
*/
|
|
380
359
|
export function decode(image, options = {}) {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
360
|
+
const { formats = null, tryHarder = true, binarizer = 'auto', profile = null } = options;
|
|
361
|
+
const want = formats ? new Set(formats.map((f) => f.toLowerCase())) : null;
|
|
362
|
+
const wantQR = !want || want.has('qr') || want.has('qrcode');
|
|
363
|
+
const wantDataMatrix = !want || want.has('datamatrix') || want.has('data-matrix');
|
|
364
|
+
const wantAztec = !want || want.has('aztec') || want.has('aztec-code');
|
|
365
|
+
const wantAztecRune = !want || want.has('aztecrune') || want.has('aztec-rune') || want.has('rune');
|
|
366
|
+
const wantPDF417 = !want || want.has('pdf417') || want.has('pdf-417');
|
|
367
|
+
const wantCompactPDF417 = !want || want.has('compactpdf417') || want.has('compact-pdf417') || want.has('compact-pdf-417');
|
|
368
|
+
const wantMicroPDF417 = !want || want.has('micropdf417') || want.has('micro-pdf417') || want.has('micro-pdf-417');
|
|
369
|
+
const wantMicroQR = !want || want.has('microqr') || want.has('micro-qr');
|
|
370
|
+
const wantRMQR = !want || want.has('rmqr') || want.has('r-mqr') || want.has('rectangular-micro-qr');
|
|
371
|
+
const wantFrameQR = !want || want.has('frameqr') || want.has('frame-qr') || want.has('canvas-qr');
|
|
372
|
+
const oneDAliases = new Set(['gs1databar14', 'databar', 'gs1-databar14']);
|
|
373
|
+
const wantOneD = !want || [...want].some((f) => f in ONED_FORMATS || oneDAliases.has(f));
|
|
374
|
+
const wantTwoD = wantQR || wantDataMatrix || wantAztec || wantAztecRune || wantPDF417
|
|
375
|
+
|| wantCompactPDF417 || wantMicroPDF417 || wantMicroQR || wantRMQR || wantFrameQR;
|
|
376
|
+
const source = LuminanceSource.fromImageData(image);
|
|
377
|
+
const results = [];
|
|
378
|
+
// Light-on-dark symbols are common on screens and packaging, so a second
|
|
379
|
+
// inverted pass is worth the cost when the first finds nothing.
|
|
380
|
+
const passes = tryHarder ? [source, source.invert()] : [source];
|
|
381
|
+
for (const pass of passes) {
|
|
382
|
+
const bits = binarize(pass, binarizer);
|
|
383
|
+
// Keep all two-dimensional detector calls in one helper so camera-only
|
|
384
|
+
// orientation retries use exactly the same validation path as the native
|
|
385
|
+
// orientation. Arbitrary-angle retries remain opt-in to the camera
|
|
386
|
+
// profile because resampling is intentionally not part of ordinary decode.
|
|
387
|
+
const readTwoD = (candidateBits, cameraRotation = 0, candidateSource = pass) => {
|
|
388
|
+
const before = results.length;
|
|
389
|
+
const add = (found, format) => {
|
|
390
|
+
if (!found)
|
|
391
|
+
return;
|
|
392
|
+
const publicFound = { ...found, format };
|
|
393
|
+
if (profile === 'camera' && cameraRotation !== 0)
|
|
394
|
+
publicFound.rotation = cameraRotation;
|
|
395
|
+
results.push(publicFound);
|
|
396
|
+
};
|
|
397
|
+
if (wantQR && qrCanDecode) {
|
|
398
|
+
try {
|
|
399
|
+
for (const found of qr.detectAndDecodeQR(candidateBits))
|
|
400
|
+
add(found, 'qr');
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
/* no QR in this pass */
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
if (wantDataMatrix && dataMatrixCanDecode) {
|
|
407
|
+
// Hybrid thresholding can erase the interior of very large, perfectly
|
|
408
|
+
// uniform modules. In auto mode keep the local-threshold attempt, then
|
|
409
|
+
// retry Data Matrix once with the global threshold before giving up.
|
|
410
|
+
const dataMatrixBits = binarizer === 'auto'
|
|
411
|
+
? [candidateBits, binarize(candidateSource, 'global')]
|
|
412
|
+
: [candidateBits];
|
|
413
|
+
for (const thresholdBits of dataMatrixBits) {
|
|
414
|
+
try {
|
|
415
|
+
const found = datamatrix.detectAndDecodeDataMatrix(thresholdBits);
|
|
416
|
+
if (found) {
|
|
417
|
+
add(found, 'datamatrix');
|
|
418
|
+
break;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
catch {
|
|
422
|
+
/* no Data Matrix with this threshold */
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
if (wantAztec && aztecCanDecode) {
|
|
427
|
+
// The central bull's-eye is a small, high-contrast target. Hybrid
|
|
428
|
+
// thresholding can flatten it on clean rendered symbols, so mirror the
|
|
429
|
+
// Data Matrix global fallback in auto mode.
|
|
430
|
+
const aztecBits = binarizer === 'auto'
|
|
431
|
+
? [candidateBits, binarize(candidateSource, 'global')]
|
|
432
|
+
: [candidateBits];
|
|
433
|
+
for (const thresholdBits of aztecBits) {
|
|
434
|
+
try {
|
|
435
|
+
const found = aztec.detectAndDecodeAztec(thresholdBits);
|
|
436
|
+
if (found) {
|
|
437
|
+
add(found, 'aztec');
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
/* no Aztec code with this threshold */
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
if (wantAztecRune && aztecRuneCanDecode) {
|
|
447
|
+
try {
|
|
448
|
+
const found = aztecRune.detectAndDecodeAztecRune(candidateBits);
|
|
449
|
+
if (found)
|
|
450
|
+
add(found, 'aztecrune');
|
|
451
|
+
}
|
|
452
|
+
catch {
|
|
453
|
+
/* no Aztec Rune in this pass */
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
if (wantPDF417 && pdf417CanDecode) {
|
|
457
|
+
try {
|
|
458
|
+
const found = pdf417.detectAndDecodePDF417(candidateBits);
|
|
459
|
+
if (found)
|
|
460
|
+
add(found, 'pdf417');
|
|
461
|
+
}
|
|
462
|
+
catch {
|
|
463
|
+
/* no PDF417 in this pass */
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
if (wantCompactPDF417 && compactPdf417CanDecode) {
|
|
467
|
+
try {
|
|
468
|
+
const found = compactPdf417.detectAndDecodeCompactPDF417(candidateBits);
|
|
469
|
+
if (found)
|
|
470
|
+
add(found, 'compactpdf417');
|
|
471
|
+
}
|
|
472
|
+
catch {
|
|
473
|
+
/* no Compact PDF417 in this pass */
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (wantMicroPDF417 && microPdf417CanDecode) {
|
|
477
|
+
// MicroPDF417 detection measures runs across the whole raster. Hybrid
|
|
478
|
+
// thresholding can alter uniform modules near local-window boundaries,
|
|
479
|
+
// so retry the global threshold in auto mode as for the other 2D codes.
|
|
480
|
+
const microPdf417Bits = binarizer === 'auto'
|
|
481
|
+
? [candidateBits, binarize(candidateSource, 'global')]
|
|
482
|
+
: [candidateBits];
|
|
483
|
+
for (const thresholdBits of microPdf417Bits) {
|
|
484
|
+
try {
|
|
485
|
+
const found = micropdf417.detectAndDecodeMicroPDF417(thresholdBits);
|
|
486
|
+
if (found) {
|
|
487
|
+
add(found, 'micropdf417');
|
|
488
|
+
break;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
catch {
|
|
492
|
+
/* no MicroPDF417 with this threshold */
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
if (wantMicroQR && microQrCanDecode) {
|
|
497
|
+
try {
|
|
498
|
+
for (const found of microqr.detectAndDecodeMicroQR(candidateBits))
|
|
499
|
+
add(found, 'microqr');
|
|
500
|
+
}
|
|
501
|
+
catch {
|
|
502
|
+
/* no Micro QR in this pass */
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (wantRMQR && rmqrCanDecode) {
|
|
506
|
+
try {
|
|
507
|
+
const found = rmqr.detectAndDecodeRMQR(candidateBits);
|
|
508
|
+
if (found)
|
|
509
|
+
add(found, 'rmqr');
|
|
510
|
+
}
|
|
511
|
+
catch {
|
|
512
|
+
/* no rMQR in this pass */
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (wantFrameQR && frameQrCanDecode) {
|
|
516
|
+
try {
|
|
517
|
+
for (const found of frameqr.detectAndDecodeFrameQR(candidateBits, options.frameqr ?? {}))
|
|
518
|
+
add(found, 'frameqr');
|
|
519
|
+
}
|
|
520
|
+
catch {
|
|
521
|
+
/* no Sythos Canvas QR profile in this pass */
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return results.length > before;
|
|
525
|
+
};
|
|
526
|
+
const twoDFound = readTwoD(bits);
|
|
527
|
+
if (profile === 'camera' && wantTwoD && !twoDFound) {
|
|
528
|
+
// Normalize a camera frame through the full eight-angle set only after
|
|
529
|
+
// the native orientation has failed. This preserves the fast path while
|
|
530
|
+
// limiting resampling to frames that need it.
|
|
531
|
+
const cameraRotations = [45, 90, 135, 180, 225, 270, 315];
|
|
532
|
+
for (const rotation of cameraRotations) {
|
|
533
|
+
const inverse = (360 - rotation) % 360;
|
|
534
|
+
const orientedSource = inverse % 90 === 0
|
|
535
|
+
? inverse === 0
|
|
536
|
+
? pass
|
|
537
|
+
: inverse === 90
|
|
538
|
+
? pass.rotate90()
|
|
539
|
+
: inverse === 180
|
|
540
|
+
? rotateLuminanceSourceByDegrees(pass, 180)
|
|
541
|
+
: pass.rotate90().rotate90().rotate90()
|
|
542
|
+
: rotateLuminanceSourceByDegrees(pass, inverse);
|
|
543
|
+
if (readTwoD(binarize(orientedSource, binarizer), rotation, orientedSource))
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
427
546
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
const found = micropdf417.detectAndDecodeMicroPDF417(candidateBits);
|
|
481
|
-
if (found) { results.push({ ...found, format: 'micropdf417' }); break; }
|
|
482
|
-
} catch {
|
|
483
|
-
/* no MicroPDF417 with this threshold */
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
if (wantMicroQR && microQrCanDecode) {
|
|
489
|
-
try {
|
|
490
|
-
for (const found of microqr.detectAndDecodeMicroQR(bits)) {
|
|
491
|
-
results.push({ ...found, format: 'microqr' });
|
|
547
|
+
if (wantOneD) {
|
|
548
|
+
const oneDFormats = want
|
|
549
|
+
? [...want].filter((f) => f in ONED_FORMATS || oneDAliases.has(f))
|
|
550
|
+
: null;
|
|
551
|
+
const oneDPasses = [{ bits, rotation: 0 }];
|
|
552
|
+
// A linear symbol rotated away from the horizontal has no usable
|
|
553
|
+
// horizontal scanline. The strict camera profile adds normalized
|
|
554
|
+
// orientations only when the native orientation found no validated 1D
|
|
555
|
+
// result. Keep the two quarter-turns first: they are the established
|
|
556
|
+
// path and avoid paying for diagonal resampling on the common case.
|
|
557
|
+
const readOneD = (candidateBits, rotation) => decodeOneD(candidateBits, {
|
|
558
|
+
...options, formats: oneDFormats, tryHarder, profile, cameraRotation: rotation,
|
|
559
|
+
});
|
|
560
|
+
let oneDResults = readOneD(bits, 0);
|
|
561
|
+
if (profile === 'camera' && oneDResults.length === 0) {
|
|
562
|
+
// `rotation` describes the supplied raster, clockwise from the
|
|
563
|
+
// canonical horizontal orientation. To normalize it, apply the
|
|
564
|
+
// inverse rotation. Include 180 explicitly so the full eight-angle
|
|
565
|
+
// set still works when tryHarder is disabled (the normal reversed-row
|
|
566
|
+
// pass also handles it without a second raster transform).
|
|
567
|
+
const cameraRotations = [90, 270, 180, 45, 135, 225, 315];
|
|
568
|
+
for (const rotation of cameraRotations) {
|
|
569
|
+
const inverse = (360 - rotation) % 360;
|
|
570
|
+
const oriented = inverse % 90 === 0
|
|
571
|
+
? inverse === 0
|
|
572
|
+
? bits.clone()
|
|
573
|
+
: inverse === 180
|
|
574
|
+
? (() => { const copy = bits.clone(); copy.rotate180(); return copy; })()
|
|
575
|
+
: rotateBitMatrix90(bits, inverse === 90)
|
|
576
|
+
: rotateBitMatrixByDegrees(bits, inverse);
|
|
577
|
+
oneDPasses.push({ bits: oriented, rotation });
|
|
578
|
+
}
|
|
579
|
+
for (let i = 1; i < oneDPasses.length && oneDResults.length === 0; i++) {
|
|
580
|
+
oneDResults = readOneD(oneDPasses[i].bits, oneDPasses[i].rotation);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
for (const found of oneDResults) {
|
|
584
|
+
const { row, ...publicFound } = found;
|
|
585
|
+
void row;
|
|
586
|
+
if (publicFound.gs1) {
|
|
587
|
+
const semanticText = publicFound.format === 'gs1databar14'
|
|
588
|
+
? `01${publicFound.gtin ?? publicFound.text}`
|
|
589
|
+
: publicFound.text;
|
|
590
|
+
try {
|
|
591
|
+
publicFound.elements = databar.decodeGS1ElementString(semanticText);
|
|
592
|
+
}
|
|
593
|
+
catch (error) {
|
|
594
|
+
publicFound.gs1ParseError = error instanceof Error ? error.message : String(error);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
results.push(publicFound);
|
|
598
|
+
}
|
|
492
599
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
}
|
|
600
|
+
if (results.length > 0)
|
|
601
|
+
break;
|
|
496
602
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
const
|
|
501
|
-
if (
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
603
|
+
// De-duplicate: the same symbol is often read on several scan rows.
|
|
604
|
+
const seen = new Set();
|
|
605
|
+
const unique = results.filter((r) => {
|
|
606
|
+
const key = `${r.format}:${r.text}`;
|
|
607
|
+
if (seen.has(key))
|
|
608
|
+
return false;
|
|
609
|
+
seen.add(key);
|
|
610
|
+
return true;
|
|
611
|
+
});
|
|
612
|
+
// On large clean rasters, hybrid thresholding can erase otherwise uniform
|
|
613
|
+
// QR/PDF417 modules. Keep auto/hybrid as the primary strategy, then make one
|
|
614
|
+
// focused global retry only when the complete primary pass found nothing.
|
|
615
|
+
// This deliberately leaves an explicit global request single-pass.
|
|
616
|
+
const retryFormats = formats
|
|
617
|
+
? formats.filter((format) => {
|
|
618
|
+
const id = String(format).toLowerCase();
|
|
619
|
+
return id === 'qr' || id === 'qrcode'
|
|
620
|
+
|| id === 'pdf417' || id === 'pdf-417'
|
|
621
|
+
|| id === 'compactpdf417' || id === 'compact-pdf417' || id === 'compact-pdf-417';
|
|
622
|
+
})
|
|
623
|
+
: ['qr', 'pdf417', 'compactpdf417'];
|
|
624
|
+
const shouldRetryGlobal = unique.length === 0
|
|
625
|
+
&& (binarizer === 'auto' || binarizer === 'hybrid')
|
|
626
|
+
&& retryFormats.length > 0;
|
|
627
|
+
if (!shouldRetryGlobal) {
|
|
628
|
+
return profile === 'camera'
|
|
629
|
+
? unique.sort((a, b) => (b.confidence ?? 0) - (a.confidence ?? 0))
|
|
630
|
+
: unique;
|
|
505
631
|
}
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
? [...want].filter((f) => f in ONED_FORMATS || oneDAliases.has(f))
|
|
520
|
-
: null;
|
|
521
|
-
const oneDPasses = [{ bits, rotation: 0 }];
|
|
522
|
-
// A linear symbol rotated by 90° has no usable horizontal scanline.
|
|
523
|
-
// The strict camera profile adds exactly two normalized orientations,
|
|
524
|
-
// only when the native orientation found no validated 1D result.
|
|
525
|
-
const readOneD = (candidateBits, rotation) => decodeOneD(candidateBits, {
|
|
526
|
-
...options, formats: oneDFormats, tryHarder, profile, cameraRotation: rotation,
|
|
527
|
-
});
|
|
528
|
-
let oneDResults = readOneD(bits, 0);
|
|
529
|
-
if (profile === 'camera' && oneDResults.length === 0) {
|
|
530
|
-
oneDPasses.push(
|
|
531
|
-
{ bits: rotateBitMatrix90(bits, false), rotation: 90 },
|
|
532
|
-
{ bits: rotateBitMatrix90(bits, true), rotation: 270 },
|
|
533
|
-
);
|
|
534
|
-
for (let i = 1; i < oneDPasses.length && oneDResults.length === 0; i++) {
|
|
535
|
-
oneDResults = readOneD(oneDPasses[i].bits, oneDPasses[i].rotation);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
for (const found of oneDResults) {
|
|
539
|
-
const { row, ...publicFound } = found;
|
|
540
|
-
void row;
|
|
541
|
-
if (publicFound.gs1) {
|
|
542
|
-
const semanticText = publicFound.format === 'gs1databar14'
|
|
543
|
-
? `01${publicFound.gtin ?? publicFound.text}`
|
|
544
|
-
: publicFound.text;
|
|
545
|
-
try {
|
|
546
|
-
publicFound.elements = databar.decodeGS1ElementString(semanticText);
|
|
547
|
-
} catch (error) {
|
|
548
|
-
publicFound.gs1ParseError = error instanceof Error ? error.message : String(error);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
results.push(publicFound);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
if (results.length > 0) break;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
// De-duplicate: the same symbol is often read on several scan rows.
|
|
559
|
-
const seen = new Set();
|
|
560
|
-
const unique = results.filter((r) => {
|
|
561
|
-
const key = `${r.format}:${r.text}`;
|
|
562
|
-
if (seen.has(key)) return false;
|
|
563
|
-
seen.add(key);
|
|
564
|
-
return true;
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
// On large clean rasters, hybrid thresholding can erase otherwise uniform
|
|
568
|
-
// QR/PDF417 modules. Keep auto/hybrid as the primary strategy, then make one
|
|
569
|
-
// focused global retry only when the complete primary pass found nothing.
|
|
570
|
-
// This deliberately leaves an explicit global request single-pass.
|
|
571
|
-
const retryFormats = formats
|
|
572
|
-
? formats.filter((format) => {
|
|
573
|
-
const id = String(format).toLowerCase();
|
|
574
|
-
return id === 'qr' || id === 'qrcode'
|
|
575
|
-
|| id === 'pdf417' || id === 'pdf-417'
|
|
576
|
-
|| id === 'compactpdf417' || id === 'compact-pdf417' || id === 'compact-pdf-417';
|
|
577
|
-
})
|
|
578
|
-
: ['qr', 'pdf417', 'compactpdf417'];
|
|
579
|
-
const shouldRetryGlobal = unique.length === 0
|
|
580
|
-
&& (binarizer === 'auto' || binarizer === 'hybrid')
|
|
581
|
-
&& retryFormats.length > 0;
|
|
582
|
-
|
|
583
|
-
if (!shouldRetryGlobal) {
|
|
632
|
+
const fallback = decode(image, {
|
|
633
|
+
...options,
|
|
634
|
+
formats: retryFormats,
|
|
635
|
+
binarizer: 'global',
|
|
636
|
+
});
|
|
637
|
+
const fallbackSeen = new Set();
|
|
638
|
+
const merged = [...unique, ...fallback].filter((r) => {
|
|
639
|
+
const key = `${r.format}:${r.text}`;
|
|
640
|
+
if (fallbackSeen.has(key))
|
|
641
|
+
return false;
|
|
642
|
+
fallbackSeen.add(key);
|
|
643
|
+
return true;
|
|
644
|
+
});
|
|
584
645
|
return profile === 'camera'
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
const fallback = decode(image, {
|
|
590
|
-
...options,
|
|
591
|
-
formats: retryFormats,
|
|
592
|
-
binarizer: 'global',
|
|
593
|
-
});
|
|
594
|
-
const fallbackSeen = new Set();
|
|
595
|
-
const merged = [...unique, ...fallback].filter((r) => {
|
|
596
|
-
const key = `${r.format}:${r.text}`;
|
|
597
|
-
if (fallbackSeen.has(key)) return false;
|
|
598
|
-
fallbackSeen.add(key);
|
|
599
|
-
return true;
|
|
600
|
-
});
|
|
601
|
-
return profile === 'camera'
|
|
602
|
-
? merged.sort((a, b) => (b.confidence ?? 0) - (a.confidence ?? 0))
|
|
603
|
-
: merged;
|
|
646
|
+
? merged.sort((a, b) => (b.confidence ?? 0) - (a.confidence ?? 0))
|
|
647
|
+
: merged;
|
|
604
648
|
}
|
|
605
|
-
|
|
606
649
|
/**
|
|
607
650
|
* @param {BitMatrix} matrix
|
|
608
651
|
* @param {boolean} clockwise
|
|
609
652
|
* @returns {BitMatrix}
|
|
610
653
|
*/
|
|
611
654
|
function rotateBitMatrix90(matrix, clockwise) {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
655
|
+
const rotated = new BitMatrix(matrix.height, matrix.width);
|
|
656
|
+
for (let y = 0; y < matrix.height; y++) {
|
|
657
|
+
for (let x = 0; x < matrix.width; x++) {
|
|
658
|
+
if (!matrix.get(x, y))
|
|
659
|
+
continue;
|
|
660
|
+
if (clockwise)
|
|
661
|
+
rotated.set(matrix.height - 1 - y, x);
|
|
662
|
+
else
|
|
663
|
+
rotated.set(y, matrix.width - 1 - x);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
return rotated;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Rotate a binarized raster by an arbitrary clockwise angle without changing
|
|
670
|
+
* the source matrix. This is intentionally used only by the strict camera
|
|
671
|
+
* profile: arbitrary-angle resampling is useful for linear symbols, but is
|
|
672
|
+
* too permissive to become a default retry for every detector.
|
|
673
|
+
*
|
|
674
|
+
* @param {BitMatrix} matrix
|
|
675
|
+
* @param {number} degrees Clockwise angle, normally one of 45/135/225/315.
|
|
676
|
+
* @returns {BitMatrix}
|
|
677
|
+
*/
|
|
678
|
+
function rotateBitMatrixByDegrees(matrix, degrees) {
|
|
679
|
+
const angle = ((degrees % 360) + 360) % 360;
|
|
680
|
+
if (angle === 0)
|
|
681
|
+
return matrix.clone();
|
|
682
|
+
if (angle === 90)
|
|
683
|
+
return rotateBitMatrix90(matrix, true);
|
|
684
|
+
if (angle === 180) {
|
|
685
|
+
const rotated = matrix.clone();
|
|
686
|
+
rotated.rotate180();
|
|
687
|
+
return rotated;
|
|
688
|
+
}
|
|
689
|
+
if (angle === 270)
|
|
690
|
+
return rotateBitMatrix90(matrix, false);
|
|
691
|
+
const radians = angle * Math.PI / 180;
|
|
692
|
+
const sin = Math.sin(radians);
|
|
693
|
+
const cos = Math.cos(radians);
|
|
694
|
+
const width = Math.ceil(Math.abs(matrix.width * cos) + Math.abs(matrix.height * sin));
|
|
695
|
+
const height = Math.ceil(Math.abs(matrix.width * sin) + Math.abs(matrix.height * cos));
|
|
696
|
+
const rotated = new BitMatrix(width, height);
|
|
697
|
+
const sourceCenterX = (matrix.width - 1) / 2;
|
|
698
|
+
const sourceCenterY = (matrix.height - 1) / 2;
|
|
699
|
+
const destinationCenterX = (width - 1) / 2;
|
|
700
|
+
const destinationCenterY = (height - 1) / 2;
|
|
701
|
+
// Inverse-map destination pixels into the source. Sampling the already
|
|
702
|
+
// binarized raster keeps the operation deterministic and leaves the caller's
|
|
703
|
+
// original image and threshold result untouched.
|
|
704
|
+
for (let y = 0; y < height; y++) {
|
|
705
|
+
const dy = y - destinationCenterY;
|
|
706
|
+
for (let x = 0; x < width; x++) {
|
|
707
|
+
const dx = x - destinationCenterX;
|
|
708
|
+
const sourceX = Math.round(cos * dx + sin * dy + sourceCenterX);
|
|
709
|
+
const sourceY = Math.round(-sin * dx + cos * dy + sourceCenterY);
|
|
710
|
+
if (sourceX >= 0 && sourceX < matrix.width && sourceY >= 0 && sourceY < matrix.height &&
|
|
711
|
+
matrix.get(sourceX, sourceY)) {
|
|
712
|
+
rotated.set(x, y);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
return rotated;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Rotate the greyscale source before thresholding. Resampling luminance rather
|
|
720
|
+
* than an already-binarized matrix preserves module contrast at diagonal
|
|
721
|
+
* orientations and gives the format-specific detectors the same input quality
|
|
722
|
+
* as the native camera frame.
|
|
723
|
+
*
|
|
724
|
+
* @param {LuminanceSource} source
|
|
725
|
+
* @param {number} degrees Clockwise angle.
|
|
726
|
+
* @returns {LuminanceSource}
|
|
727
|
+
*/
|
|
728
|
+
function rotateLuminanceSourceByDegrees(source, degrees) {
|
|
729
|
+
const angle = ((degrees % 360) + 360) % 360;
|
|
730
|
+
if (angle === 0)
|
|
731
|
+
return source;
|
|
732
|
+
if (angle === 90)
|
|
733
|
+
return source.rotate90();
|
|
734
|
+
if (angle === 180)
|
|
735
|
+
return source.rotate90().rotate90();
|
|
736
|
+
if (angle === 270)
|
|
737
|
+
return source.rotate90().rotate90().rotate90();
|
|
738
|
+
const radians = angle * Math.PI / 180;
|
|
739
|
+
const sin = Math.sin(radians);
|
|
740
|
+
const cos = Math.cos(radians);
|
|
741
|
+
const width = Math.ceil(Math.abs(source.width * cos) + Math.abs(source.height * sin));
|
|
742
|
+
const height = Math.ceil(Math.abs(source.width * sin) + Math.abs(source.height * cos));
|
|
743
|
+
const rotated = new Uint8Array(width * height);
|
|
744
|
+
rotated.fill(255);
|
|
745
|
+
const sourceCenterX = (source.width - 1) / 2;
|
|
746
|
+
const sourceCenterY = (source.height - 1) / 2;
|
|
747
|
+
const destinationCenterX = (width - 1) / 2;
|
|
748
|
+
const destinationCenterY = (height - 1) / 2;
|
|
749
|
+
for (let y = 0; y < height; y++) {
|
|
750
|
+
const dy = y - destinationCenterY;
|
|
751
|
+
for (let x = 0; x < width; x++) {
|
|
752
|
+
const dx = x - destinationCenterX;
|
|
753
|
+
const sourceX = cos * dx + sin * dy + sourceCenterX;
|
|
754
|
+
const sourceY = -sin * dx + cos * dy + sourceCenterY;
|
|
755
|
+
if (sourceX >= 0 && sourceX < source.width && sourceY >= 0 && sourceY < source.height) {
|
|
756
|
+
const left = Math.floor(sourceX), top = Math.floor(sourceY);
|
|
757
|
+
const right = Math.min(source.width - 1, left + 1);
|
|
758
|
+
const bottom = Math.min(source.height - 1, top + 1);
|
|
759
|
+
const fx = sourceX - left, fy = sourceY - top;
|
|
760
|
+
const topValue = source.get(left, top) * (1 - fx) + source.get(right, top) * fx;
|
|
761
|
+
const bottomValue = source.get(left, bottom) * (1 - fx) + source.get(right, bottom) * fx;
|
|
762
|
+
rotated[y * width + x] = Math.round(topValue * (1 - fy) + bottomValue * fy);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
618
765
|
}
|
|
619
|
-
|
|
620
|
-
return rotated;
|
|
766
|
+
return LuminanceSource.fromGrey(rotated, width, height);
|
|
621
767
|
}
|
|
622
|
-
|
|
623
768
|
/**
|
|
624
769
|
* Decode, or throw if nothing is found.
|
|
625
770
|
*
|
|
@@ -628,10 +773,10 @@ function rotateBitMatrix90(matrix, clockwise) {
|
|
|
628
773
|
* @returns {DecodeResult}
|
|
629
774
|
*/
|
|
630
775
|
export function decodeStrict(image, options) {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
776
|
+
const results = decode(image, options);
|
|
777
|
+
if (results.length === 0)
|
|
778
|
+
throw new NotFoundError('No barcode found in image');
|
|
779
|
+
return results[0];
|
|
634
780
|
}
|
|
635
|
-
|
|
636
781
|
/** Library version, matching package.json. */
|
|
637
|
-
export const VERSION = '1.5.
|
|
782
|
+
export const VERSION = '1.5.9';
|