@sythos/js_barcode_universal 1.5.8 → 1.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/LICENSE +5 -4
  2. package/NOTICE.md +2 -2
  3. package/README.md +17 -13
  4. package/bundle/sythos-barcode.esm.js +11658 -11244
  5. package/bundle/sythos-barcode.js +11658 -11244
  6. package/package.json +10 -3
  7. package/src/index.d.ts +1 -1
  8. package/src/index.js +508 -516
  9. package/src/js/aztec/decoder.js +208 -199
  10. package/src/js/aztec/detector.js +153 -126
  11. package/src/js/aztec/encoder.js +172 -153
  12. package/src/js/aztec/high-level.js +106 -101
  13. package/src/js/aztec/index.js +1 -12
  14. package/src/js/aztec/tables.js +106 -120
  15. package/src/js/aztecrune/decoder.js +76 -85
  16. package/src/js/aztecrune/detector.js +107 -93
  17. package/src/js/aztecrune/encoder.js +50 -68
  18. package/src/js/aztecrune/index.js +1 -16
  19. package/src/js/aztecrune/tables.js +59 -54
  20. package/src/js/compactpdf417/decoder.js +69 -74
  21. package/src/js/compactpdf417/detector.js +74 -75
  22. package/src/js/compactpdf417/encoder.js +68 -81
  23. package/src/js/compactpdf417/index.js +1 -13
  24. package/src/js/compactpdf417/tables.js +71 -80
  25. package/src/js/core/bit-buffer.js +106 -122
  26. package/src/js/core/bit-matrix.js +196 -194
  27. package/src/js/core/errors.js +13 -15
  28. package/src/js/core/galois-field.js +119 -133
  29. package/src/js/core/index.js +2 -19
  30. package/src/js/core/reed-solomon.js +195 -204
  31. package/src/js/databar/codec.js +93 -108
  32. package/src/js/databar/decoder.js +149 -140
  33. package/src/js/databar/encoder.js +47 -55
  34. package/src/js/databar/gs1.js +122 -123
  35. package/src/js/databar/index.js +4 -36
  36. package/src/js/databar/patterns.js +81 -85
  37. package/src/js/databar/tables.js +51 -52
  38. package/src/js/datamatrix/decoder.js +216 -182
  39. package/src/js/datamatrix/detector.js +161 -132
  40. package/src/js/datamatrix/encoder.js +192 -133
  41. package/src/js/datamatrix/index.js +1 -9
  42. package/src/js/datamatrix/tables.js +68 -69
  43. package/src/js/frameqr/decoder.js +102 -125
  44. package/src/js/frameqr/detector.js +101 -94
  45. package/src/js/frameqr/encoder.js +67 -80
  46. package/src/js/frameqr/index.js +1 -10
  47. package/src/js/frameqr/tables.js +145 -163
  48. package/src/js/image/binarizer.js +146 -162
  49. package/src/js/image/grid-sampler.js +63 -79
  50. package/src/js/image/index.js +0 -2
  51. package/src/js/image/luminance.js +129 -140
  52. package/src/js/image/perspective.js +112 -149
  53. package/src/js/micropdf417/compaction.js +64 -65
  54. package/src/js/micropdf417/decoder.js +106 -109
  55. package/src/js/micropdf417/detector.js +73 -70
  56. package/src/js/micropdf417/encoder.js +129 -154
  57. package/src/js/micropdf417/error-correction.js +6 -11
  58. package/src/js/micropdf417/index.js +2 -16
  59. package/src/js/micropdf417/tables.js +112 -99
  60. package/src/js/microqr/decoder.js +177 -182
  61. package/src/js/microqr/detector.js +240 -256
  62. package/src/js/microqr/encoder.js +239 -194
  63. package/src/js/microqr/index.js +0 -2
  64. package/src/js/microqr/tables.js +208 -200
  65. package/src/js/oned/addons.js +167 -191
  66. package/src/js/oned/index.js +27 -58
  67. package/src/js/oned/patterns.js +194 -213
  68. package/src/js/oned/reader.js +1003 -984
  69. package/src/js/oned/writers.js +411 -466
  70. package/src/js/pdf417/compaction.js +315 -222
  71. package/src/js/pdf417/decoder.js +71 -36
  72. package/src/js/pdf417/detector.js +377 -361
  73. package/src/js/pdf417/encoder.js +57 -46
  74. package/src/js/pdf417/error-correction.js +5 -8
  75. package/src/js/pdf417/tables.js +248 -250
  76. package/src/js/qr/decoder.js +311 -347
  77. package/src/js/qr/detector.js +378 -395
  78. package/src/js/qr/encoder.js +514 -599
  79. package/src/js/qr/index.js +0 -2
  80. package/src/js/qr/tables.js +375 -422
  81. package/src/js/render/image-data.js +57 -62
  82. package/src/js/render/index.js +21 -23
  83. package/src/js/render/options.js +82 -90
  84. package/src/js/render/png.js +144 -169
  85. package/src/js/render/svg.js +41 -44
  86. package/src/js/render/webgl.js +103 -109
  87. package/src/js/render/webgpu.js +205 -217
  88. package/src/js/rmqr/decoder.js +161 -53
  89. package/src/js/rmqr/detector.js +73 -41
  90. package/src/js/rmqr/encoder.js +253 -104
  91. package/src/js/rmqr/index.js +1 -5
  92. package/src/js/rmqr/tables.js +108 -85
  93. package/src/ts/aztec/decoder.ts +317 -0
  94. package/src/ts/aztec/detector.ts +224 -0
  95. package/src/ts/aztec/encoder.ts +257 -0
  96. package/src/ts/aztec/high-level.ts +211 -0
  97. package/src/ts/aztec/index.ts +45 -0
  98. package/src/ts/aztec/tables.ts +210 -0
  99. package/src/ts/aztecrune/decoder.ts +155 -0
  100. package/src/ts/aztecrune/detector.ts +166 -0
  101. package/src/ts/aztecrune/encoder.ts +121 -0
  102. package/src/ts/aztecrune/index.ts +49 -0
  103. package/src/ts/aztecrune/tables.ts +137 -0
  104. package/src/ts/compactpdf417/decoder.ts +128 -0
  105. package/src/ts/compactpdf417/detector.ts +139 -0
  106. package/src/ts/compactpdf417/encoder.ts +140 -0
  107. package/src/ts/compactpdf417/index.ts +17 -0
  108. package/src/ts/compactpdf417/tables.ts +173 -0
  109. package/src/ts/core/bit-buffer.ts +174 -0
  110. package/src/ts/core/bit-matrix.ts +241 -0
  111. package/src/ts/core/errors.ts +61 -0
  112. package/src/ts/core/galois-field.ts +207 -0
  113. package/src/ts/core/index.ts +56 -0
  114. package/src/ts/core/reed-solomon.ts +327 -0
  115. package/src/ts/databar/codec.ts +181 -0
  116. package/src/ts/databar/decoder.ts +215 -0
  117. package/src/ts/databar/encoder.ts +96 -0
  118. package/src/ts/databar/gs1.ts +177 -0
  119. package/src/ts/databar/index.ts +68 -0
  120. package/src/ts/databar/patterns.ts +143 -0
  121. package/src/ts/databar/tables.ts +124 -0
  122. package/src/ts/datamatrix/decoder.ts +262 -0
  123. package/src/ts/datamatrix/detector.ts +225 -0
  124. package/src/ts/datamatrix/encoder.ts +191 -0
  125. package/src/ts/datamatrix/index.ts +42 -0
  126. package/src/ts/datamatrix/tables.ts +123 -0
  127. package/src/ts/frameqr/decoder.ts +239 -0
  128. package/src/ts/frameqr/detector.ts +192 -0
  129. package/src/ts/frameqr/encoder.ts +156 -0
  130. package/src/ts/frameqr/index.ts +42 -0
  131. package/src/ts/frameqr/tables.ts +270 -0
  132. package/src/ts/image/binarizer.ts +270 -0
  133. package/src/ts/image/grid-sampler.ts +164 -0
  134. package/src/ts/image/index.ts +40 -0
  135. package/src/ts/image/luminance.ts +196 -0
  136. package/src/ts/image/perspective.ts +195 -0
  137. package/src/ts/index.d.ts +1 -1
  138. package/src/ts/index.ts +790 -0
  139. package/src/ts/micropdf417/compaction.ts +116 -0
  140. package/src/ts/micropdf417/decoder.ts +183 -0
  141. package/src/ts/micropdf417/detector.ts +149 -0
  142. package/src/ts/micropdf417/encoder.ts +209 -0
  143. package/src/ts/micropdf417/error-correction.ts +55 -0
  144. package/src/ts/micropdf417/index.ts +49 -0
  145. package/src/ts/micropdf417/tables.ts +184 -0
  146. package/src/ts/microqr/decoder.ts +245 -0
  147. package/src/ts/microqr/detector.ts +355 -0
  148. package/src/ts/microqr/encoder.ts +269 -0
  149. package/src/ts/microqr/index.ts +36 -0
  150. package/src/ts/microqr/tables.ts +316 -0
  151. package/src/ts/oned/addons.ts +420 -0
  152. package/src/ts/oned/index.ts +106 -0
  153. package/src/ts/oned/patterns.ts +384 -0
  154. package/src/ts/oned/reader.ts +1364 -0
  155. package/src/ts/oned/writers.ts +746 -0
  156. package/src/ts/pdf417/compaction.ts +298 -0
  157. package/src/ts/pdf417/decoder.ts +75 -0
  158. package/src/ts/pdf417/detector.ts +468 -0
  159. package/src/ts/pdf417/encoder.ts +91 -0
  160. package/src/ts/pdf417/error-correction.ts +47 -0
  161. package/src/ts/pdf417/index.ts +6 -0
  162. package/src/ts/pdf417/tables.ts +317 -0
  163. package/src/ts/qr/decoder.ts +575 -0
  164. package/src/ts/qr/detector.ts +630 -0
  165. package/src/ts/qr/encoder.ts +958 -0
  166. package/src/ts/qr/index.ts +44 -0
  167. package/src/ts/qr/tables.ts +737 -0
  168. package/src/ts/render/image-data.ts +125 -0
  169. package/src/ts/render/index.ts +130 -0
  170. package/src/ts/render/options.ts +160 -0
  171. package/src/ts/render/png.ts +295 -0
  172. package/src/ts/render/svg.ts +120 -0
  173. package/src/ts/render/webgl.ts +206 -0
  174. package/src/ts/render/webgpu.ts +369 -0
  175. package/src/ts/rmqr/decoder.ts +101 -0
  176. package/src/ts/rmqr/detector.ts +90 -0
  177. package/src/ts/rmqr/encoder.ts +172 -0
  178. package/src/ts/rmqr/index.ts +37 -0
  179. package/src/ts/rmqr/tables.ts +154 -0
