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
@@ -2,6 +2,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_image_jpeg2000_errors = require("./jpeg2000-errors.cjs");
3
3
  //#region src/image/jpeg2000-tagtree.ts
4
4
  const SENTINEL_VALUE = 2147483647;
5
+ const STUFFING_TRIGGER_BYTE = 255;
6
+ const MOST_SIGNIFICANT_BIT_MASK = 128;
7
+ const STUFFED_BYTE_BIT_COUNT = 7;
8
+ const BYTE_BIT_COUNT = 8;
5
9
  var PacketBitReader = class {
6
10
  data;
7
11
  end;
@@ -28,12 +32,12 @@ var PacketBitReader = class {
28
32
  }
29
33
  readBit() {
30
34
  if (this.available === 0) {
31
- const stuffed = this.previousByte === 255;
35
+ const stuffed = this.previousByte === STUFFING_TRIGGER_BYTE;
32
36
  const byte = this.nextByte();
33
- if (stuffed && (byte & 128) !== 0) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("a packet header byte following 0xFF has its stuffed bit set, which ISO/IEC 15444-1 B.10.1 forbids");
37
+ if (stuffed && (byte & MOST_SIGNIFICANT_BIT_MASK) !== 0) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("a packet header byte following 0xFF has its stuffed bit set, which ISO/IEC 15444-1 B.10.1 forbids");
34
38
  this.buffer = byte;
35
39
  this.previousByte = byte;
36
- this.available = stuffed ? 7 : 8;
40
+ this.available = stuffed ? STUFFED_BYTE_BIT_COUNT : BYTE_BIT_COUNT;
37
41
  }
38
42
  this.available--;
39
43
  return this.buffer >> this.available & 1;
@@ -44,7 +48,7 @@ var PacketBitReader = class {
44
48
  return value;
45
49
  }
46
50
  alignToByte() {
47
- if (this.previousByte === 255) this.nextByte();
51
+ if (this.previousByte === STUFFING_TRIGGER_BYTE) this.nextByte();
48
52
  this.available = 0;
49
53
  this.previousByte = 0;
50
54
  }
@@ -1,6 +1,10 @@
1
1
  import { Jpeg2000ParseError } from "./jpeg2000-errors.js";
2
2
  //#region src/image/jpeg2000-tagtree.ts
3
3
  const SENTINEL_VALUE = 2147483647;
4
+ const STUFFING_TRIGGER_BYTE = 255;
5
+ const MOST_SIGNIFICANT_BIT_MASK = 128;
6
+ const STUFFED_BYTE_BIT_COUNT = 7;
7
+ const BYTE_BIT_COUNT = 8;
4
8
  var PacketBitReader = class {
5
9
  data;
6
10
  end;
@@ -27,12 +31,12 @@ var PacketBitReader = class {
27
31
  }
28
32
  readBit() {
29
33
  if (this.available === 0) {
30
- const stuffed = this.previousByte === 255;
34
+ const stuffed = this.previousByte === STUFFING_TRIGGER_BYTE;
31
35
  const byte = this.nextByte();
32
- if (stuffed && (byte & 128) !== 0) throw new Jpeg2000ParseError("a packet header byte following 0xFF has its stuffed bit set, which ISO/IEC 15444-1 B.10.1 forbids");
36
+ if (stuffed && (byte & MOST_SIGNIFICANT_BIT_MASK) !== 0) throw new Jpeg2000ParseError("a packet header byte following 0xFF has its stuffed bit set, which ISO/IEC 15444-1 B.10.1 forbids");
33
37
  this.buffer = byte;
34
38
  this.previousByte = byte;
35
- this.available = stuffed ? 7 : 8;
39
+ this.available = stuffed ? STUFFED_BYTE_BIT_COUNT : BYTE_BIT_COUNT;
36
40
  }
37
41
  this.available--;
38
42
  return this.buffer >> this.available & 1;
@@ -43,7 +47,7 @@ var PacketBitReader = class {
43
47
  return value;
44
48
  }
45
49
  alignToByte() {
46
- if (this.previousByte === 255) this.nextByte();
50
+ if (this.previousByte === STUFFING_TRIGGER_BYTE) this.nextByte();
47
51
  this.available = 0;
48
52
  this.previousByte = 0;
49
53
  }
@@ -29,6 +29,8 @@ function tileDefaults(main, tile) {
29
29
  if (main.cod === void 0) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("no COD marker defines a coding style for this codestream");
30
30
  return main.cod;
31
31
  }
32
+ const CODE_BLOCK_STYLE_TERMINATE_ON_EACH_PASS_BIT = 4;
33
+ const MAX_SUPPORTED_COMPONENT_BIT_DEPTH = 31;
32
34
  function undecodableReason(codestream) {
33
35
  const main = codestream.main;
34
36
  const cod = main.cod;
@@ -46,7 +48,7 @@ function undecodableReason(codestream) {
46
48
  for (const header of headers) {
47
49
  const style = resolveCoding(main, header === main ? void 0 : header, c);
48
50
  if ((style.codeBlockStyle & 1) !== 0) return "the code-block style enables selective arithmetic coding bypass, which this decoder does not read";
49
- if ((style.codeBlockStyle & 4) !== 0) return "the code-block style terminates the arithmetic coder on every coding pass, which this decoder does not read";
51
+ if ((style.codeBlockStyle & CODE_BLOCK_STYLE_TERMINATE_ON_EACH_PASS_BIT) !== 0) return "the code-block style terminates the arithmetic coder on every coding pass, which this decoder does not read";
50
52
  }
51
53
  }
52
54
  for (const part of codestream.tileParts) {
@@ -60,7 +62,7 @@ function undecodableReason(codestream) {
60
62
  const first = codestream.siz.components[0];
61
63
  if (first !== void 0) {
62
64
  for (const size of codestream.siz.components) if (size.bitDepth !== first.bitDepth || size.signed !== first.signed) return "the codestream mixes component bit depths or signedness, which this decoder does not combine into one image";
63
- if (first.bitDepth > 31) return `a component bit depth of ${String(first.bitDepth)} exceeds what this decoder's own 32-bit sample arithmetic can hold`;
65
+ if (first.bitDepth > MAX_SUPPORTED_COMPONENT_BIT_DEPTH) return `a component bit depth of ${String(first.bitDepth)} exceeds what this decoder's own 32-bit sample arithmetic can hold`;
64
66
  }
65
67
  }
66
68
  function readJpeg2000Metadata(data) {
@@ -121,8 +123,9 @@ function concatTilePartData(codestream, tileIndex) {
121
123
  function halveTowardZero(value) {
122
124
  return value < 0 ? -(-value >> 1) : value >> 1;
123
125
  }
126
+ const MANTISSA_FIXED_POINT_SCALE = 2048;
124
127
  function quantizationStep(band, componentBitDepth) {
125
- return 2 ** (componentBitDepth + require_image_jpeg2000_t2.subbandGainLog2(band.type) - band.stepSize.exponent) * (1 + band.stepSize.mantissa / 2048);
128
+ return 2 ** (componentBitDepth + require_image_jpeg2000_t2.subbandGainLog2(band.type) - band.stepSize.exponent) * (1 + band.stepSize.mantissa / MANTISSA_FIXED_POINT_SCALE);
126
129
  }
127
130
  function decodeSubbandBlocks(band, codeBlockStyle, data, place) {
128
131
  for (const precinct of band.precincts) for (const block of precinct.codeBlocks) {
@@ -218,13 +221,14 @@ function decodeIrreversibleTileComponent(tile, componentIndex, componentBitDepth
218
221
  }
219
222
  return current;
220
223
  }
224
+ const RCT_GREEN_RECOVERY_DIVISOR = 4;
221
225
  function inverseReversibleComponentTransform(planes) {
222
226
  const y = planes[0];
223
227
  const u = planes[1];
224
228
  const v = planes[2];
225
229
  if (y === void 0 || u === void 0 || v === void 0) return;
226
230
  for (let i = 0; i < y.length; i++) {
227
- const green = (y[i] ?? 0) - Math.floor(((u[i] ?? 0) + (v[i] ?? 0)) / 4);
231
+ const green = (y[i] ?? 0) - Math.floor(((u[i] ?? 0) + (v[i] ?? 0)) / RCT_GREEN_RECOVERY_DIVISOR);
228
232
  const red = (v[i] ?? 0) + green;
229
233
  const blue = (u[i] ?? 0) + green;
230
234
  y[i] = red;
@@ -250,6 +254,7 @@ function inverseIrreversibleComponentTransform(planes) {
250
254
  cr[i] = luma + ICT_BLUE_FROM_CB * blueDiff;
251
255
  }
252
256
  }
257
+ const MULTIPLE_COMPONENT_TRANSFORM_MIN_COMPONENTS = 3;
253
258
  function decodeJpeg2000(data, options = {}) {
254
259
  const onWarning = options.onWarning ?? (() => void 0);
255
260
  const container = require_image_jp2_boxes.parseJp2Container(data);
@@ -285,11 +290,11 @@ function decodeJpeg2000(data, options = {}) {
285
290
  const tilePlanes = [];
286
291
  if (defaults.transform === "reversible-5-3") {
287
292
  const reversible = Array.from({ length: componentCount }, (_, c) => decodeReversibleTileComponent(geometry, c, tileData));
288
- if (defaults.multipleComponentTransform && componentCount >= 3) inverseReversibleComponentTransform(reversible);
293
+ if (defaults.multipleComponentTransform && componentCount >= MULTIPLE_COMPONENT_TRANSFORM_MIN_COMPONENTS) inverseReversibleComponentTransform(reversible);
289
294
  tilePlanes.push(...reversible);
290
295
  } else {
291
296
  const irreversible = Array.from({ length: componentCount }, (_, c) => decodeIrreversibleTileComponent(geometry, c, first.bitDepth, tileData));
292
- if (defaults.multipleComponentTransform && componentCount >= 3) inverseIrreversibleComponentTransform(irreversible);
297
+ if (defaults.multipleComponentTransform && componentCount >= MULTIPLE_COMPONENT_TRANSFORM_MIN_COMPONENTS) inverseIrreversibleComponentTransform(irreversible);
293
298
  tilePlanes.push(...irreversible);
294
299
  }
295
300
  for (let c = 0; c < componentCount; c++) {
@@ -28,6 +28,8 @@ function tileDefaults(main, tile) {
28
28
  if (main.cod === void 0) throw new Jpeg2000ParseError("no COD marker defines a coding style for this codestream");
29
29
  return main.cod;
30
30
  }
31
+ const CODE_BLOCK_STYLE_TERMINATE_ON_EACH_PASS_BIT = 4;
32
+ const MAX_SUPPORTED_COMPONENT_BIT_DEPTH = 31;
31
33
  function undecodableReason(codestream) {
32
34
  const main = codestream.main;
33
35
  const cod = main.cod;
@@ -45,7 +47,7 @@ function undecodableReason(codestream) {
45
47
  for (const header of headers) {
46
48
  const style = resolveCoding(main, header === main ? void 0 : header, c);
47
49
  if ((style.codeBlockStyle & 1) !== 0) return "the code-block style enables selective arithmetic coding bypass, which this decoder does not read";
48
- if ((style.codeBlockStyle & 4) !== 0) return "the code-block style terminates the arithmetic coder on every coding pass, which this decoder does not read";
50
+ if ((style.codeBlockStyle & CODE_BLOCK_STYLE_TERMINATE_ON_EACH_PASS_BIT) !== 0) return "the code-block style terminates the arithmetic coder on every coding pass, which this decoder does not read";
49
51
  }
50
52
  }
51
53
  for (const part of codestream.tileParts) {
@@ -59,7 +61,7 @@ function undecodableReason(codestream) {
59
61
  const first = codestream.siz.components[0];
60
62
  if (first !== void 0) {
61
63
  for (const size of codestream.siz.components) if (size.bitDepth !== first.bitDepth || size.signed !== first.signed) return "the codestream mixes component bit depths or signedness, which this decoder does not combine into one image";
62
- if (first.bitDepth > 31) return `a component bit depth of ${String(first.bitDepth)} exceeds what this decoder's own 32-bit sample arithmetic can hold`;
64
+ if (first.bitDepth > MAX_SUPPORTED_COMPONENT_BIT_DEPTH) return `a component bit depth of ${String(first.bitDepth)} exceeds what this decoder's own 32-bit sample arithmetic can hold`;
63
65
  }
64
66
  }
65
67
  function readJpeg2000Metadata(data) {
@@ -120,8 +122,9 @@ function concatTilePartData(codestream, tileIndex) {
120
122
  function halveTowardZero(value) {
121
123
  return value < 0 ? -(-value >> 1) : value >> 1;
122
124
  }
125
+ const MANTISSA_FIXED_POINT_SCALE = 2048;
123
126
  function quantizationStep(band, componentBitDepth) {
124
- return 2 ** (componentBitDepth + subbandGainLog2(band.type) - band.stepSize.exponent) * (1 + band.stepSize.mantissa / 2048);
127
+ return 2 ** (componentBitDepth + subbandGainLog2(band.type) - band.stepSize.exponent) * (1 + band.stepSize.mantissa / MANTISSA_FIXED_POINT_SCALE);
125
128
  }
126
129
  function decodeSubbandBlocks(band, codeBlockStyle, data, place) {
127
130
  for (const precinct of band.precincts) for (const block of precinct.codeBlocks) {
@@ -217,13 +220,14 @@ function decodeIrreversibleTileComponent(tile, componentIndex, componentBitDepth
217
220
  }
218
221
  return current;
219
222
  }
223
+ const RCT_GREEN_RECOVERY_DIVISOR = 4;
220
224
  function inverseReversibleComponentTransform(planes) {
221
225
  const y = planes[0];
222
226
  const u = planes[1];
223
227
  const v = planes[2];
224
228
  if (y === void 0 || u === void 0 || v === void 0) return;
225
229
  for (let i = 0; i < y.length; i++) {
226
- const green = (y[i] ?? 0) - Math.floor(((u[i] ?? 0) + (v[i] ?? 0)) / 4);
230
+ const green = (y[i] ?? 0) - Math.floor(((u[i] ?? 0) + (v[i] ?? 0)) / RCT_GREEN_RECOVERY_DIVISOR);
227
231
  const red = (v[i] ?? 0) + green;
228
232
  const blue = (u[i] ?? 0) + green;
229
233
  y[i] = red;
@@ -249,6 +253,7 @@ function inverseIrreversibleComponentTransform(planes) {
249
253
  cr[i] = luma + ICT_BLUE_FROM_CB * blueDiff;
250
254
  }
251
255
  }
256
+ const MULTIPLE_COMPONENT_TRANSFORM_MIN_COMPONENTS = 3;
252
257
  function decodeJpeg2000(data, options = {}) {
253
258
  const onWarning = options.onWarning ?? (() => void 0);
254
259
  const container = parseJp2Container(data);
@@ -284,11 +289,11 @@ function decodeJpeg2000(data, options = {}) {
284
289
  const tilePlanes = [];
285
290
  if (defaults.transform === "reversible-5-3") {
286
291
  const reversible = Array.from({ length: componentCount }, (_, c) => decodeReversibleTileComponent(geometry, c, tileData));
287
- if (defaults.multipleComponentTransform && componentCount >= 3) inverseReversibleComponentTransform(reversible);
292
+ if (defaults.multipleComponentTransform && componentCount >= MULTIPLE_COMPONENT_TRANSFORM_MIN_COMPONENTS) inverseReversibleComponentTransform(reversible);
288
293
  tilePlanes.push(...reversible);
289
294
  } else {
290
295
  const irreversible = Array.from({ length: componentCount }, (_, c) => decodeIrreversibleTileComponent(geometry, c, first.bitDepth, tileData));
291
- if (defaults.multipleComponentTransform && componentCount >= 3) inverseIrreversibleComponentTransform(irreversible);
296
+ if (defaults.multipleComponentTransform && componentCount >= MULTIPLE_COMPONENT_TRANSFORM_MIN_COMPONENTS) inverseIrreversibleComponentTransform(irreversible);
292
297
  tilePlanes.push(...irreversible);
293
298
  }
294
299
  for (let c = 0; c < componentCount; c++) {
@@ -4,30 +4,39 @@ const require_bytes_flate = require("../bytes/flate.cjs");
4
4
  const require_image_png_filter = require("./png-filter.cjs");
5
5
  const require_bytes_crc32 = require("../bytes/crc32.cjs");
6
6
  //#region src/image/png-decode.ts
7
+ const PNG_SIGNATURE_HIGH_BIT_MARKER = 137;
8
+ const PNG_SIGNATURE_P = 80;
9
+ const PNG_SIGNATURE_N = 78;
10
+ const PNG_SIGNATURE_G = 71;
11
+ const PNG_SIGNATURE_CR = 13;
12
+ const PNG_SIGNATURE_LF = 10;
7
13
  const PNG_SIGNATURE = [
8
- 137,
9
- 80,
10
- 78,
11
- 71,
12
- 13,
13
- 10,
14
+ PNG_SIGNATURE_HIGH_BIT_MARKER,
15
+ PNG_SIGNATURE_P,
16
+ PNG_SIGNATURE_N,
17
+ PNG_SIGNATURE_G,
18
+ PNG_SIGNATURE_CR,
19
+ PNG_SIGNATURE_LF,
14
20
  26,
15
- 10
21
+ PNG_SIGNATURE_LF
16
22
  ];
17
23
  function requireDataView(bytes) {
18
24
  return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
19
25
  }
26
+ const PNG_CHUNK_LENGTH_SIZE = 4;
27
+ const PNG_CHUNK_CRC_SIZE = 4;
28
+ const PNG_CHUNK_HEADER_SIZE = 8;
20
29
  function readChunks(bytes, onWarning) {
21
30
  const chunks = [];
22
31
  const view = requireDataView(bytes);
23
32
  let offset = PNG_SIGNATURE.length;
24
- while (offset + 8 <= bytes.length) {
33
+ while (offset + PNG_CHUNK_HEADER_SIZE <= bytes.length) {
25
34
  const length = view.getUint32(offset);
26
- const typeBytes = bytes.subarray(offset + 4, offset + 8);
35
+ const typeBytes = bytes.subarray(offset + PNG_CHUNK_LENGTH_SIZE, offset + PNG_CHUNK_HEADER_SIZE);
27
36
  const type = new TextDecoder("latin1").decode(typeBytes);
28
- const dataStart = offset + 8;
37
+ const dataStart = offset + PNG_CHUNK_HEADER_SIZE;
29
38
  const dataEnd = dataStart + length;
30
- if (dataEnd + 4 > bytes.length) throw new Error(`PNG chunk '${type}' declares a length that runs past the end of the file`);
39
+ if (dataEnd + PNG_CHUNK_CRC_SIZE > bytes.length) throw new Error(`PNG chunk '${type}' declares a length that runs past the end of the file`);
31
40
  const data = bytes.subarray(dataStart, dataEnd);
32
41
  if (onWarning !== void 0) {
33
42
  if (view.getUint32(dataEnd) !== require_bytes_crc32.crc32(require_bytes_writer.concatBytes([typeBytes, data]))) onWarning(`PNG chunk '${type}' failed its CRC32 check`);
@@ -36,42 +45,53 @@ function readChunks(bytes, onWarning) {
36
45
  type,
37
46
  data
38
47
  });
39
- offset = dataEnd + 4;
48
+ offset = dataEnd + PNG_CHUNK_CRC_SIZE;
40
49
  if (type === "IEND") break;
41
50
  }
42
51
  return chunks;
43
52
  }
53
+ const IHDR_HEIGHT_OFFSET = 4;
44
54
  function parseIhdr(data) {
45
55
  const view = requireDataView(data);
46
56
  return {
47
57
  width: view.getUint32(0),
48
- height: view.getUint32(4),
58
+ height: view.getUint32(IHDR_HEIGHT_OFFSET),
49
59
  bitDepth: data[8],
50
60
  colorType: data[9],
51
61
  interlace: data[12]
52
62
  };
53
63
  }
64
+ const PNG_COLOR_TYPE_GRAYSCALE = 0;
65
+ const PNG_COLOR_TYPE_TRUECOLOR = 2;
66
+ const PNG_COLOR_TYPE_INDEXED = 3;
67
+ const PNG_COLOR_TYPE_GRAYSCALE_ALPHA = 4;
68
+ const PNG_COLOR_TYPE_TRUECOLOR_ALPHA = 6;
69
+ const PNG_CHANNELS_TRUECOLOR = 3;
70
+ const PNG_CHANNELS_TRUECOLOR_ALPHA = 4;
54
71
  function channelsForColorType(colorType) {
55
- if (colorType === 0) return 1;
56
- if (colorType === 2) return 3;
57
- if (colorType === 3) return 1;
58
- if (colorType === 4) return 2;
59
- if (colorType === 6) return 4;
72
+ if (colorType === PNG_COLOR_TYPE_GRAYSCALE) return 1;
73
+ if (colorType === PNG_COLOR_TYPE_TRUECOLOR) return PNG_CHANNELS_TRUECOLOR;
74
+ if (colorType === PNG_COLOR_TYPE_INDEXED) return 1;
75
+ if (colorType === PNG_COLOR_TYPE_GRAYSCALE_ALPHA) return 2;
76
+ if (colorType === PNG_COLOR_TYPE_TRUECOLOR_ALPHA) return PNG_CHANNELS_TRUECOLOR_ALPHA;
60
77
  throw new Error(`unsupported PNG colour type: ${colorType}`);
61
78
  }
79
+ const BITS_PER_BYTE = 8;
62
80
  function filterBpp(bitDepth, channels) {
63
- return Math.max(1, Math.ceil(bitDepth * channels / 8));
81
+ return Math.max(1, Math.ceil(bitDepth * channels / BITS_PER_BYTE));
64
82
  }
83
+ const PNG_BIT_DEPTH_16 = 16;
84
+ const BYTE_INDEX_SHIFT = 3;
65
85
  function unpackRow(rowBytes, width, channels, bitDepth) {
66
86
  const sampleCount = width * channels;
67
87
  const samples = Array.from({ length: sampleCount });
68
- if (bitDepth === 16) for (let i = 0; i < sampleCount; i++) samples[i] = rowBytes[i * 2];
88
+ if (bitDepth === PNG_BIT_DEPTH_16) for (let i = 0; i < sampleCount; i++) samples[i] = rowBytes[i * 2];
69
89
  else {
70
90
  const mask = (1 << bitDepth) - 1;
71
91
  for (let i = 0; i < sampleCount; i++) {
72
92
  const bitOffset = i * bitDepth;
73
- const byteIndex = bitOffset >> 3;
74
- const shift = 8 - bitDepth - (bitOffset & 7);
93
+ const byteIndex = bitOffset >> BYTE_INDEX_SHIFT;
94
+ const shift = BITS_PER_BYTE - bitDepth - (bitOffset & 7);
75
95
  samples[i] = rowBytes[byteIndex] >> shift & mask;
76
96
  }
77
97
  }
@@ -80,18 +100,20 @@ function unpackRow(rowBytes, width, channels, bitDepth) {
80
100
  function readTrnsGrayValue(trns) {
81
101
  return requireDataView(trns).getUint16(0);
82
102
  }
103
+ const TRNS_RGB_BLUE_OFFSET = 4;
83
104
  function readTrnsRgbKey(trns) {
84
105
  const view = requireDataView(trns);
85
106
  return [
86
107
  view.getUint16(0),
87
108
  view.getUint16(2),
88
- view.getUint16(4)
109
+ view.getUint16(TRNS_RGB_BLUE_OFFSET)
89
110
  ];
90
111
  }
112
+ const MAX_BYTE_VALUE = 255;
91
113
  function scaleToByte(sample, bitDepth) {
92
- if (bitDepth === 16) return sample;
114
+ if (bitDepth === PNG_BIT_DEPTH_16) return sample;
93
115
  const maxSample = (1 << bitDepth) - 1;
94
- return Math.round(sample * 255 / maxSample);
116
+ return Math.round(sample * MAX_BYTE_VALUE / maxSample);
95
117
  }
96
118
  function decodePng(bytes, options = {}) {
97
119
  for (let i = 0; i < PNG_SIGNATURE.length; i++) if (bytes[i] !== PNG_SIGNATURE[i]) throw new Error("not a valid PNG file: bad signature");
@@ -102,23 +124,24 @@ function decodePng(bytes, options = {}) {
102
124
  if (ihdr.interlace !== 0) throw new Error("Adam7-interlaced PNG images are not supported");
103
125
  const channels = channelsForColorType(ihdr.colorType);
104
126
  const bpp = filterBpp(ihdr.bitDepth, channels);
105
- const bytesPerRow = Math.ceil(ihdr.width * channels * ihdr.bitDepth / 8);
127
+ const bytesPerRow = Math.ceil(ihdr.width * channels * ihdr.bitDepth / BITS_PER_BYTE);
106
128
  const idatChunks = chunks.filter((c) => c.type === "IDAT").map((c) => c.data);
107
129
  if (idatChunks.length === 0) throw new Error("PNG file has no IDAT chunks");
108
130
  const compressed = require_bytes_writer.concatBytes(idatChunks);
109
131
  const { bytes: inflated, recovered } = require_bytes_flate.inflateTolerant(compressed);
110
132
  if (recovered && options.onWarning !== void 0) options.onWarning("PNG IDAT stream required tolerant recovery (truncated or malformed)");
111
133
  const unfiltered = require_image_png_filter.unfilterScanlines(inflated, ihdr.height, bytesPerRow, bpp);
112
- const palette = ihdr.colorType === 3 ? chunks.find((c) => c.type === "PLTE")?.data : void 0;
113
- if (ihdr.colorType === 3 && palette === void 0) throw new Error("indexed-colour PNG has no PLTE chunk");
134
+ const palette = ihdr.colorType === PNG_COLOR_TYPE_INDEXED ? chunks.find((c) => c.type === "PLTE")?.data : void 0;
135
+ if (ihdr.colorType === PNG_COLOR_TYPE_INDEXED && palette === void 0) throw new Error("indexed-colour PNG has no PLTE chunk");
114
136
  const trns = chunks.find((c) => c.type === "tRNS")?.data;
115
137
  return buildRawImage(ihdr, channels, bytesPerRow, unfiltered, palette, trns);
116
138
  }
139
+ const ALPHA_SAMPLE_INDEX_IN_RGBA = 3;
117
140
  function buildRawImage(ihdr, channels, bytesPerRow, unfiltered, palette, trns) {
118
141
  const { width, height, bitDepth, colorType } = ihdr;
119
- const outChannels = colorType === 0 || colorType === 4 ? 1 : 3;
142
+ const outChannels = colorType === 0 || colorType === PNG_COLOR_TYPE_GRAYSCALE_ALPHA ? 1 : PNG_CHANNELS_TRUECOLOR;
120
143
  const data = new Uint8Array(width * height * outChannels);
121
- const alpha = colorType === 4 || colorType === 6 || trns !== void 0 ? new Uint8Array(width * height).fill(255) : void 0;
144
+ const alpha = colorType === PNG_COLOR_TYPE_GRAYSCALE_ALPHA || colorType === PNG_COLOR_TYPE_TRUECOLOR_ALPHA || trns !== void 0 ? new Uint8Array(width * height).fill(MAX_BYTE_VALUE) : void 0;
122
145
  const trnsGray = colorType === 0 && trns !== void 0 ? readTrnsGrayValue(trns) : void 0;
123
146
  const trnsRgb = colorType === 2 && trns !== void 0 ? readTrnsRgbKey(trns) : void 0;
124
147
  for (let y = 0; y < height; y++) {
@@ -131,7 +154,7 @@ function buildRawImage(ihdr, channels, bytesPerRow, unfiltered, palette, trns) {
131
154
  if (colorType === 0) {
132
155
  const g = samples[pixelBase];
133
156
  data[outBase] = scaleToByte(g, bitDepth);
134
- if (alpha !== void 0 && trnsGray !== void 0) alpha[alphaIndex] = g === trnsGray ? 0 : 255;
157
+ if (alpha !== void 0 && trnsGray !== void 0) alpha[alphaIndex] = g === trnsGray ? 0 : MAX_BYTE_VALUE;
135
158
  } else if (colorType === 2) {
136
159
  const r = samples[pixelBase];
137
160
  const g = samples[pixelBase + 1];
@@ -141,15 +164,15 @@ function buildRawImage(ihdr, channels, bytesPerRow, unfiltered, palette, trns) {
141
164
  data[outBase + 2] = b;
142
165
  if (alpha !== void 0 && trnsRgb !== void 0) {
143
166
  const [kr, kg, kb] = trnsRgb;
144
- alpha[alphaIndex] = r === kr && g === kg && b === kb ? 0 : 255;
167
+ alpha[alphaIndex] = r === kr && g === kg && b === kb ? 0 : MAX_BYTE_VALUE;
145
168
  }
146
- } else if (colorType === 3) {
169
+ } else if (colorType === PNG_COLOR_TYPE_INDEXED) {
147
170
  const index = samples[pixelBase];
148
- data[outBase] = palette[index * 3];
149
- data[outBase + 1] = palette[index * 3 + 1];
150
- data[outBase + 2] = palette[index * 3 + 2];
151
- if (alpha !== void 0 && trns !== void 0) alpha[alphaIndex] = index < trns.length ? trns[index] : 255;
152
- } else if (colorType === 4) {
171
+ data[outBase] = palette[index * PNG_CHANNELS_TRUECOLOR];
172
+ data[outBase + 1] = palette[index * PNG_CHANNELS_TRUECOLOR + 1];
173
+ data[outBase + 2] = palette[index * PNG_CHANNELS_TRUECOLOR + 2];
174
+ if (alpha !== void 0 && trns !== void 0) alpha[alphaIndex] = index < trns.length ? trns[index] : MAX_BYTE_VALUE;
175
+ } else if (colorType === PNG_COLOR_TYPE_GRAYSCALE_ALPHA) {
153
176
  const g = samples[pixelBase];
154
177
  const a = samples[pixelBase + 1];
155
178
  data[outBase] = scaleToByte(g, bitDepth);
@@ -158,7 +181,7 @@ function buildRawImage(ihdr, channels, bytesPerRow, unfiltered, palette, trns) {
158
181
  data[outBase] = samples[pixelBase];
159
182
  data[outBase + 1] = samples[pixelBase + 1];
160
183
  data[outBase + 2] = samples[pixelBase + 2];
161
- if (alpha !== void 0) alpha[alphaIndex] = samples[pixelBase + 3];
184
+ if (alpha !== void 0) alpha[alphaIndex] = samples[pixelBase + ALPHA_SAMPLE_INDEX_IN_RGBA];
162
185
  }
163
186
  }
164
187
  }
@@ -1,8 +1,9 @@
1
1
  //#region src/image/png-decode.d.ts
2
+ type ImageChannels = 1 | 3;
2
3
  interface RawImage {
3
4
  readonly width: number;
4
5
  readonly height: number;
5
- readonly channels: 1 | 3;
6
+ readonly channels: ImageChannels;
6
7
  readonly data: Uint8Array<ArrayBuffer>;
7
8
  readonly alpha?: Uint8Array<ArrayBuffer>;
8
9
  }
@@ -11,4 +12,4 @@ interface PngDecodeOptions {
11
12
  }
12
13
  declare function decodePng(bytes: Uint8Array<ArrayBuffer>, options?: PngDecodeOptions): RawImage;
13
14
  //#endregion
14
- export { PngDecodeOptions, RawImage, decodePng };
15
+ export { ImageChannels, PngDecodeOptions, RawImage, decodePng };
@@ -1,8 +1,9 @@
1
1
  //#region src/image/png-decode.d.ts
2
+ type ImageChannels = 1 | 3;
2
3
  interface RawImage {
3
4
  readonly width: number;
4
5
  readonly height: number;
5
- readonly channels: 1 | 3;
6
+ readonly channels: ImageChannels;
6
7
  readonly data: Uint8Array<ArrayBuffer>;
7
8
  readonly alpha?: Uint8Array<ArrayBuffer>;
8
9
  }
@@ -11,4 +12,4 @@ interface PngDecodeOptions {
11
12
  }
12
13
  declare function decodePng(bytes: Uint8Array<ArrayBuffer>, options?: PngDecodeOptions): RawImage;
13
14
  //#endregion
14
- export { PngDecodeOptions, RawImage, decodePng };
15
+ export { ImageChannels, PngDecodeOptions, RawImage, decodePng };