Please bookmark this page to avoid losing your image tool!

Image Vintage Advertisement Poster Generator

(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, headlineText = "AMAZING PRODUCT!", taglineText = "Get Yours Today!", fontFamily = "Oswald", primaryColor = "#3A2F2F", secondaryColor = "#EAE0D1", vintageStrength = 0.7) {
    // 0. Sanitize vintageStrength
    vintageStrength = Math.max(0, Math.min(1, parseFloat(vintageStrength) || 0));

    // 1. Font handling
    let activeFontFamily = fontFamily;
    let mainFallbackFont = "sans-serif";

    if (typeof fontFamily === 'string') {
        const lowerFontFamily = fontFamily.toLowerCase();
        if (lowerFontFamily === "oswald") {
            activeFontFamily = "Oswald"; // Standardize name
            mainFallbackFont = "sans-serif";
            if (!document.fonts.check(`12px ${activeFontFamily}`)) {
                const fontOswald = new FontFace(activeFontFamily, `url(https://fonts.gstatic.com/s/oswald/v49/TK3_WkUHHAIjg75cFRf3bXL8LICs1_FvsUtiZTaR.woff2)`);
                try {
                    await fontOswald.load();
                    document.fonts.add(fontOswald);
                    console.log(`Font '${activeFontFamily}' loaded successfully.`);
                } catch (e) {
                    console.error(`Font '${activeFontFamily}' loading failed:`, e);
                    activeFontFamily = mainFallbackFont; // Use fallback if loading fails
                }
            }
        } else if (lowerFontFamily === "bangers") {
            activeFontFamily = "Bangers"; // Standardize name
            mainFallbackFont = "cursive";
            if (!document.fonts.check(`12px ${activeFontFamily}`)) {
                const fontBangers = new FontFace(activeFontFamily, `url(https://fonts.gstatic.com/s/bangers/v20/FeVQS0BTqb0h60ACL5k.woff2)`);
                try {
                    await fontBangers.load();
                    document.fonts.add(fontBangers);
                    console.log(`Font '${activeFontFamily}' loaded successfully.`);
                } catch (e) {
                    console.error(`Font '${activeFontFamily}' loading failed:`, e);
                    activeFontFamily = mainFallbackFont; // Use fallback if loading fails
                }
            }
        } else {
            // For any other font family name, we assume it's a system font or loaded by the user elsewhere.
            // activeFontFamily is already set to fontFamily. We'll use a generic fallback.
            console.log(`Using system font or externally loaded font: '${fontFamily}'`);
        }
    } else {
        // Fallback if fontFamily parameter is not a string for some reason
        activeFontFamily = "sans-serif";
    }


    // 2. Canvas Setup
    const padding = Math.max(20, originalImg.width * 0.05); // Dynamic padding, at least 20px
    const textBlockHeightRatio = 0.25; // Proportion of image height for text block, or fixed
    let textBlockHeight = Math.max(100, originalImg.height * textBlockHeightRatio);
    if (originalImg.height < 300) textBlockHeight = 120; // Ensure minimum space for small images


    const borderWidth = Math.max(2, Math.min(10, padding * 0.1)); // Dynamic border width

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

    canvas.width = originalImg.width + 2 * padding;
    canvas.height = originalImg.height + 2 * padding + textBlockHeight;

    // 3. Background
    ctx.fillStyle = secondaryColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // 4. Draw and Process Image
    const imgX = padding;
    const imgY = padding;
    ctx.drawImage(originalImg, imgX, imgY, originalImg.width, originalImg.height);

    if (vintageStrength > 0 && originalImg.width > 0 && originalImg.height > 0) {
        try {
            const imageData = ctx.getImageData(imgX, imgY, originalImg.width, originalImg.height);
            const data = imageData.data;
            for (let i = 0; i < data.length; i += 4) {
                const r = data[i];
                const g = data[i + 1];
                const b = data[i + 2];

                // Sepia calculation
                const tr = 0.393 * r + 0.769 * g + 0.189 * b;
                const tg = 0.349 * r + 0.686 * g + 0.168 * b;
                const tb = 0.272 * r + 0.534 * g + 0.131 * b;

                // Apply sepia blended with original based on vintageStrength
                data[i] = r * (1 - vintageStrength) + Math.min(255, tr) * vintageStrength;
                data[i + 1] = g * (1 - vintageStrength) + Math.min(255, tg) * vintageStrength;
                data[i + 2] = b * (1 - vintageStrength) + Math.min(255, tb) * vintageStrength;
            }
            ctx.putImageData(imageData, imgX, imgY);
        } catch (e) {
            console.error("Error processing image pixels for vintage effect:", e);
            // If getImageData fails (e.g. tainted canvas from cross-origin image without CORS),
            // we can't apply pixel effects. The original image will remain.
            // To mitigate, draw original image again if it was cleared or partially processed.
            ctx.drawImage(originalImg, imgX, imgY, originalImg.width, originalImg.height);
        }
    }

    // 5. Add Text
    ctx.fillStyle = primaryColor;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';

    // Headline
    // Adjust font size based on available width and textBlockHeight
    let headlineFontSize = Math.max(18, Math.min(originalImg.width / 8, textBlockHeight * 0.4));
    ctx.font = `bold ${headlineFontSize}px "${activeFontFamily}", ${mainFallbackFont}`;
    const headlineY = imgY + originalImg.height + padding * 0.5 + headlineFontSize / 2;
    ctx.fillText(headlineText.toUpperCase(), canvas.width / 2, headlineY);

    // Tagline
    let taglineFontSize = Math.max(12, Math.min(originalImg.width / 15, textBlockHeight * 0.25));
    ctx.font = `${taglineFontSize}px "${activeFontFamily}", ${mainFallbackFont}`;
    const taglineY = headlineY + headlineFontSize / 2 + padding * 0.25 + taglineFontSize / 2;
    ctx.fillText(taglineText, canvas.width / 2, taglineY);
    
    // 6. Add Border
    ctx.strokeStyle = primaryColor;
    ctx.lineWidth = borderWidth;
    ctx.strokeRect(borderWidth / 2, borderWidth / 2, canvas.width - borderWidth, canvas.height - borderWidth);
    
    // Optional: Inner border for image aesthetic
    const innerBorderWidth = Math.max(1, borderWidth / 2);
    ctx.lineWidth = innerBorderWidth;
    ctx.strokeStyle = primaryColorAlpha(primaryColor, 0.5); // Slightly transparent border
    ctx.strokeRect(imgX - innerBorderWidth, imgY - innerBorderWidth, originalImg.width + 2 * innerBorderWidth, originalImg.height + 2 * innerBorderWidth);


    // 7. Global Noise Overlay (subtle)
    if (vintageStrength > 0.1 && canvas.width > 0 && canvas.height > 0) { // Only add noise if vintage effect is somewhat strong
        try {
            const noiseAmount = 25 * vintageStrength; // Max noise pixel intensity
            const noiseImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            const noiseData = noiseImageData.data;
            for (let i = 0; i < noiseData.length; i += 4) {
                // Add monochrome noise
                const noise = (Math.random() - 0.5) * noiseAmount;
                noiseData[i] = Math.min(255, Math.max(0, noiseData[i] + noise));
                noiseData[i+1] = Math.min(255, Math.max(0, noiseData[i+1] + noise));
                noiseData[i+2] = Math.min(255, Math.max(0, noiseData[i+2] + noise));
            }
            ctx.putImageData(noiseImageData, 0, 0);
        } catch (e) {
             console.error("Error applying noise effect:", e);
             // Likely due to tainted canvas.
        }
    }

    return canvas;
}

// Helper function to add alpha to a hex color for the inner border
function primaryColorAlpha(hexColor, alpha) {
    let r = 0, g = 0, b = 0;
    if (hexColor.length == 4) { // #RGB format
        r = parseInt(hexColor[1] + hexColor[1], 16);
        g = parseInt(hexColor[2] + hexColor[2], 16);
        b = parseInt(hexColor[3] + hexColor[3], 16);
    } else if (hexColor.length == 7) { // #RRGGBB format
        r = parseInt(hexColor[1] + hexColor[2], 16);
        g = parseInt(hexColor[3] + hexColor[4], 16);
        b = parseInt(hexColor[5] + hexColor[6], 16);
    }
    return `rgba(${r},${g},${b},${alpha})`;
}

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 Vintage Advertisement Poster Generator is a tool designed to transform regular images into stylish vintage advertisement posters. Users can upload an image and customize various elements, including the headline and tagline text, font style, and color scheme. The tool applies a vintage effect to enhance the aesthetic, making it suitable for creating unique promotional materials and nostalgic artworks. Ideal for marketers, graphic designers, and anyone looking to add a vintage flair to their images, this generator helps create eye-catching graphics perfect for advertisements, social media posts, or artistic projects.

Leave a Reply

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