pdf-parser.js 5.2.27 → 5.2.28

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 (145) hide show
  1. package/dist/{afm-widths-BYiX2L9D.cjs → afm-widths-BHD2HZIL.cjs} +553 -642
  2. package/dist/{afm-widths-blUDDjlI.js → afm-widths-B_IGbGky.js} +553 -642
  3. package/dist/afm-widths.cjs +1 -1
  4. package/dist/afm-widths.js +1 -1
  5. package/dist/annotations.cjs +5 -3
  6. package/dist/annotations.js +5 -3
  7. package/dist/builtin-encoding.cjs +17 -6
  8. package/dist/builtin-encoding.js +17 -6
  9. package/dist/bytes/crc32.cjs +5 -3
  10. package/dist/bytes/crc32.js +5 -3
  11. package/dist/bytes/flate.cjs +0 -1
  12. package/dist/bytes/flate.js +0 -1
  13. package/dist/cff-bounds.cjs +42 -24
  14. package/dist/cff-bounds.js +42 -24
  15. package/dist/cff.cjs +13 -6
  16. package/dist/cff.js +13 -6
  17. package/dist/cmap-table.cjs +54 -26
  18. package/dist/cmap-table.js +54 -26
  19. package/dist/cmap.cjs +5 -3
  20. package/dist/cmap.js +5 -3
  21. package/dist/content-write.cjs +3 -2
  22. package/dist/content-write.js +3 -2
  23. package/dist/crypto/aes.cjs +76 -55
  24. package/dist/crypto/aes.js +76 -55
  25. package/dist/crypto/md5.cjs +345 -149
  26. package/dist/crypto/md5.js +345 -149
  27. package/dist/crypto/rc4.cjs +5 -4
  28. package/dist/crypto/rc4.js +5 -4
  29. package/dist/crypto/sha2.cjs +92 -43
  30. package/dist/crypto/sha2.js +92 -43
  31. package/dist/embedded-font.cjs +4 -2
  32. package/dist/embedded-font.js +4 -2
  33. package/dist/encoding.cjs +1 -1
  34. package/dist/encoding.js +1 -1
  35. package/dist/encrypt-write.cjs +25 -21
  36. package/dist/encrypt-write.js +25 -21
  37. package/dist/encrypt.cjs +43 -64
  38. package/dist/encrypt.js +43 -64
  39. package/dist/filters.cjs +40 -20
  40. package/dist/filters.js +40 -20
  41. package/dist/font-face.cjs +2 -1
  42. package/dist/font-face.js +2 -1
  43. package/dist/font-read.cjs +12 -6
  44. package/dist/font-read.js +12 -6
  45. package/dist/font-tables.cjs +55 -28
  46. package/dist/font-tables.js +55 -28
  47. package/dist/gdef-table.cjs +6 -3
  48. package/dist/gdef-table.js +6 -3
  49. package/dist/glyf-contours.cjs +3 -1
  50. package/dist/glyf-contours.js +3 -1
  51. package/dist/glyf.cjs +22 -11
  52. package/dist/glyf.js +22 -11
  53. package/dist/gpos-table.cjs +37 -19
  54. package/dist/gpos-table.js +37 -19
  55. package/dist/gsub-table.cjs +28 -17
  56. package/dist/gsub-table.js +28 -17
  57. package/dist/hmtx-table.cjs +5 -3
  58. package/dist/hmtx-table.js +5 -3
  59. package/dist/image/ccitt-encode.cjs +8 -5
  60. package/dist/image/ccitt-encode.js +8 -5
  61. package/dist/image/ccitt.cjs +801 -209
  62. package/dist/image/ccitt.js +801 -209
  63. package/dist/image/jbig2-arith.cjs +340 -306
  64. package/dist/image/jbig2-arith.js +340 -306
  65. package/dist/image/jbig2-bitmap.cjs +8 -5
  66. package/dist/image/jbig2-bitmap.js +8 -5
  67. package/dist/image/jbig2-generic.cjs +240 -69
  68. package/dist/image/jbig2-generic.js +240 -69
  69. package/dist/image/jbig2-text.cjs +4 -2
  70. package/dist/image/jbig2-text.js +4 -2
  71. package/dist/image/jbig2.cjs +69 -31
  72. package/dist/image/jbig2.js +69 -31
  73. package/dist/image/jp2-boxes.cjs +52 -27
  74. package/dist/image/jp2-boxes.js +52 -27
  75. package/dist/image/jpeg-info.cjs +29 -24
  76. package/dist/image/jpeg-info.js +29 -24
  77. package/dist/image/jpeg2000-codestream.cjs +44 -24
  78. package/dist/image/jpeg2000-codestream.js +44 -24
  79. package/dist/image/jpeg2000-dwt.cjs +2 -1
  80. package/dist/image/jpeg2000-dwt.js +2 -1
  81. package/dist/image/jpeg2000-t1.cjs +21 -11
  82. package/dist/image/jpeg2000-t1.js +21 -11
  83. package/dist/image/jpeg2000-t2.cjs +12 -5
  84. package/dist/image/jpeg2000-t2.js +12 -5
  85. package/dist/image/jpeg2000-tagtree.cjs +8 -4
  86. package/dist/image/jpeg2000-tagtree.js +8 -4
  87. package/dist/image/jpeg2000.cjs +11 -6
  88. package/dist/image/jpeg2000.js +11 -6
  89. package/dist/image/png-decode.cjs +62 -39
  90. package/dist/image/png-decode.d.cts +3 -2
  91. package/dist/image/png-decode.d.ts +3 -2
  92. package/dist/image/png-decode.js +62 -39
  93. package/dist/image/png-filter.cjs +23 -15
  94. package/dist/image/png-filter.js +23 -15
  95. package/dist/images-read.cjs +41 -36
  96. package/dist/images-read.js +41 -36
  97. package/dist/index.cjs +1 -1
  98. package/dist/index.js +1 -1
  99. package/dist/interpret.cjs +39 -24
  100. package/dist/interpret.js +39 -24
  101. package/dist/lexer.cjs +86 -51
  102. package/dist/lexer.js +86 -51
  103. package/dist/math-content-write.cjs +9 -5
  104. package/dist/math-content-write.js +9 -5
  105. package/dist/math-font-write.cjs +2 -1
  106. package/dist/math-font-write.js +2 -1
  107. package/dist/math-font.cjs +16 -7
  108. package/dist/math-font.js +16 -7
  109. package/dist/math-table.cjs +25 -13
  110. package/dist/math-table.js +25 -13
  111. package/dist/matrix.cjs +3 -2
  112. package/dist/matrix.js +3 -2
  113. package/dist/measure.cjs +1 -1
  114. package/dist/measure.js +1 -1
  115. package/dist/navigation.cjs +10 -5
  116. package/dist/navigation.js +10 -5
  117. package/dist/ot-layout-common.cjs +4 -2
  118. package/dist/ot-layout-common.js +4 -2
  119. package/dist/parse.cjs +7 -5
  120. package/dist/parse.js +7 -5
  121. package/dist/pdf-text.cjs +5 -2
  122. package/dist/pdf-text.js +5 -2
  123. package/dist/predictors.cjs +14 -9
  124. package/dist/predictors.js +14 -9
  125. package/dist/raster.cjs +30 -19
  126. package/dist/raster.js +30 -19
  127. package/dist/read.cjs +17 -8
  128. package/dist/read.js +17 -8
  129. package/dist/serialize.cjs +6 -2
  130. package/dist/serialize.js +6 -2
  131. package/dist/sfnt-subset.cjs +25 -13
  132. package/dist/sfnt-subset.js +25 -13
  133. package/dist/sfnt.cjs +20 -10
  134. package/dist/sfnt.js +20 -10
  135. package/dist/text-group.cjs +0 -1
  136. package/dist/text-group.js +0 -1
  137. package/dist/tounicode.cjs +4 -2
  138. package/dist/tounicode.js +4 -2
  139. package/dist/winansi.cjs +1 -1
  140. package/dist/winansi.js +1 -1
  141. package/dist/write.cjs +20 -12
  142. package/dist/write.js +20 -12
  143. package/dist/xref.cjs +5 -2
  144. package/dist/xref.js +5 -2
  145. package/package.json +1 -1
