How to Add Watermark to Images in Node.js (3 Ways)

Updated: December 28, 2023 By: Guest Contributor Post a comment

Adding watermarks to images can be essential for copyright protection, preventing unauthorized use or distribution of your images. It helps in branding, ensuring your logo or name is visibly associated with your content. This concise, example-based article will show you several different ways to programmatically add watermarks to images in Node.js

Solution 1: Using Jimp

This solution involves using the Jimp package, a JavaScript Image Manipulation Program that has built-in support for image editing. It’s simple to use and doesn’t have any native dependencies.

  • Install Jimp via npm or yarn.
  • Load your base image and watermark image.
  • Composite the watermark over the base image.
  • Save the resultant image to the file system.
const Jimp = require('jimp');

async function addWatermark(baseImagePath, watermarkPath, outputPath) {
    const image = await Jimp.read(baseImagePath);
    const watermark = await Jimp.read(watermarkPath);
    watermark.opacity(0.5); // set watermark opacity
    image.composite(watermark, 0, 0, {
        mode: Jimp.BLEND_SOURCE_OVER,
        opacityDest: 1,
        opacitySource: 0.5
    });
    await image.writeAsync(outputPath);
}

addWatermark('path/to/image.jpg', 'path/to/watermark.png', 'path/to/output.jpg');

Pros: Easy to use; pure JavaScript; no native dependencies.

Cons: Performance may not be as good as native modules for large-scale operations.

Solution 2: Using sharp

Sharp is a high-performance Node.js module for image processing, built on top of the libvips image processing library. It’s significantly faster than most other JavaScript image processing libraries.

  • Install sharp via npm or yarn.
  • Read the base and watermark image using Sharp.
  • Composite the images together.
  • Output the final image.
const sharp = require('sharp');

sharp('path/to/image.jpg')
    .composite([{ input: 'path/to/watermark.png', gravity: 'southeast' }])
    .toFile('path/to/output.jpg')
    .catch(err => console.error(err));

Pros: Very fast; supports various image formats; advanced image processing.

Cons: Slightly more complex API; requires native dependencies.

Solution 3: Using canvas

The ‘canvas’ library allows Node.js users to perform canvas API operations similar to those available in the browser, which is useful for image manipulation tasks such as adding watermarks.

  • Install the canvas library via npm or yarn.
  • Create canvas elements for both images.
  • Draw the watermark on the base image on the canvas.
  • Export the canvas to an image file.
const { createCanvas, loadImage } = require('canvas');

async function addWatermark(baseImagePath, watermarkPath, outputPath) {
    const baseImage = await loadImage(baseImagePath);
    const watermark = await loadImage(watermarkPath);
    const canvas = createCanvas(baseImage.width, baseImage.height);
    const ctx = canvas.getContext('2d');
    ctx.drawImage(baseImage, 0, 0);
    ctx.globalAlpha = 0.5; // set watermark opacity
    ctx.drawImage(watermark, 0, 0);
    const buffer = canvas.toBuffer('image/png');
    require('fs').writeFileSync(outputPath, buffer);
}

addWatermark('path/to/image.png', 'path/to/watermark.png', 'path/to/output.png');

Pros: Flexibility of the HTML canvas API; support for custom drawing and typesetting.

Cons: More complicated setup; may have performance issues for large numbers of images.

Conclusion

Adding watermarks to images in Node.js can be achieved through various libraries. Jimp offers an easy and dependency-free approach, but may not be suitable for high-performance needs. Sharp, on the other hand, is incredibly fast and powerful but comes with the cost of complexity and native dependencies. The canvas library provides a flexible solution that leverages the familiar HTML canvas API but can be less performant with heavier processing tasks. The choice of library should be based on the specific requirements of the project in terms of performance, complexity, and ease of use.