Please bookmark this page to avoid losing your image tool!

Image Date And Zone Stamping 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.
/**
 * Stamps an image with text, such as a date, time, or custom message.
 * This function replicates the functionality of an online date stamping tool,
 * allowing for custom text, positioning, and styling. It can dynamically
 * load fonts from Google Fonts.
 *
 * @param {HTMLImageElement} originalImg - The source HTML Image object (must be fully loaded).
 * @param {string} [text="DD/MM/YYYY hh:mm:ss"] - The text to stamp. Supports placeholders: YYYY, YY, MM, DD, hh, mm, ss.
 * @param {string} [position='bottom-right'] - The position of the stamp. One of: 'top-left', 'top-center', 'top-right', 'middle-left', 'middle-center', 'middle-right', 'bottom-left', 'bottom-center', 'bottom-right'.
 * @param {number} [fontSize=25] - The font size in pixels.
 * @param {string} [fontFamily='Arial'] - The font family (e.g., 'Arial', 'Roboto'). Tries to load non-websafe fonts from Google Fonts.
 * @param {string} [fontColor='#FFFF00'] - The CSS color of the text (e.g., '#FFFF00').
 * @param {string} [fontStyle='normal'] - The style of the font. Can be 'normal', 'bold', 'italic', or 'bold italic'.
 * @param {string} [backgroundColor='rgba(0, 0, 0, 0.5)'] - The CSS color of the text background. Use 'transparent' for no background.
 * @param {number} [marginX=10] - The horizontal margin from the image edge in pixels.
 * @param {number} [marginY=10] - The vertical margin from the image edge in pixels.
 * @param {number} [padding=5] - The padding between the text and its background border in pixels.
 * @returns {Promise<HTMLCanvasElement>} A promise that resolves with a new canvas element containing the stamped image.
 */
async function processImage(
    originalImg,
    text = "DD/MM/YYYY hh:mm:ss",
    position = 'bottom-right',
    fontSize = 25,
    fontFamily = 'Arial',
    fontColor = '#FFFF00',
    fontStyle = 'normal',
    backgroundColor = 'rgba(0, 0, 0, 0.5)',
    marginX = 10,
    marginY = 10,
    padding = 5
) {

    /**
     * Dynamically loads a font from Google Fonts if it's not a standard web-safe font.
     * @param {string} font - The font family name.
     */
    const loadFontIfNeeded = async (font) => {
        const fontName = font.trim();
        const webSafeFonts = [
            'arial', 'verdana', 'helvetica', 'tahoma', 'trebuchet ms', 'times new roman',
            'georgia', 'garamond', 'courier new', 'brush script mt', 'sans-serif',
            'serif', 'monospace', 'cursive', 'fantasy', 'system-ui'
        ];

        if (webSafeFonts.includes(fontName.toLowerCase())) {
            return; // Font is web-safe, no need to load.
        }

        // Check if the font is already available or has been added by this function.
        if (document.fonts.check(`1em "${fontName}"`)) {
            return;
        }

        try {
            // This URL requests normal, bold, italic, and bold-italic styles.
            const googleFontUrl = `https://fonts.googleapis.com/css2?family=${fontName.replace(/ /g, '+')}:ital,wght@0,400;0,700;1,400;1,700&display=swap`;
            const linkId = `google-font-${fontName.replace(/ /g, '-')}`;

            if (document.getElementById(linkId)) {
                // Link already exists, just wait for the font to be ready.
                await document.fonts.load(`1em "${fontName}"`);
                return;
            }

            const link = document.createElement('link');
            link.id = linkId;
            link.href = googleFontUrl;
            link.rel = 'stylesheet';

            const loadPromise = new Promise((resolve, reject) => {
                link.onload = resolve;
                link.onerror = () => reject(new Error(`Failed to load stylesheet for font: ${fontName}`));
                document.head.appendChild(link);
            });

            await loadPromise;
            // After the stylesheet is loaded, wait for the font to be usable.
            await document.fonts.load(`1em "${fontName}"`);

        } catch (e) {
            console.error(`Error loading font "${fontName}". It may not be available on Google Fonts or the network failed. The browser will use a fallback font.`, e);
        }
    };

    await loadFontIfNeeded(fontFamily);

    const canvas = document.createElement('canvas');
    // Using willReadFrequently can be a performance hint for the browser.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });
    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;

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

    // Process the text for date/time placeholders.
    const now = new Date();
    const replacements = {
        'YYYY': now.getFullYear(),
        'YY': String(now.getFullYear()).slice(-2),
        'MM': String(now.getMonth() + 1).padStart(2, '0'),
        'DD': String(now.getDate()).padStart(2, '0'),
        'hh': String(now.getHours()).padStart(2, '0'),
        'mm': String(now.getMinutes()).padStart(2, '0'),
        'ss': String(now.getSeconds()).padStart(2, '0'),
    };
    let processedText = text;
    for (const key in replacements) {
        processedText = processedText.replace(new RegExp(key, 'g'), replacements[key]);
    }

    // Set up font style based on the 'fontStyle' parameter.
    let weight = fontStyle.includes('bold') ? 'bold' : 'normal';
    let style = fontStyle.includes('italic') ? 'italic' : 'normal';
    ctx.font = `${style} ${weight} ${fontSize}px "${fontFamily}"`;

    // Measure the text to get its dimensions for positioning.
    const metrics = ctx.measureText(processedText);
    const textWidth = metrics.width;
    const textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;

    // Calculate the dimensions of the background box.
    const boxWidth = textWidth + padding * 2;
    const boxHeight = textHeight + padding * 2;

    let boxX, boxY;

    // Calculate horizontal position of the background box.
    if (position.includes('center')) {
        boxX = (canvas.width - boxWidth) / 2;
    } else if (position.includes('right')) {
        boxX = canvas.width - boxWidth - marginX;
    } else { // 'left'
        boxX = marginX;
    }

    // Calculate vertical position of the background box.
    if (position.includes('middle')) {
        boxY = (canvas.height - boxHeight) / 2;
    } else if (position.includes('bottom')) {
        boxY = canvas.height - boxHeight - marginY;
    } else { // 'top'
        boxY = marginY;
    }

    // Draw the background if a color is specified.
    if (backgroundColor && backgroundColor !== 'transparent' && backgroundColor !== 'none') {
        ctx.fillStyle = backgroundColor;
        ctx.fillRect(boxX, boxY, boxWidth, boxHeight);
    }

    // Set text properties for drawing.
    ctx.fillStyle = fontColor;
    ctx.textBaseline = 'alphabetic'; // Use the standard baseline for precise vertical alignment.

    // Calculate the precise X, Y coordinates to draw the text inside the padded box.
    const textDrawX = boxX + padding;
    // We want the top of the text's rendered pixels to align with the top of the padded area.
    // The top of the renderable text is at `y - metrics.actualBoundingBoxAscent`.
    // We want that position to be `boxY + padding`.
    // So, `y_baseline - ascent = boxY + padding`, which means `y_baseline = boxY + padding + ascent`.
    const textDrawY = boxY + padding + metrics.actualBoundingBoxAscent;

    ctx.fillText(processedText, textDrawX, textDrawY);

    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 Date and Zone Stamping Tool allows users to stamp images with text, such as dates, times, or custom messages. This tool is useful for adding metadata directly onto images, making it ideal for photographers, event organizers, and social media enthusiasts who want to mark their photos with specific information. Users can customize the position, font size, style, color, and background of the text, as well as utilize dynamic date and time placeholders to ensure accurate and personalized stamping. Whether for documentation, personal memories, or promotional materials, this tool enhances image presentations effectively.

Leave a Reply

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