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
Enter fullscreen mode Exit fullscreen mode
npm init
Enter fullscreen mode Exit fullscreen mode

Just press Enter, Enter, Enter...

npm install --save jimp
Enter fullscreen mode Exit fullscreen mode

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

code .
Enter fullscreen mode Exit fullscreen mode

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

Now try to run

node index.js
Enter fullscreen mode Exit fullscreen mode

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

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

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

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

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

Here, we compose these two image together.

main().then(image => image.write(FILENAME));
Enter fullscreen mode Exit fullscreen mode

finally we write the result into test.jpg

That's it.
Hope it helps you :)

Top comments (2)

Collapse
 
chiacy profile image
chiacy

hi!

great piece!

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

Collapse
 
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 :)