You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, tvColor = '#2c3e50', screenBgColor = '#1a1a1a', buttonColor = '#ecf0f1', antennaColor = '#95a5a6') {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Set fixed icon size (square aspect ratio works best for icons)
const size = 512;
canvas.width = size;
canvas.height = size;
// Clear background to be fully transparent
ctx.clearRect(0, 0, size, size);
// Context helper function to draw rounded rectangles
function drawRoundRect(ctx, x, y, width, height, radius, fill, stroke) {
if (typeof stroke === 'undefined') {
stroke = false;
}
if (typeof radius === 'undefined') {
radius = 5;
}
if (typeof radius === 'number') {
radius = {tl: radius, tr: radius, br: radius, bl: radius};
}
ctx.beginPath();
ctx.moveTo(x + radius.tl, y);
ctx.lineTo(x + width - radius.tr, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr);
ctx.lineTo(x + width, y + height - radius.br);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height);
ctx.lineTo(x + radius.bl, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl);
ctx.lineTo(x, y + radius.tl);
ctx.quadraticCurveTo(x, y, x + radius.tl, y);
ctx.closePath();
if (fill) {
ctx.fill();
}
if (stroke) {
ctx.stroke();
}
}
// 1. Draw Antennas
ctx.lineWidth = 8;
ctx.strokeStyle = antennaColor;
ctx.lineCap = 'round';
const antBaseX = size / 2;
const antBaseY = 120;
// Left Antenna line
ctx.beginPath();
ctx.moveTo(antBaseX, antBaseY);
ctx.lineTo(160, 40);
ctx.stroke();
// Right Antenna line
ctx.beginPath();
ctx.moveTo(antBaseX, antBaseY);
ctx.lineTo(352, 40);
ctx.stroke();
// Antenna Balls
ctx.fillStyle = antennaColor;
ctx.beginPath();
ctx.arc(160, 40, 12, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.arc(352, 40, 12, 0, Math.PI * 2);
ctx.fill();
// Antenna Base (small bump on the top of TV)
ctx.fillStyle = tvColor;
ctx.beginPath();
ctx.ellipse(antBaseX, antBaseY - 5, 45, 12, 0, 0, Math.PI * 2);
ctx.fill();
// 2. Draw TV Body
const tvX = 40;
const tvY = 100;
const tvW = 432;
const tvH = 312;
const tvRadius = 30;
// Add a shadow to the TV body for a 3D effect
ctx.shadowColor = 'rgba(0, 0, 0, 0.4)';
ctx.shadowBlur = 20;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 15;
ctx.fillStyle = tvColor;
drawRoundRect(ctx, tvX, tvY, tvW, tvH, tvRadius, true, false);
// Reset shadow for the rest of the elements
ctx.shadowColor = 'transparent';
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
// TV body inner stroke (subtle highlight/depth)
ctx.lineWidth = 4;
ctx.strokeStyle = 'rgba(255, 255, 255, 0.15)';
drawRoundRect(ctx, tvX + 3, tvY + 3, tvW - 6, tvH - 6, tvRadius - 2, false, true);
ctx.strokeStyle = 'rgba(0, 0, 0, 0.3)';
drawRoundRect(ctx, tvX, tvY, tvW, tvH, tvRadius, false, true);
// 3. Draw Screen Bezel
const screenX = 64;
const screenY = 124;
const screenW = 296;
const screenH = 264;
const screenRadius = 20;
// Dark inset behind screen
ctx.fillStyle = '#111111';
drawRoundRect(ctx, screenX - 6, screenY - 6, screenW + 12, screenH + 12, screenRadius + 4, true, false);
// Screen base color (visible if image has transparency)
ctx.fillStyle = screenBgColor;
drawRoundRect(ctx, screenX, screenY, screenW, screenH, screenRadius, true, false);
// 4. Draw the User Image inside the Screen area
ctx.save();
// Create a clipping path for the screen limits
drawRoundRect(ctx, screenX, screenY, screenW, screenH, screenRadius, false, false);
ctx.clip();
// Calculate aspect ratios for 'object-fit: cover' logic
const imgRatio = originalImg.width / originalImg.height;
const screenRatio = screenW / screenH;
let drawW, drawH, drawX, drawY;
if (imgRatio > screenRatio) {
drawH = screenH;
drawW = originalImg.width * (screenH / originalImg.height);
drawX = screenX + (screenW - drawW) / 2;
drawY = screenY;
} else {
drawW = screenW;
drawH = originalImg.height * (screenW / originalImg.width);
drawX = screenX;
drawY = screenY + (screenH - drawH) / 2;
}
// Draw the scaled and positioned image
ctx.drawImage(originalImg, drawX, drawY, drawW, drawH);
// Glass Reflection effect over the image
ctx.fillStyle = 'rgba(255, 255, 255, 0.12)';
ctx.beginPath();
ctx.moveTo(screenX, screenY + screenRadius);
ctx.lineTo(screenX + screenW * 0.55, screenY);
ctx.lineTo(screenX + screenW, screenY);
ctx.lineTo(screenX + screenW, screenY + screenH * 0.8);
ctx.closePath();
ctx.fill();
// Curved vignette shadow overlay
const gradient = ctx.createRadialGradient(
screenX + screenW / 2, screenY + screenH / 2, screenH * 0.25,
screenX + screenW / 2, screenY + screenH / 2, screenH * 0.85
);
gradient.addColorStop(0, 'rgba(0,0,0,0)');
gradient.addColorStop(1, 'rgba(0,0,0,0.6)');
ctx.fillStyle = gradient;
ctx.fillRect(screenX, screenY, screenW, screenH);
ctx.restore();
// 5. Draw Control Panel (Right Side of TV)
const panelX = 390;
const dialCenterY1 = 166;
const dialCenterY2 = 236;
ctx.fillStyle = buttonColor;
ctx.strokeStyle = 'rgba(0, 0, 0, 0.5)';
ctx.lineWidth = 2;
// Dial 1 (Top)
ctx.beginPath();
ctx.arc(panelX + 30, dialCenterY1, 24, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();
ctx.fillStyle = '#dbdbdb'; // Inner dial
ctx.beginPath();
ctx.arc(panelX + 30, dialCenterY1, 16, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();
// Marker for Dial 1
ctx.fillStyle = '#e74c3c';
ctx.beginPath();
ctx.arc(panelX + 30 + 10 * Math.cos(Math.PI/3), dialCenterY1 - 10 * Math.sin(Math.PI/3), 4, 0, Math.PI * 2);
ctx.fill();
// Dial 2 (Bottom)
ctx.fillStyle = buttonColor;
ctx.beginPath();
ctx.arc(panelX + 30, dialCenterY2, 24, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();
ctx.fillStyle = '#dbdbdb'; // Inner dial
ctx.beginPath();
ctx.arc(panelX + 30, dialCenterY2, 16, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();
// Marker for Dial 2
ctx.fillStyle = '#3498db';
ctx.beginPath();
ctx.arc(panelX + 30 - 10 * Math.cos(Math.PI/4), dialCenterY2 - 10 * Math.sin(Math.PI/4), 4, 0, Math.PI * 2);
ctx.fill();
// Speaker Grill Slots
const grillYStart = 296;
ctx.lineWidth = 6;
ctx.lineCap = 'round';
ctx.strokeStyle = '#1a1a1a';
for (let i = 0; i < 5; i++) {
ctx.beginPath();
ctx.moveTo(panelX + 12, grillYStart + i * 14);
ctx.lineTo(panelX + 48, grillYStart + i * 14);
ctx.stroke();
}
// 6. Draw TV Bottom Legs
const legY = tvY + tvH - 4; // Start slightly inside the bottom edge
ctx.fillStyle = '#222222';
ctx.strokeStyle = '#000000';
ctx.lineWidth = 2;
// Left Leg
ctx.beginPath();
ctx.moveTo(100, legY);
ctx.lineTo(124, legY);
ctx.lineTo(134, legY + 22);
ctx.lineTo(90, legY + 22);
ctx.closePath();
ctx.fill();
ctx.stroke();
// Right Leg
ctx.beginPath();
ctx.moveTo(412, legY);
ctx.lineTo(388, legY);
ctx.lineTo(378, legY + 22);
ctx.lineTo(422, legY + 22);
ctx.closePath();
ctx.fill();
ctx.stroke();
return canvas;
}
Apply Changes