How to watermark an image with Node.js

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
npm init

Just press Enter, Enter, Enter...

npm install --save jimp

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

code .

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));

Now try to run

node index.js

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";

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)
  ]);

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);

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;

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
    }
  ]);
};

Here, we compose these two image together.

main().then(image => image.write(FILENAME));

finally we write the result into test.jpg

That's it. Hope it helps you :)