DEV Community

Dmitry Shvetsov
Dmitry Shvetsov

Posted on

8

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.

AWS Q Developer image

Your AI Code Assistant

Generate and update README files, create data-flow diagrams, and keep your project fully documented. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

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!

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay