DEV Community

Muhammad Muhajir
Muhammad Muhajir

Posted on

How to watermark an image with Node.js

It's going to be a very simple tutorial.

First, let's create a node.js project

Creating a Node.js project

mkdir jimp-watermark-demo
cd jimp-watermark-demo
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025
npm init
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

Just press Enter, Enter, Enter...

npm install --save jimp
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

Open up your favorite editor. In my case it's Visual Studio Code.
So I can just type

code .
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

in terminal.

Create a file, name it index.js.

Writing the code

Here's the working code.

const Jimp = require("jimp");

const ORIGINAL_IMAGE =
  "http://www.defence.gov.au/ADFA/Images/news_events/whiteRibbon.jpg";

const LOGO = "https://upload.wikimedia.org/wikipedia/en/thumb/9/9f/Australian_Defence_Force_Academy_coat_of_arms.svg/1200px-Australian_Defence_Force_Academy_coat_of_arms.svg.png";

const LOGO_MARGIN_PERCENTAGE = 5;

const FILENAME = "test.jpg";

const main = async () => {
  const [image, logo] = await Promise.all([
    Jimp.read(ORIGINAL_IMAGE),
    Jimp.read(LOGO)
  ]);

  logo.resize(image.bitmap.width / 10, Jimp.AUTO);

  const xMargin = (image.bitmap.width * LOGO_MARGIN_PERCENTAGE) / 100;
  const yMargin = (image.bitmap.width * LOGO_MARGIN_PERCENTAGE) / 100;

  const X = image.bitmap.width - logo.bitmap.width - xMargin;
  const Y = image.bitmap.height - logo.bitmap.height - yMargin;

  return image.composite(logo, X, Y, [
    {
      mode: Jimp.BLEND_SCREEN,
      opacitySource: 0.1,
      opacityDest: 1
    }
  ]);
};

main().then(image => image.write(FILENAME));
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

Now try to run

node index.js
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

in your terminal.

It will create test.jpg. And that's the result.

Okay, okay. Slow down. I don't get it. What does the code do?

const Jimp = require("jimp");

const ORIGINAL_IMAGE =
  "http://www.defence.gov.au/ADFA/Images/news_events/whiteRibbon.jpg";

const LOGO = "https://upload.wikimedia.org/wikipedia/en/thumb/9/9f/Australian_Defence_Force_Academy_coat_of_arms.svg/1200px-Australian_Defence_Force_Academy_coat_of_arms.svg.png";

const LOGO_MARGIN_PERCENTAGE = 5;

const FILENAME = "test.jpg";
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

This part is pretty straight forward. We're importing jimp and defining some constants.

Next we're defining an async function main. We want it to be async because we want to do async/await inside the code. async/await can only work inside a function.

const [image, logo] = await Promise.all([
    Jimp.read(ORIGINAL_IMAGE),
    Jimp.read(LOGO)
  ]);
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

Here, we're reading an image from an url using jimp. Jimp.read result is a Promise. And we want to read these image in parallel. So, we use Promise.all. Promise.all also will produce Promise. So we use await to wait the result, and then we assign the result into image, and logo

logo.resize(image.bitmap.width / 10, Jimp.AUTO);
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

We want to resize the logo size to be smaller. We want the logo width to be 10% of the image, and we just give AUTO for the height.

const xMargin = (image.bitmap.width * LOGO_MARGIN_PERCENTAGE) / 100;
const yMargin = (image.bitmap.width * LOGO_MARGIN_PERCENTAGE) / 100;

const X = image.bitmap.width - logo.bitmap.width - xMargin;
const Y = image.bitmap.height - logo.bitmap.height - yMargin;
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

This is just the position of the logo. We want to position the logo on the bottom right.

return image.composite(logo, X, Y, [
    {
      mode: Jimp.BLEND_SCREEN,
      opacitySource: 0.1,
      opacityDest: 1
    }
  ]);
};
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

Here, we compose these two image together.

main().then(image => image.write(FILENAME));
⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025 ⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025

finally we write the result into test.jpg

That's it.
Hope it helps you :)

Top comments (2)

⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025
 
chiacy profile image
chiacy •

hi!

great piece!

however, if I wanted to imposed text watermark, is it possible?

⭐ Must Read: muhajirdev/how to watermark an image with node js n - Kapook Update 2025
 
stefan_stojanovic profile image
Stefan Stojanovic •

there is a way of doing that, there is an article on SO : stackoverflow.com/questions/262940...
still works :)