Node.js - tutorial - watermarking

revision:


Prequisites

1. Install Node.js

2. Create a Project :

            mkdir watermark-project
            cd watermark-project
            npm init -y        
        

option 1: text watermark with "Jimp"

"Jimp" is great for adding text watermarks with ease.

step 1 : install depedencies

npm install jimp

step 2: create a script (text-watermark.js)

        const Jimp = require('jimp');
        async function addTextWatermark(inputPath, outputPath, text, options) {
            try {
                const image = await Jimp.read(inputPath);
                const font = await Jimp.loadFont(Jimp.FONT_SANS_32_WHITE);

                // Customize text position and alignment
                const textOptions = {
                text: text,
                alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
                alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE,
                };

                // Add text to the image
                image.print(
                font,
                10, // X offset (adjust for positioning)
                10, // Y offset
                textOptions,
                image.getWidth(),
                image.getHeight()
                );

                // Save the watermarked image
                await image.write(outputPath);
                console.log(`Watermark added successfully! Output: ${outputPath}`);
            } catch (error) {
                console.error('Error:', error);
            }
        }

        // Usage Example
        addTextWatermark(
            'input.jpg', // Path to input image
            'output-text.jpg', // Output path
            '© My Copyright 2023', // Watermark text
            {}
        );
    

Customization:

Position : adjust 10, 10 (X/Y offsets) or use Jimp.HORIZONTAL_ALIGN_CENTER for center alignment.
Font & Color : use Jimp.loadFont() for other fonts or create a custom font.
Opacity : adjust with image.bitmap.data (advanced).


option 2: image watermark with "Sharp"

"Sharp" is fast and ideal for overlaying images (e.g., logos).

step 1: install dependencies

    npm install sharp

step 2: create a script (image-watermark.js)

    const sharp = require('sharp');

    async function addImageWatermark(inputPath, watermarkPath, outputPath, position = 'southeast') {
        try {
            await sharp(inputPath)
            .composite([{ input: watermarkPath, gravity: position }])
            .toFile(outputPath);
            console.log(`Watermark added successfully! Output: ${outputPath}`);
        } catch (error) {
            console.error('Error:', error);
        }
    }

    // Usage Example
    addImageWatermark(
    'input.jpg', // Input image
    'logo.png', // Watermark image (transparent PNG recommended)
    'output-image.jpg', // Output path
    'southeast' // Position: 'top-left', 'center', 'southeast', etc.
    );

customization:

Position : Use gravity options like southeast (bottom-right), northwest (top-left), etc.
Resize Watermark : Add .resize({ width: 100 }) before .composite().
Opacity : Adjust with sharp() options (e.g., background: { r: 255, g: 255, b: 255, alpha: 0.5 }).


option 3: combine both (text + image)

use Canvas for full control over text and image overlay:

step 1: install dependencies

    npm install canvas

step 2: create a script (combined-watermark.js)

    
    const { createCanvas, loadImage } = require('canvas');
    const fs = require('fs');

    async function addCombinedWatermark(inputPath, outputPath, text, watermarkPath) {
        try {
            const image = await loadImage(inputPath);
            const canvas = createCanvas(image.width, image.height);
            const ctx = canvas.getContext('2d');

            // Draw the original image
            ctx.drawImage(image, 0, 0);

            // Add text watermark
            ctx.font = '20px Arial';
            ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(text, canvas.width / 2, canvas.height / 2);

            // Add image watermark
            const watermark = await loadImage(watermarkPath);
            ctx.drawImage(
            watermark,
            canvas.width - watermark.width - 10, // X position
            canvas.height - watermark.height - 10 // Y position
            );

            // Save the result
            fs.writeFileSync(outputPath, canvas.toBuffer());
            console.log(`Combined watermark added successfully! Output: ${outputPath}`);
        } catch (error) {
            console.error('Error:', error);
        }
    }
    // Usage Example
    addCombinedWatermark(
    'input.jpg',
    'output-combined.jpg',
    '© 2023',
    'logo.png'
    );

advanced: create a web server (optional)

use "Express" to handle image uploads via a web interface.

step 1: install dependencies

npm install express multer

step 2: create server (server.js)

    const express = require('express');
    const multer = require('multer');
    const sharp = require('sharp');
    const upload = multer({ dest: 'uploads/' });

    const app = express();
    const port = 3000;

    app.post('/watermark', upload.single('image'), async (req, res) => {
    try {
        const outputPath = `output/${Date.now()}-watermarked.jpg`;
        await sharp(req.file.path)
        .composite([{ input: 'logo.png', gravity: 'southeast' }])
        .toFile(outputPath);
        res.download(outputPath);
    } catch (error) {
        res.status(500).send('Error adding watermark');
    }
    });

    app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
    });

key considerations

Performance : use "Sharp" for large-scale or high-performance tasks; "Jimp" is simpler for text but slightly slower.

Transparency : ensure watermark images (e.g., logos) use an alpha channel (PNG format).

Error Handling : add try/catch blocks for robustness.

Customization : adjust font size, color, position, and opacity as needed.

Run your script with:

    node text-watermark.js
    node image-watermark.js
    node combined-watermark.js
    node server.js # For the web server