UNPKG

@brakebein/pdf2png

Version:

Convert pages of a PDF document to PNG images

143 lines (139 loc) 4.66 kB
import { URL } from 'node:url'; import { readFile, copyFile, writeFile } from 'node:fs/promises'; import { createWriteStream } from 'node:fs'; import tmp from 'tmp-promise'; import axios from 'axios'; import { exec as exec$1, execFile as execFile$1 } from 'node:child_process'; function exec(command, options) { return new Promise((resolve, reject) => { exec$1(command, options, (err, stdout, stderr) => { if (err) { reject({ ...err, stdout, stderr }); } else { resolve({ stdout, stderr }); } }); }); } function execFile(command, args, options) { return new Promise((resolve, reject) => { execFile$1(command, args, options, (err, stdout, stderr) => { if (err) { reject({ ...err, stdout, stderr }); } else { resolve({ stdout, stderr }); } }); }); } class PdfConvert { constructor(source, options) { this.source = source; this.options = { resolution: 600, ghostscriptPath: new URL('./executables/ghostscript', import.meta.url).pathname.replace(/^\//, ''), ...options, }; if (process.platform === 'win32') { const suffix = ';' + this.options.ghostscriptPath; const key = process.env.Path ? 'Path' : 'PATH'; if (!new RegExp(suffix.replace('/', '\\/')).test(process.env[key] || '')) { process.env[key] += suffix; } } } async convertPageToImage(page) { await this.writePDFToTemp(); if (!this.tmpFile) { throw new Error('No temporary pdf file!'); } try { const tmpImage = await tmp.file(); await execFile('gs', [ '-dQUIET', '-dPARANOIDSAFER', '-dBATCH', '-dNOPAUSE', '-dNOPROMPT', '-sDEVICE=png16m', '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4', `-r${this.options.resolution}`, `-dFirstPage=${page}`, `-dLastPage=${page}`, `-sOutputFile=${tmpImage.path}`, this.tmpFile.path, ]); const buffer = await readFile(tmpImage.path); await tmpImage.cleanup(); return buffer; } catch (err) { throw new Error('Unable to process image from page: ' + err); } } async getPageCount() { await this.writePDFToTemp(); if (!this.tmpFile) { throw new Error('No temporary pdf file!'); } try { const { stdout } = await exec(`gs -q -dNODISPLAY -c "(${this.tmpFile.path.replace(/\\/g, '/')}) (r) file runpdfbegin pdfpagecount = quit"`); return stdout ? parseInt(stdout.toString().substr(0, stdout.length - 1)) : 0; } catch (err) { throw new Error('Unable to get page count: ' + err); } } async writePDFToTemp() { if (this.tmpFile) return; try { this.tmpFile = await tmp.file(); } catch (err) { throw new Error(`Unable to open tmp file: ` + err); } if (typeof this.source === 'string') { if (/^https?:\/\//.test(this.source)) { try { const response = await axios.get(this.source, { responseType: 'stream', }); const stream = createWriteStream(this.tmpFile.path); response.data.pipe(stream); await new Promise((resolve, reject) => { stream.on('finish', resolve); stream.on('error', reject); }); } catch (err) { throw new Error('Unable to fetch file from web location: ' + err); } } else { await copyFile(this.source, this.tmpFile.path); } } else { try { await writeFile(this.tmpFile.path, this.source); } catch (err) { throw new Error('Unable to write tmp file: ' + err); } } } async dispose() { if (this.tmpFile) { await this.tmpFile.cleanup(); this.tmpFile = undefined; } } } export { PdfConvert }; //# sourceMappingURL=index.js.map