Please bookmark this page to avoid losing your image tool!

Image Tourism Poster Creator For ‘Visit [Location]’

(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.
async function processImage(originalImg, locationName = "DreamLand", textColor = "white", fontName = "Impact", fontSize = 72, textPosition = "bottom-center", strokeColor = "black", strokeWidth = 3) {

    // Helper function to get a generic CSS font family based on a specific font name's characteristics
    function _getSystemGeneric(fontNameStr) {
        if (!fontNameStr || typeof fontNameStr !== 'string') return "sans-serif";
        const lcFontName = fontNameStr.toLowerCase();
        if (lcFontName.includes("times") || lcFontName.includes("georgia") || lcFontName.includes("garamond") || lcFontName.includes("palatino") || (lcFontName.includes("serif") && !lcFontName.includes("sans-serif"))) return "serif";
        if (lcFontName.includes("courier") || lcFontName.includes("consolas") || lcFontName.includes("monaco") || lcFontName.includes("mono")) return "monospace";
        if (lcFontName.includes("cursive") || lcFontName.includes("zapfino") || lcFontName.includes("comic sans")) return "cursive"; // comic sans is often debated, but fits cursive category for some uses
        if (lcFontName.includes("fantasy") || lcFontName.includes("papyrus")) return "fantasy";
        // Default fallback for Arial, Helvetica, Verdana, Impact, Open Sans etc.
        return "sans-serif";
    }

    // Helper function to attempt to load a font, especially from Google Fonts CDN
    async function _ensureFontIsLoadedInternal(requestedFontFamily, fallbackFontFamily) {
        const webSafeFonts = [
            "arial", "helvetica", "times new roman", "times", "courier new", "courier",
            "verdana", "georgia", "palatino", "garamond", "tahoma", "impact", "comic sans ms",
            "sans-serif", "serif", "monospace", "cursive", "fantasy" // CSS generic families
        ];

        if (webSafeFonts.includes(requestedFontFamily.toLowerCase())) {
            return requestedFontFamily; // Already web-safe or generic, no loading needed
        }

        // Use Font Loading API if available
        if (document.fonts) {
            try {
                // Heuristic: if font name looks like a typical Google Font name, try to add its stylesheet.
                // This allows document.fonts.load to find non-standard fonts if they are on Google Fonts.
                // Regex matches typical Google Font naming: capitalized words, optionally with spaces. Examples: "Roboto", "Open Sans", "Noto Sans JP"
                const looksLikeGoogleFont = /^[A-Z][a-zA-Z0-9]*(?:\s[A-Z][a-zA-Z0-9]*)*$/.test(requestedFontFamily);
                if (looksLikeGoogleFont) {
                    const familyId = requestedFontFamily.replace(/\s+/g, '+');
                    const fontCssUrl = `https://fonts.googleapis.com/css2?family=${familyId}:wght@400&display=swap`; // Regular weight
                    const styleId = `google-font-stylesheet-${familyId.replace(/[+ ]/g, '-')}`; // Create a DOM-safe ID

                    if (!document.getElementById(styleId)) {
                        try {
                            await new Promise((resolve, reject) => {
                                const link = document.createElement('link');
                                link.id = styleId;
                                link.rel = 'stylesheet';
                                link.href = fontCssUrl;
                                link.onload = resolve;
                                link.onerror = (err) => {
                                  // console.warn(`Stylesheet for ${requestedFontFamily} failed to load from ${fontCssUrl}.`);
                                  reject(new Error(`Stylesheet load error for ${requestedFontFamily}`));
                                };
                                document.head.appendChild(link);
                            });
                        } catch (e) {
                            // console.warn(e.message);
                            // If stylesheet fails to load, document.fonts.load will likely also fail for this font,
                            // unless it's defined elsewhere (e.g. system font, or other CSS).
                        }
                    }
                }
                
                // Attempt to load the font. This will wait if a stylesheet (e.g. Google Fonts) is still loading.
                // It can also load system fonts not in the web-safe list if the browser supports it.
                await document.fonts.load(`1em "${requestedFontFamily}"`);
                return requestedFontFamily; // Font successfully loaded or made available
            } catch (error) {
                // console.warn(`Failed to load font "${requestedFontFamily}" using document.fonts.load API. Error: ${error}. Using fallback "${fallbackFontFamily}".`);
                return fallbackFontFamily; // Fallback if any error in loading
            }
        } else {
            // Fallback for browsers without Font Loading API (e.g. older browsers)
            // console.warn("document.fonts API not available. Font loading for non-web-safe fonts relies on browser's @font-face handling (if CSS is pre-loaded or added).");
            // Try to add Google Font stylesheet if it looks like one (fire and forget)
             const looksLikeGoogleFont = /^[A-Z][a-zA-Z0-9]*(?:\s[A-Z][a-zA-Z0-9]*)*$/.test(requestedFontFamily);
             if (looksLikeGoogleFont) {
                const familyId = requestedFontFamily.replace(/\s+/g, '+');
                const fontCssUrl = `https://fonts.googleapis.com/css2?family=${familyId}:wght@400&display=swap`;
                const styleId = `google-font-stylesheet-${familyId.replace(/[+ ]/g, '-')}`;
                if (!document.getElementById(styleId)) {
                    const link = document.createElement('link');
                    link.id = styleId;
                    link.rel = 'stylesheet';
                    link.href = fontCssUrl;
                    document.head.appendChild(link);
                }
            }
            // Cannot reliably wait for font loading here. Return requested font and hope browser finds it.
            return requestedFontFamily;
        }
    }

    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) {
        console.error("Image has no dimensions or has not loaded yet. Cannot create poster.");
        // Create a fallback canvas indicating the error
        canvas.width = 300;
        canvas.height = 100;
        ctx.fillStyle = '#F0F0F0';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = '#A0A0A0';
        ctx.font = 'bold 16px Arial';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillText("Error: Image not loaded/sized.", canvas.width / 2, canvas.height / 2);
        return canvas;
    }

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

    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    const ultimateFallbackFont = "Arial"; // A truly common font
    const loadedFontName = await _ensureFontIsLoadedInternal(fontName, ultimateFallbackFont);
    
    const finalFontCssString = `"${loadedFontName}", ${_getSystemGeneric(loadedFontName)}`;
    
    const text = "Visit " + locationName;
    const currentFontSize = Number(fontSize); // Ensure numeric type

    ctx.font = `${currentFontSize}px ${finalFontCssString}`;
    ctx.fillStyle = textColor;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle"; // Vertically center text at y coordinate

    let x, y;
    // Calculate padding based on font size to avoid text touching edges
    const padding = currentFontSize * 0.4; 

    switch (textPosition.toLowerCase()) {
        case "top-center":
            x = canvas.width / 2;
            y = (currentFontSize / 2) + padding; // Center of text from top
            break;
        case "middle-center":
            x = canvas.width / 2;
            y = canvas.height / 2;
            break;
        case "bottom-center":
        default:
            x = canvas.width / 2;
            y = canvas.height - (currentFontSize / 2) - padding; // Center of text from bottom
            break;
    }

    const currentStrokeWidth = Number(strokeWidth); // Ensure numeric type
    if (currentStrokeWidth > 0 && strokeColor && strokeColor.toLowerCase() !== "transparent" && strokeColor.toLowerCase() !== "none") {
        ctx.strokeStyle = strokeColor;
        ctx.lineWidth = currentStrokeWidth;
        ctx.strokeText(text, x, y);
    }

    ctx.fillText(text, x, y);

    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 Tourism Poster Creator for Visit [Location]’ is a tool that allows users to create visually appealing tourism posters by overlaying customized text on images. Users can specify the location name, text color, font name, font size, text position, stroke color, and stroke width to personalize their posters. This tool is ideal for travel bloggers, marketing professionals, and anyone looking to promote tourism in specific locations by creating eye-catching promotional materials.

Leave a Reply

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