pdf-parser.js 5.2.26 → 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.
- package/dist/{afm-widths-BYiX2L9D.cjs → afm-widths-BHD2HZIL.cjs} +553 -642
- package/dist/{afm-widths-blUDDjlI.js → afm-widths-B_IGbGky.js} +553 -642
- package/dist/afm-widths.cjs +1 -1
- package/dist/afm-widths.js +1 -1
- package/dist/annotations.cjs +5 -3
- package/dist/annotations.d.cts +2 -2
- package/dist/annotations.d.ts +2 -2
- package/dist/annotations.js +5 -3
- package/dist/attachments.d.cts +2 -2
- package/dist/attachments.d.ts +2 -2
- package/dist/builtin-encoding.cjs +17 -6
- package/dist/builtin-encoding.js +17 -6
- package/dist/bytes/crc32.cjs +5 -3
- package/dist/bytes/crc32.js +5 -3
- package/dist/bytes/flate.cjs +0 -1
- package/dist/bytes/flate.js +0 -1
- package/dist/cff-bounds.cjs +73 -45
- package/dist/cff-bounds.js +73 -45
- package/dist/cff.cjs +13 -6
- package/dist/cff.js +13 -6
- package/dist/cmap-table.cjs +54 -26
- package/dist/cmap-table.js +54 -26
- package/dist/cmap.cjs +5 -3
- package/dist/cmap.js +5 -3
- package/dist/content-read.d.cts +1 -1
- package/dist/content-read.d.ts +1 -1
- package/dist/content-write.cjs +21 -14
- package/dist/content-write.d.cts +2 -2
- package/dist/content-write.d.ts +2 -2
- package/dist/content-write.js +21 -14
- package/dist/crypto/aes.cjs +76 -55
- package/dist/crypto/aes.js +76 -55
- package/dist/crypto/md5.cjs +345 -149
- package/dist/crypto/md5.js +345 -149
- package/dist/crypto/rc4.cjs +5 -4
- package/dist/crypto/rc4.js +5 -4
- package/dist/crypto/sha2.cjs +92 -43
- package/dist/crypto/sha2.js +92 -43
- package/dist/document.cjs +17 -11
- package/dist/document.d.cts +1 -1
- package/dist/document.d.ts +1 -1
- package/dist/document.js +17 -11
- package/dist/{embedded-font-Bnhh4juV.d.ts → embedded-font-ByD7ZiQS.d.ts} +1 -1
- package/dist/{embedded-font-CEf-zBCA.d.cts → embedded-font-DgVBedw6.d.cts} +1 -1
- package/dist/embedded-font-write.d.cts +2 -2
- package/dist/embedded-font-write.d.ts +2 -2
- package/dist/embedded-font.cjs +4 -2
- package/dist/embedded-font.d.cts +1 -1
- package/dist/embedded-font.d.ts +1 -1
- package/dist/embedded-font.js +4 -2
- package/dist/encoding.cjs +1 -1
- package/dist/encoding.js +1 -1
- package/dist/encrypt-write.cjs +25 -21
- package/dist/encrypt-write.d.cts +1 -1
- package/dist/encrypt-write.d.ts +1 -1
- package/dist/encrypt-write.js +25 -21
- package/dist/encrypt.cjs +43 -64
- package/dist/encrypt.d.cts +1 -1
- package/dist/encrypt.d.ts +1 -1
- package/dist/encrypt.js +43 -64
- package/dist/filters.cjs +46 -26
- package/dist/filters.d.cts +1 -1
- package/dist/filters.d.ts +1 -1
- package/dist/filters.js +46 -26
- package/dist/font-face.cjs +2 -1
- package/dist/font-face.js +2 -1
- package/dist/font-read.cjs +12 -6
- package/dist/font-read.d.cts +1 -1
- package/dist/font-read.d.ts +1 -1
- package/dist/font-read.js +12 -6
- package/dist/font-registry.d.cts +3 -3
- package/dist/font-registry.d.ts +3 -3
- package/dist/font-tables.cjs +55 -28
- package/dist/font-tables.js +55 -28
- package/dist/form.cjs +13 -8
- package/dist/form.d.cts +2 -2
- package/dist/form.d.ts +2 -2
- package/dist/form.js +13 -8
- package/dist/gdef-table.cjs +6 -3
- package/dist/gdef-table.js +6 -3
- package/dist/{glyf-contours-C0epBNqP.d.ts → glyf-contours-B1PsI9oA.d.ts} +1 -1
- package/dist/{glyf-contours-BRpvd0rt.d.cts → glyf-contours-NHBpgks-.d.cts} +1 -1
- package/dist/glyf-contours.cjs +3 -1
- package/dist/glyf-contours.d.cts +1 -1
- package/dist/glyf-contours.d.ts +1 -1
- package/dist/glyf-contours.js +3 -1
- package/dist/glyf.cjs +22 -11
- package/dist/glyf.js +22 -11
- package/dist/gpos-table.cjs +37 -19
- package/dist/gpos-table.js +37 -19
- package/dist/gsub-table.cjs +40 -25
- package/dist/gsub-table.js +40 -25
- package/dist/hmtx-table.cjs +5 -3
- package/dist/hmtx-table.js +5 -3
- package/dist/image/ccitt-encode.cjs +8 -5
- package/dist/image/ccitt-encode.js +8 -5
- package/dist/image/ccitt.cjs +801 -209
- package/dist/image/ccitt.js +801 -209
- package/dist/image/jbig2-arith.cjs +340 -306
- package/dist/image/jbig2-arith.js +340 -306
- package/dist/image/jbig2-bitmap.cjs +8 -5
- package/dist/image/jbig2-bitmap.js +8 -5
- package/dist/image/jbig2-generic.cjs +240 -69
- package/dist/image/jbig2-generic.js +240 -69
- package/dist/image/jbig2-text.cjs +4 -2
- package/dist/image/jbig2-text.js +4 -2
- package/dist/image/jbig2.cjs +69 -31
- package/dist/image/jbig2.js +69 -31
- package/dist/image/jp2-boxes.cjs +52 -27
- package/dist/image/jp2-boxes.js +52 -27
- package/dist/image/jpeg-info.cjs +29 -24
- package/dist/image/jpeg-info.js +29 -24
- package/dist/image/jpeg2000-codestream.cjs +61 -32
- package/dist/image/jpeg2000-codestream.js +61 -32
- package/dist/image/jpeg2000-dwt.cjs +2 -1
- package/dist/image/jpeg2000-dwt.js +2 -1
- package/dist/image/jpeg2000-t1.cjs +21 -11
- package/dist/image/jpeg2000-t1.js +21 -11
- package/dist/image/jpeg2000-t2.cjs +12 -5
- package/dist/image/jpeg2000-t2.js +12 -5
- package/dist/image/jpeg2000-tagtree.cjs +8 -4
- package/dist/image/jpeg2000-tagtree.js +8 -4
- package/dist/image/jpeg2000.cjs +11 -6
- package/dist/image/jpeg2000.js +11 -6
- package/dist/image/png-decode.cjs +62 -39
- package/dist/image/png-decode.d.cts +3 -2
- package/dist/image/png-decode.d.ts +3 -2
- package/dist/image/png-decode.js +62 -39
- package/dist/image/png-filter.cjs +23 -15
- package/dist/image/png-filter.js +23 -15
- package/dist/images-read.cjs +41 -36
- package/dist/images-read.d.cts +2 -2
- package/dist/images-read.d.ts +2 -2
- package/dist/images-read.js +41 -36
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/interpret.cjs +68 -40
- package/dist/interpret.d.cts +1 -1
- package/dist/interpret.d.ts +1 -1
- package/dist/interpret.js +68 -40
- package/dist/lexer.cjs +86 -51
- package/dist/lexer.js +86 -51
- package/dist/math-content-write.cjs +9 -5
- package/dist/math-content-write.js +9 -5
- package/dist/math-font-write.cjs +2 -1
- package/dist/math-font-write.d.cts +1 -1
- package/dist/math-font-write.d.ts +1 -1
- package/dist/math-font-write.js +2 -1
- package/dist/math-font.cjs +16 -7
- package/dist/math-font.js +16 -7
- package/dist/math-table.cjs +25 -13
- package/dist/math-table.js +25 -13
- package/dist/matrix.cjs +3 -2
- package/dist/matrix.js +3 -2
- package/dist/measure.cjs +1 -1
- package/dist/measure.js +1 -1
- package/dist/names.cjs +7 -7
- package/dist/names.d.cts +2 -2
- package/dist/names.d.ts +2 -2
- package/dist/names.js +7 -7
- package/dist/navigation.cjs +16 -12
- package/dist/navigation.d.cts +4 -4
- package/dist/navigation.d.ts +4 -4
- package/dist/navigation.js +16 -12
- package/dist/{objects-B7HdMeWS.d.cts → objects-e2RS3-yT.d.cts} +3 -3
- package/dist/{objects-B7HdMeWS.d.ts → objects-e2RS3-yT.d.ts} +3 -3
- package/dist/objects.d.cts +1 -1
- package/dist/objects.d.ts +1 -1
- package/dist/optional-content.d.cts +2 -2
- package/dist/optional-content.d.ts +2 -2
- package/dist/ot-layout-common.cjs +22 -15
- package/dist/ot-layout-common.js +22 -15
- package/dist/parse.cjs +7 -5
- package/dist/parse.d.cts +1 -1
- package/dist/parse.d.ts +1 -1
- package/dist/parse.js +7 -5
- package/dist/pdf-text.cjs +5 -2
- package/dist/pdf-text.js +5 -2
- package/dist/predictors.cjs +14 -9
- package/dist/predictors.d.cts +1 -1
- package/dist/predictors.d.ts +1 -1
- package/dist/predictors.js +14 -9
- package/dist/raster.cjs +30 -19
- package/dist/raster.d.cts +8 -8
- package/dist/raster.d.ts +8 -8
- package/dist/raster.js +30 -19
- package/dist/read.cjs +29 -16
- package/dist/read.js +29 -16
- package/dist/serialize.cjs +6 -2
- package/dist/serialize.d.cts +1 -1
- package/dist/serialize.d.ts +1 -1
- package/dist/serialize.js +6 -2
- package/dist/sfnt-subset.cjs +25 -13
- package/dist/sfnt-subset.d.cts +1 -1
- package/dist/sfnt-subset.d.ts +1 -1
- package/dist/sfnt-subset.js +25 -13
- package/dist/sfnt.cjs +20 -10
- package/dist/sfnt.js +20 -10
- package/dist/structure.d.cts +2 -2
- package/dist/structure.d.ts +2 -2
- package/dist/text-group.cjs +0 -1
- package/dist/text-group.js +0 -1
- package/dist/text-layout.d.cts +1 -1
- package/dist/text-layout.d.ts +1 -1
- package/dist/tounicode.cjs +4 -2
- package/dist/tounicode.d.cts +1 -1
- package/dist/tounicode.d.ts +1 -1
- package/dist/tounicode.js +4 -2
- package/dist/winansi.cjs +1 -1
- package/dist/winansi.js +1 -1
- package/dist/write.cjs +20 -12
- package/dist/write.d.cts +1 -1
- package/dist/write.d.ts +1 -1
- package/dist/write.js +20 -12
- package/dist/xref.cjs +5 -2
- package/dist/xref.d.cts +1 -1
- package/dist/xref.d.ts +1 -1
- package/dist/xref.js +5 -2
- package/package.json +1 -1
package/dist/image/png-decode.js
CHANGED
|
@@ -3,30 +3,39 @@ import { inflateTolerant } from "../bytes/flate.js";
|
|
|
3
3
|
import { unfilterScanlines } from "./png-filter.js";
|
|
4
4
|
import { crc32 } from "../bytes/crc32.js";
|
|
5
5
|
//#region src/image/png-decode.ts
|
|
6
|
+
const PNG_SIGNATURE_HIGH_BIT_MARKER = 137;
|
|
7
|
+
const PNG_SIGNATURE_P = 80;
|
|
8
|
+
const PNG_SIGNATURE_N = 78;
|
|
9
|
+
const PNG_SIGNATURE_G = 71;
|
|
10
|
+
const PNG_SIGNATURE_CR = 13;
|
|
11
|
+
const PNG_SIGNATURE_LF = 10;
|
|
6
12
|
const PNG_SIGNATURE = [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
PNG_SIGNATURE_HIGH_BIT_MARKER,
|
|
14
|
+
PNG_SIGNATURE_P,
|
|
15
|
+
PNG_SIGNATURE_N,
|
|
16
|
+
PNG_SIGNATURE_G,
|
|
17
|
+
PNG_SIGNATURE_CR,
|
|
18
|
+
PNG_SIGNATURE_LF,
|
|
13
19
|
26,
|
|
14
|
-
|
|
20
|
+
PNG_SIGNATURE_LF
|
|
15
21
|
];
|
|
16
22
|
function requireDataView(bytes) {
|
|
17
23
|
return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
18
24
|
}
|
|
25
|
+
const PNG_CHUNK_LENGTH_SIZE = 4;
|
|
26
|
+
const PNG_CHUNK_CRC_SIZE = 4;
|
|
27
|
+
const PNG_CHUNK_HEADER_SIZE = 8;
|
|
19
28
|
function readChunks(bytes, onWarning) {
|
|
20
29
|
const chunks = [];
|
|
21
30
|
const view = requireDataView(bytes);
|
|
22
31
|
let offset = PNG_SIGNATURE.length;
|
|
23
|
-
while (offset +
|
|
32
|
+
while (offset + PNG_CHUNK_HEADER_SIZE <= bytes.length) {
|
|
24
33
|
const length = view.getUint32(offset);
|
|
25
|
-
const typeBytes = bytes.subarray(offset +
|
|
34
|
+
const typeBytes = bytes.subarray(offset + PNG_CHUNK_LENGTH_SIZE, offset + PNG_CHUNK_HEADER_SIZE);
|
|
26
35
|
const type = new TextDecoder("latin1").decode(typeBytes);
|
|
27
|
-
const dataStart = offset +
|
|
36
|
+
const dataStart = offset + PNG_CHUNK_HEADER_SIZE;
|
|
28
37
|
const dataEnd = dataStart + length;
|
|
29
|
-
if (dataEnd +
|
|
38
|
+
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`);
|
|
30
39
|
const data = bytes.subarray(dataStart, dataEnd);
|
|
31
40
|
if (onWarning !== void 0) {
|
|
32
41
|
if (view.getUint32(dataEnd) !== crc32(concatBytes([typeBytes, data]))) onWarning(`PNG chunk '${type}' failed its CRC32 check`);
|
|
@@ -35,42 +44,53 @@ function readChunks(bytes, onWarning) {
|
|
|
35
44
|
type,
|
|
36
45
|
data
|
|
37
46
|
});
|
|
38
|
-
offset = dataEnd +
|
|
47
|
+
offset = dataEnd + PNG_CHUNK_CRC_SIZE;
|
|
39
48
|
if (type === "IEND") break;
|
|
40
49
|
}
|
|
41
50
|
return chunks;
|
|
42
51
|
}
|
|
52
|
+
const IHDR_HEIGHT_OFFSET = 4;
|
|
43
53
|
function parseIhdr(data) {
|
|
44
54
|
const view = requireDataView(data);
|
|
45
55
|
return {
|
|
46
56
|
width: view.getUint32(0),
|
|
47
|
-
height: view.getUint32(
|
|
57
|
+
height: view.getUint32(IHDR_HEIGHT_OFFSET),
|
|
48
58
|
bitDepth: data[8],
|
|
49
59
|
colorType: data[9],
|
|
50
60
|
interlace: data[12]
|
|
51
61
|
};
|
|
52
62
|
}
|
|
63
|
+
const PNG_COLOR_TYPE_GRAYSCALE = 0;
|
|
64
|
+
const PNG_COLOR_TYPE_TRUECOLOR = 2;
|
|
65
|
+
const PNG_COLOR_TYPE_INDEXED = 3;
|
|
66
|
+
const PNG_COLOR_TYPE_GRAYSCALE_ALPHA = 4;
|
|
67
|
+
const PNG_COLOR_TYPE_TRUECOLOR_ALPHA = 6;
|
|
68
|
+
const PNG_CHANNELS_TRUECOLOR = 3;
|
|
69
|
+
const PNG_CHANNELS_TRUECOLOR_ALPHA = 4;
|
|
53
70
|
function channelsForColorType(colorType) {
|
|
54
|
-
if (colorType ===
|
|
55
|
-
if (colorType ===
|
|
56
|
-
if (colorType ===
|
|
57
|
-
if (colorType ===
|
|
58
|
-
if (colorType ===
|
|
71
|
+
if (colorType === PNG_COLOR_TYPE_GRAYSCALE) return 1;
|
|
72
|
+
if (colorType === PNG_COLOR_TYPE_TRUECOLOR) return PNG_CHANNELS_TRUECOLOR;
|
|
73
|
+
if (colorType === PNG_COLOR_TYPE_INDEXED) return 1;
|
|
74
|
+
if (colorType === PNG_COLOR_TYPE_GRAYSCALE_ALPHA) return 2;
|
|
75
|
+
if (colorType === PNG_COLOR_TYPE_TRUECOLOR_ALPHA) return PNG_CHANNELS_TRUECOLOR_ALPHA;
|
|
59
76
|
throw new Error(`unsupported PNG colour type: ${colorType}`);
|
|
60
77
|
}
|
|
78
|
+
const BITS_PER_BYTE = 8;
|
|
61
79
|
function filterBpp(bitDepth, channels) {
|
|
62
|
-
return Math.max(1, Math.ceil(bitDepth * channels /
|
|
80
|
+
return Math.max(1, Math.ceil(bitDepth * channels / BITS_PER_BYTE));
|
|
63
81
|
}
|
|
82
|
+
const PNG_BIT_DEPTH_16 = 16;
|
|
83
|
+
const BYTE_INDEX_SHIFT = 3;
|
|
64
84
|
function unpackRow(rowBytes, width, channels, bitDepth) {
|
|
65
85
|
const sampleCount = width * channels;
|
|
66
86
|
const samples = Array.from({ length: sampleCount });
|
|
67
|
-
if (bitDepth ===
|
|
87
|
+
if (bitDepth === PNG_BIT_DEPTH_16) for (let i = 0; i < sampleCount; i++) samples[i] = rowBytes[i * 2];
|
|
68
88
|
else {
|
|
69
89
|
const mask = (1 << bitDepth) - 1;
|
|
70
90
|
for (let i = 0; i < sampleCount; i++) {
|
|
71
91
|
const bitOffset = i * bitDepth;
|
|
72
|
-
const byteIndex = bitOffset >>
|
|
73
|
-
const shift =
|
|
92
|
+
const byteIndex = bitOffset >> BYTE_INDEX_SHIFT;
|
|
93
|
+
const shift = BITS_PER_BYTE - bitDepth - (bitOffset & 7);
|
|
74
94
|
samples[i] = rowBytes[byteIndex] >> shift & mask;
|
|
75
95
|
}
|
|
76
96
|
}
|
|
@@ -79,18 +99,20 @@ function unpackRow(rowBytes, width, channels, bitDepth) {
|
|
|
79
99
|
function readTrnsGrayValue(trns) {
|
|
80
100
|
return requireDataView(trns).getUint16(0);
|
|
81
101
|
}
|
|
102
|
+
const TRNS_RGB_BLUE_OFFSET = 4;
|
|
82
103
|
function readTrnsRgbKey(trns) {
|
|
83
104
|
const view = requireDataView(trns);
|
|
84
105
|
return [
|
|
85
106
|
view.getUint16(0),
|
|
86
107
|
view.getUint16(2),
|
|
87
|
-
view.getUint16(
|
|
108
|
+
view.getUint16(TRNS_RGB_BLUE_OFFSET)
|
|
88
109
|
];
|
|
89
110
|
}
|
|
111
|
+
const MAX_BYTE_VALUE = 255;
|
|
90
112
|
function scaleToByte(sample, bitDepth) {
|
|
91
|
-
if (bitDepth ===
|
|
113
|
+
if (bitDepth === PNG_BIT_DEPTH_16) return sample;
|
|
92
114
|
const maxSample = (1 << bitDepth) - 1;
|
|
93
|
-
return Math.round(sample *
|
|
115
|
+
return Math.round(sample * MAX_BYTE_VALUE / maxSample);
|
|
94
116
|
}
|
|
95
117
|
function decodePng(bytes, options = {}) {
|
|
96
118
|
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");
|
|
@@ -101,23 +123,24 @@ function decodePng(bytes, options = {}) {
|
|
|
101
123
|
if (ihdr.interlace !== 0) throw new Error("Adam7-interlaced PNG images are not supported");
|
|
102
124
|
const channels = channelsForColorType(ihdr.colorType);
|
|
103
125
|
const bpp = filterBpp(ihdr.bitDepth, channels);
|
|
104
|
-
const bytesPerRow = Math.ceil(ihdr.width * channels * ihdr.bitDepth /
|
|
126
|
+
const bytesPerRow = Math.ceil(ihdr.width * channels * ihdr.bitDepth / BITS_PER_BYTE);
|
|
105
127
|
const idatChunks = chunks.filter((c) => c.type === "IDAT").map((c) => c.data);
|
|
106
128
|
if (idatChunks.length === 0) throw new Error("PNG file has no IDAT chunks");
|
|
107
129
|
const compressed = concatBytes(idatChunks);
|
|
108
130
|
const { bytes: inflated, recovered } = inflateTolerant(compressed);
|
|
109
131
|
if (recovered && options.onWarning !== void 0) options.onWarning("PNG IDAT stream required tolerant recovery (truncated or malformed)");
|
|
110
132
|
const unfiltered = unfilterScanlines(inflated, ihdr.height, bytesPerRow, bpp);
|
|
111
|
-
const palette = ihdr.colorType ===
|
|
112
|
-
if (ihdr.colorType ===
|
|
133
|
+
const palette = ihdr.colorType === PNG_COLOR_TYPE_INDEXED ? chunks.find((c) => c.type === "PLTE")?.data : void 0;
|
|
134
|
+
if (ihdr.colorType === PNG_COLOR_TYPE_INDEXED && palette === void 0) throw new Error("indexed-colour PNG has no PLTE chunk");
|
|
113
135
|
const trns = chunks.find((c) => c.type === "tRNS")?.data;
|
|
114
136
|
return buildRawImage(ihdr, channels, bytesPerRow, unfiltered, palette, trns);
|
|
115
137
|
}
|
|
138
|
+
const ALPHA_SAMPLE_INDEX_IN_RGBA = 3;
|
|
116
139
|
function buildRawImage(ihdr, channels, bytesPerRow, unfiltered, palette, trns) {
|
|
117
140
|
const { width, height, bitDepth, colorType } = ihdr;
|
|
118
|
-
const outChannels = colorType === 0 || colorType ===
|
|
141
|
+
const outChannels = colorType === 0 || colorType === PNG_COLOR_TYPE_GRAYSCALE_ALPHA ? 1 : PNG_CHANNELS_TRUECOLOR;
|
|
119
142
|
const data = new Uint8Array(width * height * outChannels);
|
|
120
|
-
const alpha = colorType ===
|
|
143
|
+
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;
|
|
121
144
|
const trnsGray = colorType === 0 && trns !== void 0 ? readTrnsGrayValue(trns) : void 0;
|
|
122
145
|
const trnsRgb = colorType === 2 && trns !== void 0 ? readTrnsRgbKey(trns) : void 0;
|
|
123
146
|
for (let y = 0; y < height; y++) {
|
|
@@ -130,7 +153,7 @@ function buildRawImage(ihdr, channels, bytesPerRow, unfiltered, palette, trns) {
|
|
|
130
153
|
if (colorType === 0) {
|
|
131
154
|
const g = samples[pixelBase];
|
|
132
155
|
data[outBase] = scaleToByte(g, bitDepth);
|
|
133
|
-
if (alpha !== void 0 && trnsGray !== void 0) alpha[alphaIndex] = g === trnsGray ? 0 :
|
|
156
|
+
if (alpha !== void 0 && trnsGray !== void 0) alpha[alphaIndex] = g === trnsGray ? 0 : MAX_BYTE_VALUE;
|
|
134
157
|
} else if (colorType === 2) {
|
|
135
158
|
const r = samples[pixelBase];
|
|
136
159
|
const g = samples[pixelBase + 1];
|
|
@@ -140,15 +163,15 @@ function buildRawImage(ihdr, channels, bytesPerRow, unfiltered, palette, trns) {
|
|
|
140
163
|
data[outBase + 2] = b;
|
|
141
164
|
if (alpha !== void 0 && trnsRgb !== void 0) {
|
|
142
165
|
const [kr, kg, kb] = trnsRgb;
|
|
143
|
-
alpha[alphaIndex] = r === kr && g === kg && b === kb ? 0 :
|
|
166
|
+
alpha[alphaIndex] = r === kr && g === kg && b === kb ? 0 : MAX_BYTE_VALUE;
|
|
144
167
|
}
|
|
145
|
-
} else if (colorType ===
|
|
168
|
+
} else if (colorType === PNG_COLOR_TYPE_INDEXED) {
|
|
146
169
|
const index = samples[pixelBase];
|
|
147
|
-
data[outBase] = palette[index *
|
|
148
|
-
data[outBase + 1] = palette[index *
|
|
149
|
-
data[outBase + 2] = palette[index *
|
|
150
|
-
if (alpha !== void 0 && trns !== void 0) alpha[alphaIndex] = index < trns.length ? trns[index] :
|
|
151
|
-
} else if (colorType ===
|
|
170
|
+
data[outBase] = palette[index * PNG_CHANNELS_TRUECOLOR];
|
|
171
|
+
data[outBase + 1] = palette[index * PNG_CHANNELS_TRUECOLOR + 1];
|
|
172
|
+
data[outBase + 2] = palette[index * PNG_CHANNELS_TRUECOLOR + 2];
|
|
173
|
+
if (alpha !== void 0 && trns !== void 0) alpha[alphaIndex] = index < trns.length ? trns[index] : MAX_BYTE_VALUE;
|
|
174
|
+
} else if (colorType === PNG_COLOR_TYPE_GRAYSCALE_ALPHA) {
|
|
152
175
|
const g = samples[pixelBase];
|
|
153
176
|
const a = samples[pixelBase + 1];
|
|
154
177
|
data[outBase] = scaleToByte(g, bitDepth);
|
|
@@ -157,7 +180,7 @@ function buildRawImage(ihdr, channels, bytesPerRow, unfiltered, palette, trns) {
|
|
|
157
180
|
data[outBase] = samples[pixelBase];
|
|
158
181
|
data[outBase + 1] = samples[pixelBase + 1];
|
|
159
182
|
data[outBase + 2] = samples[pixelBase + 2];
|
|
160
|
-
if (alpha !== void 0) alpha[alphaIndex] = samples[pixelBase +
|
|
183
|
+
if (alpha !== void 0) alpha[alphaIndex] = samples[pixelBase + ALPHA_SAMPLE_INDEX_IN_RGBA];
|
|
161
184
|
}
|
|
162
185
|
}
|
|
163
186
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
//#region src/image/png-filter.ts
|
|
3
|
+
const FILTER_TYPE_NONE = 0;
|
|
4
|
+
const FILTER_TYPE_SUB = 1;
|
|
5
|
+
const FILTER_TYPE_UP = 2;
|
|
6
|
+
const FILTER_TYPE_AVERAGE = 3;
|
|
7
|
+
const FILTER_TYPE_PAETH = 4;
|
|
8
|
+
const BYTE_MASK = 255;
|
|
3
9
|
function paethPredictor(a, b, c) {
|
|
4
10
|
const p = a + b - c;
|
|
5
11
|
const pa = Math.abs(p - a);
|
|
@@ -10,13 +16,13 @@ function paethPredictor(a, b, c) {
|
|
|
10
16
|
return c;
|
|
11
17
|
}
|
|
12
18
|
function isPngFilterType(value) {
|
|
13
|
-
return value ===
|
|
19
|
+
return value === FILTER_TYPE_NONE || value === FILTER_TYPE_SUB || value === FILTER_TYPE_UP || value === FILTER_TYPE_AVERAGE || value === FILTER_TYPE_PAETH;
|
|
14
20
|
}
|
|
15
21
|
function predictorValue(filterType, a, b, c) {
|
|
16
|
-
if (filterType ===
|
|
17
|
-
if (filterType ===
|
|
18
|
-
if (filterType ===
|
|
19
|
-
if (filterType ===
|
|
22
|
+
if (filterType === FILTER_TYPE_SUB) return a;
|
|
23
|
+
if (filterType === FILTER_TYPE_UP) return b;
|
|
24
|
+
if (filterType === FILTER_TYPE_AVERAGE) return Math.floor((a + b) / 2);
|
|
25
|
+
if (filterType === FILTER_TYPE_PAETH) return paethPredictor(a, b, c);
|
|
20
26
|
return 0;
|
|
21
27
|
}
|
|
22
28
|
function unfilterScanlines(data, height, bytesPerRow, bpp) {
|
|
@@ -34,14 +40,16 @@ function unfilterScanlines(data, height, bytesPerRow, bpp) {
|
|
|
34
40
|
const a = x >= bpp ? out[outRowStart + x - bpp] : 0;
|
|
35
41
|
const b = prevOutRowStart === void 0 ? 0 : out[prevOutRowStart + x];
|
|
36
42
|
const c = x >= bpp && prevOutRowStart !== void 0 ? out[prevOutRowStart + x - bpp] : 0;
|
|
37
|
-
out[outRowStart + x] = raw + predictorValue(filterByte, a, b, c) &
|
|
43
|
+
out[outRowStart + x] = raw + predictorValue(filterByte, a, b, c) & BYTE_MASK;
|
|
38
44
|
}
|
|
39
45
|
}
|
|
40
46
|
return out;
|
|
41
47
|
}
|
|
48
|
+
const BYTE_RADIX = 256;
|
|
49
|
+
const SIGNED_BYTE_THRESHOLD = 128;
|
|
42
50
|
function sumOfAbsSigned(bytes) {
|
|
43
51
|
let sum = 0;
|
|
44
|
-
for (const byte of bytes) sum += byte <
|
|
52
|
+
for (const byte of bytes) sum += byte < SIGNED_BYTE_THRESHOLD ? byte : BYTE_RADIX - byte;
|
|
45
53
|
return sum;
|
|
46
54
|
}
|
|
47
55
|
function filterRowInto(raw, rowStart, prevRowStart, bytesPerRow, bpp, filterType, out, outOffset) {
|
|
@@ -50,15 +58,15 @@ function filterRowInto(raw, rowStart, prevRowStart, bytesPerRow, bpp, filterType
|
|
|
50
58
|
const a = x >= bpp ? raw[rowStart + x - bpp] : 0;
|
|
51
59
|
const b = prevRowStart === void 0 ? 0 : raw[prevRowStart + x];
|
|
52
60
|
const c = x >= bpp && prevRowStart !== void 0 ? raw[prevRowStart + x - bpp] : 0;
|
|
53
|
-
out[outOffset + x] = rawByte - predictorValue(filterType, a, b, c) &
|
|
61
|
+
out[outOffset + x] = rawByte - predictorValue(filterType, a, b, c) & BYTE_MASK;
|
|
54
62
|
}
|
|
55
63
|
}
|
|
56
64
|
const ALL_FILTER_TYPES = [
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
FILTER_TYPE_NONE,
|
|
66
|
+
FILTER_TYPE_SUB,
|
|
67
|
+
FILTER_TYPE_UP,
|
|
68
|
+
FILTER_TYPE_AVERAGE,
|
|
69
|
+
FILTER_TYPE_PAETH
|
|
62
70
|
];
|
|
63
71
|
function filterScanlines(raw, height, bytesPerRow, bpp, strategy = "adaptive") {
|
|
64
72
|
const stride = bytesPerRow + 1;
|
|
@@ -70,10 +78,10 @@ function filterScanlines(raw, height, bytesPerRow, bpp, strategy = "adaptive") {
|
|
|
70
78
|
const outRowStart = y * stride;
|
|
71
79
|
if (strategy === "none") {
|
|
72
80
|
out[outRowStart] = 0;
|
|
73
|
-
filterRowInto(raw, rowStart, prevRowStart, bytesPerRow, bpp,
|
|
81
|
+
filterRowInto(raw, rowStart, prevRowStart, bytesPerRow, bpp, FILTER_TYPE_NONE, out, outRowStart + 1);
|
|
74
82
|
continue;
|
|
75
83
|
}
|
|
76
|
-
let bestType =
|
|
84
|
+
let bestType = FILTER_TYPE_NONE;
|
|
77
85
|
let bestSum = Number.POSITIVE_INFINITY;
|
|
78
86
|
let best;
|
|
79
87
|
for (const filterType of ALL_FILTER_TYPES) {
|
package/dist/image/png-filter.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
//#region src/image/png-filter.ts
|
|
2
|
+
const FILTER_TYPE_NONE = 0;
|
|
3
|
+
const FILTER_TYPE_SUB = 1;
|
|
4
|
+
const FILTER_TYPE_UP = 2;
|
|
5
|
+
const FILTER_TYPE_AVERAGE = 3;
|
|
6
|
+
const FILTER_TYPE_PAETH = 4;
|
|
7
|
+
const BYTE_MASK = 255;
|
|
2
8
|
function paethPredictor(a, b, c) {
|
|
3
9
|
const p = a + b - c;
|
|
4
10
|
const pa = Math.abs(p - a);
|
|
@@ -9,13 +15,13 @@ function paethPredictor(a, b, c) {
|
|
|
9
15
|
return c;
|
|
10
16
|
}
|
|
11
17
|
function isPngFilterType(value) {
|
|
12
|
-
return value ===
|
|
18
|
+
return value === FILTER_TYPE_NONE || value === FILTER_TYPE_SUB || value === FILTER_TYPE_UP || value === FILTER_TYPE_AVERAGE || value === FILTER_TYPE_PAETH;
|
|
13
19
|
}
|
|
14
20
|
function predictorValue(filterType, a, b, c) {
|
|
15
|
-
if (filterType ===
|
|
16
|
-
if (filterType ===
|
|
17
|
-
if (filterType ===
|
|
18
|
-
if (filterType ===
|
|
21
|
+
if (filterType === FILTER_TYPE_SUB) return a;
|
|
22
|
+
if (filterType === FILTER_TYPE_UP) return b;
|
|
23
|
+
if (filterType === FILTER_TYPE_AVERAGE) return Math.floor((a + b) / 2);
|
|
24
|
+
if (filterType === FILTER_TYPE_PAETH) return paethPredictor(a, b, c);
|
|
19
25
|
return 0;
|
|
20
26
|
}
|
|
21
27
|
function unfilterScanlines(data, height, bytesPerRow, bpp) {
|
|
@@ -33,14 +39,16 @@ function unfilterScanlines(data, height, bytesPerRow, bpp) {
|
|
|
33
39
|
const a = x >= bpp ? out[outRowStart + x - bpp] : 0;
|
|
34
40
|
const b = prevOutRowStart === void 0 ? 0 : out[prevOutRowStart + x];
|
|
35
41
|
const c = x >= bpp && prevOutRowStart !== void 0 ? out[prevOutRowStart + x - bpp] : 0;
|
|
36
|
-
out[outRowStart + x] = raw + predictorValue(filterByte, a, b, c) &
|
|
42
|
+
out[outRowStart + x] = raw + predictorValue(filterByte, a, b, c) & BYTE_MASK;
|
|
37
43
|
}
|
|
38
44
|
}
|
|
39
45
|
return out;
|
|
40
46
|
}
|
|
47
|
+
const BYTE_RADIX = 256;
|
|
48
|
+
const SIGNED_BYTE_THRESHOLD = 128;
|
|
41
49
|
function sumOfAbsSigned(bytes) {
|
|
42
50
|
let sum = 0;
|
|
43
|
-
for (const byte of bytes) sum += byte <
|
|
51
|
+
for (const byte of bytes) sum += byte < SIGNED_BYTE_THRESHOLD ? byte : BYTE_RADIX - byte;
|
|
44
52
|
return sum;
|
|
45
53
|
}
|
|
46
54
|
function filterRowInto(raw, rowStart, prevRowStart, bytesPerRow, bpp, filterType, out, outOffset) {
|
|
@@ -49,15 +57,15 @@ function filterRowInto(raw, rowStart, prevRowStart, bytesPerRow, bpp, filterType
|
|
|
49
57
|
const a = x >= bpp ? raw[rowStart + x - bpp] : 0;
|
|
50
58
|
const b = prevRowStart === void 0 ? 0 : raw[prevRowStart + x];
|
|
51
59
|
const c = x >= bpp && prevRowStart !== void 0 ? raw[prevRowStart + x - bpp] : 0;
|
|
52
|
-
out[outOffset + x] = rawByte - predictorValue(filterType, a, b, c) &
|
|
60
|
+
out[outOffset + x] = rawByte - predictorValue(filterType, a, b, c) & BYTE_MASK;
|
|
53
61
|
}
|
|
54
62
|
}
|
|
55
63
|
const ALL_FILTER_TYPES = [
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
FILTER_TYPE_NONE,
|
|
65
|
+
FILTER_TYPE_SUB,
|
|
66
|
+
FILTER_TYPE_UP,
|
|
67
|
+
FILTER_TYPE_AVERAGE,
|
|
68
|
+
FILTER_TYPE_PAETH
|
|
61
69
|
];
|
|
62
70
|
function filterScanlines(raw, height, bytesPerRow, bpp, strategy = "adaptive") {
|
|
63
71
|
const stride = bytesPerRow + 1;
|
|
@@ -69,10 +77,10 @@ function filterScanlines(raw, height, bytesPerRow, bpp, strategy = "adaptive") {
|
|
|
69
77
|
const outRowStart = y * stride;
|
|
70
78
|
if (strategy === "none") {
|
|
71
79
|
out[outRowStart] = 0;
|
|
72
|
-
filterRowInto(raw, rowStart, prevRowStart, bytesPerRow, bpp,
|
|
80
|
+
filterRowInto(raw, rowStart, prevRowStart, bytesPerRow, bpp, FILTER_TYPE_NONE, out, outRowStart + 1);
|
|
73
81
|
continue;
|
|
74
82
|
}
|
|
75
|
-
let bestType =
|
|
83
|
+
let bestType = FILTER_TYPE_NONE;
|
|
76
84
|
let bestSum = Number.POSITIVE_INFINITY;
|
|
77
85
|
let best;
|
|
78
86
|
for (const filterType of ALL_FILTER_TYPES) {
|
package/dist/images-read.cjs
CHANGED
|
@@ -4,10 +4,14 @@ const require_filters = require("./filters.cjs");
|
|
|
4
4
|
const require_image_jpeg2000 = require("./image/jpeg2000.cjs");
|
|
5
5
|
let byte_codec = require("byte-codec");
|
|
6
6
|
//#region src/images-read.ts
|
|
7
|
+
const CMYK_COMPONENT_COUNT = 4;
|
|
8
|
+
const RGB_CHANNEL_COUNT = 3;
|
|
9
|
+
const MAX_BYTE_VALUE = 255;
|
|
10
|
+
const BITS_PER_BYTE = 8;
|
|
7
11
|
function componentsOf(cs) {
|
|
8
12
|
if (cs.kind === "gray") return 1;
|
|
9
|
-
if (cs.kind === "cmyk") return
|
|
10
|
-
return
|
|
13
|
+
if (cs.kind === "cmyk") return CMYK_COMPONENT_COUNT;
|
|
14
|
+
return RGB_CHANNEL_COUNT;
|
|
11
15
|
}
|
|
12
16
|
function resolveColorSpace(csObj, resolver, sink) {
|
|
13
17
|
const resolved = resolver.resolve(csObj);
|
|
@@ -31,7 +35,7 @@ function resolveColorSpace(csObj, resolver, sink) {
|
|
|
31
35
|
const streamObj = resolver.resolve(arr[1]);
|
|
32
36
|
const n = streamObj?.kind === "stream" ? require_objects.asNumber(require_objects.dictGet(streamObj.dict, "N")) : void 0;
|
|
33
37
|
if (n === 1) return { kind: "gray" };
|
|
34
|
-
if (n ===
|
|
38
|
+
if (n === CMYK_COMPONENT_COUNT) return { kind: "cmyk" };
|
|
35
39
|
return { kind: "rgb" };
|
|
36
40
|
}
|
|
37
41
|
if (family === "Indexed") {
|
|
@@ -55,9 +59,9 @@ function resolveColorSpace(csObj, resolver, sink) {
|
|
|
55
59
|
};
|
|
56
60
|
}
|
|
57
61
|
function unpackSamples(data, width, height, componentsPerPixel, bitsPerComponent) {
|
|
58
|
-
if (bitsPerComponent ===
|
|
62
|
+
if (bitsPerComponent === BITS_PER_BYTE) return Array.from(data.subarray(0, width * height * componentsPerPixel));
|
|
59
63
|
const samplesPerRow = width * componentsPerPixel;
|
|
60
|
-
const bytesPerRow = Math.ceil(samplesPerRow * bitsPerComponent /
|
|
64
|
+
const bytesPerRow = Math.ceil(samplesPerRow * bitsPerComponent / BITS_PER_BYTE);
|
|
61
65
|
const out = [];
|
|
62
66
|
for (let row = 0; row < height; row++) {
|
|
63
67
|
const rowStart = row * bytesPerRow;
|
|
@@ -65,8 +69,8 @@ function unpackSamples(data, width, height, componentsPerPixel, bitsPerComponent
|
|
|
65
69
|
for (let s = 0; s < samplesPerRow; s++) {
|
|
66
70
|
let value = 0;
|
|
67
71
|
for (let b = 0; b < bitsPerComponent; b++) {
|
|
68
|
-
const byteIndex = rowStart + Math.floor(bitPos /
|
|
69
|
-
const bitIndex = 7 - bitPos %
|
|
72
|
+
const byteIndex = rowStart + Math.floor(bitPos / BITS_PER_BYTE);
|
|
73
|
+
const bitIndex = 7 - bitPos % BITS_PER_BYTE;
|
|
70
74
|
const bit = (data[byteIndex] ?? 0) >> bitIndex & 1;
|
|
71
75
|
value = value << 1 | bit;
|
|
72
76
|
bitPos++;
|
|
@@ -78,13 +82,13 @@ function unpackSamples(data, width, height, componentsPerPixel, bitsPerComponent
|
|
|
78
82
|
}
|
|
79
83
|
function scaleToByte(value, maxValue, inverted) {
|
|
80
84
|
const v = inverted ? maxValue - value : value;
|
|
81
|
-
return maxValue ===
|
|
85
|
+
return maxValue === MAX_BYTE_VALUE ? v : Math.round(v * MAX_BYTE_VALUE / maxValue);
|
|
82
86
|
}
|
|
83
87
|
function cmykToRgbByte(c, m, y, k) {
|
|
84
88
|
return {
|
|
85
|
-
r: Math.round(
|
|
86
|
-
g: Math.round(
|
|
87
|
-
b: Math.round(
|
|
89
|
+
r: Math.round(MAX_BYTE_VALUE * (1 - c) * (1 - k)),
|
|
90
|
+
g: Math.round(MAX_BYTE_VALUE * (1 - m) * (1 - k)),
|
|
91
|
+
b: Math.round(MAX_BYTE_VALUE * (1 - y) * (1 - k))
|
|
88
92
|
};
|
|
89
93
|
}
|
|
90
94
|
function sampleFromPalette(base, lookup, offset) {
|
|
@@ -96,7 +100,7 @@ function sampleFromPalette(base, lookup, offset) {
|
|
|
96
100
|
b: g
|
|
97
101
|
};
|
|
98
102
|
}
|
|
99
|
-
if (base.kind === "cmyk") return cmykToRgbByte((lookup[offset] ?? 0) /
|
|
103
|
+
if (base.kind === "cmyk") return cmykToRgbByte((lookup[offset] ?? 0) / MAX_BYTE_VALUE, (lookup[offset + 1] ?? 0) / MAX_BYTE_VALUE, (lookup[offset + 2] ?? 0) / MAX_BYTE_VALUE, (lookup[offset + 3] ?? 0) / MAX_BYTE_VALUE);
|
|
100
104
|
return {
|
|
101
105
|
r: lookup[offset] ?? 0,
|
|
102
106
|
g: lookup[offset + 1] ?? 0,
|
|
@@ -108,7 +112,7 @@ function buildRawImage(data, width, height, bitsPerComponent, colorSpace, invert
|
|
|
108
112
|
if (colorSpace.kind === "indexed") {
|
|
109
113
|
const indices = unpackSamples(data, width, height, 1, bitsPerComponent);
|
|
110
114
|
const baseComponents = componentsOf(colorSpace.base);
|
|
111
|
-
const out = new Uint8Array(width * height * (colorSpace.base.kind === "gray" ? 1 :
|
|
115
|
+
const out = new Uint8Array(width * height * (colorSpace.base.kind === "gray" ? 1 : RGB_CHANNEL_COUNT));
|
|
112
116
|
let outIdx = 0;
|
|
113
117
|
for (const index of indices) {
|
|
114
118
|
const rgb = sampleFromPalette(colorSpace.base, colorSpace.lookup, index * baseComponents);
|
|
@@ -122,7 +126,7 @@ function buildRawImage(data, width, height, bitsPerComponent, colorSpace, invert
|
|
|
122
126
|
return {
|
|
123
127
|
width,
|
|
124
128
|
height,
|
|
125
|
-
channels: colorSpace.base.kind === "gray" ? 1 :
|
|
129
|
+
channels: colorSpace.base.kind === "gray" ? 1 : RGB_CHANNEL_COUNT,
|
|
126
130
|
data: out
|
|
127
131
|
};
|
|
128
132
|
}
|
|
@@ -136,26 +140,27 @@ function buildRawImage(data, width, height, bitsPerComponent, colorSpace, invert
|
|
|
136
140
|
};
|
|
137
141
|
}
|
|
138
142
|
if (colorSpace.kind === "rgb") {
|
|
139
|
-
const samples = unpackSamples(data, width, height,
|
|
143
|
+
const samples = unpackSamples(data, width, height, RGB_CHANNEL_COUNT, bitsPerComponent);
|
|
144
|
+
const out = Uint8Array.from(samples, (v) => scaleToByte(v, maxValue, inverted));
|
|
140
145
|
return {
|
|
141
146
|
width,
|
|
142
147
|
height,
|
|
143
|
-
channels:
|
|
144
|
-
data:
|
|
148
|
+
channels: RGB_CHANNEL_COUNT,
|
|
149
|
+
data: out
|
|
145
150
|
};
|
|
146
151
|
}
|
|
147
|
-
const samples = unpackSamples(data, width, height,
|
|
148
|
-
const out = new Uint8Array(width * height *
|
|
152
|
+
const samples = unpackSamples(data, width, height, CMYK_COMPONENT_COUNT, bitsPerComponent);
|
|
153
|
+
const out = new Uint8Array(width * height * RGB_CHANNEL_COUNT);
|
|
149
154
|
for (let px = 0; px < width * height; px++) {
|
|
150
|
-
const rgb = cmykToRgbByte(scaleToByte(samples[px *
|
|
151
|
-
out[px *
|
|
152
|
-
out[px *
|
|
153
|
-
out[px *
|
|
155
|
+
const rgb = cmykToRgbByte(scaleToByte(samples[px * CMYK_COMPONENT_COUNT] ?? 0, maxValue, inverted) / MAX_BYTE_VALUE, scaleToByte(samples[px * CMYK_COMPONENT_COUNT + 1] ?? 0, maxValue, inverted) / MAX_BYTE_VALUE, scaleToByte(samples[px * CMYK_COMPONENT_COUNT + 2] ?? 0, maxValue, inverted) / MAX_BYTE_VALUE, scaleToByte(samples[px * CMYK_COMPONENT_COUNT + 3] ?? 0, maxValue, inverted) / MAX_BYTE_VALUE);
|
|
156
|
+
out[px * RGB_CHANNEL_COUNT] = rgb.r;
|
|
157
|
+
out[px * RGB_CHANNEL_COUNT + 1] = rgb.g;
|
|
158
|
+
out[px * RGB_CHANNEL_COUNT + 2] = rgb.b;
|
|
154
159
|
}
|
|
155
160
|
return {
|
|
156
161
|
width,
|
|
157
162
|
height,
|
|
158
|
-
channels:
|
|
163
|
+
channels: RGB_CHANNEL_COUNT,
|
|
159
164
|
data: out
|
|
160
165
|
};
|
|
161
166
|
}
|
|
@@ -166,8 +171,8 @@ function readSoftMaskAlpha(dict, width, height, resolver, sink) {
|
|
|
166
171
|
if (decoded.remainingFilter !== void 0) return;
|
|
167
172
|
const smaskWidth = require_objects.asNumber(require_objects.dictGet(smaskObj.dict, "Width")) ?? width;
|
|
168
173
|
const smaskHeight = require_objects.asNumber(require_objects.dictGet(smaskObj.dict, "Height")) ?? height;
|
|
169
|
-
const smaskBpc = require_objects.asNumber(require_objects.dictGet(smaskObj.dict, "BitsPerComponent")) ??
|
|
170
|
-
if (smaskWidth !== width || smaskHeight !== height || smaskBpc !==
|
|
174
|
+
const smaskBpc = require_objects.asNumber(require_objects.dictGet(smaskObj.dict, "BitsPerComponent")) ?? BITS_PER_BYTE;
|
|
175
|
+
if (smaskWidth !== width || smaskHeight !== height || smaskBpc !== BITS_PER_BYTE) return;
|
|
171
176
|
return decoded.bytes.subarray(0, width * height);
|
|
172
177
|
}
|
|
173
178
|
function jpeg2000ChannelKind(image, dict, resolver, sink) {
|
|
@@ -179,7 +184,7 @@ function jpeg2000ChannelKind(image, dict, resolver, sink) {
|
|
|
179
184
|
if (image.colourSpace === "greyscale") return "gray";
|
|
180
185
|
if (image.colourSpace === "cmyk") return "cmyk";
|
|
181
186
|
if (image.colourSpace === "srgb" || image.colourSpace === "sycc" || image.colourSpace === "e-srgb" || image.colourSpace === "rommrgb") return "rgb";
|
|
182
|
-
return image.components.length >=
|
|
187
|
+
return image.components.length >= CMYK_COMPONENT_COUNT ? "cmyk" : image.components.length >= RGB_CHANNEL_COUNT ? "rgb" : "gray";
|
|
183
188
|
}
|
|
184
189
|
function readJpeg2000Image(dict, raw, resolver, sink) {
|
|
185
190
|
let image;
|
|
@@ -205,7 +210,7 @@ function readJpeg2000Image(dict, raw, resolver, sink) {
|
|
|
205
210
|
return;
|
|
206
211
|
}
|
|
207
212
|
const kind = jpeg2000ChannelKind(image, dict, resolver, sink);
|
|
208
|
-
const required = kind === "cmyk" ?
|
|
213
|
+
const required = kind === "cmyk" ? CMYK_COMPONENT_COUNT : kind === "rgb" ? RGB_CHANNEL_COUNT : 1;
|
|
209
214
|
if (image.components.length < required) {
|
|
210
215
|
sink({
|
|
211
216
|
code: "image/jpx-undecodable",
|
|
@@ -220,15 +225,15 @@ function readJpeg2000Image(dict, raw, resolver, sink) {
|
|
|
220
225
|
message: `JPXDecode image carries ${String(image.components.length)} components where its colour space needs ${String(required)}; the extra channel(s) are ignored`
|
|
221
226
|
});
|
|
222
227
|
const maximum = (1 << image.bitDepth) - 1;
|
|
223
|
-
const scale = (value) => image.bitDepth ===
|
|
228
|
+
const scale = (value) => image.bitDepth === BITS_PER_BYTE ? value : Math.round(value * MAX_BYTE_VALUE / maximum);
|
|
224
229
|
const pixels = image.width * image.height;
|
|
225
|
-
const channels = kind === "gray" ? 1 :
|
|
230
|
+
const channels = kind === "gray" ? 1 : RGB_CHANNEL_COUNT;
|
|
226
231
|
const data = new Uint8Array(pixels * channels);
|
|
227
232
|
if (kind === "cmyk") for (let i = 0; i < pixels; i++) {
|
|
228
|
-
const rgb = cmykToRgbByte(scale(image.components[0]?.[i] ?? 0) /
|
|
229
|
-
data[i *
|
|
230
|
-
data[i *
|
|
231
|
-
data[i *
|
|
233
|
+
const rgb = cmykToRgbByte(scale(image.components[0]?.[i] ?? 0) / MAX_BYTE_VALUE, scale(image.components[1]?.[i] ?? 0) / MAX_BYTE_VALUE, scale(image.components[2]?.[i] ?? 0) / MAX_BYTE_VALUE, scale(image.components[3]?.[i] ?? 0) / MAX_BYTE_VALUE);
|
|
234
|
+
data[i * RGB_CHANNEL_COUNT] = rgb.r;
|
|
235
|
+
data[i * RGB_CHANNEL_COUNT + 1] = rgb.g;
|
|
236
|
+
data[i * RGB_CHANNEL_COUNT + 2] = rgb.b;
|
|
232
237
|
}
|
|
233
238
|
else for (let channel = 0; channel < channels; channel++) {
|
|
234
239
|
const plane = image.components[channel];
|
|
@@ -302,8 +307,8 @@ function readImageXObject(dict, raw, resolver, sink) {
|
|
|
302
307
|
});
|
|
303
308
|
return;
|
|
304
309
|
}
|
|
305
|
-
const bitsPerComponent = require_objects.asNumber(require_objects.dictGet(dict, "BitsPerComponent") ?? require_objects.dictGet(dict, "BPC")) ??
|
|
306
|
-
if (bitsPerComponent !== 1 && bitsPerComponent !== 2 && bitsPerComponent !== 4 && bitsPerComponent !==
|
|
310
|
+
const bitsPerComponent = require_objects.asNumber(require_objects.dictGet(dict, "BitsPerComponent") ?? require_objects.dictGet(dict, "BPC")) ?? BITS_PER_BYTE;
|
|
311
|
+
if (bitsPerComponent !== 1 && bitsPerComponent !== 2 && bitsPerComponent !== 4 && bitsPerComponent !== BITS_PER_BYTE) {
|
|
307
312
|
sink({
|
|
308
313
|
code: "image/unsupported-bit-depth",
|
|
309
314
|
severity: "warning",
|
package/dist/images-read.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.cjs";
|
|
2
|
-
import { n as PdfDict } from "./objects-
|
|
2
|
+
import { n as PdfDict } from "./objects-e2RS3-yT.cjs";
|
|
3
3
|
import { PdfObjectResolver } from "./interpret.cjs";
|
|
4
4
|
//#region src/images-read.d.ts
|
|
5
5
|
interface ExtractedPdfImage {
|
|
@@ -13,6 +13,6 @@ interface ExtractedPdfImage {
|
|
|
13
13
|
readonly globalsBytes?: Uint8Array<ArrayBuffer>;
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
-
declare function readImageXObject(dict: PdfDict, raw: Uint8Array<ArrayBuffer>, resolver: PdfObjectResolver
|
|
16
|
+
declare function readImageXObject(dict: PdfDict, raw: Uint8Array<ArrayBuffer>, resolver: Readonly<PdfObjectResolver>, sink: PdfDiagnosticSink): ExtractedPdfImage | undefined;
|
|
17
17
|
//#endregion
|
|
18
18
|
export { ExtractedPdfImage, readImageXObject };
|
package/dist/images-read.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PdfDiagnosticSink } from "./diagnostics.js";
|
|
2
|
-
import { n as PdfDict } from "./objects-
|
|
2
|
+
import { n as PdfDict } from "./objects-e2RS3-yT.js";
|
|
3
3
|
import { PdfObjectResolver } from "./interpret.js";
|
|
4
4
|
//#region src/images-read.d.ts
|
|
5
5
|
interface ExtractedPdfImage {
|
|
@@ -13,6 +13,6 @@ interface ExtractedPdfImage {
|
|
|
13
13
|
readonly globalsBytes?: Uint8Array<ArrayBuffer>;
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
-
declare function readImageXObject(dict: PdfDict, raw: Uint8Array<ArrayBuffer>, resolver: PdfObjectResolver
|
|
16
|
+
declare function readImageXObject(dict: PdfDict, raw: Uint8Array<ArrayBuffer>, resolver: Readonly<PdfObjectResolver>, sink: PdfDiagnosticSink): ExtractedPdfImage | undefined;
|
|
17
17
|
//#endregion
|
|
18
18
|
export { ExtractedPdfImage, readImageXObject };
|