@@ -27,7 +27,6 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /**
32
31
  * Aztec Rune decoder.
33
32
  *
@@ -39,74 +38,66 @@
39
38
  *
40
39
  * @module aztecrune/decoder
41
40
  */
42
-
43
41
  import { FormatError } from '../core/errors.js';
44
42
  import { rsDecode } from '../core/reed-solomon.js';
45
- import {
46
- AZTEC_RUNE_DATA_CODEWORDS,
47
- AZTEC_RUNE_DATA_POSITIONS,
48
- AZTEC_RUNE_ECC_CODEWORDS,
49
- AZTEC_RUNE_MASK,
50
- AZTEC_RUNE_SIZE,
51
- aztecRuneField,
52
- aztecRuneStructuralValue,
53
- } from './tables.js';
54
-
43
+ import { AZTEC_RUNE_DATA_POSITIONS, AZTEC_RUNE_ECC_CODEWORDS, AZTEC_RUNE_MASK, AZTEC_RUNE_SIZE, aztecRuneField, aztecRuneStructuralValue, } from './tables.js';
55
44
  /** @param {import('../core/bit-matrix.js').BitMatrix} source @param {number} turns */
56
45
  function rotateClockwise(source, turns) {
57
- let current = source.clone();
58
- for (let turn = 0; turn < turns; turn++) {
59
- const out = new source.constructor(current.height, current.width);
60
- for (let y = 0; y < current.height; y++) for (let x = 0; x < current.width; x++) {
61
- if (current.get(x, y)) out.set(current.height - 1 - y, x);
46
+ let current = source.clone();
47
+ for (let turn = 0; turn < turns; turn++) {
48
+ const out = new source.constructor(current.height, current.width);
49
+ for (let y = 0; y < current.height; y++)
50
+ for (let x = 0; x < current.width; x++) {
51
+ if (current.get(x, y))
52
+ out.set(current.height - 1 - y, x);
53
+ }
54
+ current = out;
62
55
  }
63
- current = out;
64
- }
65
- return current;
56
+ return current;
66
57
  }
67
-
68
58
  /** @param {import('../core/bit-matrix.js').BitMatrix} matrix */
69
59
  function invert(matrix) {
70
- const out = matrix.clone();
71
- for (let y = 0; y < out.height; y++) for (let x = 0; x < out.width; x++) out.flip(x, y);
72
- return out;
60
+ const out = matrix.clone();
61
+ for (let y = 0; y < out.height; y++)
62
+ for (let x = 0; x < out.width; x++)
63
+ out.flip(x, y);
64
+ return out;
73
65
  }
74
-
75
66
  /** @param {import('../core/bit-matrix.js').BitMatrix} matrix @param {boolean} inverted */
76
67
  function structureMatches(matrix, inverted) {
77
- for (let y = 0; y < AZTEC_RUNE_SIZE; y++) for (let x = 0; x < AZTEC_RUNE_SIZE; x++) {
78
- const expected = aztecRuneStructuralValue(x, y);
79
- if (expected === null) continue;
80
- if (matrix.get(x, y) !== (inverted ? !expected : expected)) return false;
81
- }
82
- return true;
68
+ for (let y = 0; y < AZTEC_RUNE_SIZE; y++)
69
+ for (let x = 0; x < AZTEC_RUNE_SIZE; x++) {
70
+ const expected = aztecRuneStructuralValue(x, y);
71
+ if (expected === null)
72
+ continue;
73
+ if (matrix.get(x, y) !== (inverted ? !expected : expected))
74
+ return false;
75
+ }
76
+ return true;
83
77
  }
84
-
85
78
  /** @param {import('../core/bit-matrix.js').BitMatrix} matrix @param {boolean} inverted */
86
79
  function readCodewords(matrix, inverted) {
87
- const words = new Array(2 + AZTEC_RUNE_ECC_CODEWORDS).fill(0);
88
- for (let at = 0; at < AZTEC_RUNE_DATA_POSITIONS.length; at++) {
89
- const [x, y] = AZTEC_RUNE_DATA_POSITIONS[at];
90
- const bit = matrix.get(x, y) !== inverted;
91
- words[at >>> 2] = (words[at >>> 2] << 1) | (bit ? 1 : 0);
92
- }
93
- return words.map((word) => word ^ AZTEC_RUNE_MASK);
80
+ const words = new Array(2 + AZTEC_RUNE_ECC_CODEWORDS).fill(0);
81
+ for (let at = 0; at < AZTEC_RUNE_DATA_POSITIONS.length; at++) {
82
+ const [x, y] = AZTEC_RUNE_DATA_POSITIONS[at];
83
+ const bit = matrix.get(x, y) !== inverted;
84
+ words[at >>> 2] = (words[at >>> 2] << 1) | (bit ? 1 : 0);
85
+ }
86
+ return words.map((word) => word ^ AZTEC_RUNE_MASK);
94
87
  }
95
-
96
88
  /** @param {number} value @param {boolean} inverted @param {number} rotation @param {number} corrections */
97
89
  function result(value, inverted, rotation, corrections) {
98
- return {
99
- format: 'aztecrune',
100
- value,
101
- text: String(value).padStart(3, '0'),
102
- bytes: Uint8Array.of(value),
103
- dimension: AZTEC_RUNE_SIZE,
104
- inverted,
105
- rotation,
106
- corrections,
107
- };
90
+ return {
91
+ format: 'aztecrune',
92
+ value,
93
+ text: String(value).padStart(3, '0'),
94
+ bytes: Uint8Array.of(value),
95
+ dimension: AZTEC_RUNE_SIZE,
96
+ inverted,
97
+ rotation,
98
+ corrections,
99
+ };
108
100
  }
109
-
110
101
  /**
111
102
  * Decode a square Aztec Rune matrix.
112
103
  *
@@ -116,40 +107,40 @@ function result(value, inverted, rotation, corrections) {
116
107
  * @throws {FormatError} For non-Rune geometry, structure or uncorrectable data.
117
108
  */
118
109
  export function decodeAztecRune(matrix, options = {}) {
119
- if (!matrix || matrix.width !== AZTEC_RUNE_SIZE || matrix.height !== AZTEC_RUNE_SIZE) {
120
- throw new FormatError(`Aztec Rune: expected an ${AZTEC_RUNE_SIZE}x${AZTEC_RUNE_SIZE} module matrix`);
121
- }
122
- const invertedModes = options.inverted === true ? [true] : options.inverted === false ? [false] : [false, true];
123
- const rotations = Number.isInteger(options.rotation)
124
- ? [((options.rotation % 360) + 360) % 360]
125
- : [0, 90, 180, 270];
126
-
127
- let checksumError = null;
128
- for (const requestedRotation of rotations) {
129
- if (requestedRotation % 90 !== 0) continue;
130
- // To canonicalize an input rotated clockwise by k degrees, rotate it
131
- // counter-clockwise by k. `turns` is the clockwise operation we apply.
132
- const turns = (4 - requestedRotation / 90) % 4;
133
- const canonicalRotation = requestedRotation;
134
- const rotated = turns === 0 ? matrix.clone() : rotateClockwise(matrix, turns);
135
- for (const inverted of invertedModes) {
136
- const canonical = inverted ? invert(rotated) : rotated;
137
- if (!structureMatches(canonical, false)) continue;
138
- const words = readCodewords(canonical, false);
139
- try {
140
- const corrections = rsDecode(words, AZTEC_RUNE_ECC_CODEWORDS, aztecRuneField(), 1);
141
- const value = (words[0] << 4) | words[1];
142
- return result(value, inverted, canonicalRotation, corrections);
143
- } catch (error) {
144
- checksumError = error;
145
- }
110
+ if (!matrix || matrix.width !== AZTEC_RUNE_SIZE || matrix.height !== AZTEC_RUNE_SIZE) {
111
+ throw new FormatError(`Aztec Rune: expected an ${AZTEC_RUNE_SIZE}x${AZTEC_RUNE_SIZE} module matrix`);
112
+ }
113
+ const invertedModes = options.inverted === true ? [true] : options.inverted === false ? [false] : [false, true];
114
+ const rotations = Number.isInteger(options.rotation)
115
+ ? [((options.rotation % 360) + 360) % 360]
116
+ : [0, 90, 180, 270];
117
+ let checksumError = null;
118
+ for (const requestedRotation of rotations) {
119
+ if (requestedRotation % 90 !== 0)
120
+ continue;
121
+ // To canonicalize an input rotated clockwise by k degrees, rotate it
122
+ // counter-clockwise by k. `turns` is the clockwise operation we apply.
123
+ const turns = (4 - requestedRotation / 90) % 4;
124
+ const canonicalRotation = requestedRotation;
125
+ const rotated = turns === 0 ? matrix.clone() : rotateClockwise(matrix, turns);
126
+ for (const inverted of invertedModes) {
127
+ const canonical = inverted ? invert(rotated) : rotated;
128
+ if (!structureMatches(canonical, false))
129
+ continue;
130
+ const words = readCodewords(canonical, false);
131
+ try {
132
+ const corrections = rsDecode(words, AZTEC_RUNE_ECC_CODEWORDS, aztecRuneField(), 1);
133
+ const value = (words[0] << 4) | words[1];
134
+ return result(value, inverted, canonicalRotation, corrections);
135
+ }
136
+ catch (error) {
137
+ checksumError = error;
138
+ }
139
+ }
140
+ }
141
+ if (checksumError) {
142
+ throw new FormatError(`Aztec Rune: Reed-Solomon check failed: ${checksumError.message}`);
146
143
  }
147
- }
148
-
149
- if (checksumError) {
150
- throw new FormatError(`Aztec Rune: Reed-Solomon check failed: ${checksumError.message}`);
151
- }
152
- throw new FormatError('Aztec Rune: structural pattern or orientation is invalid');
144
+ throw new FormatError('Aztec Rune: structural pattern or orientation is invalid');
153
145
  }
154
-
155
146
  export { readCodewords, structureMatches };
@@ -27,7 +27,6 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /**
32
31
  * Detector for Aztec Rune symbols.
33
32
  *
@@ -39,14 +38,11 @@
39
38
  *
40
39
  * @module aztecrune/detector
41
40
  */
42
-
43
41
  import { NotFoundError } from '../core/errors.js';
44
42
  import { BitMatrix } from '../core/bit-matrix.js';
45
43
  import { decodeAztecRune } from './decoder.js';
46
44
  import { AZTEC_RUNE_SIZE } from './tables.js';
47
-
48
45
  /** @typedef {{x:number,y:number}} Point */
49
-
50
46
  /**
51
47
  * Find connected components of a polarity. Components touching the image
52
48
  * border are ignored when they exceed the plausible module area; this avoids
@@ -54,73 +50,78 @@ import { AZTEC_RUNE_SIZE } from './tables.js';
54
50
  * Rune's isolated light centre module.
55
51
  */
56
52
  function components(image, value) {
57
- const width = image.width;
58
- const height = image.height;
59
- const seen = new Uint8Array(width * height);
60
- const limit = Math.max(64, Math.floor(width * height * 0.04));
61
- const found = [];
62
-
63
- for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
64
- const start = y * width + x;
65
- if (seen[start] || image.get(x, y) !== value) continue;
66
- const queue = [[x, y]];
67
- seen[start] = 1;
68
- let head = 0;
69
- let minX = x; let maxX = x; let minY = y; let maxY = y;
70
- let count = 0;
71
- let touchesBorder = false;
72
-
73
- while (head < queue.length) {
74
- const [px, py] = queue[head++];
75
- count++;
76
- minX = Math.min(minX, px); maxX = Math.max(maxX, px);
77
- minY = Math.min(minY, py); maxY = Math.max(maxY, py);
78
- if (px === 0 || py === 0 || px === width - 1 || py === height - 1) touchesBorder = true;
79
- for (const [nx, ny] of [[px - 1, py], [px + 1, py], [px, py - 1], [px, py + 1]]) {
80
- if (nx < 0 || ny < 0 || nx >= width || ny >= height) continue;
81
- const at = ny * width + nx;
82
- if (!seen[at] && image.get(nx, ny) === value) {
83
- seen[at] = 1;
84
- queue.push([nx, ny]);
53
+ const width = image.width;
54
+ const height = image.height;
55
+ const seen = new Uint8Array(width * height);
56
+ const limit = Math.max(64, Math.floor(width * height * 0.04));
57
+ const found = [];
58
+ for (let y = 0; y < height; y++)
59
+ for (let x = 0; x < width; x++) {
60
+ const start = y * width + x;
61
+ if (seen[start] || image.get(x, y) !== value)
62
+ continue;
63
+ const queue = [[x, y]];
64
+ seen[start] = 1;
65
+ let head = 0;
66
+ let minX = x;
67
+ let maxX = x;
68
+ let minY = y;
69
+ let maxY = y;
70
+ let count = 0;
71
+ let touchesBorder = false;
72
+ while (head < queue.length) {
73
+ const [px, py] = queue[head++];
74
+ count++;
75
+ minX = Math.min(minX, px);
76
+ maxX = Math.max(maxX, px);
77
+ minY = Math.min(minY, py);
78
+ maxY = Math.max(maxY, py);
79
+ if (px === 0 || py === 0 || px === width - 1 || py === height - 1)
80
+ touchesBorder = true;
81
+ for (const [nx, ny] of [[px - 1, py], [px + 1, py], [px, py - 1], [px, py + 1]]) {
82
+ if (nx < 0 || ny < 0 || nx >= width || ny >= height)
83
+ continue;
84
+ const at = ny * width + nx;
85
+ if (!seen[at] && image.get(nx, ny) === value) {
86
+ seen[at] = 1;
87
+ queue.push([nx, ny]);
88
+ }
89
+ }
90
+ }
91
+ const boxWidth = maxX - minX + 1;
92
+ const boxHeight = maxY - minY + 1;
93
+ if (count <= limit && !touchesBorder &&
94
+ Math.abs(boxWidth - boxHeight) <= Math.max(1, Math.ceil(Math.max(boxWidth, boxHeight) * 0.35)) &&
95
+ count >= boxWidth * boxHeight * 0.45) {
96
+ found.push({ x: (minX + maxX) / 2, y: (minY + maxY) / 2, width: boxWidth, height: boxHeight, count });
97
+ }
85
98
  }
86
- }
87
- }
88
-
89
- const boxWidth = maxX - minX + 1;
90
- const boxHeight = maxY - minY + 1;
91
- if (count <= limit && !touchesBorder &&
92
- Math.abs(boxWidth - boxHeight) <= Math.max(1, Math.ceil(Math.max(boxWidth, boxHeight) * 0.35)) &&
93
- count >= boxWidth * boxHeight * 0.45) {
94
- found.push({ x: (minX + maxX) / 2, y: (minY + maxY) / 2, width: boxWidth, height: boxHeight, count });
95
- }
96
- }
97
- return found.sort((a, b) => b.count - a.count);
99
+ return found.sort((a, b) => b.count - a.count);
98
100
  }
99
101
  /** @param {import('../core/bit-matrix.js').BitMatrix} image @param {Point} center @param {number} pitch */
100
102
  function sample(image, center, pitch) {
101
- const matrix = new BitMatrix(AZTEC_RUNE_SIZE);
102
- for (let y = 0; y < AZTEC_RUNE_SIZE; y++) for (let x = 0; x < AZTEC_RUNE_SIZE; x++) {
103
- const px = Math.round(center.x + (x - 5) * pitch);
104
- const py = Math.round(center.y + (y - 5) * pitch);
105
- if (px >= 0 && py >= 0 && px < image.width && py < image.height && image.get(px, py)) matrix.set(x, y);
106
- }
107
- return matrix;
103
+ const matrix = new BitMatrix(AZTEC_RUNE_SIZE);
104
+ for (let y = 0; y < AZTEC_RUNE_SIZE; y++)
105
+ for (let x = 0; x < AZTEC_RUNE_SIZE; x++) {
106
+ const px = Math.round(center.x + (x - 5) * pitch);
107
+ const py = Math.round(center.y + (y - 5) * pitch);
108
+ if (px >= 0 && py >= 0 && px < image.width && py < image.height && image.get(px, py))
109
+ matrix.set(x, y);
110
+ }
111
+ return matrix;
108
112
  }
109
-
110
113
  function corners(center, pitch) {
111
- const half = AZTEC_RUNE_SIZE * pitch / 2;
112
- return [
113
- { x: center.x - half, y: center.y - half },
114
- { x: center.x + half, y: center.y - half },
115
- { x: center.x + half, y: center.y + half },
116
- { x: center.x - half, y: center.y + half },
117
- ];
114
+ const half = AZTEC_RUNE_SIZE * pitch / 2;
115
+ return [
116
+ { x: center.x - half, y: center.y - half },
117
+ { x: center.x + half, y: center.y - half },
118
+ { x: center.x + half, y: center.y + half },
119
+ { x: center.x - half, y: center.y + half },
120
+ ];
118
121
  }
119
-
120
122
  function sameCandidate(left, right) {
121
- return Math.hypot(left.center.x - right.center.x, left.center.y - right.center.y) <= Math.max(left.moduleSize, right.moduleSize) * 2;
123
+ return Math.hypot(left.center.x - right.center.x, left.center.y - right.center.y) <= Math.max(left.moduleSize, right.moduleSize) * 2;
122
124
  }
123
-
124
125
  /**
125
126
  * Detect the most prominent Aztec Rune in a binarized image.
126
127
  *
@@ -128,39 +129,52 @@ function sameCandidate(left, right) {
128
129
  * @returns {{corners:Point[],dimension:11,moduleSize:number,matrix:BitMatrix,result:object}|null}
129
130
  */
130
131
  export function detectAztecRune(binaryImage) {
131
- if (!binaryImage || !binaryImage.width || !binaryImage.height) {
132
- throw new NotFoundError('detectAztecRune: no image supplied');
133
- }
134
- const candidates = [];
135
- for (const value of [true, false]) {
136
- for (const component of components(binaryImage, value)) {
137
- const pitch = (component.width + component.height) / 2;
138
- if (pitch < 0.8) continue;
139
- const matrix = sample(binaryImage, component, pitch);
140
- let decoded;
141
- try { decoded = decodeAztecRune(matrix); } catch { continue; }
142
- const candidate = {
143
- center: component,
144
- corners: corners(component, pitch),
145
- dimension: AZTEC_RUNE_SIZE,
146
- moduleSize: pitch,
147
- matrix,
148
- result: decoded,
149
- };
150
- if (!candidates.some((entry) => sameCandidate(entry, candidate))) candidates.push(candidate);
132
+ if (!binaryImage || !binaryImage.width || !binaryImage.height) {
133
+ throw new NotFoundError('detectAztecRune: no image supplied');
151
134
  }
152
- }
153
- candidates.sort((a, b) => b.moduleSize - a.moduleSize);
154
- const best = candidates[0];
155
- if (!best) return null;
156
- delete best.center;
157
- return best;
135
+ const candidates = [];
136
+ for (const value of [true, false]) {
137
+ for (const component of components(binaryImage, value)) {
138
+ const pitch = (component.width + component.height) / 2;
139
+ if (pitch < 0.8)
140
+ continue;
141
+ const matrix = sample(binaryImage, component, pitch);
142
+ let decoded;
143
+ try {
144
+ decoded = decodeAztecRune(matrix);
145
+ }
146
+ catch {
147
+ continue;
148
+ }
149
+ const candidate = {
150
+ center: component,
151
+ corners: corners(component, pitch),
152
+ dimension: AZTEC_RUNE_SIZE,
153
+ moduleSize: pitch,
154
+ matrix,
155
+ result: decoded,
156
+ };
157
+ if (!candidates.some((entry) => sameCandidate(entry, candidate)))
158
+ candidates.push(candidate);
159
+ }
160
+ }
161
+ candidates.sort((a, b) => b.moduleSize - a.moduleSize);
162
+ const best = candidates[0];
163
+ if (!best)
164
+ return null;
165
+ delete best.center;
166
+ return best;
158
167
  }
159
-
160
168
  /** Detect and decode one Aztec Rune, or return `null` when none is verified. */
161
169
  export function detectAndDecodeAztecRune(binaryImage) {
162
- let detection;
163
- try { detection = detectAztecRune(binaryImage); } catch { return null; }
164
- if (!detection) return null;
165
- return { ...detection.result, corners: detection.corners, moduleSize: detection.moduleSize };
170
+ let detection;
171
+ try {
172
+ detection = detectAztecRune(binaryImage);
173
+ }
174
+ catch {
175
+ return null;
176
+ }
177
+ if (!detection)
178
+ return null;
179
+ return { ...detection.result, corners: detection.corners, moduleSize: detection.moduleSize };
166
180
  }
@@ -27,71 +27,52 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
- /**
32
- * Aztec Rune encoder.
33
- *
34
- * A Rune carries exactly one byte. Numeric strings are accepted for convenient
35
- * human-readable input and are normalized to the canonical three-digit text;
36
- * binary callers can pass one byte in an ArrayBuffer or typed-array view.
37
- *
38
- * @module aztecrune/encoder
39
- */
40
-
41
- import { BitMatrix } from '../core/bit-matrix.js';
42
30
  import { EncodeError } from '../core/errors.js';
43
31
  import { rsEncode } from '../core/reed-solomon.js';
44
- import {
45
- AZTEC_RUNE_DATA_POSITIONS,
46
- AZTEC_RUNE_ECC_CODEWORDS,
47
- AZTEC_RUNE_MASK,
48
- AZTEC_RUNE_SIZE,
49
- aztecRuneField,
50
- buildAztecRuneStructure,
51
- } from './tables.js';
52
-
32
+ import { AZTEC_RUNE_DATA_POSITIONS, AZTEC_RUNE_ECC_CODEWORDS, AZTEC_RUNE_MASK, AZTEC_RUNE_SIZE, aztecRuneField, buildAztecRuneStructure, } from './tables.js';
53
33
  /** @param {unknown} value @returns {number} */
54
34
  export function normalizeAztecRuneValue(value) {
55
- if (typeof value === 'number') {
56
- if (Number.isInteger(value) && value >= 0 && value <= 255) return value;
57
- throw new EncodeError('Aztec Rune: numeric value must be an integer from 0 to 255');
58
- }
59
-
60
- if (typeof value === 'string') {
61
- if (!/^\d{1,3}$/.test(value)) throw new EncodeError('Aztec Rune: text input must contain one to three decimal digits');
62
- const numeric = Number(value);
63
- if (numeric > 255) throw new EncodeError('Aztec Rune: decimal value must be from 000 to 255');
64
- return numeric;
65
- }
66
-
67
- let bytes = null;
68
- if (value instanceof ArrayBuffer) bytes = new Uint8Array(value);
69
- else if (ArrayBuffer.isView(value)) bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
70
- if (bytes) {
71
- if (bytes.length !== 1) throw new EncodeError('Aztec Rune: binary input must contain exactly one byte');
72
- return bytes[0];
73
- }
74
- throw new EncodeError('Aztec Rune: expected a number, decimal string or one-byte binary value');
35
+ if (typeof value === 'number') {
36
+ if (Number.isInteger(value) && value >= 0 && value <= 255)
37
+ return value;
38
+ throw new EncodeError('Aztec Rune: numeric value must be an integer from 0 to 255');
39
+ }
40
+ if (typeof value === 'string') {
41
+ if (!/^\d{1,3}$/.test(value))
42
+ throw new EncodeError('Aztec Rune: text input must contain one to three decimal digits');
43
+ const numeric = Number(value);
44
+ if (numeric > 255)
45
+ throw new EncodeError('Aztec Rune: decimal value must be from 000 to 255');
46
+ return numeric;
47
+ }
48
+ let bytes = null;
49
+ if (value instanceof ArrayBuffer)
50
+ bytes = new Uint8Array(value);
51
+ else if (ArrayBuffer.isView(value))
52
+ bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
53
+ if (bytes) {
54
+ if (bytes.length !== 1)
55
+ throw new EncodeError('Aztec Rune: binary input must contain exactly one byte');
56
+ return bytes[0];
57
+ }
58
+ throw new EncodeError('Aztec Rune: expected a number, decimal string or one-byte binary value');
75
59
  }
76
-
77
60
  /** @param {number} value @returns {number[]} */
78
61
  function codewordsForValue(value) {
79
- const data = [value >>> 4, value & 0x0f];
80
- const parity = rsEncode(data, AZTEC_RUNE_ECC_CODEWORDS, aztecRuneField(), 1);
81
- return data.concat(parity).map((word) => word ^ AZTEC_RUNE_MASK);
62
+ const data = [value >>> 4, value & 0x0f];
63
+ const parity = rsEncode(data, AZTEC_RUNE_ECC_CODEWORDS, aztecRuneField(), 1);
64
+ return data.concat(parity).map((word) => word ^ AZTEC_RUNE_MASK);
82
65
  }
83
-
84
66
  /** @param {BitMatrix} matrix @param {number[]} codewords */
85
67
  function writeDataRing(matrix, codewords) {
86
- for (let word = 0; word < codewords.length; word++) {
87
- for (let bit = 0; bit < 4; bit++) {
88
- const at = word * 4 + bit;
89
- const [x, y] = AZTEC_RUNE_DATA_POSITIONS[at];
90
- matrix.setValue(x, y, ((codewords[word] >>> (3 - bit)) & 1) !== 0);
68
+ for (let word = 0; word < codewords.length; word++) {
69
+ for (let bit = 0; bit < 4; bit++) {
70
+ const at = word * 4 + bit;
71
+ const [x, y] = AZTEC_RUNE_DATA_POSITIONS[at];
72
+ matrix.setValue(x, y, ((codewords[word] >>> (3 - bit)) & 1) !== 0);
73
+ }
91
74
  }
92
- }
93
75
  }
94
-
95
76
  /**
96
77
  * Encode one byte as an Aztec Rune.
97
78
  *
@@ -102,20 +83,21 @@ function writeDataRing(matrix, codewords) {
102
83
  * }}
103
84
  */
104
85
  export function encodeAztecRune(value, options = {}) {
105
- const numeric = normalizeAztecRuneValue(value);
106
- if (options.inverted !== undefined && typeof options.inverted !== 'boolean') {
107
- throw new EncodeError('Aztec Rune: inverted must be boolean');
108
- }
109
- const inverted = options.inverted === true;
110
- const matrix = buildAztecRuneStructure();
111
- writeDataRing(matrix, codewordsForValue(numeric));
112
- if (inverted) {
113
- for (let y = 0; y < AZTEC_RUNE_SIZE; y++) for (let x = 0; x < AZTEC_RUNE_SIZE; x++) matrix.flip(x, y);
114
- }
115
- matrix.format = 'aztecrune';
116
- matrix.value = numeric;
117
- matrix.inverted = inverted;
118
- return matrix;
86
+ const numeric = normalizeAztecRuneValue(value);
87
+ if (options.inverted !== undefined && typeof options.inverted !== 'boolean') {
88
+ throw new EncodeError('Aztec Rune: inverted must be boolean');
89
+ }
90
+ const inverted = options.inverted === true;
91
+ const matrix = buildAztecRuneStructure();
92
+ writeDataRing(matrix, codewordsForValue(numeric));
93
+ if (inverted) {
94
+ for (let y = 0; y < AZTEC_RUNE_SIZE; y++)
95
+ for (let x = 0; x < AZTEC_RUNE_SIZE; x++)
96
+ matrix.flip(x, y);
97
+ }
98
+ matrix.format = 'aztecrune';
99
+ matrix.value = numeric;
100
+ matrix.inverted = inverted;
101
+ return matrix;
119
102
  }
120
-
121
103
  export { codewordsForValue };
@@ -27,23 +27,8 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /** Aztec Rune entry points. @module aztecrune */
32
-
33
31
  export { encodeAztecRune, normalizeAztecRuneValue } from './encoder.js';
34
32
  export { decodeAztecRune } from './decoder.js';
35
33
  export { detectAztecRune, detectAndDecodeAztecRune } from './detector.js';
36
- export {
37
- AZTEC_RUNE_SIZE,
38
- AZTEC_RUNE_DATA_BITS,
39
- AZTEC_RUNE_WORD_SIZE,
40
- AZTEC_RUNE_DATA_CODEWORDS,
41
- AZTEC_RUNE_ECC_CODEWORDS,
42
- AZTEC_RUNE_TOTAL_CODEWORDS,
43
- AZTEC_RUNE_MASK,
44
- AZTEC_RUNE_DATA_POSITIONS,
45
- aztecRuneStructuralValue,
46
- buildAztecRuneStructure,
47
- aztecRuneField,
48
- validateAztecRuneTables,
49
- } from './tables.js';
34
+ export { AZTEC_RUNE_SIZE, AZTEC_RUNE_DATA_BITS, AZTEC_RUNE_WORD_SIZE, AZTEC_RUNE_DATA_CODEWORDS, AZTEC_RUNE_ECC_CODEWORDS, AZTEC_RUNE_TOTAL_CODEWORDS, AZTEC_RUNE_MASK, AZTEC_RUNE_DATA_POSITIONS, aztecRuneStructuralValue, buildAztecRuneStructure, aztecRuneField, validateAztecRuneTables, } from './tables.js';