Please bookmark this page to avoid losing your image tool!

Photo Performance Showcase

(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, title = 'The Grand Showcase', subtitle = 'A Masterpiece Unveiled', curtainColor = '#8B0000', spotlightIntensity = 0.7, fontName = 'Playfair Display') {
    /**
     * Dynamically loads a Google Font into the document.
     * @param {string} font - The name of the font to load.
     * @returns {Promise<void>}
     */
    const loadFont = async (font) => {
        const fontId = `google-font-${font.replace(/\s/g, '-')}`;
        if (document.getElementById(fontId)) {
            return; // Font already requested
        }
        try {
            const fontUrl = `https://fonts.googleapis.com/css2?family=${font.replace(/ /g, '+')}:wght@400;700&display=swap`;
            const link = document.createElement('link');
            link.id = fontId;
            link.href = fontUrl;
            link.rel = 'stylesheet';
            document.head.appendChild(link);
            // Wait for the font to be ready to use
            await document.fonts.load(`12px "${font}"`);
        } catch (e) {
            console.error(`Could not load font: ${font}`, e);
            throw e; // Rethrow to be caught by the caller
        }
    };

    let effectiveFont = fontName;
    try {
        await loadFont(fontName);
    } catch (e) {
        console.warn(`Falling back to serif font as '${fontName}' could not be loaded.`);
        effectiveFont = 'serif'; // Set a web-safe fallback font
    }

    // 1. Canvas Setup and Sizing
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    const sceneAspectRatio = 16 / 9;
    const sceneWidth = Math.max(800, originalImg.width * 1.5);
    const sceneHeight = sceneWidth / sceneAspectRatio;
    canvas.width = sceneWidth;
    canvas.height = sceneHeight;

    // Calculate the display size for the image to fit nicely on the stage
    const stageAreaWidth = sceneWidth * 0.5;
    const stageAreaHeight = sceneHeight * 0.55;
    let displayW, displayH;

    if (originalImg.width / originalImg.height > stageAreaWidth / stageAreaHeight) {
        displayW = stageAreaWidth;
        displayH = displayW * (originalImg.height / originalImg.width);
    } else {
        displayH = stageAreaHeight;
        displayW = displayH * (originalImg.width / originalImg.height);
    }

    const imgX = (canvas.width - displayW) / 2;
    const imgY = canvas.height * 0.25;
    const floorLevel = imgY + displayH + (canvas.height * 0.05);

    // 2. Draw Stage Background
    // Dark theater backdrop
    const backdropGrad = ctx.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
    backdropGrad.addColorStop(0, '#3a3a4e');
    backdropGrad.addColorStop(1, '#1a1a2a');
    ctx.fillStyle = backdropGrad;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Wooden stage floor with perspective
    ctx.fillStyle = '#4a2a1a';
    ctx.beginPath();
    ctx.moveTo(0, floorLevel);
    ctx.lineTo(canvas.width, floorLevel);
    ctx.lineTo(canvas.width * 1.2, canvas.height);
    ctx.lineTo(canvas.width * -0.2, canvas.height);
    ctx.closePath();
    ctx.fill();

    // 3. Draw Image with Shadow and Frame
    ctx.save();
    ctx.shadowColor = 'rgba(0, 0, 0, 0.8)';
    ctx.shadowBlur = Math.min(displayW, displayH) * 0.1;
    ctx.shadowOffsetY = canvas.height * 0.02;

    // Simple black frame
    const frameSize = Math.min(displayW, displayH) * 0.03;
    ctx.fillStyle = '#111111';
    ctx.fillRect(imgX - frameSize, imgY - frameSize, displayW + 2 * frameSize, displayH + 2 * frameSize);
    ctx.restore();

    // Draw the main image
    ctx.drawImage(originalImg, imgX, imgY, displayW, displayH);

    // 4. Draw Stage Curtains
    const drawCurtain = (isRightSide) => {
        const x = isRightSide ? canvas.width : 0;
        const dir = isRightSide ? -1 : 1;
        const width = canvas.width * 0.22;

        ctx.beginPath();
        ctx.moveTo(x, 0);
        ctx.lineTo(x + dir * width * 0.7, 0);
        ctx.quadraticCurveTo(x + dir * width * 1.5, canvas.height / 2, x + dir * width * 0.6, canvas.height);
        ctx.lineTo(x, canvas.height);
        ctx.closePath();
        
        ctx.fillStyle = curtainColor;
        ctx.fill();

        // Add shading for depth
        const shadeGrad = ctx.createLinearGradient(x, 0, x + dir * width, 0);
        shadeGrad.addColorStop(0, 'rgba(0,0,0,0.6)');
        shadeGrad.addColorStop(0.5, 'rgba(255,255,255,0.1)');
        shadeGrad.addColorStop(1, 'rgba(0,0,0,0.4)');
        ctx.fillStyle = shadeGrad;
        ctx.fill();
    };
    
    // Top valance (curtain banner)
    const valanceHeight = canvas.height * 0.1;
    ctx.fillStyle = curtainColor;
    ctx.fillRect(0, 0, canvas.width, valanceHeight);
    const valanceShade = ctx.createLinearGradient(0, 0, 0, valanceHeight * 1.5);
    valanceShade.addColorStop(0, 'rgba(0,0,0,0.6)');
    valanceShade.addColorStop(1, 'rgba(0,0,0,0)');
    ctx.fillStyle = valanceShade;
    ctx.fillRect(0, 0, canvas.width, valanceHeight * 1.5);

    // Side curtains
    drawCurtain(false); // Left
    drawCurtain(true); // Right

    // 5. Draw Spotlight Vignette
    const safeIntensity = Math.max(0, Math.min(1, 1 - spotlightIntensity));
    const centerX = canvas.width / 2;
    const centerY = imgY + displayH / 2;
    const vignette = ctx.createRadialGradient(centerX, centerY, displayW * 0.3, centerX, centerY, canvas.width * 0.8);
    vignette.addColorStop(0, 'rgba(0,0,0,0)');
    vignette.addColorStop(1, `rgba(0,0,0,${safeIntensity})`);
    ctx.fillStyle = vignette;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // 6. Draw Text
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.shadowColor = 'rgba(0,0,0,0.9)';
    ctx.shadowBlur = 10;

    // Title text
    const titleSize = Math.round(canvas.height * 0.06);
    ctx.font = `700 ${titleSize}px "${effectiveFont}", serif`;
    ctx.fillStyle = '#eaeaea';
    ctx.fillText(title, canvas.width / 2, valanceHeight / 2 + titleSize * 0.1);

    // Subtitle text
    const subtitleSize = Math.round(canvas.height * 0.025);
    ctx.font = `400 ${subtitleSize}px "${effectiveFont}", serif`;
    ctx.fillStyle = '#cccccc';
    const subtitleY = floorLevel + (canvas.height - floorLevel) / 2;
    ctx.fillText(subtitle, canvas.width / 2, subtitleY);

    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

Photo Performance Showcase is a creative tool that allows users to present their images in a visually appealing stage-like environment. It enhances photographs by adding dynamic backgrounds, spotlight effects, curtains, and stylish text options, making it ideal for showcasing artwork, photography, or meaningful memories. This tool can be particularly useful for artists, photographers, teachers, or anyone looking to create visually captivating displays for personal or social media use.

Leave a Reply

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