DEV Community

Dmitry Shvetsov
Dmitry Shvetsov

Posted on

Add an Image to a PDF file using Node.JS (script)

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');
Enter fullscreen mode Exit fullscreen mode

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));
  // ...
Enter fullscreen mode Exit fullscreen mode

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()
  });
  // ...
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Usage:

$ npm start ../checklist.pdf ~/Downloads/cover.png
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
fritzsierra profile image
Fritzsierra

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

});
}

Collapse
 
parthshah27 profile image
parthshah27

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 ?

Collapse
 
dmshvetsov profile image
Dmitry Shvetsov

Nice!

BTW you can use github.com/adam-p/markdown-here/wi... to make your code looks great and readable.

Collapse
 
fritzsierra profile image
Fritzsierra

Hi Iamdi, a question, can you convert that code with the pdf-lib library to an executable? Thank you

Thread Thread
 
dmshvetsov profile image
Dmitry Shvetsov

You can use pkg npm package npmjs.com/package/pkg

Collapse
 
spock123 profile image
Lars Rye Jeppesen

Any idea how to insert an image generated as an arrayBuffer?

Collapse
 
_fones profile image
Wojtek Grześkowiak

I will use it to signing pdfs, so I don't need to print them, sign and scan.

Collapse
 
dmshvetsov profile image
Dmitry Shvetsov

Haha, nice!