From e5cd2e6ab59333ff2133df49a271e7b03b04f1f6 Mon Sep 17 00:00:00 2001 From: Sebastian Espei Date: Sun, 30 Nov 2025 23:45:27 +0100 Subject: [PATCH] feat(pdf-to-png): direct download resulting image and adjust filename --- src/js/logic/pdf-to-png.ts | 68 ++++++++++++++++++++++++++++---------- src/js/ui.ts | 2 +- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/js/logic/pdf-to-png.ts b/src/js/logic/pdf-to-png.ts index ef95173..a593285 100644 --- a/src/js/logic/pdf-to-png.ts +++ b/src/js/logic/pdf-to-png.ts @@ -1,11 +1,18 @@ import { showLoader, hideLoader, showAlert } from '../ui.js'; -import { downloadFile, readFileAsArrayBuffer, getPDFDocument } from '../utils/helpers.js'; +import { + downloadFile, + readFileAsArrayBuffer, + getPDFDocument, +} from '../utils/helpers.js'; import { state } from '../state.js'; import JSZip from 'jszip'; import * as pdfjsLib from 'pdfjs-dist'; +import { PDFPageProxy } from 'pdfjs-dist'; -pdfjsLib.GlobalWorkerOptions.workerSrc = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString(); - +pdfjsLib.GlobalWorkerOptions.workerSrc = new URL( + 'pdfjs-dist/build/pdf.worker.min.mjs', + import.meta.url +).toString(); export async function pdfToPng() { showLoader('Converting to PNG...'); @@ -13,26 +20,30 @@ export async function pdfToPng() { const pdf = await getPDFDocument( await readFileAsArrayBuffer(state.files[0]) ).promise; - const zip = new JSZip(); - const qualityInput = document.getElementById('png-quality') as HTMLInputElement; + const qualityInput = document.getElementById( + 'png-quality' + ) as HTMLInputElement; const scale = qualityInput ? parseFloat(qualityInput.value) : 2.0; - for (let i = 1; i <= pdf.numPages; i++) { - const page = await pdf.getPage(i); - const viewport = page.getViewport({ scale }); - const canvas = document.createElement('canvas'); - canvas.height = viewport.height; - canvas.width = viewport.width; - const context = canvas.getContext('2d'); - await page.render({ canvasContext: context, viewport: viewport, canvas }).promise; - const blob = await new Promise((resolve) => - canvas.toBlob(resolve, 'image/png') + if (pdf.numPages === 1) { + downloadFile( + await pageToBlob(await pdf.getPage(1), scale), + getCleanFilename(state.files[0].name) + '.png' + ); + } else { + const zip = new JSZip(); + + for (let i = 1; i <= pdf.numPages; i++) { + const page = await pdf.getPage(i); + zip.file(`page_${i}.png`, await pageToBlob(page, scale)); + } + const zipBlob = await zip.generateAsync({ type: 'blob' }); + downloadFile( + zipBlob, + getCleanFilename(state.files[0].name) + '_pngs.zip' ); - zip.file(`page_${i}.png`, blob as Blob); } - const zipBlob = await zip.generateAsync({ type: 'blob' }); - downloadFile(zipBlob, 'converted_pngs.zip'); } catch (e) { console.error(e); showAlert('Error', 'Failed to convert PDF to PNG.'); @@ -40,3 +51,24 @@ export async function pdfToPng() { hideLoader(); } } + +async function pageToBlob(page: PDFPageProxy, scale: number): Promise { + const viewport = page.getViewport({ scale }); + const canvas = document.createElement('canvas'); + canvas.height = viewport.height; + canvas.width = viewport.width; + const context = canvas.getContext('2d'); + await page.render({ + canvasContext: context, + viewport: viewport, + canvas, + }).promise; + const blob = await new Promise((resolve) => + canvas.toBlob(resolve, 'image/png') + ); + return blob as Blob; +} + +function getCleanFilename(fileName: string): string { + return fileName.replace(/\.pdf$/i, ''); +} \ No newline at end of file diff --git a/src/js/ui.ts b/src/js/ui.ts index d057ced..7faf2fd 100644 --- a/src/js/ui.ts +++ b/src/js/ui.ts @@ -833,7 +833,7 @@ export const toolTemplates = {

Higher scale = better quality but larger file size

Your file is ready. Click the button to download a ZIP file containing all PNG images.

- + `, 'png-to-pdf': () => `