@brakebein/pdf2png
Version:
Convert pages of a PDF document to PNG images
143 lines (139 loc) • 4.66 kB
JavaScript
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