@embedpdf/engines 2.11.0 → 2.12.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/dist/browser-B5n5EUyW.cjs +2 -0
- package/dist/browser-B5n5EUyW.cjs.map +1 -0
- package/dist/{browser-BISJ9naB.js → browser-BKLM0ThC.js} +98 -6
- package/dist/browser-BKLM0ThC.js.map +1 -0
- package/dist/{direct-engine-cyecHjwI.js → direct-engine-B7gUkBcT.js} +158 -11
- package/dist/direct-engine-B7gUkBcT.js.map +1 -0
- package/dist/direct-engine-DDe3a0AP.cjs +2 -0
- package/dist/direct-engine-DDe3a0AP.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +3 -3
- package/dist/lib/converters/index.cjs +1 -1
- package/dist/lib/converters/index.js +1 -1
- package/dist/lib/image-encoder/bmp.d.ts +13 -0
- package/dist/lib/image-encoder/image-encoder-worker.d.ts +1 -1
- package/dist/lib/image-encoder/worker-pool.d.ts +1 -1
- package/dist/lib/pdfium/engine.d.ts +16 -0
- package/dist/lib/pdfium/index.cjs +1 -1
- package/dist/lib/pdfium/index.js +4 -4
- package/dist/lib/pdfium/web/direct-engine.cjs +1 -1
- package/dist/lib/pdfium/web/direct-engine.js +3 -3
- package/dist/lib/pdfium/web/worker-engine.cjs +1 -1
- package/dist/lib/pdfium/web/worker-engine.cjs.map +1 -1
- package/dist/lib/pdfium/web/worker-engine.js +130 -5
- package/dist/lib/pdfium/web/worker-engine.js.map +1 -1
- package/dist/{pdf-engine-Dj-haWhC.js → pdf-engine-D9v0RfKe.js} +3 -3
- package/dist/pdf-engine-D9v0RfKe.js.map +1 -0
- package/dist/pdf-engine-DeiICuca.cjs +2 -0
- package/dist/pdf-engine-DeiICuca.cjs.map +1 -0
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.js +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.js +1 -1
- package/dist/svelte/index.cjs +1 -1
- package/dist/svelte/index.js +1 -1
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.js +1 -1
- package/package.json +4 -4
- package/dist/browser-13mzox-R.cjs +0 -2
- package/dist/browser-13mzox-R.cjs.map +0 -1
- package/dist/browser-BISJ9naB.js.map +0 -1
- package/dist/direct-engine-BNQEVS9L.cjs +0 -2
- package/dist/direct-engine-BNQEVS9L.cjs.map +0 -1
- package/dist/direct-engine-cyecHjwI.js.map +0 -1
- package/dist/pdf-engine-BoFryxxe.cjs +0 -2
- package/dist/pdf-engine-BoFryxxe.cjs.map +0 -1
- package/dist/pdf-engine-Dj-haWhC.js.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";function e(e,t,r){const n=t*r*4,a=e=>[255&e,e>>>8&255,e>>>16&255,e>>>24&255],o=new Uint8Array([66,77,...a(66+n),0,0,0,0,66,0,0,0,40,0,0,0,...a(t),...a(-r),1,0,32,0,3,0,0,0,...a(n),0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,0,0,255,0,0,0,0,255,0]);return new Blob([o,new Uint8Array(e.buffer,e.byteOffset,e.byteLength)],{type:"image/bmp"})}class t extends Error{constructor(e){super(e),this.name="ImageConverterError"}}const r=(r,n="image/png",a)=>{const o=r();if("image/bmp"===n)return Promise.resolve(e(o.data,o.width,o.height));if("undefined"==typeof document)return Promise.reject(new t("document is not available. This converter requires a browser environment."));const i=new ImageData(o.data,o.width,o.height);return new Promise((e,r)=>{const o=document.createElement("canvas");o.width=i.width,o.height=i.height,o.getContext("2d").putImageData(i,0,0),o.toBlob(n=>{n?e(n):r(new t("Canvas toBlob returned null"))},n,a)})};exports.ImageConverterError=t,exports.browserImageDataToBlobConverter=r,exports.createHybridImageConverter=function(t){const n=async(n,a="image/png",o)=>{const i=n();if("image/bmp"===a)return e(i.data,i.width,i.height);try{const e=new Uint8ClampedArray(i.data);return await t.encode({data:e,width:i.width,height:i.height},a,o)}catch(s){return console.warn("Worker encoding failed, falling back to main-thread Canvas:",s),r(n,a,o)}};return n.destroy=()=>t.destroy(),n},exports.createWorkerPoolImageConverter=function(t){const r=(r,n="image/png",a)=>{const o=r();if("image/bmp"===n)return Promise.resolve(e(o.data,o.width,o.height));const i=new Uint8ClampedArray(o.data);return t.encode({data:i,width:o.width,height:o.height},n,a)};return r.destroy=()=>t.destroy(),r};
|
|
2
|
+
//# sourceMappingURL=browser-B5n5EUyW.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-B5n5EUyW.cjs","sources":["../src/lib/image-encoder/bmp.ts","../src/lib/converters/browser.ts"],"sourcesContent":["/**\n * Creates an uncompressed BMP blob from raw RGBA pixel data.\n *\n * Uses BI_BITFIELDS with channel masks matching RGBA byte order, so no\n * per-pixel byte swapping is needed. Top-down row order (negative height)\n * avoids row flipping. The result is a valid BMP that all modern browsers\n * can decode natively in `<img>` elements.\n *\n * This is dramatically faster than PNG/WebP/JPEG encoding via canvas.toBlob()\n * because it performs no compression — just a 66-byte header prepended to the\n * raw pixel buffer.\n */\nexport function rgbaToBmpBlob(rgba: Uint8ClampedArray, width: number, height: number): Blob {\n const pixels = width * height * 4;\n const headerLength = 66;\n const le32 = (v: number) => [v & 0xff, (v >>> 8) & 0xff, (v >>> 16) & 0xff, (v >>> 24) & 0xff];\n\n // prettier-ignore\n const header = new Uint8Array([\n 0x42, 0x4D, // 'BM' signature\n ...le32(headerLength + pixels), // file size\n 0, 0, 0, 0, // reserved\n headerLength, 0, 0, 0, // pixel data offset\n 40, 0, 0, 0, // DIB header size\n ...le32(width), // width\n ...le32(-height), // height (negative = top-down)\n 1, 0, // color planes\n 32, 0, // bits per pixel\n 3, 0, 0, 0, // compression = BI_BITFIELDS\n ...le32(pixels), // image data size\n 0, 0, 0, 0, // h resolution\n 0, 0, 0, 0, // v resolution\n 0, 0, 0, 0, // colors in palette\n 0, 0, 0, 0, // important colors\n 0xFF, 0, 0, 0, // R channel mask\n 0, 0xFF, 0, 0, // G channel mask\n 0, 0, 0xFF, 0, // B channel mask\n ]);\n\n return new Blob(\n [header, new Uint8Array(rgba.buffer as ArrayBuffer, rgba.byteOffset, rgba.byteLength)],\n { type: 'image/bmp' },\n );\n}\n","import type { ImageConversionTypes } from '@embedpdf/models';\nimport type { ImageDataConverter, LazyImageData } from './types';\nimport { ImageEncoderWorkerPool } from '../image-encoder';\nimport { rgbaToBmpBlob } from '../image-encoder/bmp';\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\nexport class ImageConverterError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ImageConverterError';\n }\n}\n\n// ============================================================================\n// Browser Converters\n// ============================================================================\n\n/**\n * Main-thread Canvas-based image converter\n * Simple and works everywhere, but blocks the main thread during encoding\n *\n * Use this as a fallback when worker-based encoding isn't available\n */\nexport const browserImageDataToBlobConverter: ImageDataConverter<Blob> = (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/png',\n quality?: number,\n): Promise<Blob> => {\n const pdfImage = getImageData();\n\n // Fast path: BMP needs no canvas — just a header prepended to raw pixels\n if (imageType === 'image/bmp') {\n return Promise.resolve(rgbaToBmpBlob(pdfImage.data, pdfImage.width, pdfImage.height));\n }\n\n if (typeof document === 'undefined') {\n return Promise.reject(\n new ImageConverterError(\n 'document is not available. This converter requires a browser environment.',\n ),\n );\n }\n\n const imageData = new ImageData(pdfImage.data, pdfImage.width, pdfImage.height);\n\n return new Promise((resolve, reject) => {\n const canvas = document.createElement('canvas');\n canvas.width = imageData.width;\n canvas.height = imageData.height;\n canvas.getContext('2d')!.putImageData(imageData, 0, 0);\n\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new ImageConverterError('Canvas toBlob returned null'));\n }\n },\n imageType,\n quality,\n );\n });\n};\n\n/**\n * Worker pool image converter using OffscreenCanvas in dedicated workers\n * Non-blocking - encoding happens off the main thread\n *\n * This is the preferred approach for performance\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function with destroy() for cleanup\n */\nexport function createWorkerPoolImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n const converter: ImageDataConverter<Blob> = (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/png',\n quality?: number,\n ): Promise<Blob> => {\n const pdfImage = getImageData();\n\n // Fast path: BMP needs no worker round-trip\n if (imageType === 'image/bmp') {\n return Promise.resolve(rgbaToBmpBlob(pdfImage.data, pdfImage.width, pdfImage.height));\n }\n\n // Copy the data since we'll transfer it to another worker\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n };\n\n // Attach destroy method to clean up worker pool\n converter.destroy = () => workerPool.destroy();\n\n return converter;\n}\n\n/**\n * Hybrid converter: Worker pool (OffscreenCanvas) → Main thread Canvas fallback\n *\n * Best of both worlds:\n * - Primary: Non-blocking worker-based encoding with OffscreenCanvas\n * - Fallback: Main-thread Canvas for older browsers without OffscreenCanvas in workers\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function with destroy() for cleanup\n */\nexport function createHybridImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n const converter: ImageDataConverter<Blob> = async (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/png',\n quality?: number,\n ): Promise<Blob> => {\n const pdfImage = getImageData();\n\n // Fast path: BMP needs no worker round-trip\n if (imageType === 'image/bmp') {\n return rgbaToBmpBlob(pdfImage.data, pdfImage.width, pdfImage.height);\n }\n\n try {\n // Try worker pool encoding first (OffscreenCanvas in worker)\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return await workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n } catch (error) {\n // Fallback to main-thread Canvas\n console.warn('Worker encoding failed, falling back to main-thread Canvas:', error);\n return browserImageDataToBlobConverter(getImageData, imageType, quality);\n }\n };\n\n // Attach destroy method to clean up worker pool\n converter.destroy = () => workerPool.destroy();\n\n return converter;\n}\n"],"names":["rgbaToBmpBlob","rgba","width","height","pixels","le32","v","header","Uint8Array","Blob","buffer","byteOffset","byteLength","type","ImageConverterError","Error","constructor","message","super","this","name","browserImageDataToBlobConverter","getImageData","imageType","quality","pdfImage","Promise","resolve","data","document","reject","imageData","ImageData","canvas","createElement","getContext","putImageData","toBlob","blob","workerPool","converter","async","dataCopy","Uint8ClampedArray","encode","error","console","warn","destroy"],"mappings":"aAYO,SAASA,EAAcC,EAAyBC,EAAeC,GACpE,MAAMC,EAASF,EAAQC,EAAS,EAE1BE,EAAQC,GAAc,CAAK,IAAJA,EAAWA,IAAM,EAAK,IAAOA,IAAM,GAAM,IAAOA,IAAM,GAAM,KAGnFC,EAAS,IAAIC,WAAW,CAC5B,GAAM,MACHH,EANgB,GAMID,GACvB,EAAG,EAAG,EAAG,EAPU,GAQL,EAAG,EAAG,EACpB,GAAI,EAAG,EAAG,KACPC,EAAKH,MACLG,GAAMF,GACT,EAAG,EACH,GAAI,EACJ,EAAG,EAAG,EAAG,KACNE,EAAKD,GACR,EAAG,EAAG,EAAG,EACT,EAAG,EAAG,EAAG,EACT,EAAG,EAAG,EAAG,EACT,EAAG,EAAG,EAAG,EACT,IAAM,EAAG,EAAG,EACZ,EAAG,IAAM,EAAG,EACZ,EAAG,EAAG,IAAM,IAGd,OAAO,IAAIK,KACT,CAACF,EAAQ,IAAIC,WAAWP,EAAKS,OAAuBT,EAAKU,WAAYV,EAAKW,aAC1E,CAAEC,KAAM,aAEZ,CClCO,MAAMC,UAA4BC,MACvC,WAAAC,CAAYC,GACVC,MAAMD,GACNE,KAAKC,KAAO,qBACd,EAaK,MAAMC,EAA4D,CACvEC,EACAC,EAAkC,YAClCC,KAEA,MAAMC,EAAWH,IAGjB,GAAkB,cAAdC,EACF,OAAOG,QAAQC,QAAQ3B,EAAcyB,EAASG,KAAMH,EAASvB,MAAOuB,EAAStB,SAG/E,GAAwB,oBAAb0B,SACT,OAAOH,QAAQI,OACb,IAAIhB,EACF,8EAKN,MAAMiB,EAAY,IAAIC,UAAUP,EAASG,KAAMH,EAASvB,MAAOuB,EAAStB,QAExE,OAAO,IAAIuB,QAAQ,CAACC,EAASG,KAC3B,MAAMG,EAASJ,SAASK,cAAc,UACtCD,EAAO/B,MAAQ6B,EAAU7B,MACzB+B,EAAO9B,OAAS4B,EAAU5B,OAC1B8B,EAAOE,WAAW,MAAOC,aAAaL,EAAW,EAAG,GAEpDE,EAAOI,OACJC,IACKA,EACFX,EAAQW,GAERR,EAAO,IAAIhB,EAAoB,iCAGnCS,EACAC,iHA2DC,SACLe,GAEA,MAAMC,EAAsCC,MAC1CnB,EACAC,EAAkC,YAClCC,KAEA,MAAMC,EAAWH,IAGjB,GAAkB,cAAdC,EACF,OAAOvB,EAAcyB,EAASG,KAAMH,EAASvB,MAAOuB,EAAStB,QAG/D,IAEE,MAAMuC,EAAW,IAAIC,kBAAkBlB,EAASG,MAEhD,aAAaW,EAAWK,OACtB,CACEhB,KAAMc,EACNxC,MAAOuB,EAASvB,MAChBC,OAAQsB,EAAStB,QAEnBoB,EACAC,EAEJ,OAASqB,GAGP,OADAC,QAAQC,KAAK,8DAA+DF,GACrExB,EAAgCC,EAAcC,EAAWC,EAClE,GAMF,OAFAgB,EAAUQ,QAAU,IAAMT,EAAWS,UAE9BR,CACT,yCApFO,SACLD,GAEA,MAAMC,EAAsC,CAC1ClB,EACAC,EAAkC,YAClCC,KAEA,MAAMC,EAAWH,IAGjB,GAAkB,cAAdC,EACF,OAAOG,QAAQC,QAAQ3B,EAAcyB,EAASG,KAAMH,EAASvB,MAAOuB,EAAStB,SAI/E,MAAMuC,EAAW,IAAIC,kBAAkBlB,EAASG,MAEhD,OAAOW,EAAWK,OAChB,CACEhB,KAAMc,EACNxC,MAAOuB,EAASvB,MAChBC,OAAQsB,EAAStB,QAEnBoB,EACAC,IAOJ,OAFAgB,EAAUQ,QAAU,IAAMT,EAAWS,UAE9BR,CACT"}
|
|
@@ -1,10 +1,97 @@
|
|
|
1
|
+
function rgbaToBmpBlob(rgba, width, height) {
|
|
2
|
+
const pixels = width * height * 4;
|
|
3
|
+
const headerLength = 66;
|
|
4
|
+
const le32 = (v) => [v & 255, v >>> 8 & 255, v >>> 16 & 255, v >>> 24 & 255];
|
|
5
|
+
const header = new Uint8Array([
|
|
6
|
+
66,
|
|
7
|
+
77,
|
|
8
|
+
// 'BM' signature
|
|
9
|
+
...le32(headerLength + pixels),
|
|
10
|
+
// file size
|
|
11
|
+
0,
|
|
12
|
+
0,
|
|
13
|
+
0,
|
|
14
|
+
0,
|
|
15
|
+
// reserved
|
|
16
|
+
headerLength,
|
|
17
|
+
0,
|
|
18
|
+
0,
|
|
19
|
+
0,
|
|
20
|
+
// pixel data offset
|
|
21
|
+
40,
|
|
22
|
+
0,
|
|
23
|
+
0,
|
|
24
|
+
0,
|
|
25
|
+
// DIB header size
|
|
26
|
+
...le32(width),
|
|
27
|
+
// width
|
|
28
|
+
...le32(-height),
|
|
29
|
+
// height (negative = top-down)
|
|
30
|
+
1,
|
|
31
|
+
0,
|
|
32
|
+
// color planes
|
|
33
|
+
32,
|
|
34
|
+
0,
|
|
35
|
+
// bits per pixel
|
|
36
|
+
3,
|
|
37
|
+
0,
|
|
38
|
+
0,
|
|
39
|
+
0,
|
|
40
|
+
// compression = BI_BITFIELDS
|
|
41
|
+
...le32(pixels),
|
|
42
|
+
// image data size
|
|
43
|
+
0,
|
|
44
|
+
0,
|
|
45
|
+
0,
|
|
46
|
+
0,
|
|
47
|
+
// h resolution
|
|
48
|
+
0,
|
|
49
|
+
0,
|
|
50
|
+
0,
|
|
51
|
+
0,
|
|
52
|
+
// v resolution
|
|
53
|
+
0,
|
|
54
|
+
0,
|
|
55
|
+
0,
|
|
56
|
+
0,
|
|
57
|
+
// colors in palette
|
|
58
|
+
0,
|
|
59
|
+
0,
|
|
60
|
+
0,
|
|
61
|
+
0,
|
|
62
|
+
// important colors
|
|
63
|
+
255,
|
|
64
|
+
0,
|
|
65
|
+
0,
|
|
66
|
+
0,
|
|
67
|
+
// R channel mask
|
|
68
|
+
0,
|
|
69
|
+
255,
|
|
70
|
+
0,
|
|
71
|
+
0,
|
|
72
|
+
// G channel mask
|
|
73
|
+
0,
|
|
74
|
+
0,
|
|
75
|
+
255,
|
|
76
|
+
0
|
|
77
|
+
// B channel mask
|
|
78
|
+
]);
|
|
79
|
+
return new Blob(
|
|
80
|
+
[header, new Uint8Array(rgba.buffer, rgba.byteOffset, rgba.byteLength)],
|
|
81
|
+
{ type: "image/bmp" }
|
|
82
|
+
);
|
|
83
|
+
}
|
|
1
84
|
class ImageConverterError extends Error {
|
|
2
85
|
constructor(message) {
|
|
3
86
|
super(message);
|
|
4
87
|
this.name = "ImageConverterError";
|
|
5
88
|
}
|
|
6
89
|
}
|
|
7
|
-
const browserImageDataToBlobConverter = (getImageData, imageType = "image/
|
|
90
|
+
const browserImageDataToBlobConverter = (getImageData, imageType = "image/png", quality) => {
|
|
91
|
+
const pdfImage = getImageData();
|
|
92
|
+
if (imageType === "image/bmp") {
|
|
93
|
+
return Promise.resolve(rgbaToBmpBlob(pdfImage.data, pdfImage.width, pdfImage.height));
|
|
94
|
+
}
|
|
8
95
|
if (typeof document === "undefined") {
|
|
9
96
|
return Promise.reject(
|
|
10
97
|
new ImageConverterError(
|
|
@@ -12,7 +99,6 @@ const browserImageDataToBlobConverter = (getImageData, imageType = "image/webp",
|
|
|
12
99
|
)
|
|
13
100
|
);
|
|
14
101
|
}
|
|
15
|
-
const pdfImage = getImageData();
|
|
16
102
|
const imageData = new ImageData(pdfImage.data, pdfImage.width, pdfImage.height);
|
|
17
103
|
return new Promise((resolve, reject) => {
|
|
18
104
|
const canvas = document.createElement("canvas");
|
|
@@ -33,8 +119,11 @@ const browserImageDataToBlobConverter = (getImageData, imageType = "image/webp",
|
|
|
33
119
|
});
|
|
34
120
|
};
|
|
35
121
|
function createWorkerPoolImageConverter(workerPool) {
|
|
36
|
-
const converter = (getImageData, imageType = "image/
|
|
122
|
+
const converter = (getImageData, imageType = "image/png", quality) => {
|
|
37
123
|
const pdfImage = getImageData();
|
|
124
|
+
if (imageType === "image/bmp") {
|
|
125
|
+
return Promise.resolve(rgbaToBmpBlob(pdfImage.data, pdfImage.width, pdfImage.height));
|
|
126
|
+
}
|
|
38
127
|
const dataCopy = new Uint8ClampedArray(pdfImage.data);
|
|
39
128
|
return workerPool.encode(
|
|
40
129
|
{
|
|
@@ -50,9 +139,12 @@ function createWorkerPoolImageConverter(workerPool) {
|
|
|
50
139
|
return converter;
|
|
51
140
|
}
|
|
52
141
|
function createHybridImageConverter(workerPool) {
|
|
53
|
-
const converter = async (getImageData, imageType = "image/
|
|
142
|
+
const converter = async (getImageData, imageType = "image/png", quality) => {
|
|
143
|
+
const pdfImage = getImageData();
|
|
144
|
+
if (imageType === "image/bmp") {
|
|
145
|
+
return rgbaToBmpBlob(pdfImage.data, pdfImage.width, pdfImage.height);
|
|
146
|
+
}
|
|
54
147
|
try {
|
|
55
|
-
const pdfImage = getImageData();
|
|
56
148
|
const dataCopy = new Uint8ClampedArray(pdfImage.data);
|
|
57
149
|
return await workerPool.encode(
|
|
58
150
|
{
|
|
@@ -77,4 +169,4 @@ export {
|
|
|
77
169
|
browserImageDataToBlobConverter as b,
|
|
78
170
|
createHybridImageConverter as c
|
|
79
171
|
};
|
|
80
|
-
//# sourceMappingURL=browser-
|
|
172
|
+
//# sourceMappingURL=browser-BKLM0ThC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-BKLM0ThC.js","sources":["../src/lib/image-encoder/bmp.ts","../src/lib/converters/browser.ts"],"sourcesContent":["/**\n * Creates an uncompressed BMP blob from raw RGBA pixel data.\n *\n * Uses BI_BITFIELDS with channel masks matching RGBA byte order, so no\n * per-pixel byte swapping is needed. Top-down row order (negative height)\n * avoids row flipping. The result is a valid BMP that all modern browsers\n * can decode natively in `<img>` elements.\n *\n * This is dramatically faster than PNG/WebP/JPEG encoding via canvas.toBlob()\n * because it performs no compression — just a 66-byte header prepended to the\n * raw pixel buffer.\n */\nexport function rgbaToBmpBlob(rgba: Uint8ClampedArray, width: number, height: number): Blob {\n const pixels = width * height * 4;\n const headerLength = 66;\n const le32 = (v: number) => [v & 0xff, (v >>> 8) & 0xff, (v >>> 16) & 0xff, (v >>> 24) & 0xff];\n\n // prettier-ignore\n const header = new Uint8Array([\n 0x42, 0x4D, // 'BM' signature\n ...le32(headerLength + pixels), // file size\n 0, 0, 0, 0, // reserved\n headerLength, 0, 0, 0, // pixel data offset\n 40, 0, 0, 0, // DIB header size\n ...le32(width), // width\n ...le32(-height), // height (negative = top-down)\n 1, 0, // color planes\n 32, 0, // bits per pixel\n 3, 0, 0, 0, // compression = BI_BITFIELDS\n ...le32(pixels), // image data size\n 0, 0, 0, 0, // h resolution\n 0, 0, 0, 0, // v resolution\n 0, 0, 0, 0, // colors in palette\n 0, 0, 0, 0, // important colors\n 0xFF, 0, 0, 0, // R channel mask\n 0, 0xFF, 0, 0, // G channel mask\n 0, 0, 0xFF, 0, // B channel mask\n ]);\n\n return new Blob(\n [header, new Uint8Array(rgba.buffer as ArrayBuffer, rgba.byteOffset, rgba.byteLength)],\n { type: 'image/bmp' },\n );\n}\n","import type { ImageConversionTypes } from '@embedpdf/models';\nimport type { ImageDataConverter, LazyImageData } from './types';\nimport { ImageEncoderWorkerPool } from '../image-encoder';\nimport { rgbaToBmpBlob } from '../image-encoder/bmp';\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\nexport class ImageConverterError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ImageConverterError';\n }\n}\n\n// ============================================================================\n// Browser Converters\n// ============================================================================\n\n/**\n * Main-thread Canvas-based image converter\n * Simple and works everywhere, but blocks the main thread during encoding\n *\n * Use this as a fallback when worker-based encoding isn't available\n */\nexport const browserImageDataToBlobConverter: ImageDataConverter<Blob> = (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/png',\n quality?: number,\n): Promise<Blob> => {\n const pdfImage = getImageData();\n\n // Fast path: BMP needs no canvas — just a header prepended to raw pixels\n if (imageType === 'image/bmp') {\n return Promise.resolve(rgbaToBmpBlob(pdfImage.data, pdfImage.width, pdfImage.height));\n }\n\n if (typeof document === 'undefined') {\n return Promise.reject(\n new ImageConverterError(\n 'document is not available. This converter requires a browser environment.',\n ),\n );\n }\n\n const imageData = new ImageData(pdfImage.data, pdfImage.width, pdfImage.height);\n\n return new Promise((resolve, reject) => {\n const canvas = document.createElement('canvas');\n canvas.width = imageData.width;\n canvas.height = imageData.height;\n canvas.getContext('2d')!.putImageData(imageData, 0, 0);\n\n canvas.toBlob(\n (blob) => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new ImageConverterError('Canvas toBlob returned null'));\n }\n },\n imageType,\n quality,\n );\n });\n};\n\n/**\n * Worker pool image converter using OffscreenCanvas in dedicated workers\n * Non-blocking - encoding happens off the main thread\n *\n * This is the preferred approach for performance\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function with destroy() for cleanup\n */\nexport function createWorkerPoolImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n const converter: ImageDataConverter<Blob> = (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/png',\n quality?: number,\n ): Promise<Blob> => {\n const pdfImage = getImageData();\n\n // Fast path: BMP needs no worker round-trip\n if (imageType === 'image/bmp') {\n return Promise.resolve(rgbaToBmpBlob(pdfImage.data, pdfImage.width, pdfImage.height));\n }\n\n // Copy the data since we'll transfer it to another worker\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n };\n\n // Attach destroy method to clean up worker pool\n converter.destroy = () => workerPool.destroy();\n\n return converter;\n}\n\n/**\n * Hybrid converter: Worker pool (OffscreenCanvas) → Main thread Canvas fallback\n *\n * Best of both worlds:\n * - Primary: Non-blocking worker-based encoding with OffscreenCanvas\n * - Fallback: Main-thread Canvas for older browsers without OffscreenCanvas in workers\n *\n * @param workerPool - Instance of ImageEncoderWorkerPool\n * @returns ImageDataConverter function with destroy() for cleanup\n */\nexport function createHybridImageConverter(\n workerPool: ImageEncoderWorkerPool,\n): ImageDataConverter<Blob> {\n const converter: ImageDataConverter<Blob> = async (\n getImageData: LazyImageData,\n imageType: ImageConversionTypes = 'image/png',\n quality?: number,\n ): Promise<Blob> => {\n const pdfImage = getImageData();\n\n // Fast path: BMP needs no worker round-trip\n if (imageType === 'image/bmp') {\n return rgbaToBmpBlob(pdfImage.data, pdfImage.width, pdfImage.height);\n }\n\n try {\n // Try worker pool encoding first (OffscreenCanvas in worker)\n const dataCopy = new Uint8ClampedArray(pdfImage.data);\n\n return await workerPool.encode(\n {\n data: dataCopy,\n width: pdfImage.width,\n height: pdfImage.height,\n },\n imageType,\n quality,\n );\n } catch (error) {\n // Fallback to main-thread Canvas\n console.warn('Worker encoding failed, falling back to main-thread Canvas:', error);\n return browserImageDataToBlobConverter(getImageData, imageType, quality);\n }\n };\n\n // Attach destroy method to clean up worker pool\n converter.destroy = () => workerPool.destroy();\n\n return converter;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { init } from "@embedpdf/pdfium";
|
|
2
|
-
import { Rotation, NoopLogger, PdfTaskHelper, PdfErrorCode, pdfDateToDate, PdfJavaScriptActionTrigger, PdfAnnotationSubtype, isUuidV4, uuidV4, PdfJavaScriptWidgetEventType, PDF_ANNOT_AACTION_EVENT, PDF_FORM_FIELD_TYPE, PdfPageFlattenFlag, stripPdfUnwantedMarkers, PdfAnnotationName, PdfAnnotationColorType, PdfAnnotationBorderStyle, PdfStandardFont, PDF_FORM_FIELD_FLAG, webColorToPdfColor, pdfColorToWebColor, PdfAnnotationLineEnding, PdfStampFit, PdfTrappedStatus, pdfAlphaToWebOpacity, webOpacityToPdfAlpha, PdfAnnotationReplyType, dateToPdfDate, quadToRect, rectToQuad, PdfPageObjectType, flagsToNames, namesToFlags, AppearanceMode, Task, toIntRect, transformRect, buildUserToDeviceMatrix, AP_MODE_NORMAL, AP_MODE_ROLLOVER, AP_MODE_DOWN, PdfZoomMode, PdfActionType } from "@embedpdf/models";
|
|
3
|
-
import { P as PdfEngine } from "./pdf-engine-
|
|
4
|
-
import { b as browserImageDataToBlobConverter } from "./browser-
|
|
2
|
+
import { Rotation, NoopLogger, PdfTaskHelper, PdfErrorCode, pdfDateToDate, PdfJavaScriptActionTrigger, PdfAnnotationSubtype, isUuidV4, uuidV4, PdfJavaScriptWidgetEventType, PDF_ANNOT_AACTION_EVENT, PDF_FORM_FIELD_TYPE, PdfPageFlattenFlag, stripPdfUnwantedMarkers, PdfAnnotationName, PdfAnnotationColorType, PdfAnnotationBorderStyle, PdfStandardFont, PDF_FORM_FIELD_FLAG, webColorToPdfColor, pdfColorToWebColor, PdfAnnotationLineEnding, getImageMetadata, PdfStampFit, PdfTrappedStatus, pdfAlphaToWebOpacity, webOpacityToPdfAlpha, PdfAnnotationReplyType, dateToPdfDate, quadToRect, rectToQuad, PdfPageObjectType, flagsToNames, namesToFlags, AppearanceMode, Task, toIntRect, transformRect, buildUserToDeviceMatrix, AP_MODE_NORMAL, AP_MODE_ROLLOVER, AP_MODE_DOWN, PdfZoomMode, PdfActionType } from "@embedpdf/models";
|
|
3
|
+
import { P as PdfEngine } from "./pdf-engine-D9v0RfKe.js";
|
|
4
|
+
import { b as browserImageDataToBlobConverter } from "./browser-BKLM0ThC.js";
|
|
5
5
|
function readString(wasmModule, readChars, parseChars, defaultLength = 100) {
|
|
6
6
|
let buffer = wasmModule.wasmExports.malloc(defaultLength);
|
|
7
7
|
for (let i = 0; i < defaultLength; i++) {
|
|
@@ -4104,9 +4104,42 @@ class PdfiumNative {
|
|
|
4104
4104
|
if (stampName && !this.setAnnotationName(annotationPtr, stampName)) {
|
|
4105
4105
|
return false;
|
|
4106
4106
|
}
|
|
4107
|
-
if (context && "
|
|
4108
|
-
|
|
4109
|
-
|
|
4107
|
+
if (context && "data" in context && context.data) {
|
|
4108
|
+
const meta = getImageMetadata(context.data);
|
|
4109
|
+
if (!meta) return false;
|
|
4110
|
+
if (meta.mimeType === "application/pdf") {
|
|
4111
|
+
if (!this.setAppearanceFromPdf(docPtr, annotationPtr, context.data)) {
|
|
4112
|
+
return false;
|
|
4113
|
+
}
|
|
4114
|
+
} else {
|
|
4115
|
+
for (let i = this.pdfiumModule.FPDFAnnot_GetObjectCount(annotationPtr) - 1; i >= 0; i--) {
|
|
4116
|
+
this.pdfiumModule.FPDFAnnot_RemoveObject(annotationPtr, i);
|
|
4117
|
+
}
|
|
4118
|
+
if (meta.mimeType === "image/png") {
|
|
4119
|
+
if (!this.addPngImageObject(
|
|
4120
|
+
doc,
|
|
4121
|
+
docPtr,
|
|
4122
|
+
page,
|
|
4123
|
+
pagePtr,
|
|
4124
|
+
annotationPtr,
|
|
4125
|
+
annotation.rect,
|
|
4126
|
+
context.data
|
|
4127
|
+
)) {
|
|
4128
|
+
return false;
|
|
4129
|
+
}
|
|
4130
|
+
} else if (meta.mimeType === "image/jpeg") {
|
|
4131
|
+
if (!this.addJpegImageObject(
|
|
4132
|
+
doc,
|
|
4133
|
+
docPtr,
|
|
4134
|
+
page,
|
|
4135
|
+
pagePtr,
|
|
4136
|
+
annotationPtr,
|
|
4137
|
+
annotation.rect,
|
|
4138
|
+
context.data
|
|
4139
|
+
)) {
|
|
4140
|
+
return false;
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4110
4143
|
}
|
|
4111
4144
|
} else if (context && "imageData" in context && context.imageData) {
|
|
4112
4145
|
for (let i = this.pdfiumModule.FPDFAnnot_GetObjectCount(annotationPtr) - 1; i >= 0; i--) {
|
|
@@ -4123,6 +4156,10 @@ class PdfiumNative {
|
|
|
4123
4156
|
)) {
|
|
4124
4157
|
return false;
|
|
4125
4158
|
}
|
|
4159
|
+
} else if (context && "appearance" in context && context.appearance) {
|
|
4160
|
+
if (!this.setAppearanceFromPdf(docPtr, annotationPtr, context.appearance)) {
|
|
4161
|
+
return false;
|
|
4162
|
+
}
|
|
4126
4163
|
}
|
|
4127
4164
|
if (!this.applyBaseAnnotationProperties(doc, page, pagePtr, annotationPtr, annotation)) {
|
|
4128
4165
|
return false;
|
|
@@ -4203,10 +4240,10 @@ class PdfiumNative {
|
|
|
4203
4240
|
return false;
|
|
4204
4241
|
}
|
|
4205
4242
|
const matrixPtr = this.memoryManager.malloc(6 * 4);
|
|
4206
|
-
this.pdfiumModule.pdfium.setValue(matrixPtr,
|
|
4243
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr, rect.size.width, "float");
|
|
4207
4244
|
this.pdfiumModule.pdfium.setValue(matrixPtr + 4, 0, "float");
|
|
4208
4245
|
this.pdfiumModule.pdfium.setValue(matrixPtr + 8, 0, "float");
|
|
4209
|
-
this.pdfiumModule.pdfium.setValue(matrixPtr + 12,
|
|
4246
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 12, rect.size.height, "float");
|
|
4210
4247
|
this.pdfiumModule.pdfium.setValue(matrixPtr + 16, 0, "float");
|
|
4211
4248
|
this.pdfiumModule.pdfium.setValue(matrixPtr + 20, 0, "float");
|
|
4212
4249
|
if (!this.pdfiumModule.FPDFPageObj_SetMatrix(imageObjectPtr, matrixPtr)) {
|
|
@@ -4219,8 +4256,8 @@ class PdfiumNative {
|
|
|
4219
4256
|
this.memoryManager.free(matrixPtr);
|
|
4220
4257
|
const pagePos = this.convertDevicePointToPagePoint(doc, page, {
|
|
4221
4258
|
x: rect.origin.x,
|
|
4222
|
-
y: rect.origin.y +
|
|
4223
|
-
// shift down by the
|
|
4259
|
+
y: rect.origin.y + rect.size.height
|
|
4260
|
+
// shift down by the authored display height
|
|
4224
4261
|
});
|
|
4225
4262
|
this.pdfiumModule.FPDFPageObj_Transform(imageObjectPtr, 1, 0, 0, 1, pagePos.x, pagePos.y);
|
|
4226
4263
|
if (!this.pdfiumModule.FPDFAnnot_AppendObject(annotationPtr, imageObjectPtr)) {
|
|
@@ -4233,6 +4270,116 @@ class PdfiumNative {
|
|
|
4233
4270
|
this.memoryManager.free(bitmapBufferPtr);
|
|
4234
4271
|
return true;
|
|
4235
4272
|
}
|
|
4273
|
+
/**
|
|
4274
|
+
* Add PNG image object to annotation using native PNG import.
|
|
4275
|
+
* Passes raw PNG bytes to PDFium which decodes and stores them with
|
|
4276
|
+
* FlateDecode + PNG prediction filters for optimal compression.
|
|
4277
|
+
*
|
|
4278
|
+
* @private
|
|
4279
|
+
*/
|
|
4280
|
+
addPngImageObject(doc, docPtr, page, pagePtr, annotationPtr, rect, pngData) {
|
|
4281
|
+
const imageObjectPtr = this.pdfiumModule.FPDFPageObj_NewImageObj(docPtr);
|
|
4282
|
+
if (!imageObjectPtr) {
|
|
4283
|
+
return false;
|
|
4284
|
+
}
|
|
4285
|
+
const pngBytes = new Uint8Array(pngData);
|
|
4286
|
+
const pngPtr = this.memoryManager.malloc(pngBytes.byteLength);
|
|
4287
|
+
if (!pngPtr) {
|
|
4288
|
+
this.pdfiumModule.FPDFPageObj_Destroy(imageObjectPtr);
|
|
4289
|
+
return false;
|
|
4290
|
+
}
|
|
4291
|
+
this.pdfiumModule.pdfium.HEAPU8.set(pngBytes, pngPtr);
|
|
4292
|
+
if (!this.pdfiumModule.EPDFImageObj_SetPng(
|
|
4293
|
+
pagePtr,
|
|
4294
|
+
0,
|
|
4295
|
+
imageObjectPtr,
|
|
4296
|
+
pngPtr,
|
|
4297
|
+
pngBytes.byteLength
|
|
4298
|
+
)) {
|
|
4299
|
+
this.memoryManager.free(pngPtr);
|
|
4300
|
+
this.pdfiumModule.FPDFPageObj_Destroy(imageObjectPtr);
|
|
4301
|
+
return false;
|
|
4302
|
+
}
|
|
4303
|
+
this.memoryManager.free(pngPtr);
|
|
4304
|
+
const matrixPtr = this.memoryManager.malloc(6 * 4);
|
|
4305
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr, rect.size.width, "float");
|
|
4306
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 4, 0, "float");
|
|
4307
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 8, 0, "float");
|
|
4308
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 12, rect.size.height, "float");
|
|
4309
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 16, 0, "float");
|
|
4310
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 20, 0, "float");
|
|
4311
|
+
if (!this.pdfiumModule.FPDFPageObj_SetMatrix(imageObjectPtr, matrixPtr)) {
|
|
4312
|
+
this.memoryManager.free(matrixPtr);
|
|
4313
|
+
this.pdfiumModule.FPDFPageObj_Destroy(imageObjectPtr);
|
|
4314
|
+
return false;
|
|
4315
|
+
}
|
|
4316
|
+
this.memoryManager.free(matrixPtr);
|
|
4317
|
+
const pagePos = this.convertDevicePointToPagePoint(doc, page, {
|
|
4318
|
+
x: rect.origin.x,
|
|
4319
|
+
y: rect.origin.y + rect.size.height
|
|
4320
|
+
});
|
|
4321
|
+
this.pdfiumModule.FPDFPageObj_Transform(imageObjectPtr, 1, 0, 0, 1, pagePos.x, pagePos.y);
|
|
4322
|
+
if (!this.pdfiumModule.FPDFAnnot_AppendObject(annotationPtr, imageObjectPtr)) {
|
|
4323
|
+
this.pdfiumModule.FPDFPageObj_Destroy(imageObjectPtr);
|
|
4324
|
+
return false;
|
|
4325
|
+
}
|
|
4326
|
+
return true;
|
|
4327
|
+
}
|
|
4328
|
+
/**
|
|
4329
|
+
* Add JPEG image object to annotation using native JPEG pass-through.
|
|
4330
|
+
* Passes raw JPEG bytes to PDFium which embeds them as a DCTDecode
|
|
4331
|
+
* stream — no decode/re-encode roundtrip.
|
|
4332
|
+
*
|
|
4333
|
+
* @private
|
|
4334
|
+
*/
|
|
4335
|
+
addJpegImageObject(doc, docPtr, page, pagePtr, annotationPtr, rect, jpegData) {
|
|
4336
|
+
const imageObjectPtr = this.pdfiumModule.FPDFPageObj_NewImageObj(docPtr);
|
|
4337
|
+
if (!imageObjectPtr) {
|
|
4338
|
+
return false;
|
|
4339
|
+
}
|
|
4340
|
+
const jpegBytes = new Uint8Array(jpegData);
|
|
4341
|
+
const jpegPtr = this.memoryManager.malloc(jpegBytes.byteLength);
|
|
4342
|
+
if (!jpegPtr) {
|
|
4343
|
+
this.pdfiumModule.FPDFPageObj_Destroy(imageObjectPtr);
|
|
4344
|
+
return false;
|
|
4345
|
+
}
|
|
4346
|
+
this.pdfiumModule.pdfium.HEAPU8.set(jpegBytes, jpegPtr);
|
|
4347
|
+
if (!this.pdfiumModule.EPDFImageObj_SetJpeg(
|
|
4348
|
+
pagePtr,
|
|
4349
|
+
0,
|
|
4350
|
+
imageObjectPtr,
|
|
4351
|
+
jpegPtr,
|
|
4352
|
+
jpegBytes.byteLength
|
|
4353
|
+
)) {
|
|
4354
|
+
this.memoryManager.free(jpegPtr);
|
|
4355
|
+
this.pdfiumModule.FPDFPageObj_Destroy(imageObjectPtr);
|
|
4356
|
+
return false;
|
|
4357
|
+
}
|
|
4358
|
+
this.memoryManager.free(jpegPtr);
|
|
4359
|
+
const matrixPtr = this.memoryManager.malloc(6 * 4);
|
|
4360
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr, rect.size.width, "float");
|
|
4361
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 4, 0, "float");
|
|
4362
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 8, 0, "float");
|
|
4363
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 12, rect.size.height, "float");
|
|
4364
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 16, 0, "float");
|
|
4365
|
+
this.pdfiumModule.pdfium.setValue(matrixPtr + 20, 0, "float");
|
|
4366
|
+
if (!this.pdfiumModule.FPDFPageObj_SetMatrix(imageObjectPtr, matrixPtr)) {
|
|
4367
|
+
this.memoryManager.free(matrixPtr);
|
|
4368
|
+
this.pdfiumModule.FPDFPageObj_Destroy(imageObjectPtr);
|
|
4369
|
+
return false;
|
|
4370
|
+
}
|
|
4371
|
+
this.memoryManager.free(matrixPtr);
|
|
4372
|
+
const pagePos = this.convertDevicePointToPagePoint(doc, page, {
|
|
4373
|
+
x: rect.origin.x,
|
|
4374
|
+
y: rect.origin.y + rect.size.height
|
|
4375
|
+
});
|
|
4376
|
+
this.pdfiumModule.FPDFPageObj_Transform(imageObjectPtr, 1, 0, 0, 1, pagePos.x, pagePos.y);
|
|
4377
|
+
if (!this.pdfiumModule.FPDFAnnot_AppendObject(annotationPtr, imageObjectPtr)) {
|
|
4378
|
+
this.pdfiumModule.FPDFPageObj_Destroy(imageObjectPtr);
|
|
4379
|
+
return false;
|
|
4380
|
+
}
|
|
4381
|
+
return true;
|
|
4382
|
+
}
|
|
4236
4383
|
/**
|
|
4237
4384
|
* Save document to array buffer
|
|
4238
4385
|
* @param docPtr - pointer to pdf document
|
|
@@ -9685,4 +9832,4 @@ export {
|
|
|
9685
9832
|
isValidCustomKey as i,
|
|
9686
9833
|
readArrayBuffer as r
|
|
9687
9834
|
};
|
|
9688
|
-
//# sourceMappingURL=direct-engine-
|
|
9835
|
+
//# sourceMappingURL=direct-engine-B7gUkBcT.js.map
|