modern-pdf-lib 0.26.0 → 0.28.0
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/README.md +16 -3
- package/dist/{batchOptimize-C1W3O68Q.cjs → batchOptimize-CXC9gNqD.cjs} +55 -55
- package/dist/{batchOptimize-BCJEEN8J.mjs → batchOptimize-CjLGD5ie.mjs} +25 -25
- package/dist/{bridge-DMEuGtfn.cjs → bridge-ByvzPu5h.cjs} +29 -31
- package/dist/{bridge-DaS-gzEd.mjs → bridge-ZD6O6QQa.mjs} +4 -5
- package/dist/browser.cjs +245 -154
- package/dist/browser.d.cts +166 -166
- package/dist/browser.d.cts.map +1 -1
- package/dist/browser.d.mts +166 -166
- package/dist/browser.d.mts.map +1 -1
- package/dist/browser.mjs +15 -19
- package/dist/cli/index.cjs +7 -7
- package/dist/cli/index.mjs +8 -8
- package/dist/{compressionAnalysis-CwknBtqx.mjs → compressionAnalysis-BgKy45pA.mjs} +55 -69
- package/dist/{compressionAnalysis-Ch7t-HXn.d.mts → compressionAnalysis-CDOp_vPr.d.mts} +136 -136
- package/dist/compressionAnalysis-CDOp_vPr.d.mts.map +1 -0
- package/dist/{compressionAnalysis-B-FPzgzw.cjs → compressionAnalysis-Djv-Zvcd.cjs} +85 -99
- package/dist/{compressionAnalysis-Dgv1TtHJ.d.cts → compressionAnalysis-UfmonqbM.d.cts} +136 -136
- package/dist/compressionAnalysis-UfmonqbM.d.cts.map +1 -0
- package/dist/create.cjs +21 -23
- package/dist/create.d.cts +2 -2
- package/dist/create.d.mts +2 -2
- package/dist/create.mjs +3 -5
- package/dist/{deduplicateImages-DIon68zB.mjs → deduplicateImages-BTCyAPfJ.mjs} +4 -5
- package/dist/{deduplicateImages-cKsnD6Ep.cjs → deduplicateImages-CaGgaqyS.cjs} +14 -15
- package/dist/{fieldAppearance-C8PoLFSc.d.mts → fieldAppearance-Df1262CT.d.cts} +44 -44
- package/dist/fieldAppearance-Df1262CT.d.cts.map +1 -0
- package/dist/{fieldAppearance-CdiGFG5e.d.cts → fieldAppearance-_CZdoUCD.d.mts} +44 -44
- package/dist/fieldAppearance-_CZdoUCD.d.mts.map +1 -0
- package/dist/fontEmbed-DGiZS0h2.d.cts +677 -0
- package/dist/fontEmbed-DGiZS0h2.d.cts.map +1 -0
- package/dist/fontEmbed-DtA_riGC.d.mts +677 -0
- package/dist/fontEmbed-DtA_riGC.d.mts.map +1 -0
- package/dist/forms.cjs +3 -4
- package/dist/forms.d.cts +2 -2
- package/dist/forms.d.mts +2 -2
- package/dist/forms.mjs +2 -3
- package/dist/{grayscaleDetect-C6kFF3dk.mjs → grayscaleDetect-6GJrgBRT.mjs} +3 -3
- package/dist/{grayscaleDetect-C2m-eEXR.cjs → grayscaleDetect-DAUqxjgR.cjs} +13 -14
- package/dist/{imageExtract-zEb1gnkb.cjs → imageExtract-DT50Hp_g.cjs} +13 -14
- package/dist/{imageExtract-Dnk_Ssv7.mjs → imageExtract-Dapir-ux.mjs} +3 -4
- package/dist/index-C1lZe66f.d.mts +8682 -0
- package/dist/index-C1lZe66f.d.mts.map +1 -0
- package/dist/index-D1SvXWSI.d.cts +8682 -0
- package/dist/index-D1SvXWSI.d.cts.map +1 -0
- package/dist/index.cjs +245 -153
- package/dist/index.d.cts +7 -7
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +14 -17
- package/dist/{layout-DQh05VP-.cjs → layout-C4vbTlBW.cjs} +184 -134
- package/dist/{layout-CrqeJBMI.mjs → layout-lO4x64kY.mjs} +50 -12
- package/dist/{loader-CVB-c_3Z.mjs → loader-B1Ix7ozU.mjs} +248 -12
- package/dist/{loader-DYCH3n7d.cjs → loader-DR7H0XOf.cjs} +332 -66
- package/dist/parse.cjs +7 -8
- package/dist/parse.d.cts +3 -3
- package/dist/parse.d.mts +3 -3
- package/dist/parse.mjs +6 -7
- package/dist/pdfDocument-CH2E4UCc.d.mts +5160 -0
- package/dist/pdfDocument-CH2E4UCc.d.mts.map +1 -0
- package/dist/{pdfDocument-D9uYNSb-.cjs → pdfDocument-C_7mrBCL.cjs} +22409 -11624
- package/dist/pdfDocument-CzOipXnw.d.cts +5160 -0
- package/dist/pdfDocument-CzOipXnw.d.cts.map +1 -0
- package/dist/{pdfDocument-D7aFSQEY.mjs → pdfDocument-DRbT6HZw.mjs} +10830 -855
- package/dist/{pdfForm-BpqDGp29.cjs → pdfForm-BVS_do95.cjs} +112 -107
- package/dist/pdfForm-Ca86NDWn.d.cts +897 -0
- package/dist/pdfForm-Ca86NDWn.d.cts.map +1 -0
- package/dist/pdfForm-Ca86NDWn.d.mts +897 -0
- package/dist/pdfForm-Ca86NDWn.d.mts.map +1 -0
- package/dist/{pdfForm-C3mC9FoQ.mjs → pdfForm-CfLnlsj-.mjs} +22 -17
- package/dist/{pdfObjects-1veop1_d.cjs → pdfObjects-BcPlSI0a.cjs} +62 -53
- package/dist/{pdfObjects-uEsWlfzU.mjs → pdfObjects-CB7TEdbW.mjs} +12 -2
- package/dist/rolldown-runtime-ak5kbic3.cjs +18 -0
- package/dist/{src-lFqJHb1C.cjs → src-C-IDXuvi.cjs} +8692 -1916
- package/dist/{src-QZWP21qF.mjs → src-DJaD-bJ2.mjs} +7278 -982
- package/dist/{streamDecode-Bj568Nc9.mjs → streamDecode-BamENT3k.mjs} +129 -150
- package/dist/{streamDecode-CvgErkFu.cjs → streamDecode-DcaZz309.cjs} +139 -160
- package/package.json +25 -22
- package/dist/compressionAnalysis-Ch7t-HXn.d.mts.map +0 -1
- package/dist/compressionAnalysis-Dgv1TtHJ.d.cts.map +0 -1
- package/dist/fflateAdapter-DuNiByKx.mjs +0 -196
- package/dist/fflateAdapter-LTAeAhaD.cjs +0 -207
- package/dist/fieldAppearance-C8PoLFSc.d.mts.map +0 -1
- package/dist/fieldAppearance-CdiGFG5e.d.cts.map +0 -1
- package/dist/fontEmbed-3YhUPLFj.d.cts +0 -659
- package/dist/fontEmbed-3YhUPLFj.d.cts.map +0 -1
- package/dist/fontEmbed-DlVnVCZU.d.mts +0 -659
- package/dist/fontEmbed-DlVnVCZU.d.mts.map +0 -1
- package/dist/fontSubset-5SLWMmEw.cjs +0 -518
- package/dist/fontSubset-BGFDIMmT.mjs +0 -495
- package/dist/index-B4S61WjK.d.mts +0 -6507
- package/dist/index-B4S61WjK.d.mts.map +0 -1
- package/dist/index-xfJP6Ycm.d.cts +0 -6507
- package/dist/index-xfJP6Ycm.d.cts.map +0 -1
- package/dist/libdeflateWasm-CcA1W04G.mjs +0 -220
- package/dist/libdeflateWasm-DLw-I1CY.cjs +0 -237
- package/dist/pdfCatalog-Bqq4FiLn.cjs +0 -174
- package/dist/pdfCatalog-CnKMAtIo.mjs +0 -139
- package/dist/pdfDocument-Bc_vAO74.d.cts +0 -4758
- package/dist/pdfDocument-Bc_vAO74.d.cts.map +0 -1
- package/dist/pdfDocument-Bi-NoyXv.d.mts +0 -4758
- package/dist/pdfDocument-Bi-NoyXv.d.mts.map +0 -1
- package/dist/pdfForm-BiyNtYem.d.mts +0 -905
- package/dist/pdfForm-BiyNtYem.d.mts.map +0 -1
- package/dist/pdfForm-SOXJ72LW.d.cts +0 -905
- package/dist/pdfForm-SOXJ72LW.d.cts.map +0 -1
- package/dist/pdfPage-BJIE5hc6.mjs +0 -8180
- package/dist/pdfPage-C_tjEjj1.cjs +0 -8893
- package/dist/pngEmbed-CGi7cym7.mjs +0 -552
- package/dist/pngEmbed-CTn9IeNB.cjs +0 -563
- package/dist/rolldown-runtime-CKhH4XqG.cjs +0 -24
|
@@ -1,563 +0,0 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('./rolldown-runtime-CKhH4XqG.cjs');
|
|
2
|
-
let fflate = require("fflate");
|
|
3
|
-
|
|
4
|
-
//#region src/assets/image/pngEmbed.ts
|
|
5
|
-
/**
|
|
6
|
-
* @module assets/image/pngEmbed
|
|
7
|
-
*
|
|
8
|
-
* PNG decoding and embedding for PDF image XObjects.
|
|
9
|
-
*
|
|
10
|
-
* Parses a PNG file to extract dimensions, color type, bit depth, and
|
|
11
|
-
* pixel data. Produces the data needed for a PDF image XObject
|
|
12
|
-
* dictionary with the appropriate `/ColorSpace`, `/BitsPerComponent`,
|
|
13
|
-
* `/Filter`, and `/SMask` entries.
|
|
14
|
-
*
|
|
15
|
-
* Handles all standard PNG color types:
|
|
16
|
-
* - Type 0: Grayscale
|
|
17
|
-
* - Type 2: RGB (Truecolor)
|
|
18
|
-
* - Type 3: Indexed (Palette)
|
|
19
|
-
* - Type 4: Grayscale + Alpha
|
|
20
|
-
* - Type 6: RGBA (Truecolor + Alpha)
|
|
21
|
-
*
|
|
22
|
-
* For images with alpha channels (types 4 and 6), the alpha channel
|
|
23
|
-
* is separated into a /SMask soft-mask image.
|
|
24
|
-
*
|
|
25
|
-
* WASM-accelerated decoding is supported with a JS fallback.
|
|
26
|
-
*
|
|
27
|
-
* No Buffer — uses Uint8Array exclusively.
|
|
28
|
-
* No fs — no file system access.
|
|
29
|
-
* No require() — ESM import only.
|
|
30
|
-
*/
|
|
31
|
-
var pngEmbed_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
|
|
32
|
-
embedPng: () => embedPng,
|
|
33
|
-
initPngWasm: () => initPngWasm
|
|
34
|
-
});
|
|
35
|
-
/** PNG file signature (8 bytes). */
|
|
36
|
-
const PNG_SIGNATURE = new Uint8Array([
|
|
37
|
-
137,
|
|
38
|
-
80,
|
|
39
|
-
78,
|
|
40
|
-
71,
|
|
41
|
-
13,
|
|
42
|
-
10,
|
|
43
|
-
26,
|
|
44
|
-
10
|
|
45
|
-
]);
|
|
46
|
-
/** Color type constants from the PNG spec. */
|
|
47
|
-
var PngColorType = /* @__PURE__ */ function(PngColorType) {
|
|
48
|
-
PngColorType[PngColorType["Grayscale"] = 0] = "Grayscale";
|
|
49
|
-
PngColorType[PngColorType["RGB"] = 2] = "RGB";
|
|
50
|
-
PngColorType[PngColorType["Indexed"] = 3] = "Indexed";
|
|
51
|
-
PngColorType[PngColorType["GrayscaleAlpha"] = 4] = "GrayscaleAlpha";
|
|
52
|
-
PngColorType[PngColorType["RGBA"] = 6] = "RGBA";
|
|
53
|
-
return PngColorType;
|
|
54
|
-
}(PngColorType || {});
|
|
55
|
-
/**
|
|
56
|
-
* Validate the PNG signature.
|
|
57
|
-
*
|
|
58
|
-
* @param data - The raw PNG bytes.
|
|
59
|
-
* @throws If the signature does not match.
|
|
60
|
-
*/
|
|
61
|
-
function validatePngSignature(data) {
|
|
62
|
-
if (data.length < 8) throw new Error("PNG data too small — expected at least 8 bytes for the signature");
|
|
63
|
-
for (let i = 0; i < 8; i++) if (data[i] !== PNG_SIGNATURE[i]) throw new Error("Invalid PNG signature");
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Iterate over all chunks in a PNG file.
|
|
67
|
-
*
|
|
68
|
-
* @param data - The raw PNG bytes.
|
|
69
|
-
* @returns An array of parsed chunks.
|
|
70
|
-
*/
|
|
71
|
-
function parseChunks(data) {
|
|
72
|
-
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
73
|
-
const chunks = [];
|
|
74
|
-
let offset = 8;
|
|
75
|
-
while (offset < data.length) {
|
|
76
|
-
if (offset + 8 > data.length) break;
|
|
77
|
-
const length = view.getUint32(offset, false);
|
|
78
|
-
const type = String.fromCharCode(data[offset + 4], data[offset + 5], data[offset + 6], data[offset + 7]);
|
|
79
|
-
const chunkData = data.slice(offset + 8, offset + 8 + length);
|
|
80
|
-
chunks.push({
|
|
81
|
-
type,
|
|
82
|
-
data: chunkData
|
|
83
|
-
});
|
|
84
|
-
offset += 12 + length;
|
|
85
|
-
if (type === "IEND") break;
|
|
86
|
-
}
|
|
87
|
-
return chunks;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Parse the IHDR chunk.
|
|
91
|
-
*/
|
|
92
|
-
function parseIhdr(chunk) {
|
|
93
|
-
if (chunk.type !== "IHDR" || chunk.data.length < 13) throw new Error("Invalid PNG: missing or malformed IHDR chunk");
|
|
94
|
-
const view = new DataView(chunk.data.buffer, chunk.data.byteOffset, chunk.data.byteLength);
|
|
95
|
-
return {
|
|
96
|
-
width: view.getUint32(0, false),
|
|
97
|
-
height: view.getUint32(4, false),
|
|
98
|
-
bitDepth: chunk.data[8],
|
|
99
|
-
colorType: chunk.data[9],
|
|
100
|
-
compressionMethod: chunk.data[10],
|
|
101
|
-
filterMethod: chunk.data[11],
|
|
102
|
-
interlaceMethod: chunk.data[12]
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Concatenate all IDAT chunk data into a single Uint8Array.
|
|
107
|
-
*/
|
|
108
|
-
function concatenateIdatChunks(chunks) {
|
|
109
|
-
const idatChunks = chunks.filter((c) => c.type === "IDAT");
|
|
110
|
-
if (idatChunks.length === 0) throw new Error("Invalid PNG: no IDAT chunks found");
|
|
111
|
-
const totalLength = idatChunks.reduce((sum, c) => sum + c.data.length, 0);
|
|
112
|
-
const result = new Uint8Array(totalLength);
|
|
113
|
-
let pos = 0;
|
|
114
|
-
for (const chunk of idatChunks) {
|
|
115
|
-
result.set(chunk.data, pos);
|
|
116
|
-
pos += chunk.data.length;
|
|
117
|
-
}
|
|
118
|
-
return result;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Find the PLTE (palette) chunk data if present.
|
|
122
|
-
*/
|
|
123
|
-
function findPalette(chunks) {
|
|
124
|
-
return chunks.find((c) => c.type === "PLTE")?.data;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Find the tRNS (transparency) chunk data if present.
|
|
128
|
-
*/
|
|
129
|
-
function findTransparency(chunks) {
|
|
130
|
-
return chunks.find((c) => c.type === "tRNS")?.data;
|
|
131
|
-
}
|
|
132
|
-
let pngWasmInstance;
|
|
133
|
-
/**
|
|
134
|
-
* Initialize the PNG decoding WASM module.
|
|
135
|
-
*
|
|
136
|
-
* @param wasmSource - The WASM binary, URL, or Response.
|
|
137
|
-
*/
|
|
138
|
-
async function initPngWasm(wasmSource) {
|
|
139
|
-
if (pngWasmInstance) return;
|
|
140
|
-
const imports = { env: {} };
|
|
141
|
-
let result;
|
|
142
|
-
try {
|
|
143
|
-
if (wasmSource instanceof Uint8Array) result = await WebAssembly.instantiate(wasmSource.buffer, imports);
|
|
144
|
-
else if (typeof Response !== "undefined" && wasmSource instanceof Response) result = await WebAssembly.instantiateStreaming(wasmSource, imports);
|
|
145
|
-
else if (typeof wasmSource === "string" || wasmSource instanceof URL) {
|
|
146
|
-
const resp = await fetch(String(wasmSource));
|
|
147
|
-
result = await WebAssembly.instantiateStreaming(resp, imports);
|
|
148
|
-
} else {
|
|
149
|
-
const { loadWasmModule } = await Promise.resolve().then(() => require("./loader-DYCH3n7d.cjs")).then((n) => n.loader_exports);
|
|
150
|
-
const bytes = await loadWasmModule("png");
|
|
151
|
-
result = await WebAssembly.instantiate(bytes.buffer, imports);
|
|
152
|
-
}
|
|
153
|
-
pngWasmInstance = result.instance.exports;
|
|
154
|
-
} catch {
|
|
155
|
-
pngWasmInstance = void 0;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Decompress the zlib data from IDAT chunks.
|
|
160
|
-
*
|
|
161
|
-
* Uses the DecompressionStream API (available in modern browsers,
|
|
162
|
-
* Node 18+, Deno) or falls back to a manual inflate.
|
|
163
|
-
*
|
|
164
|
-
* @internal
|
|
165
|
-
*/
|
|
166
|
-
function decompressZlib(compressed) {
|
|
167
|
-
return (0, fflate.unzlibSync)(compressed);
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Apply PNG filter reconstruction to a decompressed scanline buffer.
|
|
171
|
-
*
|
|
172
|
-
* Each scanline is prefixed with a 1-byte filter type:
|
|
173
|
-
* 0=None, 1=Sub, 2=Up, 3=Average, 4=Paeth
|
|
174
|
-
*
|
|
175
|
-
* @internal
|
|
176
|
-
*/
|
|
177
|
-
function reconstructFilters(decompressed, width, height, bytesPerPixel) {
|
|
178
|
-
const stride = width * bytesPerPixel;
|
|
179
|
-
const result = new Uint8Array(height * stride);
|
|
180
|
-
let srcOffset = 0;
|
|
181
|
-
let dstOffset = 0;
|
|
182
|
-
for (let y = 0; y < height; y++) {
|
|
183
|
-
const filterType = decompressed[srcOffset];
|
|
184
|
-
srcOffset++;
|
|
185
|
-
const scanline = decompressed.subarray(srcOffset, srcOffset + stride);
|
|
186
|
-
srcOffset += stride;
|
|
187
|
-
const prevLine = y > 0 ? result.subarray((y - 1) * stride, y * stride) : new Uint8Array(stride);
|
|
188
|
-
for (let x = 0; x < stride; x++) {
|
|
189
|
-
const raw = scanline[x];
|
|
190
|
-
const a = x >= bytesPerPixel ? result[dstOffset + x - bytesPerPixel] : 0;
|
|
191
|
-
const b = prevLine[x];
|
|
192
|
-
const c = x >= bytesPerPixel && y > 0 ? result[(y - 1) * stride + x - bytesPerPixel] : 0;
|
|
193
|
-
let reconstructed;
|
|
194
|
-
switch (filterType) {
|
|
195
|
-
case 0:
|
|
196
|
-
reconstructed = raw;
|
|
197
|
-
break;
|
|
198
|
-
case 1:
|
|
199
|
-
reconstructed = raw + a & 255;
|
|
200
|
-
break;
|
|
201
|
-
case 2:
|
|
202
|
-
reconstructed = raw + b & 255;
|
|
203
|
-
break;
|
|
204
|
-
case 3:
|
|
205
|
-
reconstructed = raw + Math.floor((a + b) / 2) & 255;
|
|
206
|
-
break;
|
|
207
|
-
case 4:
|
|
208
|
-
reconstructed = raw + paethPredictor(a, b, c) & 255;
|
|
209
|
-
break;
|
|
210
|
-
default: throw new Error(`Unknown PNG filter type: ${filterType}`);
|
|
211
|
-
}
|
|
212
|
-
result[dstOffset + x] = reconstructed;
|
|
213
|
-
}
|
|
214
|
-
dstOffset += stride;
|
|
215
|
-
}
|
|
216
|
-
return result;
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* Paeth predictor function.
|
|
220
|
-
* @internal
|
|
221
|
-
*/
|
|
222
|
-
function paethPredictor(a, b, c) {
|
|
223
|
-
const p = a + b - c;
|
|
224
|
-
const pa = Math.abs(p - a);
|
|
225
|
-
const pb = Math.abs(p - b);
|
|
226
|
-
const pc = Math.abs(p - c);
|
|
227
|
-
if (pa <= pb && pa <= pc) return a;
|
|
228
|
-
if (pb <= pc) return b;
|
|
229
|
-
return c;
|
|
230
|
-
}
|
|
231
|
-
/**
|
|
232
|
-
* Compute the bytes per pixel for a given color type and bit depth.
|
|
233
|
-
* @internal
|
|
234
|
-
*/
|
|
235
|
-
function bytesPerPixel(colorType, bitDepth) {
|
|
236
|
-
const channels = colorType === PngColorType.Grayscale ? 1 : colorType === PngColorType.RGB ? 3 : colorType === PngColorType.Indexed ? 1 : colorType === PngColorType.GrayscaleAlpha ? 2 : colorType === PngColorType.RGBA ? 4 : 1;
|
|
237
|
-
return Math.max(1, Math.ceil(channels * bitDepth / 8));
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Separate RGBA pixels into RGB data + alpha mask.
|
|
241
|
-
* @internal
|
|
242
|
-
*/
|
|
243
|
-
function separateRgba(pixels, width, height) {
|
|
244
|
-
const pixelCount = width * height;
|
|
245
|
-
const rgb = new Uint8Array(pixelCount * 3);
|
|
246
|
-
const alpha = new Uint8Array(pixelCount);
|
|
247
|
-
for (let i = 0; i < pixelCount; i++) {
|
|
248
|
-
const srcIdx = i * 4;
|
|
249
|
-
const dstIdx = i * 3;
|
|
250
|
-
rgb[dstIdx] = pixels[srcIdx];
|
|
251
|
-
rgb[dstIdx + 1] = pixels[srcIdx + 1];
|
|
252
|
-
rgb[dstIdx + 2] = pixels[srcIdx + 2];
|
|
253
|
-
alpha[i] = pixels[srcIdx + 3];
|
|
254
|
-
}
|
|
255
|
-
return {
|
|
256
|
-
rgb,
|
|
257
|
-
alpha
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Separate Grayscale+Alpha pixels into gray data + alpha mask.
|
|
262
|
-
* @internal
|
|
263
|
-
*/
|
|
264
|
-
function separateGrayscaleAlpha(pixels, width, height) {
|
|
265
|
-
const pixelCount = width * height;
|
|
266
|
-
const gray = new Uint8Array(pixelCount);
|
|
267
|
-
const alpha = new Uint8Array(pixelCount);
|
|
268
|
-
for (let i = 0; i < pixelCount; i++) {
|
|
269
|
-
gray[i] = pixels[i * 2];
|
|
270
|
-
alpha[i] = pixels[i * 2 + 1];
|
|
271
|
-
}
|
|
272
|
-
return {
|
|
273
|
-
gray,
|
|
274
|
-
alpha
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Compress data using deflate for FlateDecode.
|
|
279
|
-
* @internal
|
|
280
|
-
*/
|
|
281
|
-
function compressForPdf(data) {
|
|
282
|
-
return (0, fflate.deflateSync)(data, { level: 6 });
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Embed a PNG image for use as a PDF image XObject.
|
|
286
|
-
*
|
|
287
|
-
* Parses the PNG file, decodes pixel data, separates alpha channels,
|
|
288
|
-
* and produces all the data needed for the PDF image XObject
|
|
289
|
-
* dictionary.
|
|
290
|
-
*
|
|
291
|
-
* @param pngData - The raw PNG file as a Uint8Array.
|
|
292
|
-
* @returns The embedding result with all data needed for a PDF image XObject.
|
|
293
|
-
*
|
|
294
|
-
* @example
|
|
295
|
-
* ```ts
|
|
296
|
-
* const pngBytes = await readFile('photo.png');
|
|
297
|
-
* const result = embedPng(pngBytes);
|
|
298
|
-
*
|
|
299
|
-
* // Create image XObject with:
|
|
300
|
-
* // /Width result.width
|
|
301
|
-
* // /Height result.height
|
|
302
|
-
* // /ColorSpace result.colorSpace
|
|
303
|
-
* // /BitsPerComponent result.bitsPerComponent
|
|
304
|
-
* // /Filter /FlateDecode
|
|
305
|
-
* // stream: result.imageData
|
|
306
|
-
* //
|
|
307
|
-
* // If result.smaskData is defined, create a second XObject for the SMask.
|
|
308
|
-
* ```
|
|
309
|
-
*/
|
|
310
|
-
function embedPng(pngData) {
|
|
311
|
-
validatePngSignature(pngData);
|
|
312
|
-
const chunks = parseChunks(pngData);
|
|
313
|
-
if (chunks.length === 0) throw new Error("Invalid PNG: no chunks found");
|
|
314
|
-
const ihdr = parseIhdr(chunks[0]);
|
|
315
|
-
const idatData = concatenateIdatChunks(chunks);
|
|
316
|
-
const palette = findPalette(chunks);
|
|
317
|
-
const transparency = findTransparency(chunks);
|
|
318
|
-
const hasAlpha = ihdr.colorType === PngColorType.GrayscaleAlpha || ihdr.colorType === PngColorType.RGBA;
|
|
319
|
-
const isInterlaced = ihdr.interlaceMethod !== 0;
|
|
320
|
-
if (ihdr.colorType === PngColorType.Indexed && !isInterlaced && ihdr.bitDepth === 8) return embedIndexedPng(ihdr, idatData, palette, transparency);
|
|
321
|
-
if (!hasAlpha && !isInterlaced && ihdr.bitDepth === 8) return embedDirectPng(ihdr, idatData, transparency);
|
|
322
|
-
return embedComplexPng(ihdr, idatData, palette, transparency);
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Embed an indexed (palette-based) PNG.
|
|
326
|
-
* @internal
|
|
327
|
-
*/
|
|
328
|
-
function embedIndexedPng(ihdr, idatData, palette, transparency) {
|
|
329
|
-
if (!palette) throw new Error("Invalid PNG: indexed color type requires PLTE chunk");
|
|
330
|
-
if (!transparency || transparency.length === 0) return {
|
|
331
|
-
width: ihdr.width,
|
|
332
|
-
height: ihdr.height,
|
|
333
|
-
bitsPerComponent: 8,
|
|
334
|
-
colorSpace: "Indexed",
|
|
335
|
-
palette,
|
|
336
|
-
imageData: idatData,
|
|
337
|
-
filter: "FlateDecode",
|
|
338
|
-
hasTransparency: false,
|
|
339
|
-
decodeParms: {
|
|
340
|
-
predictor: 15,
|
|
341
|
-
columns: ihdr.width,
|
|
342
|
-
colors: 1,
|
|
343
|
-
bitsPerComponent: 8
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
const decompressed = decompressZlib(idatData);
|
|
347
|
-
const bpp = bytesPerPixel(ihdr.colorType, ihdr.bitDepth);
|
|
348
|
-
const pixels = reconstructFilters(decompressed, ihdr.width, ihdr.height, bpp);
|
|
349
|
-
const imageData = compressForPdf(pixels);
|
|
350
|
-
const pixelCount = ihdr.width * ihdr.height;
|
|
351
|
-
const alpha = new Uint8Array(pixelCount);
|
|
352
|
-
for (let i = 0; i < pixelCount; i++) {
|
|
353
|
-
const paletteIndex = pixels[i];
|
|
354
|
-
alpha[i] = paletteIndex < transparency.length ? transparency[paletteIndex] : 255;
|
|
355
|
-
}
|
|
356
|
-
const smaskData = compressForPdf(alpha);
|
|
357
|
-
return {
|
|
358
|
-
width: ihdr.width,
|
|
359
|
-
height: ihdr.height,
|
|
360
|
-
bitsPerComponent: 8,
|
|
361
|
-
colorSpace: "Indexed",
|
|
362
|
-
palette,
|
|
363
|
-
imageData,
|
|
364
|
-
filter: "FlateDecode",
|
|
365
|
-
smaskData,
|
|
366
|
-
smaskBitsPerComponent: 8,
|
|
367
|
-
hasTransparency: true
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
/**
|
|
371
|
-
* Embed a direct (Grayscale or RGB) PNG without alpha.
|
|
372
|
-
* @internal
|
|
373
|
-
*/
|
|
374
|
-
function embedDirectPng(ihdr, idatData, transparency) {
|
|
375
|
-
const colorSpace = ihdr.colorType === PngColorType.Grayscale ? "DeviceGray" : "DeviceRGB";
|
|
376
|
-
const colors = ihdr.colorType === PngColorType.Grayscale ? 1 : 3;
|
|
377
|
-
if (!transparency || transparency.length === 0) return {
|
|
378
|
-
width: ihdr.width,
|
|
379
|
-
height: ihdr.height,
|
|
380
|
-
bitsPerComponent: ihdr.bitDepth,
|
|
381
|
-
colorSpace,
|
|
382
|
-
imageData: idatData,
|
|
383
|
-
filter: "FlateDecode",
|
|
384
|
-
hasTransparency: false,
|
|
385
|
-
decodeParms: {
|
|
386
|
-
predictor: 15,
|
|
387
|
-
columns: ihdr.width,
|
|
388
|
-
colors,
|
|
389
|
-
bitsPerComponent: ihdr.bitDepth
|
|
390
|
-
}
|
|
391
|
-
};
|
|
392
|
-
const decompressed = decompressZlib(idatData);
|
|
393
|
-
const bpp = bytesPerPixel(ihdr.colorType, ihdr.bitDepth);
|
|
394
|
-
const pixels = reconstructFilters(decompressed, ihdr.width, ihdr.height, bpp);
|
|
395
|
-
const imageData = compressForPdf(pixels);
|
|
396
|
-
let smaskData;
|
|
397
|
-
const pixelCount = ihdr.width * ihdr.height;
|
|
398
|
-
const alpha = new Uint8Array(pixelCount);
|
|
399
|
-
alpha.fill(255);
|
|
400
|
-
if (ihdr.colorType === PngColorType.Grayscale && transparency.length >= 2) {
|
|
401
|
-
const trnsGray = transparency[0] << 8 | transparency[1];
|
|
402
|
-
for (let i = 0; i < pixelCount; i++) if (pixels[i] === trnsGray) alpha[i] = 0;
|
|
403
|
-
smaskData = compressForPdf(alpha);
|
|
404
|
-
} else if (ihdr.colorType === PngColorType.RGB && transparency.length >= 6) {
|
|
405
|
-
const trnsR = transparency[0] << 8 | transparency[1];
|
|
406
|
-
const trnsG = transparency[2] << 8 | transparency[3];
|
|
407
|
-
const trnsB = transparency[4] << 8 | transparency[5];
|
|
408
|
-
for (let i = 0; i < pixelCount; i++) {
|
|
409
|
-
const idx = i * 3;
|
|
410
|
-
if (pixels[idx] === trnsR && pixels[idx + 1] === trnsG && pixels[idx + 2] === trnsB) alpha[i] = 0;
|
|
411
|
-
}
|
|
412
|
-
smaskData = compressForPdf(alpha);
|
|
413
|
-
}
|
|
414
|
-
return {
|
|
415
|
-
width: ihdr.width,
|
|
416
|
-
height: ihdr.height,
|
|
417
|
-
bitsPerComponent: ihdr.bitDepth,
|
|
418
|
-
colorSpace,
|
|
419
|
-
imageData,
|
|
420
|
-
filter: "FlateDecode",
|
|
421
|
-
smaskData,
|
|
422
|
-
smaskBitsPerComponent: smaskData ? 8 : void 0,
|
|
423
|
-
hasTransparency: true
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
/**
|
|
427
|
-
* Full decompression path for PNGs that need alpha separation,
|
|
428
|
-
* de-interlacing, or bit-depth normalization.
|
|
429
|
-
* @internal
|
|
430
|
-
*/
|
|
431
|
-
function embedComplexPng(ihdr, idatData, palette, transparency) {
|
|
432
|
-
const decompressed = decompressZlib(idatData);
|
|
433
|
-
const bpp = bytesPerPixel(ihdr.colorType, ihdr.bitDepth);
|
|
434
|
-
let pixels;
|
|
435
|
-
if (ihdr.interlaceMethod !== 0) {
|
|
436
|
-
const startingRow = [
|
|
437
|
-
0,
|
|
438
|
-
0,
|
|
439
|
-
4,
|
|
440
|
-
0,
|
|
441
|
-
2,
|
|
442
|
-
0,
|
|
443
|
-
1
|
|
444
|
-
];
|
|
445
|
-
const startingCol = [
|
|
446
|
-
0,
|
|
447
|
-
4,
|
|
448
|
-
0,
|
|
449
|
-
2,
|
|
450
|
-
0,
|
|
451
|
-
1,
|
|
452
|
-
0
|
|
453
|
-
];
|
|
454
|
-
const rowStride = [
|
|
455
|
-
8,
|
|
456
|
-
8,
|
|
457
|
-
8,
|
|
458
|
-
4,
|
|
459
|
-
4,
|
|
460
|
-
2,
|
|
461
|
-
2
|
|
462
|
-
];
|
|
463
|
-
const colStride = [
|
|
464
|
-
8,
|
|
465
|
-
8,
|
|
466
|
-
4,
|
|
467
|
-
4,
|
|
468
|
-
2,
|
|
469
|
-
2,
|
|
470
|
-
1
|
|
471
|
-
];
|
|
472
|
-
const stride = ihdr.width * bpp;
|
|
473
|
-
const finalPixels = new Uint8Array(ihdr.height * stride);
|
|
474
|
-
let srcOffset = 0;
|
|
475
|
-
for (let pass = 0; pass < 7; pass++) {
|
|
476
|
-
const startRow = startingRow[pass];
|
|
477
|
-
const startCol = startingCol[pass];
|
|
478
|
-
const rStride = rowStride[pass];
|
|
479
|
-
const cStride = colStride[pass];
|
|
480
|
-
const passWidth = ihdr.width <= startCol ? 0 : Math.ceil((ihdr.width - startCol) / cStride);
|
|
481
|
-
const passHeight = ihdr.height <= startRow ? 0 : Math.ceil((ihdr.height - startRow) / rStride);
|
|
482
|
-
if (passWidth === 0 || passHeight === 0) continue;
|
|
483
|
-
const passDataLength = passHeight * (1 + passWidth * bpp);
|
|
484
|
-
const passData = decompressed.subarray(srcOffset, srcOffset + passDataLength);
|
|
485
|
-
srcOffset += passDataLength;
|
|
486
|
-
const passPixels = reconstructFilters(passData, passWidth, passHeight, bpp);
|
|
487
|
-
for (let py = 0; py < passHeight; py++) {
|
|
488
|
-
const finalY = startRow + py * rStride;
|
|
489
|
-
for (let px = 0; px < passWidth; px++) {
|
|
490
|
-
const finalX = startCol + px * cStride;
|
|
491
|
-
const srcIdx = (py * passWidth + px) * bpp;
|
|
492
|
-
const dstIdx = finalY * stride + finalX * bpp;
|
|
493
|
-
for (let b = 0; b < bpp; b++) finalPixels[dstIdx + b] = passPixels[srcIdx + b];
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
pixels = finalPixels;
|
|
498
|
-
} else pixels = reconstructFilters(decompressed, ihdr.width, ihdr.height, bpp);
|
|
499
|
-
let imageData;
|
|
500
|
-
let smaskData;
|
|
501
|
-
let colorSpace;
|
|
502
|
-
let bitsPerComponent = ihdr.bitDepth;
|
|
503
|
-
switch (ihdr.colorType) {
|
|
504
|
-
case PngColorType.RGBA: {
|
|
505
|
-
const { rgb, alpha } = separateRgba(pixels, ihdr.width, ihdr.height);
|
|
506
|
-
imageData = compressForPdf(rgb);
|
|
507
|
-
smaskData = compressForPdf(alpha);
|
|
508
|
-
colorSpace = "DeviceRGB";
|
|
509
|
-
bitsPerComponent = 8;
|
|
510
|
-
break;
|
|
511
|
-
}
|
|
512
|
-
case PngColorType.GrayscaleAlpha: {
|
|
513
|
-
const { gray, alpha } = separateGrayscaleAlpha(pixels, ihdr.width, ihdr.height);
|
|
514
|
-
imageData = compressForPdf(gray);
|
|
515
|
-
smaskData = compressForPdf(alpha);
|
|
516
|
-
colorSpace = "DeviceGray";
|
|
517
|
-
bitsPerComponent = 8;
|
|
518
|
-
break;
|
|
519
|
-
}
|
|
520
|
-
case PngColorType.Grayscale:
|
|
521
|
-
imageData = compressForPdf(pixels);
|
|
522
|
-
colorSpace = "DeviceGray";
|
|
523
|
-
break;
|
|
524
|
-
case PngColorType.RGB:
|
|
525
|
-
imageData = compressForPdf(pixels);
|
|
526
|
-
colorSpace = "DeviceRGB";
|
|
527
|
-
break;
|
|
528
|
-
case PngColorType.Indexed:
|
|
529
|
-
if (!palette) throw new Error("Invalid PNG: indexed color type requires PLTE chunk");
|
|
530
|
-
imageData = compressForPdf(pixels);
|
|
531
|
-
colorSpace = "Indexed";
|
|
532
|
-
bitsPerComponent = ihdr.bitDepth;
|
|
533
|
-
break;
|
|
534
|
-
default: throw new Error(`Unsupported PNG color type: ${ihdr.colorType}`);
|
|
535
|
-
}
|
|
536
|
-
return {
|
|
537
|
-
width: ihdr.width,
|
|
538
|
-
height: ihdr.height,
|
|
539
|
-
bitsPerComponent,
|
|
540
|
-
colorSpace,
|
|
541
|
-
palette: ihdr.colorType === PngColorType.Indexed ? palette : void 0,
|
|
542
|
-
imageData,
|
|
543
|
-
filter: "FlateDecode",
|
|
544
|
-
smaskData,
|
|
545
|
-
smaskBitsPerComponent: smaskData ? 8 : void 0,
|
|
546
|
-
hasTransparency: smaskData !== void 0 || transparency !== void 0 && transparency.length > 0
|
|
547
|
-
};
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
//#endregion
|
|
551
|
-
Object.defineProperty(exports, 'embedPng', {
|
|
552
|
-
enumerable: true,
|
|
553
|
-
get: function () {
|
|
554
|
-
return embedPng;
|
|
555
|
-
}
|
|
556
|
-
});
|
|
557
|
-
Object.defineProperty(exports, 'pngEmbed_exports', {
|
|
558
|
-
enumerable: true,
|
|
559
|
-
get: function () {
|
|
560
|
-
return pngEmbed_exports;
|
|
561
|
-
}
|
|
562
|
-
});
|
|
563
|
-
//# sourceMappingURL=pngEmbed-CTn9IeNB.cjs.map
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
//#region \0rolldown/runtime.js
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __exportAll = (all, no_symbols) => {
|
|
4
|
-
let target = {};
|
|
5
|
-
for (var name in all) {
|
|
6
|
-
__defProp(target, name, {
|
|
7
|
-
get: all[name],
|
|
8
|
-
enumerable: true
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
if (!no_symbols) {
|
|
12
|
-
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
13
|
-
}
|
|
14
|
-
return target;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
//#endregion
|
|
18
|
-
|
|
19
|
-
Object.defineProperty(exports, '__exportAll', {
|
|
20
|
-
enumerable: true,
|
|
21
|
-
get: function () {
|
|
22
|
-
return __exportAll;
|
|
23
|
-
}
|
|
24
|
-
});
|