Please bookmark this page to avoid losing your image tool!

Image Date And Location Stamp Adder

(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 date and location information, similar to a camera timestamp.
 * This function is async because it may need to fetch the user's location over the network.
 *
 * @param {Image} originalImg The original Image object to stamp.
 * @param {string} [stampText=''] The text to stamp. Supports newlines (\n). If empty, text is generated from date/location. Providing this makes the function synchronous.
 * @param {string} [dateFormat='YYYY-MM-DD HH:mm:ss'] The format for the date. Used only if stampText is empty. Replaces YYYY, MM, DD, HH, mm, ss.
 * @param {string} [locationFormat='[road], [zone], [country]'] The format for the location. Used only if stampText is empty. Placeholders like [road], [zone], [city], [state], [country] are replaced with geodata.
 * @param {string} [textColor='#FFFFFF'] The color of the stamped text.
 * @param {number} [fontSize=24] The font size of the text in pixels.
 * @param {string} [fontFamily='Arial'] The font family for the text. Use web-safe fonts.
 * @param {string} [position='Bottom-Right'] The position of the stamp. Options: 'Top-Left', 'Top-Center', 'Top-Right', 'Middle-Left', 'Middle-Center', 'Middle-Right', 'Bottom-Left', 'Bottom-Center', 'Bottom-Right'.
 * @param {number} [margin=10] The margin in pixels from the edge of the image.
 * @param {number} [textOpacity=1.0] The opacity of the text and its background (0.0 to 1.0).
 * @param {string} [backgroundColor='rgba(0, 0, 0, 0.5)'] The color of the background rectangle behind the text for readability. Use 'transparent' for none.
 * @param {number} [backgroundPadding=5] The padding in pixels for the background rectangle.
 * @returns {Promise<HTMLCanvasElement>} A Promise that resolves to a new canvas element with the stamp applied.
 */
async function processImage(
    originalImg,
    stampText = '',
    dateFormat = 'YYYY-MM-DD HH:mm:ss',
    locationFormat = '[road], [zone], [country]',
    textColor = '#FFFFFF',
    fontSize = 24,
    fontFamily = 'Arial',
    position = 'Bottom-Right',
    margin = 10,
    textOpacity = 1.0,
    backgroundColor = 'rgba(0, 0, 0, 0.5)',
    backgroundPadding = 5
) {
    // 1. Setup Canvas
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.width = originalImg.naturalWidth || originalImg.width;
    canvas.height = originalImg.naturalHeight || originalImg.height;
    ctx.drawImage(originalImg, 0, 0);

    // 2. Prepare text to be stamped
    let finalText = stampText;
    if (!finalText) {
        // 2a. Format Date
        const d = new Date();
        const dateStr = dateFormat
            .replace('YYYY', d.getFullYear())
            .replace('MM', String(d.getMonth() + 1).padStart(2, '0'))
            .replace('DD', String(d.getDate()).padStart(2, '0'))
            .replace('HH', String(d.getHours()).padStart(2, '0'))
            .replace('mm', String(d.getMinutes()).padStart(2, '0'))
            .replace('ss', String(d.getSeconds()).padStart(2, '0'));

        // 2b. Get and Format Location (async part)
        let locationStr = 'Location unavailable';
        try {
            const coords = await new Promise((resolve, reject) => {
                if (!navigator.geolocation) {
                    return reject(new Error('Geolocation is not supported.'));
                }
                navigator.geolocation.getCurrentPosition(
                    (pos) => resolve(pos.coords),
                    (err) => reject(new Error(err.message)), {
                        enableHighAccuracy: true,
                        timeout: 10000,
                        maximumAge: 0
                    }
                );
            });

            const response = await fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${coords.latitude}&lon=${coords.longitude}&addressdetails=1`);
            if (!response.ok) throw new Error(`Reverse geocoding failed: ${response.statusText}`);
            const data = await response.json();

            if (data && data.address) {
                const addr = data.address;
                locationStr = locationFormat.replace(/\[(\w+)\]/g, (match, key) => {
                    const keyMap = {
                        zone: addr.suburb || addr.city_district || ''
                    };
                    return keyMap[key.toLowerCase()] || addr[key.toLowerCase()] || '';
                });
                locationStr = locationStr.split(',').map(s => s.trim()).filter(Boolean).join(', ');
            }
        } catch (error) {
            console.error("Could not get location:", error);
            // locationStr is already set to the error message
        }
        finalText = `${dateStr}\n${locationStr}`;
    }

    // 3. Setup text drawing properties
    ctx.font = `${fontSize}px ${fontFamily}`;
    const lines = finalText.split('\n');
    const lineHeight = fontSize * 1.2;
    const totalTextHeight = lines.length * lineHeight - (lineHeight - fontSize); // More precise height

    let maxTextWidth = 0;
    lines.forEach(line => {
        const metrics = ctx.measureText(line);
        if (metrics.width > maxTextWidth) {
            maxTextWidth = metrics.width;
        }
    });

    // 4. Calculate text block position
    let x, y_block_top;
    
    // Vertical position
    if (position.startsWith('Top')) {
        y_block_top = margin;
    } else if (position.startsWith('Middle')) {
        y_block_top = (canvas.height - totalTextHeight) / 2;
    } else { // Bottom
        y_block_top = canvas.height - margin - totalTextHeight;
    }
    
    // Horizontal position
    if (position.includes('Left')) {
        ctx.textAlign = 'left';
        x = margin;
    } else if (position.includes('Center')) {
        ctx.textAlign = 'center';
        x = canvas.width / 2;
    } else { // Right
        ctx.textAlign = 'right';
        x = canvas.width - margin;
    }

    // 5. Draw background and text
    ctx.globalAlpha = textOpacity;
    
    // Draw background rectangle
    if (backgroundColor && backgroundColor !== 'transparent') {
        ctx.fillStyle = backgroundColor;
        let rectX;
        if (ctx.textAlign === 'left') {
            rectX = x - backgroundPadding;
        } else if (ctx.textAlign === 'center') {
            rectX = x - (maxTextWidth / 2) - backgroundPadding;
        } else { // right
            rectX = x - maxTextWidth - backgroundPadding;
        }
        ctx.fillRect(
            rectX,
            y_block_top - backgroundPadding,
            maxTextWidth + backgroundPadding * 2,
            totalTextHeight + backgroundPadding * 2
        );
    }
    
    // Draw text lines
    ctx.fillStyle = textColor;
    ctx.textBaseline = 'top';
    lines.forEach((line, index) => {
        ctx.fillText(line, x, y_block_top + index * lineHeight);
    });

    // 6. Restore context and return canvas
    ctx.globalAlpha = 1.0;
    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 Location Stamp Adder is a versatile online tool that allows users to add timestamps and geographic location information onto their images. Users can customize the text format to include date and location details, select the font style, color, size, and positioning of the stamp, as well as control the opacity and background style for improved readability. This tool is ideal for photographers who wish to document when and where their photos were taken, ensuring that important contextual information is preserved. It can also be useful for social media enthusiasts who want to enhance their image-sharing by providing viewers with specific details about the captured moment.

Leave a Reply

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