Please bookmark this page to avoid losing your image tool!

Free Photo Web Interface Tool

(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.
function processImage(originalImg, theme = "mac", url = "https://www.example.com", padding = 40, bgColor = "#e0e5ec", headerColor = "#f1f5f9") {
    const pad = Number(padding);
    const w = originalImg.width;
    const h = originalImg.height;
    const headerHeight = 50;
    const radius = 10;

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

    // Setting canvas dimensions adding padding and header
    canvas.width = w + pad * 2;
    canvas.height = h + headerHeight + pad * 2;

    // 1. Draw outer background
    ctx.fillStyle = String(bgColor);
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    const winX = pad;
    const winY = pad;
    const winW = w;
    const winH = h + headerHeight;

    // 2. Setup shadow for browser window
    ctx.shadowColor = 'rgba(0, 0, 0, 0.2)';
    ctx.shadowBlur = 20;
    ctx.shadowOffsetY = 10;
    ctx.shadowOffsetX = 0;

    // Main window boundary path builder
    const drawWindowPath = () => {
        ctx.beginPath();
        ctx.moveTo(winX + radius, winY);
        ctx.lineTo(winX + winW - radius, winY);
        ctx.quadraticCurveTo(winX + winW, winY, winX + winW, winY + radius);
        ctx.lineTo(winX + winW, winY + winH - radius);
        ctx.quadraticCurveTo(winX + winW, winY + winH, winX + winW - radius, winY + winH);
        ctx.lineTo(winX + radius, winY + winH);
        ctx.quadraticCurveTo(winX, winY + winH, winX, winY + winH - radius);
        ctx.lineTo(winX, winY + radius);
        ctx.quadraticCurveTo(winX, winY, winX + radius, winY);
        ctx.closePath();
    };

    // Draw main window background to apply shadow
    drawWindowPath();
    ctx.fillStyle = '#ffffff';
    ctx.fill();

    // Reset shadow for internal rendering
    ctx.shadowColor = 'transparent';
    ctx.shadowBlur = 0;
    ctx.shadowOffsetY = 0;
    ctx.shadowOffsetX = 0;

    // Clip rendering inside the browser window
    ctx.save();
    drawWindowPath();
    ctx.clip();

    // Draw internal white background (useful for transparent images)
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(winX, winY, winW, winH);

    // 3. Draw browser header
    ctx.fillStyle = String(headerColor);
    ctx.fillRect(winX, winY, winW, headerHeight);

    // Separator line underneath the header
    ctx.strokeStyle = '#e2e8f0';
    ctx.lineWidth = 1;
    ctx.beginPath();
    ctx.moveTo(winX, winY + headerHeight);
    ctx.lineTo(winX + winW, winY + headerHeight);
    ctx.stroke();

    // 4. Draw Window Controls (Mac/Windows)
    if (String(theme).toLowerCase() === 'windows') {
        // Windows style controls (Top-Right)
        ctx.strokeStyle = '#475569';
        ctx.lineWidth = 1.2;

        // Close (X)
        const closeX = winX + winW - 24;
        const btnY = winY + headerHeight / 2;
        ctx.beginPath();
        ctx.moveTo(closeX - 5, btnY - 5);
        ctx.lineTo(closeX + 5, btnY + 5);
        ctx.moveTo(closeX + 5, btnY - 5);
        ctx.lineTo(closeX - 5, btnY + 5);
        ctx.stroke();

        // Maximize (Square)
        ctx.strokeRect(winX + winW - 55, btnY - 4.5, 9, 9);

        // Minimize (Line)
        ctx.beginPath();
        ctx.moveTo(winX + winW - 85, btnY + 1);
        ctx.lineTo(winX + winW - 75, btnY + 1);
        ctx.stroke();
    } else {
        // Mac style controls (Top-Left)
        const colors = ['#FF605C', '#FFBD44', '#00CA4E'];
        colors.forEach((c, i) => {
            ctx.beginPath();
            ctx.arc(winX + 20 + i * 18, winY + headerHeight / 2, 5.5, 0, Math.PI * 2);
            ctx.fillStyle = c;
            ctx.fill();
        });
    }

    // 5. Draw URL Bar
    // Calculate URL bar width dynamically based on window width
    let urlW = winW * 0.5;
    if (urlW > 400) urlW = 400;
    if (winW - urlW < 160) urlW = Math.max(30, winW - 160);

    if (urlW > 40) {
        const urlH = 26;
        const urlX = winX + (winW - urlW) / 2;
        const urlY = winY + (headerHeight - urlH) / 2;
        const urlRadius = 4;

        // URL Box Background
        ctx.fillStyle = '#ffffff';
        ctx.beginPath();
        ctx.moveTo(urlX + urlRadius, urlY);
        ctx.lineTo(urlX + urlW - urlRadius, urlY);
        ctx.quadraticCurveTo(urlX + urlW, urlY, urlX + urlW, urlY + urlRadius);
        ctx.lineTo(urlX + urlW, urlY + urlH - urlRadius);
        ctx.quadraticCurveTo(urlX + urlW, urlY + urlH, urlX + urlW - urlRadius, urlY + urlH);
        ctx.lineTo(urlX + urlRadius, urlY + urlH);
        ctx.quadraticCurveTo(urlX, urlY + urlH, urlX, urlY + urlH - urlRadius);
        ctx.lineTo(urlX, urlY + urlRadius);
        ctx.quadraticCurveTo(urlX, urlY, urlX + urlRadius, urlY);
        ctx.closePath();
        ctx.fill();

        // URL Box Stroke
        ctx.strokeStyle = '#cbd5e1';
        ctx.lineWidth = 1;
        ctx.stroke();

        // Lock Icon
        if (urlW > 100) {
            ctx.strokeStyle = '#64748b';
            ctx.lineWidth = 1.2;
            const lockX = urlX + 16;
            const lockY = urlY + urlH / 2 + 2;
            ctx.strokeRect(lockX - 4, lockY - 2.5, 8, 5.5);
            ctx.beginPath();
            ctx.arc(lockX, lockY - 2.5, 2.5, Math.PI, 0);
            ctx.stroke();
        }

        // URL Text Mapping
        ctx.fillStyle = '#475569';
        ctx.font = '12px "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, sans-serif';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        
        // Overflow and string truncation check
        let displayUrl = String(url);
        let textMaxW = urlW - 40;
        let pUrl = displayUrl;
        
        while(ctx.measureText(pUrl).width > textMaxW && pUrl.length > 3) {
            pUrl = pUrl.slice(0, -1);
        }
        if(pUrl !== displayUrl) pUrl += '...';

        const textOffsetX = urlW > 100 ? 5 : 0;
        ctx.fillText(pUrl, urlX + urlW / 2 + textOffsetX, urlY + urlH / 2 + 1);
    }

    // 6. Draw original photo
    ctx.drawImage(originalImg, winX, winY + headerHeight, w, h);

    // End Clipping
    ctx.restore();

    // 7. Add a subtle border overlay to crisp the edges of the window
    drawWindowPath();
    ctx.strokeStyle = 'rgba(0, 0, 0, 0.1)';
    ctx.lineWidth = 1;
    ctx.stroke();

    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

This tool allows you to wrap your images within a stylized web browser interface. It can transform a standard photo into a professional-looking screenshot mockup, featuring customizable themes such as macOS or Windows-style window controls, a URL bar, and adjustable padding and background colors. This is ideal for designers and marketers who want to present website screenshots, digital products, or portfolio pieces in a clean, realistic browser frame for social media, presentations, or website mockups.

Leave a Reply

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