Please bookmark this page to avoid losing your image tool!

Television Icon 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.
function processImage(originalImg, iconSize = 512, casingColor = "#D9381E", screenBorderColor = "#222222", knobColor = "#E0E0E0") {
    // Validate and parse parameters
    iconSize = parseInt(iconSize) || 512;
    
    // Create canvas
    const canvas = document.createElement("canvas");
    canvas.width = iconSize;
    canvas.height = iconSize;
    const ctx = canvas.getContext("2d");

    // Helper function to draw rounded rectangles
    function drawRoundRect(x, y, w, h, r, fill, stroke, strokeWidth) {
        ctx.beginPath();
        ctx.moveTo(x + r, y);
        ctx.lineTo(x + w - r, y);
        ctx.arcTo(x + w, y, x + w, y + h, r);
        ctx.lineTo(x + w, y + h - r);
        ctx.arcTo(x + w, y + h, x + w - r, y + h, r);
        ctx.lineTo(x + r, y + h);
        ctx.arcTo(x, y + h, x, y + h - r, r);
        ctx.lineTo(x, y + r);
        ctx.arcTo(x, y, x + r, y, r);
        ctx.closePath();
        if (fill) {
            ctx.fillStyle = fill;
            ctx.fill();
        }
        if (stroke) {
            ctx.lineWidth = strokeWidth;
            ctx.strokeStyle = stroke;
            ctx.stroke();
        }
    }

    // Calculations based on icon scale
    const S = iconSize;
    const bodyW = S * 0.8;
    const bodyH = S * 0.6;
    const bodyX = (S - bodyW) / 2;
    const bodyY = (S - bodyH) / 2 + S * 0.08; 

    // === DRAW ANTENNA ===
    const antBaseX = S / 2;
    const antBaseY = bodyY;
    const antLeftX = S * 0.35;
    const antLeftY = bodyY - S * 0.15;
    const antRightX = S * 0.7;
    const antRightY = bodyY - S * 0.2;

    ctx.lineWidth = S * 0.015;
    ctx.lineCap = "round";
    ctx.strokeStyle = screenBorderColor;

    ctx.beginPath();
    ctx.moveTo(antBaseX, antBaseY);
    ctx.lineTo(antLeftX, antLeftY);
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(antBaseX, antBaseY);
    ctx.lineTo(antRightX, antRightY);
    ctx.stroke();

    // Antenna tips
    ctx.fillStyle = screenBorderColor;
    ctx.beginPath();
    ctx.arc(antLeftX, antLeftY, S * 0.02, 0, Math.PI * 2);
    ctx.fill();
    ctx.beginPath();
    ctx.arc(antRightX, antRightY, S * 0.02, 0, Math.PI * 2);
    ctx.fill();

    // === DRAW FEET (STAND) ===
    ctx.lineWidth = S * 0.025;
    
    // Left foot
    ctx.beginPath();
    ctx.moveTo(bodyX + S * 0.15, bodyY + bodyH - S * 0.02);
    ctx.lineTo(bodyX + S * 0.05, bodyY + bodyH + S * 0.1);
    ctx.stroke();

    // Right foot
    ctx.beginPath();
    ctx.moveTo(bodyX + bodyW - S * 0.15, bodyY + bodyH - S * 0.02);
    ctx.lineTo(bodyX + bodyW - S * 0.05, bodyY + bodyH + S * 0.1);
    ctx.stroke();

    // === DRAW TV CASING ===
    const radius = S * 0.05;
    drawRoundRect(bodyX, bodyY, bodyW, bodyH, radius, casingColor, screenBorderColor, S * 0.015);

    // Coordinate prep for inner elements
    const screenX = bodyX + S * 0.04;
    const screenY = bodyY + S * 0.04;
    const screenH = bodyH - S * 0.08;
    const panelW = S * 0.16;
    const screenW = bodyW - S * 0.08 - panelW - S * 0.02;
    const panelX = screenX + screenW + S * 0.02;

    // === DRAW CONTROL PANEL ===
    // Dials
    const dialR = panelW * 0.3;
    const dialX = panelX + panelW / 2;
    const dialY1 = screenY + S * 0.05 + dialR;
    const dialY2 = dialY1 + dialR * 2.8;

    [dialY1, dialY2].forEach((y, index) => {
        // Knob base
        ctx.beginPath();
        ctx.arc(dialX, y, dialR, 0, Math.PI * 2);
        ctx.fillStyle = screenBorderColor;
        ctx.fill();
        // Knob top
        ctx.beginPath();
        ctx.arc(dialX, y, dialR * 0.75, 0, Math.PI * 2);
        ctx.fillStyle = knobColor;
        ctx.fill();
        // Knob indicator (varying angles)
        const angle = index === 0 ? -Math.PI / 4 : Math.PI / 2;
        ctx.beginPath();
        ctx.moveTo(dialX, y);
        ctx.lineTo(dialX + Math.cos(angle) * dialR * 0.5, y + Math.sin(angle) * dialR * 0.5);
        ctx.strokeStyle = screenBorderColor;
        ctx.lineWidth = S * 0.01;
        ctx.stroke();
    });

    // Speaker Grills
    const grillY = dialY2 + S * 0.08;
    const grillH = screenH - (grillY - screenY) - S * 0.02;
    const grillW = panelW * 0.7;
    const grillX = panelX + (panelW - grillW) / 2;

    ctx.fillStyle = screenBorderColor;
    const lines = 6;
    for (let i = 0; i < lines; i++) {
        const lineY = grillY + (grillH / lines) * i;
        drawRoundRect(grillX, lineY, grillW, S * 0.01, S * 0.005, screenBorderColor, null, 0);
    }

    // === DRAW SCREEN BEZEL ===
    drawRoundRect(screenX, screenY, screenW, screenH, radius, screenBorderColor, null, 0);

    // === DRAW ACTUAL SCREEN IMAGE ===
    const innerScreenX = screenX + S * 0.025;
    const innerScreenY = screenY + S * 0.025;
    const innerScreenW = screenW - S * 0.05;
    const innerScreenH = screenH - S * 0.05;
    const innerRadius = radius * 0.7;

    ctx.save();
    // Path for clipping the screen contents
    drawRoundRect(innerScreenX, innerScreenY, innerScreenW, innerScreenH, innerRadius, "#000", null, 0);
    ctx.clip(); 

    // Compute object-fit: cover for the original image
    const imgRatio = originalImg.width / originalImg.height;
    const scnRatio = innerScreenW / innerScreenH;

    let drawW = innerScreenW;
    let drawH = innerScreenH;
    let drawX = innerScreenX;
    let drawY = innerScreenY;

    if (imgRatio > scnRatio) {
        drawW = innerScreenH * imgRatio;
        drawX = innerScreenX - (drawW - innerScreenW) / 2;
    } else {
        drawH = innerScreenW / imgRatio;
        drawY = innerScreenY - (drawH - innerScreenH) / 2;
    }

    ctx.drawImage(originalImg, drawX, drawY, drawW, drawH);

    // Add retro CRT scanlines overlay
    ctx.fillStyle = "rgba(0, 0, 0, 0.15)";
    for (let y = innerScreenY; y < innerScreenY + innerScreenH; y += S * 0.01) {
        ctx.fillRect(innerScreenX, y, innerScreenW, S * 0.004);
    }

    // Add CRT screen glass reflection
    ctx.beginPath();
    ctx.moveTo(innerScreenX - S * 0.2, innerScreenY - S * 0.2);
    ctx.lineTo(innerScreenX + innerScreenW * 0.65, innerScreenY - S * 0.2);
    ctx.lineTo(innerScreenX - S * 0.2, innerScreenY + innerScreenH + S * 0.2);
    ctx.closePath();
    ctx.fillStyle = "rgba(255, 255, 255, 0.12)";
    ctx.fill();

    // Add inner shadow/vignette to screen edge
    const gradient = ctx.createRadialGradient(
        innerScreenX + innerScreenW / 2, innerScreenY + innerScreenH / 2, Math.max(innerScreenW, innerScreenH) * 0.3,
        innerScreenX + innerScreenW / 2, innerScreenY + innerScreenH / 2, Math.max(innerScreenW, innerScreenH) * 0.7
    );
    gradient.addColorStop(0, "rgba(0,0,0,0)");
    gradient.addColorStop(1, "rgba(0,0,0,0.6)");
    ctx.fillStyle = gradient;
    ctx.fillRect(innerScreenX, innerScreenY, innerScreenW, innerScreenH);

    ctx.restore(); // Remove screen clipping

    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 Television Icon Generator allows you to transform any image into a stylized retro television icon. The tool wraps your uploaded image within a classic CRT-style television casing, complete with features like antennas, control knobs, speaker grills, and a stand. It also applies artistic effects such as scanlines and glass reflections to enhance the vintage aesthetic. This tool is ideal for graphic designers creating retro-themed content, web developers looking for unique UI elements, or anyone wanting to add a nostalgic touch to their digital photos and social media assets.

Leave a Reply

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