@@ -15,6 +15,11 @@ const MARKER_COM = 65380;
15
15
  const MARKER_SOT = 65424;
16
16
  const MARKER_SOD = 65427;
17
17
  const MARKER_EOC = 65497;
18
+ const BITS_PER_BYTE = 8;
19
+ const HEX_RADIX = 16;
20
+ const NIBBLE_MASK = 15;
21
+ const NIBBLE_BITS = 4;
22
+ const UINT16_MODULUS = 65536;
18
23
  var MarkerCursor = class {
19
24
  data;
20
25
  position;
@@ -32,10 +37,10 @@ var MarkerCursor = class {
32
37
  return value;
33
38
  }
34
39
  uint16() {
35
- return this.uint8() << 8 | this.uint8();
40
+ return this.uint8() << BITS_PER_BYTE | this.uint8();
36
41
  }
37
42
  uint32() {
38
- return this.uint16() * 65536 + this.uint16();
43
+ return this.uint16() * UINT16_MODULUS + this.uint16();
39
44
  }
40
45
  bytes(length) {
41
46
  if (length < 0 || this.position + length > this.data.length) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("a JPEG 2000 marker segment declares more data than the codestream carries");
@@ -44,6 +49,9 @@ var MarkerCursor = class {
44
49
  return slice;
45
50
  }
46
51
  };
52
+ const SIZ_COMPONENT_RECORD_SIZE = 3;
53
+ const SSIZ_SIGNED_BIT = 128;
54
+ const SSIZ_BIT_DEPTH_MASK = 127;
47
55
  function readImageSize(cursor, segmentEnd) {
48
56
  cursor.uint16();
49
57
  const xsiz = cursor.uint32();
@@ -56,13 +64,13 @@ function readImageSize(cursor, segmentEnd) {
56
64
  const ytosiz = cursor.uint32();
57
65
  const count = cursor.uint16();
58
66
  if (count === 0) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("SIZ declares zero components");
59
- if (cursor.position + count * 3 > segmentEnd) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`SIZ declares ${String(count)} components but its own length leaves room for fewer`);
67
+ if (cursor.position + count * SIZ_COMPONENT_RECORD_SIZE > segmentEnd) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`SIZ declares ${String(count)} components but its own length leaves room for fewer`);
60
68
  const components = [];
61
69
  for (let i = 0; i < count; i++) {
62
70
  const ssiz = cursor.uint8();
63
71
  components.push({
64
- signed: (ssiz & 128) !== 0,
65
- bitDepth: (ssiz & 127) + 1,
72
+ signed: (ssiz & SSIZ_SIGNED_BIT) !== 0,
73
+ bitDepth: (ssiz & SSIZ_BIT_DEPTH_MASK) + 1,
66
74
  dx: cursor.uint8(),
67
75
  dy: cursor.uint8()
68
76
  });
@@ -82,20 +90,21 @@ function readImageSize(cursor, segmentEnd) {
82
90
  };
83
91
  }
84
92
  const DEFAULT_PRECINCT_EXPONENT = 15;
93
+ const CODE_BLOCK_AREA_EXPONENT_MAX = 12;
85
94
  function readCodingStyleParameters(cursor, explicitPrecincts) {
86
95
  const decompositionLevels = cursor.uint8();
87
- const codeBlockWidthExp = (cursor.uint8() & 15) + 2;
88
- const codeBlockHeightExp = (cursor.uint8() & 15) + 2;
96
+ const codeBlockWidthExp = (cursor.uint8() & NIBBLE_MASK) + 2;
97
+ const codeBlockHeightExp = (cursor.uint8() & NIBBLE_MASK) + 2;
89
98
  const codeBlockStyle = cursor.uint8();
90
99
  const transformCode = cursor.uint8();
91
100
  if (transformCode !== 0 && transformCode !== 1) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`SPcod/SPcoc declares transformation ${String(transformCode)}, which is neither of the two ISO/IEC 15444-1 defines`);
92
- if (codeBlockWidthExp + codeBlockHeightExp > 12) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`code-block size 2^${String(codeBlockWidthExp)} by 2^${String(codeBlockHeightExp)} is outside the range ISO/IEC 15444-1 Table A.18 permits`);
101
+ if (codeBlockWidthExp + codeBlockHeightExp > CODE_BLOCK_AREA_EXPONENT_MAX) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`code-block size 2^${String(codeBlockWidthExp)} by 2^${String(codeBlockHeightExp)} is outside the range ISO/IEC 15444-1 Table A.18 permits`);
93
102
  const precinctSizes = [];
94
103
  if (explicitPrecincts) for (let r = 0; r <= decompositionLevels; r++) {
95
104
  const packed = cursor.uint8();
96
105
  precinctSizes.push({
97
- ppx: packed & 15,
98
- ppy: packed >> 4 & 15
106
+ ppx: packed & NIBBLE_MASK,
107
+ ppy: packed >> NIBBLE_BITS & NIBBLE_MASK
99
108
  });
100
109
  }
