You can edit the below JavaScript code to customize the image tool.
Apply Changes
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;
}
Apply Changes