Please bookmark this page to avoid losing your image tool!

Image Watermark Filter Tool

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, watermarkText = "Sample Watermark", fontSize = 30, fontFamily = "Arial", textColor = "rgba(0, 0, 0, 0.5)", position = "bottom-right", padding = 10, rotationDegrees = 0, tileGap = 50) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;

    if (imgWidth === 0 || imgHeight === 0) {
        // Return a small, empty canvas or throw error if image dimensions are invalid
        console.warn("Image has zero dimensions. Returning 1x1 canvas.");
        canvas.width = 1;
        canvas.height = 1;
        return canvas;
    }

    canvas.width = imgWidth;
    canvas.height = imgHeight;

    // Draw the original image
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    // If watermark text is empty, no need to proceed further with watermarking
    if (!watermarkText || watermarkText.trim() === "") {
        return canvas;
    }

    // Prepare watermark styles
    ctx.font = `${fontSize}px ${fontFamily}`;
    ctx.fillStyle = textColor;
    const angleInRadians = rotationDegrees * Math.PI / 180;

    // Function to draw rotated text
    // (x,y) is the anchor point of the text, its meaning depends on textAlign and textBaseline
    const drawRotatedText = (text, x, y, angleRad) => {
        ctx.save();
        ctx.translate(x, y);
        ctx.rotate(angleRad);
        ctx.fillText(text, 0, 0);
        ctx.restore();
    };

    const metrics = ctx.measureText(watermarkText);
    const textWidth = metrics.width;
    
    let actualTextHeight;
    // Prefer actualBoundingBox for more precise height of the given text
    if (metrics.actualBoundingBoxAscent && metrics.actualBoundingBoxDescent) {
        actualTextHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
    } 
    // Fallback to fontBoundingBox for overall font height
    else if (metrics.fontBoundingBoxAscent && metrics.fontBoundingBoxDescent) {
        actualTextHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
    }
    // Final fallback to fontSize if no detailed metrics are available
    else {
        actualTextHeight = fontSize; 
    }
    // Ensure actualTextHeight is a positive number
    if (!(actualTextHeight > 0)) {
        actualTextHeight = fontSize; // Default to fontSize if calculated height is not usable
    }


    if (position === "tile") {
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';

        const cosA = Math.cos(angleInRadians);
        const sinA = Math.sin(angleInRadians);

        // Calculate Axis-Aligned Bounding Box (AABB) of the rotated text
        const AABB_width = Math.abs(textWidth * cosA) + Math.abs(actualTextHeight * sinA);
        const AABB_height = Math.abs(textWidth * sinA) + Math.abs(actualTextHeight * cosA);

        // Define cell dimensions for tiling grid (text AABB + gap)
        const cellWidth = AABB_width + tileGap;
        const cellHeight = AABB_height + tileGap;

        if (cellWidth <= 0 || cellHeight <= 0) { // Avoid infinite loops if dimensions are non-positive
             console.warn("Calculated cell dimensions for tiling are non-positive. Skipping tiling.");
             return canvas;
        }
        
        // Iterate to fill the canvas with tiled watermarks
        // Start drawing from outside the canvas to ensure full coverage including edges
        const startX = (tileGap / 2) + (AABB_width / 2);
        const startY = (tileGap / 2) + (AABB_height / 2);

        for (let yPos = startY - cellHeight; yPos < canvas.height + AABB_height; yPos += cellHeight) {
            for (let xPos = startX - cellWidth; xPos < canvas.width + AABB_width; xPos += cellWidth) {
                drawRotatedText(watermarkText, xPos, yPos, angleInRadians);
            }
        }

    } else {
        let x, y;
        switch (position) {
            case "top-left":
                ctx.textAlign = 'left';
                ctx.textBaseline = 'top'; // Use 'top' for y to be top edge of text
                x = padding;
                y = padding;
                break;
            case "top-right":
                ctx.textAlign = 'right';
                ctx.textBaseline = 'top';
                x = canvas.width - padding;
                y = padding;
                break;
            case "bottom-left":
                ctx.textAlign = 'left';
                ctx.textBaseline = 'bottom'; // Use 'bottom' for y to be bottom edge
                x = padding;
                y = canvas.height - padding;
                break;
            case "center":
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                x = canvas.width / 2;
                y = canvas.height / 2;
                break;
            case "bottom-right":
            default: // Default to bottom-right
                ctx.textAlign = 'right';
                ctx.textBaseline = 'bottom';
                x = canvas.width - padding;
                y = canvas.height - padding;
                break;
        }
        drawRotatedText(watermarkText, x, y, angleInRadians);
    }

    return canvas;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Image Watermark Filter Tool allows users to easily add customizable text watermarks to their images. With options for font size, font family, color, position, and rotation, this tool is ideal for photographers, graphic designers, and content creators who want to protect their images from unauthorized use or to provide branding. Users can choose to tile the watermark across the image or place it at specific corners or the center, making it versatile for various creative needs.

Leave a Reply

Your email address will not be published. Required fields are marked *