@sythos/js_barcode_universal 1.5.8 → 1.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/LICENSE +5 -4
  2. package/NOTICE.md +2 -2
  3. package/README.md +61 -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,59 +27,49 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /** Compact PDF417 (truncated PDF417) encoder. @module compactpdf417/encoder */
32
-
33
31
  import { BitMatrix } from '../core/bit-matrix.js';
34
32
  import { EncodeError } from '../core/errors.js';
35
33
  import { compactPdf417 } from '../pdf417/compaction.js';
36
34
  import { pdf417ErrorCorrection, pdf417EccLength } from '../pdf417/error-correction.js';
37
35
  import { pdf417PatternForCodeword } from '../pdf417/tables.js';
38
- import {
39
- COMPACT_PDF417_START,
40
- compactPdf417Indicators,
41
- compactPdf417Width,
42
- validateCompactPdf417Options,
43
- } from './tables.js';
44
-
36
+ import { COMPACT_PDF417_START, compactPdf417Indicators, compactPdf417Width, validateCompactPdf417Options, } from './tables.js';
45
37
  function appendWidths(matrix, y, x, sequence, height) {
46
- let dark = true;
47
- for (const digit of sequence) {
48
- const width = digit.charCodeAt(0) - 48;
49
- if (!Number.isInteger(width) || width < 1 || width > 8) {
50
- throw new EncodeError('Compact PDF417: invalid module-width sequence');
38
+ let dark = true;
39
+ for (const digit of sequence) {
40
+ const width = digit.charCodeAt(0) - 48;
41
+ if (!Number.isInteger(width) || width < 1 || width > 8) {
42
+ throw new EncodeError('Compact PDF417: invalid module-width sequence');
43
+ }
44
+ if (dark)
45
+ matrix.setRegion(x, y, width, height);
46
+ x += width;
47
+ dark = !dark;
51
48
  }
52
- if (dark) matrix.setRegion(x, y, width, height);
53
- x += width;
54
- dark = !dark;
55
- }
56
- return x;
49
+ return x;
57
50
  }
58
-
59
51
  function patternSequence(pattern) {
60
- return pattern.toString(2).padStart(17, '0').replace(/0+|1+/g, (run) => String(run.length));
52
+ return pattern.toString(2).padStart(17, '0').replace(/0+|1+/g, (run) => String(run.length));
61
53
  }
62
-
63
54
  function dimensions(needed, level, options, rowHeight) {
64
- const ecc = pdf417EccLength(level);
65
- let best = null;
66
- for (let rows = options.rows ?? 3; rows <= (options.rows ?? 90); rows++) {
67
- for (let columns = options.columns ?? 1; columns <= (options.columns ?? 30); columns++) {
68
- if (rows * columns > 928 || rows * columns - ecc < needed) continue;
69
- const ratio = compactPdf417Width(columns) / (rows * rowHeight);
70
- const score = (rows * columns - ecc - needed) * 10 +
71
- Math.abs(ratio - (options.aspectRatio ?? 3));
72
- if (!best || score < best.score) best = { rows, columns, score };
55
+ const ecc = pdf417EccLength(level);
56
+ let best = null;
57
+ for (let rows = options.rows ?? 3; rows <= (options.rows ?? 90); rows++) {
58
+ for (let columns = options.columns ?? 1; columns <= (options.columns ?? 30); columns++) {
59
+ if (rows * columns > 928 || rows * columns - ecc < needed)
60
+ continue;
61
+ const ratio = compactPdf417Width(columns) / (rows * rowHeight);
62
+ const score = (rows * columns - ecc - needed) * 10 +
63
+ Math.abs(ratio - (options.aspectRatio ?? 3));
64
+ if (!best || score < best.score)
65
+ best = { rows, columns, score };
66
+ }
73
67
  }
74
- }
75
- if (!best) {
76
- throw new EncodeError(
77
- 'Compact PDF417: payload does not fit the requested dimensions and error correction level'
78
- );
79
- }
80
- return best;
68
+ if (!best) {
69
+ throw new EncodeError('Compact PDF417: payload does not fit the requested dimensions and error correction level');
70
+ }
71
+ return best;
81
72
  }
82
-
83
73
  /**
84
74
  * Encode Compact PDF417.
85
75
  *
@@ -93,48 +83,45 @@ function dimensions(needed, level, options, rowHeight) {
93
83
  * @returns {import('../core/bit-matrix.js').BitMatrix}
94
84
  */
95
85
  export function encodeCompactPDF417(value, options = {}) {
96
- const rowHeight = validateCompactPdf417Options(options);
97
- const level = options.eccLevel ?? 2;
98
- if (!Number.isInteger(level) || level < 0 || level > 8) {
99
- throw new EncodeError('Compact PDF417: eccLevel must be an integer in 0..8');
100
- }
101
-
102
- const payload = compactPdf417(value, { compaction: options.compaction, charset: options.charset });
103
- const { rows, columns } = dimensions(payload.length + 1, level, options, rowHeight);
104
- const eccLength = pdf417EccLength(level);
105
- const dataLength = rows * columns - eccLength;
106
- const data = [dataLength, ...payload];
107
- while (data.length < dataLength) data.push(900);
108
- const codewords = data.concat(pdf417ErrorCorrection(data, level));
109
-
110
- const matrix = new BitMatrix(compactPdf417Width(columns), rows * rowHeight);
111
- for (let row = 0; row < rows; row++) {
112
- const y = row * rowHeight;
113
- const cluster = (row % 3) * 3;
114
- let x = appendWidths(matrix, y, 0, COMPACT_PDF417_START, rowHeight);
115
- const left = compactPdf417Indicators(row, rows, columns, level);
116
- x = appendWidths(matrix, y, x, patternSequence(pdf417PatternForCodeword(left, cluster)), rowHeight);
117
- for (let column = 0; column < columns; column++) {
118
- const codeword = codewords[row * columns + column];
119
- x = appendWidths(matrix, y, x,
120
- patternSequence(pdf417PatternForCodeword(codeword, cluster)), rowHeight);
86
+ const rowHeight = validateCompactPdf417Options(options);
87
+ const level = options.eccLevel ?? 2;
88
+ if (!Number.isInteger(level) || level < 0 || level > 8) {
89
+ throw new EncodeError('Compact PDF417: eccLevel must be an integer in 0..8');
90
+ }
91
+ const payload = compactPdf417(value, { compaction: options.compaction, charset: options.charset });
92
+ const { rows, columns } = dimensions(payload.length + 1, level, options, rowHeight);
93
+ const eccLength = pdf417EccLength(level);
94
+ const dataLength = rows * columns - eccLength;
95
+ const data = [dataLength, ...payload];
96
+ while (data.length < dataLength)
97
+ data.push(900);
98
+ const codewords = data.concat(pdf417ErrorCorrection(data, level));
99
+ const matrix = new BitMatrix(compactPdf417Width(columns), rows * rowHeight);
100
+ for (let row = 0; row < rows; row++) {
101
+ const y = row * rowHeight;
102
+ const cluster = (row % 3) * 3;
103
+ let x = appendWidths(matrix, y, 0, COMPACT_PDF417_START, rowHeight);
104
+ const left = compactPdf417Indicators(row, rows, columns, level);
105
+ x = appendWidths(matrix, y, x, patternSequence(pdf417PatternForCodeword(left, cluster)), rowHeight);
106
+ for (let column = 0; column < columns; column++) {
107
+ const codeword = codewords[row * columns + column];
108
+ x = appendWidths(matrix, y, x, patternSequence(pdf417PatternForCodeword(codeword, cluster)), rowHeight);
109
+ }
110
+ // Compact PDF417 terminates every row with one dark module, not the normal
111
+ // right indicator plus 18-module stop pattern.
112
+ matrix.setRegion(x, y, 1, rowHeight);
113
+ x++;
114
+ if (x !== matrix.width)
115
+ throw new EncodeError('Compact PDF417: internal row width mismatch');
121
116
  }
122
- // Compact PDF417 terminates every row with one dark module, not the normal
123
- // right indicator plus 18-module stop pattern.
124
- matrix.setRegion(x, y, 1, rowHeight);
125
- x++;
126
- if (x !== matrix.width) throw new EncodeError('Compact PDF417: internal row width mismatch');
127
- }
128
-
129
- matrix.compactPdf417 = {
130
- rows,
131
- columns,
132
- eccLevel: level,
133
- rowHeight,
134
- codewords,
135
- layout: 'compact',
136
- };
137
- return matrix;
117
+ matrix.compactPdf417 = {
118
+ rows,
119
+ columns,
120
+ eccLevel: level,
121
+ rowHeight,
122
+ codewords,
123
+ layout: 'compact',
124
+ };
125
+ return matrix;
138
126
  }
139
-
140
127
  export { dimensions as compactPdf417Dimensions };
@@ -1,17 +1,5 @@
1
1
  /* Compact PDF417 public module exports. */
2
-
3
- export {
4
- COMPACT_PDF417_START,
5
- COMPACT_PDF417_START_BITS,
6
- COMPACT_PDF417_STOP_MODULES,
7
- COMPACT_PDF417_LIMITS,
8
- compactPdf417Width,
9
- compactPdf417Geometry,
10
- compactPdf417Indicators,
11
- compactPdf417MatchingLevels,
12
- validateCompactPdf417Options,
13
- validateCompactPdf417Tables,
14
- } from './tables.js';
2
+ export { COMPACT_PDF417_START, COMPACT_PDF417_START_BITS, COMPACT_PDF417_STOP_MODULES, COMPACT_PDF417_LIMITS, compactPdf417Width, compactPdf417Geometry, compactPdf417Indicators, compactPdf417MatchingLevels, validateCompactPdf417Options, validateCompactPdf417Tables, } from './tables.js';
15
3
  export { encodeCompactPDF417, compactPdf417Dimensions } from './encoder.js';
16
4
  export { decodeCompactPDF417 } from './decoder.js';
17
5
  export { detectCompactPDF417, detectAndDecodeCompactPDF417 } from './detector.js';
@@ -27,7 +27,6 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /**
32
31
  * Compact (truncated) PDF417 layout.
33
32
  *
@@ -40,27 +39,21 @@
40
39
  *
41
40
  * @module compactpdf417/tables
42
41
  */
43
-
44
42
  import { EncodeError } from '../core/errors.js';
45
-
46
43
  /** PDF417 start pattern, in module widths. */
47
44
  export const COMPACT_PDF417_START = '81111113';
48
-
49
45
  /** Binary module representation of the start pattern. */
50
46
  export const COMPACT_PDF417_START_BITS = '11111111010101000';
51
-
52
47
  /** Compact PDF417's reduced stop is one dark module. */
53
48
  export const COMPACT_PDF417_STOP_MODULES = 1;
54
-
55
49
  /** Minimum/maximum number of rows and data columns. */
56
50
  export const COMPACT_PDF417_LIMITS = Object.freeze({
57
- minRows: 3,
58
- maxRows: 90,
59
- minColumns: 1,
60
- maxColumns: 30,
61
- maxCodewords: 928,
51
+ minRows: 3,
52
+ maxRows: 90,
53
+ minColumns: 1,
54
+ maxColumns: 30,
55
+ maxCodewords: 928,
62
56
  });
63
-
64
57
  /**
65
58
  * Return the printed width in modules for a compact symbol.
66
59
  *
@@ -68,12 +61,11 @@ export const COMPACT_PDF417_LIMITS = Object.freeze({
68
61
  * @param {number} columns
69
62
  */
70
63
  export function compactPdf417Width(columns) {
71
- if (!Number.isInteger(columns) || columns < 1 || columns > 30) {
72
- throw new RangeError(`Compact PDF417: columns must be an integer in 1..30, got ${columns}`);
73
- }
74
- return 35 + columns * 17;
64
+ if (!Number.isInteger(columns) || columns < 1 || columns > 30) {
65
+ throw new RangeError(`Compact PDF417: columns must be an integer in 1..30, got ${columns}`);
66
+ }
67
+ return 35 + columns * 17;
75
68
  }
76
-
77
69
  /**
78
70
  * Validate a compact matrix geometry and return its dimensions.
79
71
  *
@@ -82,92 +74,91 @@ export function compactPdf417Width(columns) {
82
74
  * @param {number} rowHeight
83
75
  */
84
76
  export function compactPdf417Geometry(width, height, rowHeight = 3) {
85
- if (!Number.isInteger(width) || !Number.isInteger(height)) {
86
- throw new RangeError('Compact PDF417: matrix dimensions must be integers');
87
- }
88
- if (!Number.isInteger(rowHeight) || rowHeight < 1) {
89
- throw new RangeError('Compact PDF417: rowHeight must be a positive integer');
90
- }
91
- if ((width - 35) % 17 !== 0) {
92
- throw new RangeError(`Compact PDF417: width ${width} does not match the compact layout`);
93
- }
94
- const columns = (width - 35) / 17;
95
- const rows = height / rowHeight;
96
- if (!Number.isInteger(rows) || rows < 3 || rows > 90) {
97
- throw new RangeError(`Compact PDF417: rows must be an integer in 3..90, got ${rows}`);
98
- }
99
- if (columns < 1 || columns > 30) {
100
- throw new RangeError(`Compact PDF417: columns must be an integer in 1..30, got ${columns}`);
101
- }
102
- return { rows, columns, rowHeight, width, height };
77
+ if (!Number.isInteger(width) || !Number.isInteger(height)) {
78
+ throw new RangeError('Compact PDF417: matrix dimensions must be integers');
79
+ }
80
+ if (!Number.isInteger(rowHeight) || rowHeight < 1) {
81
+ throw new RangeError('Compact PDF417: rowHeight must be a positive integer');
82
+ }
83
+ if ((width - 35) % 17 !== 0) {
84
+ throw new RangeError(`Compact PDF417: width ${width} does not match the compact layout`);
85
+ }
86
+ const columns = (width - 35) / 17;
87
+ const rows = height / rowHeight;
88
+ if (!Number.isInteger(rows) || rows < 3 || rows > 90) {
89
+ throw new RangeError(`Compact PDF417: rows must be an integer in 3..90, got ${rows}`);
90
+ }
91
+ if (columns < 1 || columns > 30) {
92
+ throw new RangeError(`Compact PDF417: columns must be an integer in 1..30, got ${columns}`);
93
+ }
94
+ return { rows, columns, rowHeight, width, height };
103
95
  }
104
-
105
96
  /**
106
97
  * Validate encoder dimensions before codeword packing.
107
98
  * @param {object} options
108
99
  */
109
100
  export function validateCompactPdf417Options(options = {}) {
110
- const { minRows, maxRows, minColumns, maxColumns } = COMPACT_PDF417_LIMITS;
111
- const rowHeight = options.rowHeight ?? 3;
112
- if (!Number.isInteger(rowHeight) || rowHeight < 3) {
113
- throw new EncodeError('Compact PDF417: rowHeight must be an integer of at least 3');
114
- }
115
- for (const [name, value, min, max] of [
116
- ['rows', options.rows, minRows, maxRows],
117
- ['columns', options.columns, minColumns, maxColumns],
118
- ]) {
119
- if (value !== undefined && (!Number.isInteger(value) || value < min || value > max)) {
120
- throw new EncodeError(`Compact PDF417: ${name} must be an integer in ${min}..${max}`);
101
+ const { minRows, maxRows, minColumns, maxColumns } = COMPACT_PDF417_LIMITS;
102
+ const rowHeight = options.rowHeight ?? 3;
103
+ if (!Number.isInteger(rowHeight) || rowHeight < 3) {
104
+ throw new EncodeError('Compact PDF417: rowHeight must be an integer of at least 3');
105
+ }
106
+ for (const [name, value, min, max] of [
107
+ ['rows', options.rows, minRows, maxRows],
108
+ ['columns', options.columns, minColumns, maxColumns],
109
+ ]) {
110
+ if (value !== undefined && (!Number.isInteger(value) || value < min || value > max)) {
111
+ throw new EncodeError(`Compact PDF417: ${name} must be an integer in ${min}..${max}`);
112
+ }
113
+ }
114
+ if (options.aspectRatio !== undefined &&
115
+ (!Number.isFinite(options.aspectRatio) || options.aspectRatio <= 0)) {
116
+ throw new EncodeError('Compact PDF417: aspectRatio must be positive');
121
117
  }
122
- }
123
- if (options.aspectRatio !== undefined &&
124
- (!Number.isFinite(options.aspectRatio) || options.aspectRatio <= 0)) {
125
- throw new EncodeError('Compact PDF417: aspectRatio must be positive');
126
- }
127
- return rowHeight;
118
+ return rowHeight;
128
119
  }
129
-
130
120
  /**
131
121
  * The row indicator values used by ordinary PDF417 are retained unchanged.
132
122
  * Compact symbols omit only the right indicator, so the left indicator still
133
123
  * carries the row group, row count, error-correction level and column count.
134
124
  */
135
125
  export function compactPdf417Indicators(row, rows, columns, level) {
136
- const group = Math.floor(row / 3);
137
- const y = Math.floor((rows - 1) / 3);
138
- const z = level * 3 + (rows - 1) % 3;
139
- const v = columns - 1;
140
- if (row % 3 === 0) return 30 * group + y;
141
- if (row % 3 === 1) return 30 * group + z;
142
- return 30 * group + v;
126
+ const group = Math.floor(row / 3);
127
+ const y = Math.floor((rows - 1) / 3);
128
+ const z = level * 3 + (rows - 1) % 3;
129
+ const v = columns - 1;
130
+ if (row % 3 === 0)
131
+ return 30 * group + y;
132
+ if (row % 3 === 1)
133
+ return 30 * group + z;
134
+ return 30 * group + v;
143
135
  }
144
-
145
136
  /**
146
137
  * Return all standard ECC levels which agree with the observed left
147
138
  * indicators. This is kept as a table helper so decoder and tests share the
148
139
  * same compact-layout rule.
149
140
  */
150
141
  export function compactPdf417MatchingLevels(leftIndicators, rows, columns) {
151
- const matches = [];
152
- for (let level = 0; level <= 8; level++) {
153
- if (leftIndicators.every((value, row) =>
154
- value === compactPdf417Indicators(row, rows, columns, level))) matches.push(level);
155
- }
156
- return matches;
142
+ const matches = [];
143
+ for (let level = 0; level <= 8; level++) {
144
+ if (leftIndicators.every((value, row) => value === compactPdf417Indicators(row, rows, columns, level)))
145
+ matches.push(level);
146
+ }
147
+ return matches;
157
148
  }
158
-
159
149
  /** Validate representative layout invariants. */
160
150
  export function validateCompactPdf417Tables() {
161
- const problems = [];
162
- for (const columns of [1, 2, 3, 10, 30]) {
163
- const width = compactPdf417Width(columns);
164
- if (width !== 35 + columns * 17) problems.push(`columns ${columns}: width mismatch`);
165
- }
166
- for (const rows of [3, 4, 5, 6, 90]) {
167
- const left = Array.from({ length: rows }, (_, row) => compactPdf417Indicators(row, rows, 3, 2));
168
- if (compactPdf417MatchingLevels(left, rows, 3).length !== 1) {
169
- problems.push(`rows ${rows}: row indicators do not identify one ECC level`);
151
+ const problems = [];
152
+ for (const columns of [1, 2, 3, 10, 30]) {
153
+ const width = compactPdf417Width(columns);
154
+ if (width !== 35 + columns * 17)
155
+ problems.push(`columns ${columns}: width mismatch`);
156
+ }
157
+ for (const rows of [3, 4, 5, 6, 90]) {
158
+ const left = Array.from({ length: rows }, (_, row) => compactPdf417Indicators(row, rows, 3, 2));
159
+ if (compactPdf417MatchingLevels(left, rows, 3).length !== 1) {
160
+ problems.push(`rows ${rows}: row indicators do not identify one ECC level`);
161
+ }
170
162
  }
171
- }
172
- return problems;
163
+ return problems;
173
164
  }
@@ -27,7 +27,6 @@
27
27
  *
28
28
  * Original work. No code from any other barcode implementation.
29
29
  */
30
-
31
30
  /**
32
31
  * Bit-level writing and reading, MSB-first.
33
32
  *
@@ -38,137 +37,122 @@
38
37
  *
39
38
  * @module core/bit-buffer
40
39
  */
41
-
42
40
  import { FormatError } from './errors.js';
43
-
44
41
  /** Growable MSB-first bit writer. */
45
42
  export class BitWriter {
46
- constructor() {
47
- /** @type {number[]} Packed bytes; the last one may be partially filled. */
48
- this.bytes = [];
49
- this.bitLength = 0;
50
- }
51
-
52
- /** @returns {number} Bits written so far. */
53
- get length() {
54
- return this.bitLength;
55
- }
56
-
57
- /**
58
- * Append the low `count` bits of `value`, most significant first.
59
- *
60
- * @param {number} value
61
- * @param {number} count
62
- */
63
- put(value, count) {
64
- for (let i = count - 1; i >= 0; i--) {
65
- this.putBit(((value >>> i) & 1) === 1);
43
+ constructor() {
44
+ /** @type {number[]} Packed bytes; the last one may be partially filled. */
45
+ this.bytes = [];
46
+ this.bitLength = 0;
66
47
  }
67
- }
68
-
69
- /** @param {boolean} bit */
70
- putBit(bit) {
71
- const idx = this.bitLength >>> 3;
72
- if (this.bytes.length <= idx) this.bytes.push(0);
73
- if (bit) this.bytes[idx] |= 0x80 >>> (this.bitLength & 7);
74
- this.bitLength++;
75
- }
76
-
77
- /** @param {ArrayLike<number>} data */
78
- putBytes(data) {
79
- for (let i = 0; i < data.length; i++) this.put(data[i], 8);
80
- }
81
-
82
- /** Pad with zero bits until the length is a multiple of 8. */
83
- padToByte() {
84
- while (this.bitLength & 7) this.putBit(false);
85
- }
86
-
87
- /**
88
- * @returns {Uint8Array} Byte view; trailing bits of the final byte are zero.
89
- */
90
- toBytes() {
91
- return Uint8Array.from(this.bytes);
92
- }
93
-
94
- /** @returns {string} Debug view, e.g. "0100 0011 0101". */
95
- toString() {
96
- let s = '';
97
- for (let i = 0; i < this.bitLength; i++) {
98
- if (i && i % 4 === 0) s += ' ';
99
- s += (this.bytes[i >>> 3] >>> (7 - (i & 7))) & 1;
48
+ /** @returns {number} Bits written so far. */
49
+ get length() {
50
+ return this.bitLength;
51
+ }
52
+ /**
53
+ * Append the low `count` bits of `value`, most significant first.
54
+ *
55
+ * @param {number} value
56
+ * @param {number} count
57
+ */
58
+ put(value, count) {
59
+ for (let i = count - 1; i >= 0; i--) {
60
+ this.putBit(((value >>> i) & 1) === 1);
61
+ }
62
+ }
63
+ /** @param {boolean} bit */
64
+ putBit(bit) {
65
+ const idx = this.bitLength >>> 3;
66
+ if (this.bytes.length <= idx)
67
+ this.bytes.push(0);
68
+ if (bit)
69
+ this.bytes[idx] |= 0x80 >>> (this.bitLength & 7);
70
+ this.bitLength++;
71
+ }
72
+ /** @param {ArrayLike<number>} data */
73
+ putBytes(data) {
74
+ for (let i = 0; i < data.length; i++)
75
+ this.put(data[i], 8);
76
+ }
77
+ /** Pad with zero bits until the length is a multiple of 8. */
78
+ padToByte() {
79
+ while (this.bitLength & 7)
80
+ this.putBit(false);
81
+ }
82
+ /**
83
+ * @returns {Uint8Array} Byte view; trailing bits of the final byte are zero.
84
+ */
85
+ toBytes() {
86
+ return Uint8Array.from(this.bytes);
87
+ }
88
+ /** @returns {string} Debug view, e.g. "0100 0011 0101". */
89
+ toString() {
90
+ let s = '';
91
+ for (let i = 0; i < this.bitLength; i++) {
92
+ if (i && i % 4 === 0)
93
+ s += ' ';
94
+ s += (this.bytes[i >>> 3] >>> (7 - (i & 7))) & 1;
95
+ }
96
+ return s;
100
97
  }
101
- return s;
102
- }
103
98
  }
104
-
105
99
  /** MSB-first bit reader over a byte array. */
106
100
  export class BitReader {
107
- /** @param {ArrayLike<number>} bytes */
108
- constructor(bytes) {
109
- this.bytes = bytes;
110
- this.byteOffset = 0;
111
- this.bitOffset = 0;
112
- }
113
-
114
- /** @returns {number} Bits not yet consumed. */
115
- available() {
116
- return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset;
117
- }
118
-
119
- /**
120
- * Read `count` bits (1..32) as an unsigned integer, most significant first.
121
- *
122
- * @param {number} count
123
- * @returns {number}
124
- * @throws {FormatError} If the stream is exhausted.
125
- */
126
- read(count) {
127
- if (count < 1 || count > 32) {
128
- throw new FormatError(`BitReader: cannot read ${count} bits`);
129
- }
130
- if (count > this.available()) {
131
- throw new FormatError(
132
- `BitReader: needed ${count} bits, ${this.available()} remain`
133
- );
134
- }
135
-
136
- let result = 0;
137
- let remaining = count;
138
-
139
- // Finish the partially consumed byte first, then take whole bytes.
140
- if (this.bitOffset > 0) {
141
- const inCurrent = 8 - this.bitOffset;
142
- const take = Math.min(remaining, inCurrent);
143
- const shift = inCurrent - take;
144
- const mask = (0xff >> this.bitOffset) & ~((1 << shift) - 1);
145
- result = (this.bytes[this.byteOffset] & mask) >> shift;
146
- remaining -= take;
147
- this.bitOffset += take;
148
- if (this.bitOffset === 8) {
101
+ /** @param {ArrayLike<number>} bytes */
102
+ constructor(bytes) {
103
+ this.bytes = bytes;
104
+ this.byteOffset = 0;
149
105
  this.bitOffset = 0;
150
- this.byteOffset++;
151
- }
152
106
  }
153
-
154
- while (remaining >= 8) {
155
- result = (result << 8) | (this.bytes[this.byteOffset] & 0xff);
156
- this.byteOffset++;
157
- remaining -= 8;
107
+ /** @returns {number} Bits not yet consumed. */
108
+ available() {
109
+ return 8 * (this.bytes.length - this.byteOffset) - this.bitOffset;
110
+ }
111
+ /**
112
+ * Read `count` bits (1..32) as an unsigned integer, most significant first.
113
+ *
114
+ * @param {number} count
115
+ * @returns {number}
116
+ * @throws {FormatError} If the stream is exhausted.
117
+ */
118
+ read(count) {
119
+ if (count < 1 || count > 32) {
120
+ throw new FormatError(`BitReader: cannot read ${count} bits`);
121
+ }
122
+ if (count > this.available()) {
123
+ throw new FormatError(`BitReader: needed ${count} bits, ${this.available()} remain`);
124
+ }
125
+ let result = 0;
126
+ let remaining = count;
127
+ // Finish the partially consumed byte first, then take whole bytes.
128
+ if (this.bitOffset > 0) {
129
+ const inCurrent = 8 - this.bitOffset;
130
+ const take = Math.min(remaining, inCurrent);
131
+ const shift = inCurrent - take;
132
+ const mask = (0xff >> this.bitOffset) & ~((1 << shift) - 1);
133
+ result = (this.bytes[this.byteOffset] & mask) >> shift;
134
+ remaining -= take;
135
+ this.bitOffset += take;
136
+ if (this.bitOffset === 8) {
137
+ this.bitOffset = 0;
138
+ this.byteOffset++;
139
+ }
140
+ }
141
+ while (remaining >= 8) {
142
+ result = (result << 8) | (this.bytes[this.byteOffset] & 0xff);
143
+ this.byteOffset++;
144
+ remaining -= 8;
145
+ }
146
+ if (remaining > 0) {
147
+ const shift = 8 - remaining;
148
+ const mask = ~((1 << shift) - 1) & 0xff;
149
+ result = (result << remaining) | ((this.bytes[this.byteOffset] & mask) >> shift);
150
+ this.bitOffset += remaining;
151
+ }
152
+ return result >>> 0;
158
153
  }
159
-
160
- if (remaining > 0) {
161
- const shift = 8 - remaining;
162
- const mask = ~((1 << shift) - 1) & 0xff;
163
- result = (result << remaining) | ((this.bytes[this.byteOffset] & mask) >> shift);
164
- this.bitOffset += remaining;
154
+ /** @returns {boolean} */
155
+ readBit() {
156
+ return this.read(1) === 1;
165
157
  }
166
-
167
- return result >>> 0;
168
- }
169
-
170
- /** @returns {boolean} */
171
- readBit() {
172
- return this.read(1) === 1;
173
- }
174
158
  }