From b59cf9c58361b50985ccdfa0e116c679d8d5f466 Mon Sep 17 00:00:00 2001 From: Kresna <13603341+slaveofcode@users.noreply.github.com> Date: Fri, 14 Aug 2026 11:08:10 +0700 Subject: [PATCH] fix(pdf): reliably extract PDF images across browsers - Use pdf.js legacy build (polyfills Uint8Array.toHex etc.) so extraction no longer crashes on browsers without the newest JS. - Draw the decoded image using its own width/height (pdf.js stores the bitmap dimensions there, not on the bitmap), so ImageBitmap objects now encode correctly instead of producing a 0-size canvas. Verified end-to-end in a headless browser: a sample PDF now yields all its embedded images instead of 'no images found'. --- src/tools/pdf/extract-images.lib.ts | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/tools/pdf/extract-images.lib.ts b/src/tools/pdf/extract-images.lib.ts index 3d238e4..f9917e3 100644 --- a/src/tools/pdf/extract-images.lib.ts +++ b/src/tools/pdf/extract-images.lib.ts @@ -38,10 +38,18 @@ async function objToBlob(obj: PdfImageObj): Promise<{ blob: Blob; width: number; const ctx = canvas.getContext('2d'); if (!ctx) return null; - if (obj.bitmap) { - canvas.width = obj.bitmap.width; - canvas.height = obj.bitmap.height; - ctx.drawImage(obj.bitmap, 0, 0); + const drawable = obj.bitmap as CanvasImageSource | undefined; + const w = obj.width || (drawable as { width?: number })?.width || 0; + const h = obj.height || (drawable as { height?: number })?.height || 0; + + if (drawable && w && h) { + canvas.width = w; + canvas.height = h; + try { + ctx.drawImage(drawable, 0, 0, w, h); + } catch { + return null; // e.g. a detached ImageBitmap + } } else if (obj.data && obj.width && obj.height) { const { width, height, data } = obj; const pixels = width * height; @@ -79,8 +87,10 @@ function resolveObj(page: { objs: { has(n: string): boolean; get(n: string, cb?: /** Extract every embedded raster image from the PDF bytes. */ export async function extractPdfImages(data: ArrayBuffer | Uint8Array): Promise { - const pdfjs = await import('pdfjs-dist'); - const PdfjsWorker = (await import('pdfjs-dist/build/pdf.worker.min.mjs?worker')).default; + // Use the legacy build: it polyfills newer JS (e.g. Uint8Array.prototype.toHex, + // which pdf.js's default build assumes) so extraction works on older browsers. + const pdfjs = await import('pdfjs-dist/legacy/build/pdf.mjs'); + const PdfjsWorker = (await import('pdfjs-dist/legacy/build/pdf.worker.min.mjs?worker')).default; const worker = new PdfjsWorker(); pdfjs.GlobalWorkerOptions.workerPort = worker;