I needed to add a cover for the PDF book. And I did not want to install a huge Acrobat or buy PDF editors for such a simple task. Therefore, I wrote a simple Node.JS script to add an image to the beginning of a PDF file.
To do this, we need the following packages and modules:
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const { PDFDocument } = require('pdf-lib');
Prepare PDF and Image instance with PDFDocument
.
const run = async ({ pathToPDF, pathToImage }) => {
const pdfDoc = await PDFDocument.load(fs.readFileSync(pathToPDF));
const img = await pdfDoc.embedPng(fs.readFileSync(pathToImage));
// ...
Append a new page to the file and insert an image in full width and height.
// ...
const imagePage = pdfDoc.insertPage(0);
imagePage.drawImage(img, {
x: 0,
y: 0,
width: imagePage.getWidth(),
height: imagePage.getHeight()
});
// ...
Save result in a new PDF file in the current directory.
// ...
const pdfBytes = await pdfDoc.save();
const newFilePath = `${path.basename(pathToPDF, '.pdf')}-result.pdf`;
fs.writeFileSync(newFilePath, pdfBytes);
}
And the code for running the main function and check that all required arguments are passed.
const ERRORS = {
ARGUMENTS: 'Please provide a path to the PDF file as a first argument and path to an image as the second argument'
};
const pathToPDF = process.argv[2];
assert.notEqual(pathToPDF, null, ERRORS.ARGUMENTS);
const pathToImage = process.argv[3];
assert.notEqual(pathToImage, null, ERRORS.ARGUMENTS);
run({ pathToPDF, pathToImage }).catch(console.error);
Altogether:
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const { PDFDocument } = require('pdf-lib');
const run = async ({ pathToPDF, pathToImage }) => {
const pdfDoc = await PDFDocument.load(fs.readFileSync(pathToPDF));
const img = await pdfDoc.embedPng(fs.readFileSync(pathToImage));
const imagePage = pdfDoc.insertPage(0);
imagePage.drawImage(img, {
x: 0,
y: 0,
width: imagePage.getWidth(),
height: imagePage.getHeight()
});
const pdfBytes = await pdfDoc.save();
const newFilePath = `${path.basename(pathToPDF, '.pdf')}-result.pdf`;
fs.writeFileSync(newFilePath, pdfBytes);
}
const ERRORS = {
ARGUMENTS: 'Please provide a path to the PDF file as a first argument and path to an image as the second argument'
};
const pathToPDF = process.argv[2];
assert.notEqual(pathToPDF, null, ERRORS.ARGUMENTS);
const pathToImage = process.argv[3];
assert.notEqual(pathToImage, null, ERRORS.ARGUMENTS);
run({ pathToPDF, pathToImage }).catch(console.error);
Usage:
$ npm start ../checklist.pdf ~/Downloads/cover.png
If you need to append an image to a PDF file quickly get this script run npm i
and npm path/to/file.pdf path/to/image.png
.
Check out my twitter profile where every day I share helpful stuff about soft-skills and how to write clean code with good design.
Top comments (8)
Thank you for sharing your code, I have used it to be able to insert stamps in the upper right corner of all pages.
(async () => {
const pdfDoc = await PDFDocument.load(fs.readFileSync("CONSOLIDADO_FSIERRA_27-06-2020 03-32-27.pdf"));
const img = await pdfDoc.embedPng(fs.readFileSync("image.PNG"));
for (let i = 0; i < pdfDoc.getPageCount(); i++) {
let imagePage='';
imagePage = pdfDoc.getPage(i);
console.log(i+1)
console.log(imagePage.getWidth())
let xx=imagePage.getWidth()
console.log(imagePage.getHeight())
let yy=imagePage.getHeight()
imagePage.drawImage(img, {
x: xx-70,
y: yy-70,
width: 70,
height: 70
});
}
Hey @fritzsierra ,
In your code how can we set stamp height and width dynamically. I have used your logic to add stamp on pdf but not getting whole image as we specified fix height and width ?
Nice!
BTW you can use github.com/adam-p/markdown-here/wi... to make your code looks great and readable.
Hi Iamdi, a question, can you convert that code with the pdf-lib library to an executable? Thank you
You can use
pkg
npm package npmjs.com/package/pkgAny idea how to insert an image generated as an arrayBuffer?
I will use it to signing pdfs, so I don't need to print them, sign and scan.
Haha, nice!