101
110
  else for (let r = 0; r <= decompositionLevels; r++) precinctSizes.push({
@@ -111,6 +120,7 @@ function readCodingStyleParameters(cursor, explicitPrecincts) {
111
120
  precinctSizes
112
121
  };
113
122
  }
123
+ const SCOD_USE_EPH_BIT = 4;
114
124
  function readCodingDefaults(cursor) {
115
125
  const progressionOrders = [
116
126
  "LRCP",
@@ -131,17 +141,22 @@ function readCodingDefaults(cursor) {
131
141
  layers,
132
142
  multipleComponentTransform,
133
143
  useSop: (scod & 2) !== 0,
134
- useEph: (scod & 4) !== 0
144
+ useEph: (scod & SCOD_USE_EPH_BIT) !== 0
135
145
  };
136
146
  }
147
+ const SQCD_GUARD_BITS_SHIFT = 5;
148
+ const SQCD_STYLE_MASK = 31;
149
+ const SPQCD_NONE_EXPONENT_SHIFT = 3;
150
+ const SPQCD_EXPONENT_SHIFT = 11;
151
+ const SPQCD_MANTISSA_MASK = 2047;
137
152
  function readQuantization(cursor, segmentEnd) {
138
153
  const sq = cursor.uint8();
139
- const guardBits = sq >> 5;
140
- const styleCode = sq & 31;
154
+ const guardBits = sq >> SQCD_GUARD_BITS_SHIFT;
155
+ const styleCode = sq & SQCD_STYLE_MASK;
141
156
  const stepSizes = [];
142
157
  if (styleCode === 0) {
143
158
  while (cursor.position < segmentEnd) stepSizes.push({
144
- exponent: cursor.uint8() >> 3,
159
+ exponent: cursor.uint8() >> SPQCD_NONE_EXPONENT_SHIFT,
145
160
  mantissa: 0
146
161
  });
147
162
  return {
@@ -154,8 +169,8 @@ function readQuantization(cursor, segmentEnd) {
154
169
  while (cursor.position + 1 < segmentEnd) {
155
170
  const packed = cursor.uint16();
156
171
  stepSizes.push({
157
- exponent: packed >> 11,
158
- mantissa: packed & 2047
172
+ exponent: packed >> SPQCD_EXPONENT_SHIFT,
173
+ mantissa: packed & SPQCD_MANTISSA_MASK
159
174
  });
160
175
  }
161
176
  return {
@@ -166,8 +181,9 @@ function readQuantization(cursor, segmentEnd) {
166
181
  }
167
182
  throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`QCD/QCC declares quantization style ${String(styleCode)}, which ISO/IEC 15444-1 Table A.28 does not define`);
168
183
  }
184
+ const COMPONENT_INDEX_WIDTH_THRESHOLD = 257;
169
185
  function readComponentIndex(cursor, componentCount) {
170
- return componentCount < 257 ? cursor.uint8() : cursor.uint16();
186
+ return componentCount < COMPONENT_INDEX_WIDTH_THRESHOLD ? cursor.uint8() : cursor.uint16();
171
187
  }
172
188
  function emptyHeader() {
173
189
  return {
@@ -212,9 +228,9 @@ var CodestreamComments = class {
212
228
  };
213
229
  function readHeaderSegment(marker, cursor, header, componentCount, comments) {
214
230
  const length = cursor.uint16();
215
- if (length < 2) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`marker segment 0x${marker.toString(16)} declares a length of ${String(length)}, which is shorter than the length field itself`);
231
+ if (length < 2) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`marker segment 0x${marker.toString(HEX_RADIX)} declares a length of ${String(length)}, which is shorter than the length field itself`);
216
232
  const segmentEnd = cursor.position + length - 2;
217
- if (segmentEnd > cursor.data.length) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`marker segment 0x${marker.toString(16)} declares more data than the codestream carries`);
233
+ if (segmentEnd > cursor.data.length) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`marker segment 0x${marker.toString(HEX_RADIX)} declares more data than the codestream carries`);
218
234
  if (marker === MARKER_COD) header.cod = readCodingDefaults(cursor);
219
235
  else if (marker === MARKER_COC) {
220
236
  const component = readComponentIndex(cursor, componentCount);
@@ -237,9 +253,10 @@ function validateMainHeader(header) {
237
253
  if (header.cod === void 0) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("the main header carries no COD marker, so no coding style is defined for any tile");
238
254
  if (header.qcd === void 0) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("the main header carries no QCD marker, so no quantization is defined for any tile");
239
255
  }
256
+ const MIN_HEADER_BYTES = 4;
240
257
  function parseJpeg2000Codestream(data) {
241
258
  const cursor = new MarkerCursor(data);
242
- if (cursor.remaining < 4 || cursor.uint16() !== MARKER_SOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("codestream does not begin with an SOC marker");
259
+ if (cursor.remaining < MIN_HEADER_BYTES || cursor.uint16() !== MARKER_SOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("codestream does not begin with an SOC marker");
243
260
  if (cursor.uint16() !== MARKER_SIZ) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("the SOC marker is not immediately followed by SIZ, which ISO/IEC 15444-1 A.3 requires");
244
261
  const sizLength = cursor.uint16();
245
262
  const sizEnd = cursor.position + sizLength - 2;
@@ -262,7 +279,7 @@ function parseJpeg2000Codestream(data) {
262
279
  tileParts.push(readTilePart(cursor, siz.components.length, comments));
263
280
  continue;
264
281
  }
265
- if (marker === MARKER_SOD || marker === MARKER_SOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`unexpected marker 0x${marker.toString(16)} in the main header`);
282
+ if (marker === MARKER_SOD || marker === MARKER_SOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`unexpected marker 0x${marker.toString(HEX_RADIX)} in the main header`);
266
283
  readHeaderSegment(marker, cursor, main, siz.components.length, comments);
267
284
  }
268
285
  validateMainHeader(main);
@@ -279,11 +296,12 @@ function parseJpeg2000Codestream(data) {
279
296
  truncated: !sawEoc
280
297
  };
281
298
  }
299
+ const SOT_SEGMENT_LENGTH = 10;
282
300
  function readTilePart(cursor, componentCount, comments) {
283
301
  const sotStart = cursor.position;
284
302
  cursor.uint16();
285
303
  const lsot = cursor.uint16();
286
- if (lsot !== 10) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`SOT declares a length of ${String(lsot)}, but ISO/IEC 15444-1 A.4.2 fixes it at 10`);
304
+ if (lsot !== SOT_SEGMENT_LENGTH) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`SOT declares a length of ${String(lsot)}, but ISO/IEC 15444-1 A.4.2 fixes it at 10`);
287
305
  const tileIndex = cursor.uint16();
288
306
  const psot = cursor.uint32();
289
307
  const partIndex = cursor.uint8();
@@ -293,7 +311,7 @@ function readTilePart(cursor, componentCount, comments) {
293
311
  if (cursor.remaining < 2) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("a tile-part header ended without an SOD marker");
294
312
  const marker = cursor.uint16();
295
313
  if (marker === MARKER_SOD) break;
296
- if (marker === MARKER_SOT || marker === MARKER_EOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`a tile-part header ended at marker 0x${marker.toString(16)} rather than at SOD`);
314
+ if (marker === MARKER_SOT || marker === MARKER_EOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`a tile-part header ended at marker 0x${marker.toString(HEX_RADIX)} rather than at SOD`);
297
315
  readHeaderSegment(marker, cursor, header, componentCount, comments);
298
316
  }
299
317
  const dataStart = cursor.position;
@@ -310,8 +328,10 @@ function readTilePart(cursor, componentCount, comments) {
310
328
  dataEnd: trimmedEnd
311
329
  };
312
330
  }
331
+ const MARKER_EOC_HIGH_BYTE = 255;
332
+ const MARKER_EOC_LOW_BYTE = 217;
313
333
  function trimTrailingEoc(data, end) {
314
- if (data[end - 2] === 255 && data[end - 1] === 217) return end - 2;
334
+ if (data[end - 2] === MARKER_EOC_HIGH_BYTE && data[end - 1] === MARKER_EOC_LOW_BYTE) return end - 2;
315
335
  return end;
316
336
  }
317
337
  //#endregion
@@ -14,6 +14,11 @@ const MARKER_COM = 65380;
14
14
  const MARKER_SOT = 65424;
15
15
  const MARKER_SOD = 65427;
16
16
  const MARKER_EOC = 65497;
17
+ const BITS_PER_BYTE = 8;
18
+ const HEX_RADIX = 16;
19
+ const NIBBLE_MASK = 15;
20
+ const NIBBLE_BITS = 4;
21
+ const UINT16_MODULUS = 65536;
17
22
  var MarkerCursor = class {
18
23
  data;
19
24
  position;
@@ -31,10 +36,10 @@ var MarkerCursor = class {
31
36
  return value;
32
37
  }
33
38
  uint16() {
34
- return this.uint8() << 8 | this.uint8();
39
+ return this.uint8() << BITS_PER_BYTE | this.uint8();
35
40
  }
36
41
  uint32() {
37
- return this.uint16() * 65536 + this.uint16();
42
+ return this.uint16() * UINT16_MODULUS + this.uint16();
38
43
  }
39
44
  bytes(length) {
40
45
  if (length < 0 || this.position + length > this.data.length) throw new Jpeg2000ParseError("a JPEG 2000 marker segment declares more data than the codestream carries");
@@ -43,6 +48,9 @@ var MarkerCursor = class {
43
48
  return slice;
44
49
  }
45
50
  };
51
+ const SIZ_COMPONENT_RECORD_SIZE = 3;
52
+ const SSIZ_SIGNED_BIT = 128;
53
+ const SSIZ_BIT_DEPTH_MASK = 127;
46
54
  function readImageSize(cursor, segmentEnd) {
47
55
  cursor.uint16();
48
56
  const xsiz = cursor.uint32();
@@ -55,13 +63,13 @@ function readImageSize(cursor, segmentEnd) {
55
63
  const ytosiz = cursor.uint32();
56
64
  const count = cursor.uint16();
57
65
  if (count === 0) throw new Jpeg2000ParseError("SIZ declares zero components");
58
- if (cursor.position + count * 3 > segmentEnd) throw new Jpeg2000ParseError(`SIZ declares ${String(count)} components but its own length leaves room for fewer`);
66
+ if (cursor.position + count * SIZ_COMPONENT_RECORD_SIZE > segmentEnd) throw new Jpeg2000ParseError(`SIZ declares ${String(count)} components but its own length leaves room for fewer`);
59
67
  const components = [];
60
68
  for (let i = 0; i < count; i++) {
61
69
  const ssiz = cursor.uint8();
62
70
  components.push({
63
- signed: (ssiz & 128) !== 0,
64
- bitDepth: (ssiz & 127) + 1,
71
+ signed: (ssiz & SSIZ_SIGNED_BIT) !== 0,
72
+ bitDepth: (ssiz & SSIZ_BIT_DEPTH_MASK) + 1,
65
73
  dx: cursor.uint8(),
66
74
  dy: cursor.uint8()
67
75
  });
@@ -81,20 +89,21 @@ function readImageSize(cursor, segmentEnd) {
81
89
  };
82
90
  }
83
91
  const DEFAULT_PRECINCT_EXPONENT = 15;
92
+ const CODE_BLOCK_AREA_EXPONENT_MAX = 12;
84
93
  function readCodingStyleParameters(cursor, explicitPrecincts) {
85
94
  const decompositionLevels = cursor.uint8();
86
- const codeBlockWidthExp = (cursor.uint8() & 15) + 2;
87
- const codeBlockHeightExp = (cursor.uint8() & 15) + 2;
95
+ const codeBlockWidthExp = (cursor.uint8() & NIBBLE_MASK) + 2;
96
+ const codeBlockHeightExp = (cursor.uint8() & NIBBLE_MASK) + 2;
88
97
  const codeBlockStyle = cursor.uint8();
89
98
  const transformCode = cursor.uint8();
90
99
  if (transformCode !== 0 && transformCode !== 1) throw new Jpeg2000ParseError(`SPcod/SPcoc declares transformation ${String(transformCode)}, which is neither of the two ISO/IEC 15444-1 defines`);
91
- if (codeBlockWidthExp + codeBlockHeightExp > 12) throw new Jpeg2000ParseError(`code-block size 2^${String(codeBlockWidthExp)} by 2^${String(codeBlockHeightExp)} is outside the range ISO/IEC 15444-1 Table A.18 permits`);
100
+ if (codeBlockWidthExp + codeBlockHeightExp > CODE_BLOCK_AREA_EXPONENT_MAX) throw new Jpeg2000ParseError(`code-block size 2^${String(codeBlockWidthExp)} by 2^${String(codeBlockHeightExp)} is outside the range ISO/IEC 15444-1 Table A.18 permits`);
92
101
  const precinctSizes = [];
93
102
  if (explicitPrecincts) for (let r = 0; r <= decompositionLevels; r++) {
94
103
  const packed = cursor.uint8();
95
104
  precinctSizes.push({
96
- ppx: packed & 15,
97
- ppy: packed >> 4 & 15
105
+ ppx: packed & NIBBLE_MASK,
106
+ ppy: packed >> NIBBLE_BITS & NIBBLE_MASK
98
107
  });
99
108
  }
100
109
  else for (let r = 0; r <= decompositionLevels; r++) precinctSizes.push({
@@ -110,6 +119,7 @@ function readCodingStyleParameters(cursor, explicitPrecincts) {
110
119
  precinctSizes
111
120
  };
112
121
  }
122
+ const SCOD_USE_EPH_BIT = 4;
113
123
  function readCodingDefaults(cursor) {
114
124
  const progressionOrders = [
115
125
  "LRCP",
@@ -130,17 +140,22 @@ function readCodingDefaults(cursor) {
130
140
  layers,
131
141
  multipleComponentTransform,
132
142
  useSop: (scod & 2) !== 0,
133
- useEph: (scod & 4) !== 0
143
+ useEph: (scod & SCOD_USE_EPH_BIT) !== 0
134
144
  };
135
145
  }
146
+ const SQCD_GUARD_BITS_SHIFT = 5;
147
+ const SQCD_STYLE_MASK = 31;
148
+ const SPQCD_NONE_EXPONENT_SHIFT = 3;
149
+ const SPQCD_EXPONENT_SHIFT = 11;
150
+ const SPQCD_MANTISSA_MASK = 2047;
136
151
  function readQuantization(cursor, segmentEnd) {
137
152
  const sq = cursor.uint8();
138
- const guardBits = sq >> 5;
139
- const styleCode = sq & 31;
153
+ const guardBits = sq >> SQCD_GUARD_BITS_SHIFT;
154
+ const styleCode = sq & SQCD_STYLE_MASK;
140
155
  const stepSizes = [];
141
156
  if (styleCode === 0) {
142
157
  while (cursor.position < segmentEnd) stepSizes.push({
143
- exponent: cursor.uint8() >> 3,
158
+ exponent: cursor.uint8() >> SPQCD_NONE_EXPONENT_SHIFT,
144
159
  mantissa: 0
145
160
  });
146
161
  return {
@@ -153,8 +168,8 @@ function readQuantization(cursor, segmentEnd) {
153
168
  while (cursor.position + 1 < segmentEnd) {
154
169
  const packed = cursor.uint16();
155
170
  stepSizes.push({
156
- exponent: packed >> 11,
157
- mantissa: packed & 2047
171
+ exponent: packed >> SPQCD_EXPONENT_SHIFT,
172
+ mantissa: packed & SPQCD_MANTISSA_MASK
158
173
  });
159
174
  }
160
175
  return {
@@ -165,8 +180,9 @@ function readQuantization(cursor, segmentEnd) {
165
180
  }
166
181
  throw new Jpeg2000ParseError(`QCD/QCC declares quantization style ${String(styleCode)}, which ISO/IEC 15444-1 Table A.28 does not define`);
167
182
  }
183
+ const COMPONENT_INDEX_WIDTH_THRESHOLD = 257;
168
184
  function readComponentIndex(cursor, componentCount) {
169
- return componentCount < 257 ? cursor.uint8() : cursor.uint16();
185
+ return componentCount < COMPONENT_INDEX_WIDTH_THRESHOLD ? cursor.uint8() : cursor.uint16();
170
186
  }
171
187
  function emptyHeader() {
172
188
  return {
@@ -211,9 +227,9 @@ var CodestreamComments = class {
211
227
  };
212
228
  function readHeaderSegment(marker, cursor, header, componentCount, comments) {
213
229
  const length = cursor.uint16();
214
- if (length < 2) throw new Jpeg2000ParseError(`marker segment 0x${marker.toString(16)} declares a length of ${String(length)}, which is shorter than the length field itself`);
230
+ if (length < 2) throw new Jpeg2000ParseError(`marker segment 0x${marker.toString(HEX_RADIX)} declares a length of ${String(length)}, which is shorter than the length field itself`);
215
231
  const segmentEnd = cursor.position + length - 2;
216
- if (segmentEnd > cursor.data.length) throw new Jpeg2000ParseError(`marker segment 0x${marker.toString(16)} declares more data than the codestream carries`);
232
+ if (segmentEnd > cursor.data.length) throw new Jpeg2000ParseError(`marker segment 0x${marker.toString(HEX_RADIX)} declares more data than the codestream carries`);
217
233
  if (marker === MARKER_COD) header.cod = readCodingDefaults(cursor);
218
234
  else if (marker === MARKER_COC) {
219
235
  const component = readComponentIndex(cursor, componentCount);
@@ -236,9 +252,10 @@ function validateMainHeader(header) {
236
252
  if (header.cod === void 0) throw new Jpeg2000ParseError("the main header carries no COD marker, so no coding style is defined for any tile");
237
253
  if (header.qcd === void 0) throw new Jpeg2000ParseError("the main header carries no QCD marker, so no quantization is defined for any tile");
238
254
  }
255
+ const MIN_HEADER_BYTES = 4;
239
256
  function parseJpeg2000Codestream(data) {
240
257
  const cursor = new MarkerCursor(data);
241
- if (cursor.remaining < 4 || cursor.uint16() !== MARKER_SOC) throw new Jpeg2000ParseError("codestream does not begin with an SOC marker");
258
+ if (cursor.remaining < MIN_HEADER_BYTES || cursor.uint16() !== MARKER_SOC) throw new Jpeg2000ParseError("codestream does not begin with an SOC marker");
242
259
  if (cursor.uint16() !== MARKER_SIZ) throw new Jpeg2000ParseError("the SOC marker is not immediately followed by SIZ, which ISO/IEC 15444-1 A.3 requires");
243
260
  const sizLength = cursor.uint16();
244
261
  const sizEnd = cursor.position + sizLength - 2;
@@ -261,7 +278,7 @@ function parseJpeg2000Codestream(data) {
261
278
  tileParts.push(readTilePart(cursor, siz.components.length, comments));
262
279
  continue;
263
280
  }
264
- if (marker === MARKER_SOD || marker === MARKER_SOC) throw new Jpeg2000ParseError(`unexpected marker 0x${marker.toString(16)} in the main header`);
281
+ if (marker === MARKER_SOD || marker === MARKER_SOC) throw new Jpeg2000ParseError(`unexpected marker 0x${marker.toString(HEX_RADIX)} in the main header`);
265
282
  readHeaderSegment(marker, cursor, main, siz.components.length, comments);
266
283
  }
267
284
  validateMainHeader(main);
@@ -278,11 +295,12 @@ function parseJpeg2000Codestream(data) {
278
295
  truncated: !sawEoc
279
296
  };
280
297
  }
298
+ const SOT_SEGMENT_LENGTH = 10;
281
299
  function readTilePart(cursor, componentCount, comments) {
282
300
  const sotStart = cursor.position;
283
301
  cursor.uint16();
284
302
  const lsot = cursor.uint16();
285
- if (lsot !== 10) throw new Jpeg2000ParseError(`SOT declares a length of ${String(lsot)}, but ISO/IEC 15444-1 A.4.2 fixes it at 10`);
303
+ if (lsot !== SOT_SEGMENT_LENGTH) throw new Jpeg2000ParseError(`SOT declares a length of ${String(lsot)}, but ISO/IEC 15444-1 A.4.2 fixes it at 10`);
286
304
  const tileIndex = cursor.uint16();
287
305
  const psot = cursor.uint32();
288
306
  const partIndex = cursor.uint8();
@@ -292,7 +310,7 @@ function readTilePart(cursor, componentCount, comments) {
292
310
  if (cursor.remaining < 2) throw new Jpeg2000ParseError("a tile-part header ended without an SOD marker");
293
311
  const marker = cursor.uint16();
294
312
  if (marker === MARKER_SOD) break;
295
- if (marker === MARKER_SOT || marker === MARKER_EOC) throw new Jpeg2000ParseError(`a tile-part header ended at marker 0x${marker.toString(16)} rather than at SOD`);
313
+ if (marker === MARKER_SOT || marker === MARKER_EOC) throw new Jpeg2000ParseError(`a tile-part header ended at marker 0x${marker.toString(HEX_RADIX)} rather than at SOD`);
296
314
  readHeaderSegment(marker, cursor, header, componentCount, comments);
297
315
  }
298
316
  const dataStart = cursor.position;
@@ -309,8 +327,10 @@ function readTilePart(cursor, componentCount, comments) {
309
327
  dataEnd: trimmedEnd
310
328
  };
311
329
  }
330
+ const MARKER_EOC_HIGH_BYTE = 255;
331
+ const MARKER_EOC_LOW_BYTE = 217;
312
332
  function trimTrailingEoc(data, end) {
313
- if (data[end - 2] === 255 && data[end - 1] === 217) return end - 2;
333
+ if (data[end - 2] === MARKER_EOC_HIGH_BYTE && data[end - 1] === MARKER_EOC_LOW_BYTE) return end - 2;
314
334
  return end;
315
335
  }
316
336
  //#endregion
@@ -30,13 +30,14 @@ function interleave(source, bounds, write) {
30
30
  for (let v = sub.hV0; v < sub.hV1; v++) for (let u = sub.llU0; u < sub.llU1; u++) write(2 * u, 2 * v + 1, source.lh(u, v));
31
31
  for (let v = sub.hV0; v < sub.hV1; v++) for (let u = sub.hU0; u < sub.hU1; u++) write(2 * u + 1, 2 * v + 1, source.hh(u, v));
32
32
  }
33
+ const LOW_PASS_UPDATE_DIVISOR = 4;
33
34
  function inverse53Filter(buffer, i0, i1) {
34
35
  const base = EXTENSION_MARGIN - i0;
35
36
  const first = Math.floor(i0 / 2) - 1;
36
37
  const last = Math.floor(i1 / 2) + 1;
37
38
  for (let n = first; n <= last; n++) {
38
39
  const index = base + 2 * n;
39
- buffer[index] = (buffer[index] ?? 0) - Math.floor(((buffer[index - 1] ?? 0) + (buffer[index + 1] ?? 0) + 2) / 4);
40
+ buffer[index] = (buffer[index] ?? 0) - Math.floor(((buffer[index - 1] ?? 0) + (buffer[index + 1] ?? 0) + 2) / LOW_PASS_UPDATE_DIVISOR);
40
41
  }
41
42
  for (let n = first; n < last; n++) {
42
43
  const index = base + 2 * n + 1;
@@ -29,13 +29,14 @@ function interleave(source, bounds, write) {
29
29
  for (let v = sub.hV0; v < sub.hV1; v++) for (let u = sub.llU0; u < sub.llU1; u++) write(2 * u, 2 * v + 1, source.lh(u, v));
30
30
  for (let v = sub.hV0; v < sub.hV1; v++) for (let u = sub.hU0; u < sub.hU1; u++) write(2 * u + 1, 2 * v + 1, source.hh(u, v));
31
31
  }
32
+ const LOW_PASS_UPDATE_DIVISOR = 4;
32
33
  function inverse53Filter(buffer, i0, i1) {
33
34
  const base = EXTENSION_MARGIN - i0;
34
35
  const first = Math.floor(i0 / 2) - 1;
35
36
  const last = Math.floor(i1 / 2) + 1;
36
37
  for (let n = first; n <= last; n++) {
37
38
  const index = base + 2 * n;
38
- buffer[index] = (buffer[index] ?? 0) - Math.floor(((buffer[index - 1] ?? 0) + (buffer[index + 1] ?? 0) + 2) / 4);
39
+ buffer[index] = (buffer[index] ?? 0) - Math.floor(((buffer[index - 1] ?? 0) + (buffer[index + 1] ?? 0) + 2) / LOW_PASS_UPDATE_DIVISOR);
39
40
  }
40
41
  for (let n = first; n < last; n++) {
41
42
  const index = base + 2 * n + 1;
@@ -15,7 +15,9 @@ const STYLE_TERMINATE_ALL = 4;
15
15
  const STYLE_VERTICALLY_CAUSAL = 8;
16
16
  const STYLE_SEGMENTATION_SYMBOLS = 32;
17
17
  const SEGMENTATION_SYMBOL = 10;
18
+ const SEGMENTATION_SYMBOL_MSB_SHIFT = 3;
18
19
  const STRIPE_HEIGHT = 4;
20
+ const HEX_RADIX = 16;
19
21
  const PASS_SIGNIFICANCE = 0;
20
22
  const PASS_REFINEMENT = 1;
21
23
  const PASS_CLEANUP = 2;
@@ -23,25 +25,33 @@ function throwForUnsupportedStyle(style) {
23
25
  if ((style & STYLE_SELECTIVE_BYPASS) !== 0) throw new require_image_jpeg2000_errors.Jpeg2000UnsupportedError("the code-block style enables selective arithmetic coding bypass (lazy mode), which splits a code-block into raw and arithmetically coded segments this decoder does not read");
24
26
  if ((style & STYLE_TERMINATE_ALL) !== 0) throw new require_image_jpeg2000_errors.Jpeg2000UnsupportedError("the code-block style terminates the arithmetic coder on every coding pass, which splits a code-block into one segment per pass this decoder does not read");
25
27
  }
28
+ const ZC_CONTEXT_3 = 3;
29
+ const ZC_CONTEXT_4 = 4;
30
+ const ZC_CONTEXT_5 = 5;
31
+ const ZC_CONTEXT_6 = 6;
32
+ const ZC_CONTEXT_7 = 7;
33
+ const ZC_CONTEXT_8 = 8;
34
+ const HH_DIAGONAL_NEIGHBOURS_HIGH = 3;
26
35
  function zeroCodingContext(subband, horizontal, vertical, diagonal) {
27
36
  if (subband === "HH") {
28
37
  const straight = horizontal + vertical;
29
- if (diagonal >= 3) return 8;
30
- if (diagonal === 2) return straight >= 1 ? 7 : 6;
31
- if (diagonal === 1) return straight >= 2 ? 5 : straight === 1 ? 4 : 3;
38
+ if (diagonal >= HH_DIAGONAL_NEIGHBOURS_HIGH) return ZC_CONTEXT_8;
39
+ if (diagonal === 2) return straight >= 1 ? ZC_CONTEXT_7 : ZC_CONTEXT_6;
40
+ if (diagonal === 1) return straight >= 2 ? ZC_CONTEXT_5 : straight === 1 ? ZC_CONTEXT_4 : ZC_CONTEXT_3;
32
41
  return straight >= 2 ? 2 : straight === 1 ? 1 : 0;
33
42
  }
34
43
  const primary = subband === "HL" ? vertical : horizontal;
35
44
  const secondary = subband === "HL" ? horizontal : vertical;
36
- if (primary === 2) return 8;
45
+ if (primary === 2) return ZC_CONTEXT_8;
37
46
  if (primary === 1) {
38
- if (secondary >= 1) return 7;
39
- return diagonal >= 1 ? 6 : 5;
47
+ if (secondary >= 1) return ZC_CONTEXT_7;
48
+ return diagonal >= 1 ? ZC_CONTEXT_6 : ZC_CONTEXT_5;
40
49
  }
41
- if (secondary === 2) return 4;
42
- if (secondary === 1) return 3;
50
+ if (secondary === 2) return ZC_CONTEXT_4;
51
+ if (secondary === 1) return ZC_CONTEXT_3;
43
52
  return diagonal >= 2 ? 2 : diagonal === 1 ? 1 : 0;
44
53
  }
54
+ const SIGN_CONTEXT_TABLE_ROW_STRIDE = 3;
45
55
  const SIGN_XOR_FLAG = 8;
46
56
  const SIGN_CONTEXT_TABLE = [
47
57
  12,
@@ -102,7 +112,7 @@ function decodeJpeg2000CodeBlock(options) {
102
112
  const below = belowVisible(y, stripeEnd);
103
113
  const horizontal = clampToUnit(contribution(n - 1) + contribution(n + 1));
104
114
  const vertical = clampToUnit(contribution(n - stride) + (below ? contribution(n + stride) : 0));
105
- const packed = SIGN_CONTEXT_TABLE[(horizontal + 1) * 3 + (vertical + 1)] ?? 0;
115
+ const packed = SIGN_CONTEXT_TABLE[(horizontal + 1) * SIGN_CONTEXT_TABLE_ROW_STRIDE + (vertical + 1)] ?? 0;
106
116
  const decision = mq.decode(contexts, SIGN_CONTEXT_BASE + (packed & -9));
107
117
  negative[n] = decision ^ ((packed & SIGN_XOR_FLAG) !== 0 ? 1 : 0);
108
118
  };
@@ -160,8 +170,8 @@ function decodeJpeg2000CodeBlock(options) {
160
170
  }
161
171
  }
162
172
  if (segmentationSymbols) {
163
- const symbol = mq.decode(contexts, UNIFORM_CONTEXT) << 3 | mq.decode(contexts, UNIFORM_CONTEXT) << 2 | mq.decode(contexts, UNIFORM_CONTEXT) << 1 | mq.decode(contexts, UNIFORM_CONTEXT);
164
- if (symbol !== SEGMENTATION_SYMBOL) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`a cleanup pass ended with segmentation symbol 0x${symbol.toString(16)} rather than the 0xA ISO/IEC 15444-1 D.3.4 requires, so this code-block's coded data is corrupt`);
173
+ const symbol = mq.decode(contexts, UNIFORM_CONTEXT) << SEGMENTATION_SYMBOL_MSB_SHIFT | mq.decode(contexts, UNIFORM_CONTEXT) << 2 | mq.decode(contexts, UNIFORM_CONTEXT) << 1 | mq.decode(contexts, UNIFORM_CONTEXT);
174
+ if (symbol !== SEGMENTATION_SYMBOL) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`a cleanup pass ended with segmentation symbol 0x${symbol.toString(HEX_RADIX)} rather than the 0xA ISO/IEC 15444-1 D.3.4 requires, so this code-block's coded data is corrupt`);
165
175
  }
166
176
  codedThisPlane.fill(0);
167
177
  };
@@ -14,7 +14,9 @@ const STYLE_TERMINATE_ALL = 4;
14
14
  const STYLE_VERTICALLY_CAUSAL = 8;
15
15
  const STYLE_SEGMENTATION_SYMBOLS = 32;
16
16
  const SEGMENTATION_SYMBOL = 10;
17
+ const SEGMENTATION_SYMBOL_MSB_SHIFT = 3;
17
18
  const STRIPE_HEIGHT = 4;
19
+ const HEX_RADIX = 16;
18
20
  const PASS_SIGNIFICANCE = 0;
19
21
  const PASS_REFINEMENT = 1;
20
22
  const PASS_CLEANUP = 2;
@@ -22,25 +24,33 @@ function throwForUnsupportedStyle(style) {
22
24
  if ((style & STYLE_SELECTIVE_BYPASS) !== 0) throw new Jpeg2000UnsupportedError("the code-block style enables selective arithmetic coding bypass (lazy mode), which splits a code-block into raw and arithmetically coded segments this decoder does not read");
23
25
  if ((style & STYLE_TERMINATE_ALL) !== 0) throw new Jpeg2000UnsupportedError("the code-block style terminates the arithmetic coder on every coding pass, which splits a code-block into one segment per pass this decoder does not read");
24
26
  }
27
+ const ZC_CONTEXT_3 = 3;
28
+ const ZC_CONTEXT_4 = 4;
29
+ const ZC_CONTEXT_5 = 5;
30
+ const ZC_CONTEXT_6 = 6;
31
+ const ZC_CONTEXT_7 = 7;
32
+ const ZC_CONTEXT_8 = 8;
33
+ const HH_DIAGONAL_NEIGHBOURS_HIGH = 3;
25
34
  function zeroCodingContext(subband, horizontal, vertical, diagonal) {
26
35
  if (subband === "HH") {
27
36
  const straight = horizontal + vertical;
28
- if (diagonal >= 3) return 8;
29
- if (diagonal === 2) return straight >= 1 ? 7 : 6;
30
- if (diagonal === 1) return straight >= 2 ? 5 : straight === 1 ? 4 : 3;
37
+ if (diagonal >= HH_DIAGONAL_NEIGHBOURS_HIGH) return ZC_CONTEXT_8;
38
+ if (diagonal === 2) return straight >= 1 ? ZC_CONTEXT_7 : ZC_CONTEXT_6;
39
+ if (diagonal === 1) return straight >= 2 ? ZC_CONTEXT_5 : straight === 1 ? ZC_CONTEXT_4 : ZC_CONTEXT_3;
31
40
  return straight >= 2 ? 2 : straight === 1 ? 1 : 0;
32
41
  }
33
42
  const primary = subband === "HL" ? vertical : horizontal;
34
43
  const secondary = subband === "HL" ? horizontal : vertical;
35
- if (primary === 2) return 8;
44
+ if (primary === 2) return ZC_CONTEXT_8;
36
45
  if (primary === 1) {
37
- if (secondary >= 1) return 7;
38
- return diagonal >= 1 ? 6 : 5;
46
+ if (secondary >= 1) return ZC_CONTEXT_7;
47
+ return diagonal >= 1 ? ZC_CONTEXT_6 : ZC_CONTEXT_5;
39
48
  }
40
- if (secondary === 2) return 4;
41
- if (secondary === 1) return 3;
49
+ if (secondary === 2) return ZC_CONTEXT_4;
50
+ if (secondary === 1) return ZC_CONTEXT_3;
42
51
  return diagonal >= 2 ? 2 : diagonal === 1 ? 1 : 0;
43
52
  }
53
+ const SIGN_CONTEXT_TABLE_ROW_STRIDE = 3;
44
54
  const SIGN_XOR_FLAG = 8;
45
55
  const SIGN_CONTEXT_TABLE = [
46
56
  12,
@@ -101,7 +111,7 @@ function decodeJpeg2000CodeBlock(options) {
101
111
  const below = belowVisible(y, stripeEnd);
102
112
  const horizontal = clampToUnit(contribution(n - 1) + contribution(n + 1));
103
113
  const vertical = clampToUnit(contribution(n - stride) + (below ? contribution(n + stride) : 0));
104
- const packed = SIGN_CONTEXT_TABLE[(horizontal + 1) * 3 + (vertical + 1)] ?? 0;
114
+ const packed = SIGN_CONTEXT_TABLE[(horizontal + 1) * SIGN_CONTEXT_TABLE_ROW_STRIDE + (vertical + 1)] ?? 0;
105
115
  const decision = mq.decode(contexts, SIGN_CONTEXT_BASE + (packed & -9));
106
116
  negative[n] = decision ^ ((packed & SIGN_XOR_FLAG) !== 0 ? 1 : 0);
107
117
  };
@@ -159,8 +169,8 @@ function decodeJpeg2000CodeBlock(options) {
159
169
  }
160
170
  }
161
171
  if (segmentationSymbols) {
162
- const symbol = mq.decode(contexts, UNIFORM_CONTEXT) << 3 | mq.decode(contexts, UNIFORM_CONTEXT) << 2 | mq.decode(contexts, UNIFORM_CONTEXT) << 1 | mq.decode(contexts, UNIFORM_CONTEXT);
163
- if (symbol !== SEGMENTATION_SYMBOL) throw new Jpeg2000ParseError(`a cleanup pass ended with segmentation symbol 0x${symbol.toString(16)} rather than the 0xA ISO/IEC 15444-1 D.3.4 requires, so this code-block's coded data is corrupt`);
172
+ const symbol = mq.decode(contexts, UNIFORM_CONTEXT) << SEGMENTATION_SYMBOL_MSB_SHIFT | mq.decode(contexts, UNIFORM_CONTEXT) << 2 | mq.decode(contexts, UNIFORM_CONTEXT) << 1 | mq.decode(contexts, UNIFORM_CONTEXT);
173
+ if (symbol !== SEGMENTATION_SYMBOL) throw new Jpeg2000ParseError(`a cleanup pass ended with segmentation symbol 0x${symbol.toString(HEX_RADIX)} rather than the 0xA ISO/IEC 15444-1 D.3.4 requires, so this code-block's coded data is corrupt`);
164
174
  }
165
175
  codedThisPlane.fill(0);
166
176
  };
@@ -63,8 +63,9 @@ function bandCoordinate(componentCoordinate, levels, orientation) {
63
63
  const half = 2 ** (levels - 1);
64
64
  return Math.ceil((componentCoordinate - half * orientation) / (2 * half));
65
65
  }
66
+ const SUBBANDS_PER_RESOLUTION_LEVEL = 3;
66
67
  function quantizationIndex(resolution, bandIndex) {
67
- return resolution === 0 ? 0 : 3 * (resolution - 1) + bandIndex + 1;
68
+ return resolution === 0 ? 0 : SUBBANDS_PER_RESOLUTION_LEVEL * (resolution - 1) + bandIndex + 1;
68
69
  }
69
70
  function stepSizeFor(quantization, resolution, bandIndex) {
70
71
  if (quantization.style === "derived") {
@@ -203,14 +204,20 @@ function buildTileGeometry(siz, tileX, tileY, codingPerComponent, quantizationPe
203
204
  function subbandGainLog2(type) {
204
205
  return SUBBAND_GAIN_LOG2[type];
205
206
  }
207
+ const CODING_PASSES_RANGE_3_5_BASE = 3;
208
+ const CODING_PASSES_5_BIT_FIELD_WIDTH = 5;
209
+ const CODING_PASSES_5_BIT_FIELD_ESCAPE = 31;
210
+ const CODING_PASSES_RANGE_6_36_BASE = 6;
211
+ const CODING_PASSES_RANGE_37_164_BASE = 37;
212
+ const CODING_PASSES_7_BIT_FIELD_WIDTH = 7;
206
213
  function readCodingPasses(reader) {
207
214
  if (reader.readBit() === 0) return 1;
208
215
  if (reader.readBit() === 0) return 2;
209
216
  const twoBit = reader.readBits(2);
210
- if (twoBit < 3) return 3 + twoBit;
211
- const fiveBit = reader.readBits(5);
212
- if (fiveBit < 31) return 6 + fiveBit;
213
- return 37 + reader.readBits(7);
217
+ if (twoBit < CODING_PASSES_RANGE_3_5_BASE) return CODING_PASSES_RANGE_3_5_BASE + twoBit;
218
+ const fiveBit = reader.readBits(CODING_PASSES_5_BIT_FIELD_WIDTH);
219
+ if (fiveBit < CODING_PASSES_5_BIT_FIELD_ESCAPE) return CODING_PASSES_RANGE_6_36_BASE + fiveBit;
220
+ return CODING_PASSES_RANGE_37_164_BASE + reader.readBits(CODING_PASSES_7_BIT_FIELD_WIDTH);
214
221
  }
215
222
  function buildPacketSequence(tile, order, layers) {
216
223
  const maxResolutions = Math.max(...tile.components.map((component) => component.resolutions.length));
@@ -62,8 +62,9 @@ function bandCoordinate(componentCoordinate, levels, orientation) {
62
62
  const half = 2 ** (levels - 1);
63
63
  return Math.ceil((componentCoordinate - half * orientation) / (2 * half));
64
64
  }
65
+ const SUBBANDS_PER_RESOLUTION_LEVEL = 3;
65
66
  function quantizationIndex(resolution, bandIndex) {
66
- return resolution === 0 ? 0 : 3 * (resolution - 1) + bandIndex + 1;
67
+ return resolution === 0 ? 0 : SUBBANDS_PER_RESOLUTION_LEVEL * (resolution - 1) + bandIndex + 1;
67
68
  }
68
69
  function stepSizeFor(quantization, resolution, bandIndex) {
69
70
  if (quantization.style === "derived") {
@@ -202,14 +203,20 @@ function buildTileGeometry(siz, tileX, tileY, codingPerComponent, quantizationPe
202
203
  function subbandGainLog2(type) {
203
204
  return SUBBAND_GAIN_LOG2[type];
204
205
  }
206
+ const CODING_PASSES_RANGE_3_5_BASE = 3;
207
+ const CODING_PASSES_5_BIT_FIELD_WIDTH = 5;
208
+ const CODING_PASSES_5_BIT_FIELD_ESCAPE = 31;
209
+ const CODING_PASSES_RANGE_6_36_BASE = 6;
210
+ const CODING_PASSES_RANGE_37_164_BASE = 37;
211
+ const CODING_PASSES_7_BIT_FIELD_WIDTH = 7;
205
212
  function readCodingPasses(reader) {
206
213
  if (reader.readBit() === 0) return 1;
207
214
  if (reader.readBit() === 0) return 2;
208
215
  const twoBit = reader.readBits(2);
209
- if (twoBit < 3) return 3 + twoBit;
210
- const fiveBit = reader.readBits(5);
211
- if (fiveBit < 31) return 6 + fiveBit;
212
- return 37 + reader.readBits(7);
216
+ if (twoBit < CODING_PASSES_RANGE_3_5_BASE) return CODING_PASSES_RANGE_3_5_BASE + twoBit;
217
+ const fiveBit = reader.readBits(CODING_PASSES_5_BIT_FIELD_WIDTH);
218
+ if (fiveBit < CODING_PASSES_5_BIT_FIELD_ESCAPE) return CODING_PASSES_RANGE_6_36_BASE + fiveBit;
219
+ return CODING_PASSES_RANGE_37_164_BASE + reader.readBits(CODING_PASSES_7_BIT_FIELD_WIDTH);
213
220
  }
214
221
  function buildPacketSequence(tile, order, layers) {
215
222
  const maxResolutions = Math.max(...tile.components.map((component) => component.resolutions.length));