@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
  * Greyscale to black-and-white.
33
32
  *
@@ -46,17 +45,13 @@
46
45
  *
47
46
  * @module image/binarizer
48
47
  */
49
-
50
48
  import { BitMatrix } from '../core/bit-matrix.js';
51
49
  import { NotFoundError } from '../core/errors.js';
52
-
53
50
  /** Side of a block, in pixels. */
54
51
  const BLOCK = 8;
55
52
  const BLOCK_SHIFT = 3;
56
-
57
53
  /** Below this spread, a block is treated as uniform rather than as edges. */
58
54
  const MIN_DYNAMIC_RANGE = 24;
59
-
60
55
  /**
61
56
  * One threshold for the entire image, chosen from the luminance histogram.
62
57
  *
@@ -68,74 +63,70 @@ const MIN_DYNAMIC_RANGE = 24;
68
63
  * @returns {BitMatrix} Set bit = dark module.
69
64
  */
70
65
  export function binarizeGlobal(source) {
71
- const { grey, width, height } = source;
72
- const buckets = new Int32Array(32);
73
- for (let i = 0; i < grey.length; i++) buckets[grey[i] >> 3]++;
74
-
75
- const threshold = pickThreshold(buckets);
76
- const out = new BitMatrix(width, height);
77
- for (let y = 0; y < height; y++) {
78
- const base = y * width;
79
- for (let x = 0; x < width; x++) {
80
- if (grey[base + x] < threshold) out.set(x, y);
66
+ const { grey, width, height } = source;
67
+ const buckets = new Int32Array(32);
68
+ for (let i = 0; i < grey.length; i++)
69
+ buckets[grey[i] >> 3]++;
70
+ const threshold = pickThreshold(buckets);
71
+ const out = new BitMatrix(width, height);
72
+ for (let y = 0; y < height; y++) {
73
+ const base = y * width;
74
+ for (let x = 0; x < width; x++) {
75
+ if (grey[base + x] < threshold)
76
+ out.set(x, y);
77
+ }
81
78
  }
82
- }
83
- return out;
79
+ return out;
84
80
  }
85
-
86
81
  /**
87
82
  * @param {Int32Array} buckets
88
83
  * @returns {number} Threshold in 0-255.
89
84
  */
90
85
  function pickThreshold(buckets) {
91
- const n = buckets.length;
92
-
93
- let firstPeak = 0, firstPeakSize = 0;
94
- for (let i = 0; i < n; i++) {
95
- if (buckets[i] > firstPeakSize) {
96
- firstPeakSize = buckets[i];
97
- firstPeak = i;
86
+ const n = buckets.length;
87
+ let firstPeak = 0, firstPeakSize = 0;
88
+ for (let i = 0; i < n; i++) {
89
+ if (buckets[i] > firstPeakSize) {
90
+ firstPeakSize = buckets[i];
91
+ firstPeak = i;
92
+ }
98
93
  }
99
- }
100
-
101
- // Score candidates by population scaled by squared distance from the first
102
- // peak: the second peak must be both populous and clearly separated.
103
- let secondPeak = 0, secondScore = 0;
104
- for (let i = 0; i < n; i++) {
105
- const d = i - firstPeak;
106
- const score = buckets[i] * d * d;
107
- if (score > secondScore) {
108
- secondScore = score;
109
- secondPeak = i;
94
+ // Score candidates by population scaled by squared distance from the first
95
+ // peak: the second peak must be both populous and clearly separated.
96
+ let secondPeak = 0, secondScore = 0;
97
+ for (let i = 0; i < n; i++) {
98
+ const d = i - firstPeak;
99
+ const score = buckets[i] * d * d;
100
+ if (score > secondScore) {
101
+ secondScore = score;
102
+ secondPeak = i;
103
+ }
104
+ }
105
+ let low = Math.min(firstPeak, secondPeak);
106
+ let high = Math.max(firstPeak, secondPeak);
107
+ if (high - low <= n >> 4) {
108
+ // Effectively unimodal — a blank region, or an image with no ink. Fall
109
+ // back to the midpoint of the occupied range rather than inventing edges.
110
+ let lo = 0, hi = n - 1;
111
+ while (lo < n && buckets[lo] === 0)
112
+ lo++;
113
+ while (hi > 0 && buckets[hi] === 0)
114
+ hi--;
115
+ return (((lo + hi) >> 1) << 3) + 4;
110
116
  }
111
- }
112
-
113
- let low = Math.min(firstPeak, secondPeak);
114
- let high = Math.max(firstPeak, secondPeak);
115
-
116
- if (high - low <= n >> 4) {
117
- // Effectively unimodal a blank region, or an image with no ink. Fall
118
- // back to the midpoint of the occupied range rather than inventing edges.
119
- let lo = 0, hi = n - 1;
120
- while (lo < n && buckets[lo] === 0) lo++;
121
- while (hi > 0 && buckets[hi] === 0) hi--;
122
- return (((lo + hi) >> 1) << 3) + 4;
123
- }
124
-
125
- // Deepest valley between the peaks, biased toward the middle.
126
- let valley = low, valleyScore = -1;
127
- for (let i = low + 1; i < high; i++) {
128
- const fromLow = i - low;
129
- const fromHigh = high - i;
130
- const score = fromLow * fromHigh * (firstPeakSize - buckets[i]);
131
- if (score > valleyScore) {
132
- valleyScore = score;
133
- valley = i;
117
+ // Deepest valley between the peaks, biased toward the middle.
118
+ let valley = low, valleyScore = -1;
119
+ for (let i = low + 1; i < high; i++) {
120
+ const fromLow = i - low;
121
+ const fromHigh = high - i;
122
+ const score = fromLow * fromHigh * (firstPeakSize - buckets[i]);
123
+ if (score > valleyScore) {
124
+ valleyScore = score;
125
+ valley = i;
126
+ }
134
127
  }
135
- }
136
- return (valley << 3) + 4;
128
+ return (valley << 3) + 4;
137
129
  }
138
-
139
130
  /**
140
131
  * Locally adaptive thresholding.
141
132
  *
@@ -153,100 +144,92 @@ function pickThreshold(buckets) {
153
144
  * @returns {BitMatrix}
154
145
  */
155
146
  export function binarizeHybrid(source) {
156
- const { grey, width, height } = source;
157
-
158
- // Too small to block up meaningfully; the global pass is strictly better.
159
- if (width < BLOCK * 5 || height < BLOCK * 5) return binarizeGlobal(source);
160
-
161
- const bw = (width + BLOCK - 1) >> BLOCK_SHIFT;
162
- const bh = (height + BLOCK - 1) >> BLOCK_SHIFT;
163
- const means = new Int32Array(bw * bh);
164
- const ranges = new Int32Array(bw * bh);
165
-
166
- for (let by = 0; by < bh; by++) {
167
- const y0 = by << BLOCK_SHIFT;
168
- const y1 = Math.min(y0 + BLOCK, height);
169
- for (let bx = 0; bx < bw; bx++) {
170
- const x0 = bx << BLOCK_SHIFT;
171
- const x1 = Math.min(x0 + BLOCK, width);
172
-
173
- let sum = 0, min = 255, max = 0, count = 0;
174
- for (let y = y0; y < y1; y++) {
175
- const base = y * width;
176
- for (let x = x0; x < x1; x++) {
177
- const v = grey[base + x];
178
- sum += v;
179
- if (v < min) min = v;
180
- if (v > max) max = v;
181
- count++;
147
+ const { grey, width, height } = source;
148
+ // Too small to block up meaningfully; the global pass is strictly better.
149
+ if (width < BLOCK * 5 || height < BLOCK * 5)
150
+ return binarizeGlobal(source);
151
+ const bw = (width + BLOCK - 1) >> BLOCK_SHIFT;
152
+ const bh = (height + BLOCK - 1) >> BLOCK_SHIFT;
153
+ const means = new Int32Array(bw * bh);
154
+ const ranges = new Int32Array(bw * bh);
155
+ for (let by = 0; by < bh; by++) {
156
+ const y0 = by << BLOCK_SHIFT;
157
+ const y1 = Math.min(y0 + BLOCK, height);
158
+ for (let bx = 0; bx < bw; bx++) {
159
+ const x0 = bx << BLOCK_SHIFT;
160
+ const x1 = Math.min(x0 + BLOCK, width);
161
+ let sum = 0, min = 255, max = 0, count = 0;
162
+ for (let y = y0; y < y1; y++) {
163
+ const base = y * width;
164
+ for (let x = x0; x < x1; x++) {
165
+ const v = grey[base + x];
166
+ sum += v;
167
+ if (v < min)
168
+ min = v;
169
+ if (v > max)
170
+ max = v;
171
+ count++;
172
+ }
173
+ }
174
+ const idx = by * bw + bx;
175
+ means[idx] = count ? (sum / count) | 0 : 128;
176
+ ranges[idx] = max - min;
182
177
  }
183
- }
184
- const idx = by * bw + bx;
185
- means[idx] = count ? (sum / count) | 0 : 128;
186
- ranges[idx] = max - min;
187
- }
188
- }
189
-
190
- // Flat blocks adopt a threshold from context. Looking left and up is enough
191
- // because those neighbours are already resolved, and it makes the pass
192
- // single-shot rather than iterative.
193
- for (let by = 0; by < bh; by++) {
194
- for (let bx = 0; bx < bw; bx++) {
195
- const idx = by * bw + bx;
196
- if (ranges[idx] >= MIN_DYNAMIC_RANGE) continue;
197
-
198
- let inherited = means[idx];
199
- if (bx > 0 && by > 0) {
200
- const neighbours = [
201
- means[idx - 1],
202
- means[idx - bw],
203
- means[idx - bw - 1],
204
- ];
205
- const avg = (neighbours[0] + neighbours[1] + neighbours[2]) / 3;
206
- // A flat block darker than its surroundings is ink; lighter is paper.
207
- // Either way the local minimum is the safer threshold than the mean.
208
- inherited = Math.min(avg, means[idx]);
209
- }
210
- means[idx] = inherited | 0;
211
178
  }
212
- }
213
-
214
- const out = new BitMatrix(width, height);
215
- const R = 2; // 5x5 block window
216
-
217
- for (let by = 0; by < bh; by++) {
218
- const y0 = by << BLOCK_SHIFT;
219
- const y1 = Math.min(y0 + BLOCK, height);
220
- const byLo = Math.max(0, by - R);
221
- const byHi = Math.min(bh - 1, by + R);
222
-
223
- for (let bx = 0; bx < bw; bx++) {
224
- const bxLo = Math.max(0, bx - R);
225
- const bxHi = Math.min(bw - 1, bx + R);
226
-
227
- let sum = 0, count = 0;
228
- for (let ny = byLo; ny <= byHi; ny++) {
229
- for (let nx = bxLo; nx <= bxHi; nx++) {
230
- sum += means[ny * bw + nx];
231
- count++;
179
+ // Flat blocks adopt a threshold from context. Looking left and up is enough
180
+ // because those neighbours are already resolved, and it makes the pass
181
+ // single-shot rather than iterative.
182
+ for (let by = 0; by < bh; by++) {
183
+ for (let bx = 0; bx < bw; bx++) {
184
+ const idx = by * bw + bx;
185
+ if (ranges[idx] >= MIN_DYNAMIC_RANGE)
186
+ continue;
187
+ let inherited = means[idx];
188
+ if (bx > 0 && by > 0) {
189
+ const neighbours = [
190
+ means[idx - 1],
191
+ means[idx - bw],
192
+ means[idx - bw - 1],
193
+ ];
194
+ const avg = (neighbours[0] + neighbours[1] + neighbours[2]) / 3;
195
+ // A flat block darker than its surroundings is ink; lighter is paper.
196
+ // Either way the local minimum is the safer threshold than the mean.
197
+ inherited = Math.min(avg, means[idx]);
198
+ }
199
+ means[idx] = inherited | 0;
232
200
  }
233
- }
234
- const threshold = sum / count;
235
-
236
- const x0 = bx << BLOCK_SHIFT;
237
- const x1 = Math.min(x0 + BLOCK, width);
238
- for (let y = y0; y < y1; y++) {
239
- const base = y * width;
240
- for (let x = x0; x < x1; x++) {
241
- if (grey[base + x] < threshold) out.set(x, y);
201
+ }
202
+ const out = new BitMatrix(width, height);
203
+ const R = 2; // 5x5 block window
204
+ for (let by = 0; by < bh; by++) {
205
+ const y0 = by << BLOCK_SHIFT;
206
+ const y1 = Math.min(y0 + BLOCK, height);
207
+ const byLo = Math.max(0, by - R);
208
+ const byHi = Math.min(bh - 1, by + R);
209
+ for (let bx = 0; bx < bw; bx++) {
210
+ const bxLo = Math.max(0, bx - R);
211
+ const bxHi = Math.min(bw - 1, bx + R);
212
+ let sum = 0, count = 0;
213
+ for (let ny = byLo; ny <= byHi; ny++) {
214
+ for (let nx = bxLo; nx <= bxHi; nx++) {
215
+ sum += means[ny * bw + nx];
216
+ count++;
217
+ }
218
+ }
219
+ const threshold = sum / count;
220
+ const x0 = bx << BLOCK_SHIFT;
221
+ const x1 = Math.min(x0 + BLOCK, width);
222
+ for (let y = y0; y < y1; y++) {
223
+ const base = y * width;
224
+ for (let x = x0; x < x1; x++) {
225
+ if (grey[base + x] < threshold)
226
+ out.set(x, y);
227
+ }
228
+ }
242
229
  }
243
- }
244
230
  }
245
- }
246
-
247
- return out;
231
+ return out;
248
232
  }
249
-
250
233
  /**
251
234
  * Binarize with the named strategy.
252
235
  *
@@ -255,16 +238,17 @@ export function binarizeHybrid(source) {
255
238
  * @returns {BitMatrix}
256
239
  */
257
240
  export function binarize(source, strategy = 'auto') {
258
- if (!source || !source.grey) throw new NotFoundError('binarize: no luminance source');
259
- switch (strategy) {
260
- case 'global': return binarizeGlobal(source);
261
- case 'hybrid': return binarizeHybrid(source);
262
- case 'auto':
263
- // Small images are almost always generated rather than photographed.
264
- return source.width * source.height < 200 * 200
265
- ? binarizeGlobal(source)
266
- : binarizeHybrid(source);
267
- default:
268
- throw new NotFoundError(`Unknown binarizer strategy: ${strategy}`);
269
- }
241
+ if (!source || !source.grey)
242
+ throw new NotFoundError('binarize: no luminance source');
243
+ switch (strategy) {
244
+ case 'global': return binarizeGlobal(source);
245
+ case 'hybrid': return binarizeHybrid(source);
246
+ case 'auto':
247
+ // Small images are almost always generated rather than photographed.
248
+ return source.width * source.height < 200 * 200
249
+ ? binarizeGlobal(source)
250
+ : binarizeHybrid(source);
251
+ default:
252
+ throw new NotFoundError(`Unknown binarizer strategy: ${strategy}`);
253
+ }
270
254
  }
@@ -27,7 +27,6 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /**
32
31
  * Resample a distorted symbol in the image into an upright module grid.
33
32
  *
@@ -38,11 +37,9 @@
38
37
  *
39
38
  * @module image/grid-sampler
40
39
  */
41
-
42
40
  import { BitMatrix } from '../core/bit-matrix.js';
43
41
  import { NotFoundError } from '../core/errors.js';
44
42
  import { PerspectiveTransform } from './perspective.js';
45
-
46
43
  /**
47
44
  * Sample a `dimension` x `dimension` grid (or `width` x `height`).
48
45
  *
@@ -54,33 +51,28 @@ import { PerspectiveTransform } from './perspective.js';
54
51
  * @throws {NotFoundError} If the grid falls outside the image.
55
52
  */
56
53
  export function sampleGrid(image, width, height, transform) {
57
- const out = new BitMatrix(width, height);
58
- const points = new Float32Array(width * 2);
59
-
60
- for (let y = 0; y < height; y++) {
61
- // Module centres: offset by half a module in both axes.
62
- const gridY = y + 0.5;
63
- for (let x = 0; x < width; x++) {
64
- points[x * 2] = x + 0.5;
65
- points[x * 2 + 1] = gridY;
66
- }
67
- transform.transform(points);
68
-
69
- for (let x = 0; x < width; x++) {
70
- const px = points[x * 2] | 0;
71
- const py = points[x * 2 + 1] | 0;
72
- if (px < 0 || py < 0 || px >= image.width || py >= image.height) {
73
- throw new NotFoundError(
74
- `Sampling grid escapes the image at module (${x}, ${y})`
75
- );
76
- }
77
- if (image.get(px, py)) out.set(x, y);
54
+ const out = new BitMatrix(width, height);
55
+ const points = new Float32Array(width * 2);
56
+ for (let y = 0; y < height; y++) {
57
+ // Module centres: offset by half a module in both axes.
58
+ const gridY = y + 0.5;
59
+ for (let x = 0; x < width; x++) {
60
+ points[x * 2] = x + 0.5;
61
+ points[x * 2 + 1] = gridY;
62
+ }
63
+ transform.transform(points);
64
+ for (let x = 0; x < width; x++) {
65
+ const px = points[x * 2] | 0;
66
+ const py = points[x * 2 + 1] | 0;
67
+ if (px < 0 || py < 0 || px >= image.width || py >= image.height) {
68
+ throw new NotFoundError(`Sampling grid escapes the image at module (${x}, ${y})`);
69
+ }
70
+ if (image.get(px, py))
71
+ out.set(x, y);
72
+ }
78
73
  }
79
- }
80
-
81
- return out;
74
+ return out;
82
75
  }
83
-
84
76
  /**
85
77
  * Sample with a 3x3 majority vote per module.
86
78
  *
@@ -95,48 +87,44 @@ export function sampleGrid(image, width, height, transform) {
95
87
  * @returns {BitMatrix}
96
88
  */
97
89
  export function sampleGridVoting(image, width, height, transform) {
98
- const out = new BitMatrix(width, height);
99
-
100
- // Spacing between module centres, measured in image pixels, so the vote
101
- // spreads across the module rather than a fixed pixel radius that would be
102
- // meaningless at a different scale.
103
- const p0 = transform.transformPoint(0.5, 0.5);
104
- const p1 = transform.transformPoint(1.5, 0.5);
105
- const p2 = transform.transformPoint(0.5, 1.5);
106
- const stepX = Math.hypot(p1.x - p0.x, p1.y - p0.y);
107
- const stepY = Math.hypot(p2.x - p0.x, p2.y - p0.y);
108
- const rx = Math.max(1, Math.round(stepX / 4));
109
- const ry = Math.max(1, Math.round(stepY / 4));
110
-
111
- for (let y = 0; y < height; y++) {
112
- for (let x = 0; x < width; x++) {
113
- const c = transform.transformPoint(x + 0.5, y + 0.5);
114
- const cx = c.x | 0;
115
- const cy = c.y | 0;
116
- if (cx < 0 || cy < 0 || cx >= image.width || cy >= image.height) {
117
- throw new NotFoundError(
118
- `Sampling grid escapes the image at module (${x}, ${y})`
119
- );
120
- }
121
-
122
- let dark = 0;
123
- let total = 0;
124
- for (let dy = -1; dy <= 1; dy++) {
125
- for (let dx = -1; dx <= 1; dx++) {
126
- const sx = cx + dx * rx;
127
- const sy = cy + dy * ry;
128
- if (sx < 0 || sy < 0 || sx >= image.width || sy >= image.height) continue;
129
- total++;
130
- if (image.get(sx, sy)) dark++;
90
+ const out = new BitMatrix(width, height);
91
+ // Spacing between module centres, measured in image pixels, so the vote
92
+ // spreads across the module rather than a fixed pixel radius that would be
93
+ // meaningless at a different scale.
94
+ const p0 = transform.transformPoint(0.5, 0.5);
95
+ const p1 = transform.transformPoint(1.5, 0.5);
96
+ const p2 = transform.transformPoint(0.5, 1.5);
97
+ const stepX = Math.hypot(p1.x - p0.x, p1.y - p0.y);
98
+ const stepY = Math.hypot(p2.x - p0.x, p2.y - p0.y);
99
+ const rx = Math.max(1, Math.round(stepX / 4));
100
+ const ry = Math.max(1, Math.round(stepY / 4));
101
+ for (let y = 0; y < height; y++) {
102
+ for (let x = 0; x < width; x++) {
103
+ const c = transform.transformPoint(x + 0.5, y + 0.5);
104
+ const cx = c.x | 0;
105
+ const cy = c.y | 0;
106
+ if (cx < 0 || cy < 0 || cx >= image.width || cy >= image.height) {
107
+ throw new NotFoundError(`Sampling grid escapes the image at module (${x}, ${y})`);
108
+ }
109
+ let dark = 0;
110
+ let total = 0;
111
+ for (let dy = -1; dy <= 1; dy++) {
112
+ for (let dx = -1; dx <= 1; dx++) {
113
+ const sx = cx + dx * rx;
114
+ const sy = cy + dy * ry;
115
+ if (sx < 0 || sy < 0 || sx >= image.width || sy >= image.height)
116
+ continue;
117
+ total++;
118
+ if (image.get(sx, sy))
119
+ dark++;
120
+ }
121
+ }
122
+ if (total > 0 && dark * 2 > total)
123
+ out.set(x, y);
131
124
  }
132
- }
133
- if (total > 0 && dark * 2 > total) out.set(x, y);
134
125
  }
135
- }
136
-
137
- return out;
126
+ return out;
138
127
  }
139
-
140
128
  /**
141
129
  * Build the transform for a symbol whose four corners are known, and sample it.
142
130
  *
@@ -149,16 +137,12 @@ export function sampleGridVoting(image, width, height, transform) {
149
137
  * @returns {BitMatrix}
150
138
  */
151
139
  export function sampleQuad(image, dimension, corners, voting = false) {
152
- if (corners.length !== 4) throw new NotFoundError('sampleQuad needs exactly 4 corners');
153
- const [tl, tr, br, bl] = corners;
154
- const d = dimension;
155
-
156
- const transform = PerspectiveTransform.quadToQuad(
157
- 0, 0, d, 0, d, d, 0, d,
158
- tl.x, tl.y, tr.x, tr.y, br.x, br.y, bl.x, bl.y
159
- );
160
-
161
- return voting
162
- ? sampleGridVoting(image, d, d, transform)
163
- : sampleGrid(image, d, d, transform);
140
+ if (corners.length !== 4)
141
+ throw new NotFoundError('sampleQuad needs exactly 4 corners');
142
+ const [tl, tr, br, bl] = corners;
143
+ const d = dimension;
144
+ const transform = PerspectiveTransform.quadToQuad(0, 0, d, 0, d, d, 0, d, tl.x, tl.y, tr.x, tr.y, br.x, br.y, bl.x, bl.y);
145
+ return voting
146
+ ? sampleGridVoting(image, d, d, transform)
147
+ : sampleGrid(image, d, d, transform);
164
148
  }
@@ -27,13 +27,11 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /**
32
31
  * Image pipeline, re-exported.
33
32
  *
34
33
  * @module image
35
34
  */
36
-
37
35
  export { LuminanceSource } from './luminance.js';
38
36
  export { binarize, binarizeGlobal, binarizeHybrid } from './binarizer.js';
39
37
  export { PerspectiveTransform } from './perspective.js';