pdf-to-png-converter-allow-yarn
Version:
Node.js utility to convert PDF file/buffer pages to PNG files/buffers with no native dependencies.
96 lines (95 loc) • 4.44 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.pdfToPng = pdfToPng;
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const const_1 = require("./const");
const propsToPdfDocInitParams_1 = require("./propsToPdfDocInitParams");
const node_canvas_factory_1 = require("./node.canvas.factory");
/**
* Converts a PDF file to PNG images.
*
* @param pdfFile - The path to the PDF file or a buffer containing the PDF data.
* @param props - Optional properties to customize the conversion process.
* @returns A promise that resolves to an array of PNG page outputs.
*
* @throws Will throw an error if invalid pages are requested when `strictPagesToProcess` is true.
*
* @example
* ```typescript
* const pngPages = await pdfToPng('/path/to/pdf/file.pdf', {
* pagesToProcess: [1, 2, 3],
* outputFolder: '/path/to/output/folder',
* viewportScale: 2.0,
* outputFileMaskFunc: (pageNumber) => `custom_name_page_${pageNumber}.png`,
* });
* ```
*/
async function pdfToPng(pdfFile, props) {
const isBuffer = Buffer.isBuffer(pdfFile);
const pdfFileBuffer = isBuffer ? pdfFile : (await node_fs_1.promises.readFile(pdfFile)).buffer;
const pdfDocument = await getPdfDocument(pdfFileBuffer, props);
// Get the pages to process based on the provided options, invalid pages will be filtered out
const pagesToProcess = props?.pagesToProcess ?? Array.from({ length: pdfDocument.numPages }, (_, index) => index + 1);
const pngPagesOutput = [];
try {
// Process each page in parallel
const pngPageOutputs = await Promise.all(pagesToProcess
// Filter out invalid page numbers
.filter((pageNumber) => pageNumber <= pdfDocument.numPages && pageNumber >= 1)
// Process the page
.map((pageNumber) => {
const pageViewportScale = props?.viewportScale !== undefined ? props.viewportScale : const_1.PDF_TO_PNG_OPTIONS_DEFAULTS.viewportScale;
const defaultMask = isBuffer ? const_1.PDF_TO_PNG_OPTIONS_DEFAULTS.outputFileMask : (0, node_path_1.parse)(pdfFile).name;
const pageName = props?.outputFileMaskFunc?.(pageNumber) ?? `${defaultMask}_page_${pageNumber}.png`;
return processPdfPage(pdfDocument, pageName, pageNumber, pageViewportScale);
}));
pngPagesOutput.push(...pngPageOutputs);
}
finally {
await pdfDocument.cleanup();
}
// Save the PNG files to the output folder
if (props?.outputFolder) {
await node_fs_1.promises.mkdir(props.outputFolder, { recursive: true });
for (const pngPageOutput of pngPagesOutput) {
pngPageOutput.path = (0, node_path_1.resolve)(props.outputFolder, pngPageOutput.name);
await node_fs_1.promises.writeFile(pngPageOutput.path, pngPageOutput.content);
pngPageOutput.path = (0, node_path_1.resolve)(props.outputFolder, pngPageOutput.name);
}
}
return pngPagesOutput;
}
/**
* Asynchronously retrieves a PDF document from a given ArrayBuffer.
*
* @param pdfFileBuffer - The buffer containing the PDF file data.
* @param props - Optional properties to customize the PDF document initialization.
* @returns A promise that resolves to a PDFDocumentProxy object representing the PDF document.
*/
async function getPdfDocument(pdfFileBuffer, props) {
const { getDocument } = await import('pdfjs-dist/legacy/build/pdf.mjs');
const documentInitParameters = (0, propsToPdfDocInitParams_1.propsToPdfDocInitParams)(props);
return await getDocument({
...documentInitParameters,
data: new Uint8Array(pdfFileBuffer),
}).promise;
}
async function processPdfPage(pdfDocument, pageName, pageNumber, pageViewportScale) {
const page = await pdfDocument.getPage(pageNumber);
const viewport = page.getViewport({ scale: pageViewportScale });
const canvasFactory = new node_canvas_factory_1.NodeCanvasFactory();
const { canvas, context } = canvasFactory.create(viewport.width, viewport.height);
await page.render({ canvasContext: context, viewport }).promise;
const pngPageOutput = {
pageNumber,
name: pageName,
content: canvas.toBuffer('image/png'),
path: '',
width: viewport.width,
height: viewport.height,
};
page.cleanup();
canvasFactory.destroy({ canvas, context });
return pngPageOutput;
}