Please bookmark this page to avoid losing your image tool!

Image Wedding Announcement Poster Maker

(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,
    titleText = "Save The Date",
    groomName = "Alexander",
    brideName = "Olivia",
    conjunction = "&",
    weddingDate = "Saturday, June 10, 2028",
    weddingTime = "at Four O'Clock in the Afternoon",
    venueName = "The Enchanted Garden",
    venueAddress = "123 Blossom Lane, Dreamville",
    mainFontFamily = "Dancing Script", // For titles and names. Examples: "Dancing Script", "Great Vibes"
    detailsFontFamily = "Roboto",     // For date, time, venue. Examples: "Roboto", "Montserrat", "Georgia"
    textColor = "#FFFFFF",
    titleFontSize = 0.08,   // Relative to canvas height
    namesFontSize = 0.1,    // Relative to canvas height
    detailsFontSize = 0.035, // Relative to canvas height
    nameConjunctionFontSize = 0.07, // Relative to canvas height for '&'
    overlayColor = "rgba(0, 0, 0, 0.4)" // e.g., "rgba(0,0,0,0.4)" for dark, "rgba(255,255,255,0.3)" for light. Empty string for no overlay.
) {

    // Helper function to load Google Fonts.
    // If fontFamilyToLoad is a common web-safe font, it should just work.
    // If it's a known Google Font, it attempts to load it.
    // Otherwise, it assumes the font is available or relies on system fallbacks.
    const _loadGoogleFont = async (fontFamilyToLoad, fallbackFont) => {
        try {
            // Check if font is already loaded/available (e.g., web-safe like 'Arial', 'Georgia')
            // or if it was loaded in a previous call.
            if (document.fonts.check(`12px "${fontFamilyToLoad}"`)) {
                return fontFamilyToLoad;
            }
        } catch (e) {
            // document.fonts might not be available in some rare contexts.
            console.warn("Could not check font status using document.fonts.check. Proceeding with font: " + fontFamilyToLoad, e);
            // Fallback to trying to load or assuming it's available.
        }

        let fontUrl = "";
        // Add URLs for common Google fonts you want to support dynamically.
        // These URLs point to WOFF2 files for specific weights (usually Regular 400).
        if (fontFamilyToLoad === "Dancing Script") {
            fontUrl = "https://fonts.gstatic.com/s/dancingscript/v25/If2RXTr6YS-zF4S-kcSWSVi_szLviuEViw.woff2";
        } else if (fontFamilyToLoad === "Roboto") {
            fontUrl = "https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Mu4mxK.woff2";
        } else if (fontFamilyToLoad === "Great Vibes") {
            fontUrl = "https://fonts.gstatic.com/s/greatvibes/v18/RWmMoKWR9v4ksMfaWd_JN-XMaltJ.woff2";
        } else if (fontFamilyToLoad === "Montserrat") {
            fontUrl = "https://fonts.gstatic.com/s/montserrat/v26/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw0aXpsog.woff2"; // Regular 400
        }
        // Add more fonts here if needed

        if (fontUrl) {
            const font = new FontFace(fontFamilyToLoad, `url(${fontUrl})`);
            try {
                await font.load();
                document.fonts.add(font);
                // console.log(`Successfully loaded Google Font: ${fontFamilyToLoad}`);
                return fontFamilyToLoad;
            } catch (e) {
                console.error(`Failed to load Google Font '${fontFamilyToLoad}' from ${fontUrl}. Using fallback font '${fallbackFont}'. Error:`, e);
                return fallbackFont;
            }
        } else {
            // console.log(`No pre-configured URL for "${fontFamilyToLoad}". Assuming it's web-safe or already loaded on the system.`);
            // If it's not a known Google Font and not web-safe, the browser will use its default font.
            return fontFamilyToLoad;
        }
    };

    // Load fonts, using fallbacks if specified fonts fail or aren't pre-configured for dynamic loading
    const actualMainFont = await _loadGoogleFont(mainFontFamily, "Georgia, serif");
    const actualDetailsFont = await _loadGoogleFont(detailsFontFamily, "Arial, sans-serif");

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Set canvas dimensions and background
    if (!originalImg || typeof originalImg.naturalWidth === 'undefined' || !originalImg.naturalWidth || !originalImg.naturalHeight) {
        console.warn("Original image is invalid or has no dimensions. Using default canvas size 800x1000 and a placeholder background.");
        canvas.width = 800;
        canvas.height = 1000;
        ctx.fillStyle = "#E0E0E0"; // Light gray placeholder background
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        ctx.fillStyle = "#333333"; // Dark text for placeholder message
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        const defaultMsgFont = "Arial";
        ctx.font = `bold ${Math.round(canvas.height * 0.025)}px ${defaultMsgFont}`; // 20px for 800px height
        ctx.fillText("Invalid or Missing Background Image", canvas.width / 2, canvas.height / 2 - Math.round(canvas.height * 0.02));
        ctx.font = `${Math.round(canvas.height * 0.02)}px ${defaultMsgFont}`; // 16px for 800px height
        ctx.fillText(`Using ${canvas.width}x${canvas.height} placeholder`, canvas.width/2, canvas.height/2 + Math.round(canvas.height * 0.0125));

    } else {
        canvas.width = originalImg.naturalWidth;
        canvas.height = originalImg.naturalHeight;
        ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    }

    // Apply overlay if specified
    if (overlayColor && overlayColor.trim() !== "") {
        ctx.fillStyle = overlayColor;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
    }

    // Text properties
    ctx.fillStyle = textColor;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle'; // Ensures text is vertically centered around the y-coordinate

    let currentY = canvas.height * 0.18; // Starting Y position for the first line of text (18% from top)
    const xPos = canvas.width / 2; // All text is centered horizontally
    
    const baseLineHeightMultiplier = 1.2;         // Multiplier for basic line height (e.g., 1.2 times font size)
    const sectionSpacingInFontSizeUnits = 0.6;    // Additional spacing after a text "section" (e.g. after title, after names block)
                                                  // This is relative to the current line's font size.

    // Helper function to draw a line of text and advance currentY
    function drawTextLine(text, fontFace, fontSizePercent, additionalSpacingUnitsAfter = 0) {
        if (text && text.trim() !== "") {
            // Calculate font size in pixels, with a minimum practical size (e.g., 10px)
            const fontSizePx = Math.max(10, Math.round(canvas.height * fontSizePercent));
            ctx.font = `${fontSizePx}px "${fontFace}"`; // Quote font name for safety with spaces
            ctx.fillText(text, xPos, currentY);
            
            // Advance Y position for the next line
            currentY += fontSizePx * baseLineHeightMultiplier; // Base line height
            currentY += fontSizePx * additionalSpacingUnitsAfter; // Additional spacing if any
        }
    }
    
    // Draw Wedding Announcement Content
    drawTextLine(titleText, actualMainFont, titleFontSize, sectionSpacingInFontSizeUnits);
    
    drawTextLine(groomName, actualMainFont, namesFontSize);
    drawTextLine(conjunction, actualMainFont, nameConjunctionFontSize); // conjunction usually same font, maybe different size
    drawTextLine(brideName, actualMainFont, namesFontSize, sectionSpacingInFontSizeUnits);
    
    drawTextLine(weddingDate, actualDetailsFont, detailsFontSize);
    drawTextLine(weddingTime, actualDetailsFont, detailsFontSize, sectionSpacingInFontSizeUnits * 0.7); // A bit of space before venue details
    
    drawTextLine(venueName, actualDetailsFont, detailsFontSize);
    drawTextLine(venueAddress, actualDetailsFont, detailsFontSize * 0.9); // Venue address often slightly smaller

    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 Wedding Announcement Poster Maker allows you to create personalized wedding announcement posters by combining your chosen images with custom text elements. You can input details such as the couple’s names, wedding date, time, and venue, as well as select font styles and colors to suit your aesthetic. This tool is perfect for anyone planning a wedding, as it helps to design elegant and memorable ‘Save the Date’ announcements or invitations that can be shared online or printed for guests.

Leave a Reply

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