You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, tvColor = '#D3A068', bezelColor = '#333333', detailsColor = '#EEEEEE') {
const canvas = document.createElement('canvas');
// Define a base virtual size for the icon design
const baseSize = 512;
// Make the actual output size depend on the user's image resolution (minimum 512px)
const size = Math.max(originalImg.width, originalImg.height, baseSize);
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext('2d');
// Smooth scaled drawing
ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = 'high';
// Apply scaling to draw identically to our visual vector coordinates
const s = size / baseSize;
ctx.scale(s, s);
function roundRectPath(ctx, x, y, width, height, radius) {
if (typeof radius === 'undefined') radius = 5;
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
}
function roundRect(ctx, x, y, width, height, radius, fill, stroke) {
roundRectPath(ctx, x, y, width, height, radius);
if (fill) ctx.fill();
if (stroke) ctx.stroke();
}
// 1. TV Leg Shadows
ctx.fillStyle = 'rgba(0,0,0,0.15)';
ctx.beginPath(); ctx.moveTo(76, 456); ctx.lineTo(116, 456); ctx.lineTo(96, 496); ctx.lineTo(66, 496); ctx.closePath(); ctx.fill();
ctx.beginPath(); ctx.moveTo(448, 456); ctx.lineTo(408, 456); ctx.lineTo(428, 496); ctx.lineTo(458, 496); ctx.closePath(); ctx.fill();
// 2. TV Legs
ctx.fillStyle = '#1A1A1A';
ctx.strokeStyle = '#1A1A1A';
ctx.lineWidth = 6;
ctx.beginPath(); ctx.moveTo(70, 450); ctx.lineTo(110, 450); ctx.lineTo(90, 490); ctx.lineTo(60, 490); ctx.closePath(); ctx.fill(); ctx.stroke();
ctx.beginPath(); ctx.moveTo(442, 450); ctx.lineTo(402, 450); ctx.lineTo(422, 490); ctx.lineTo(452, 490); ctx.closePath(); ctx.fill(); ctx.stroke();
// Leg Highlights
ctx.strokeStyle = '#666666'; ctx.lineWidth = 2;
ctx.beginPath(); ctx.moveTo(68, 454); ctx.lineTo(60, 488); ctx.stroke();
ctx.beginPath(); ctx.moveTo(402, 454); ctx.lineTo(420, 488); ctx.stroke();
// 3. Antenna Rods Outline & Fill
ctx.lineWidth = 12;
ctx.strokeStyle = '#1A1A1A';
ctx.lineCap = 'round';
ctx.beginPath(); ctx.moveTo(240, 70); ctx.lineTo(130, 20); ctx.stroke();
ctx.beginPath(); ctx.moveTo(272, 70); ctx.lineTo(400, 25); ctx.stroke();
ctx.lineWidth = 6;
ctx.strokeStyle = detailsColor;
ctx.beginPath(); ctx.moveTo(240, 70); ctx.lineTo(130, 20); ctx.stroke();
ctx.beginPath(); ctx.moveTo(272, 70); ctx.lineTo(400, 25); ctx.stroke();
ctx.lineCap = 'butt';
// 4. Antenna Mount Base
ctx.fillStyle = detailsColor;
ctx.lineWidth = 6;
ctx.strokeStyle = '#1A1A1A';
ctx.beginPath(); ctx.arc(256, 80, 30, Math.PI, 0); ctx.closePath(); ctx.fill(); ctx.stroke();
ctx.strokeStyle = 'rgba(255,255,255,0.4)';
ctx.lineWidth = 3;
ctx.beginPath(); ctx.arc(256, 80, 22, Math.PI * 1.05, Math.PI * 1.95); ctx.stroke();
// 5. Main TV Body Shadow
ctx.fillStyle = 'rgba(0,0,0,0.15)';
roundRect(ctx, 36, 86, 452, 380, 24, true, false);
// 6. Main TV Body
ctx.fillStyle = tvColor;
ctx.lineWidth = 6;
ctx.strokeStyle = '#1A1A1A';
roundRect(ctx, 30, 80, 452, 380, 24, true, true);
// Top edge highlight vector
ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)';
ctx.lineWidth = 4;
ctx.beginPath(); ctx.moveTo(38, 120); ctx.quadraticCurveTo(38, 88, 57, 88);
ctx.lineTo(455, 88); ctx.quadraticCurveTo(474, 88, 474, 120); ctx.stroke();
// 7. Outer Screen Bezel
ctx.fillStyle = bezelColor;
ctx.lineWidth = 6;
ctx.strokeStyle = '#1A1A1A';
roundRect(ctx, 50, 100, 320, 340, 20, true, true);
ctx.strokeStyle = 'rgba(255, 255, 255, 0.15)';
ctx.lineWidth = 3;
ctx.beginPath(); ctx.moveTo(56, 130); ctx.quadraticCurveTo(56, 106, 71, 106);
ctx.lineTo(349, 106); ctx.quadraticCurveTo(364, 106, 364, 130); ctx.stroke();
// 8. Screen Inner Container (CRT logic)
ctx.save();
roundRectPath(ctx, 60, 110, 300, 320, 12);
ctx.clip(); // Mask content inner to curved area
ctx.fillStyle = '#000000'; // Black backdrop
ctx.fillRect(60, 110, 300, 320);
// Object-fit Cover calculations for originalImg proportions
const imgRatio = originalImg.width / originalImg.height;
const screenRatio = 300 / 320;
let drawW = 300, drawH = 320, drawX = 60, drawY = 110;
if (imgRatio > screenRatio) {
drawH = 320;
drawW = drawH * imgRatio;
drawX = 60 - (drawW - 300) / 2;
} else {
drawW = 300;
drawH = drawW / imgRatio;
drawY = 110 - (drawH - 320) / 2;
}
ctx.drawImage(originalImg, drawX, drawY, drawW, drawH);
// Inner CRT Border Fake Depth
const grad = ctx.createRadialGradient(210, 270, 100, 210, 270, 220);
grad.addColorStop(0, 'rgba(0,0,0,0)');
grad.addColorStop(1, 'rgba(0,0,0,0.6)');
ctx.fillStyle = grad;
ctx.fillRect(60, 110, 300, 320);
// Swooping TV Glass Curved Glare
ctx.fillStyle = 'rgba(255,255,255,0.12)';
ctx.beginPath(); ctx.moveTo(60, 110); ctx.lineTo(260, 110);
ctx.bezierCurveTo(250, 200, 190, 300, 60, 280); ctx.closePath(); ctx.fill();
ctx.restore();
// Inner screen line border
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(0,0,0,0.8)';
roundRect(ctx, 60, 110, 300, 320, 12, false, true);
// 9. Side Control Panel Components
// Big Dial (Channel)
ctx.fillStyle = detailsColor; ctx.lineWidth = 4; ctx.strokeStyle = '#1A1A1A';
ctx.beginPath(); ctx.arc(425, 140, 28, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
ctx.strokeStyle = 'rgba(255,255,255,0.6)'; ctx.lineWidth = 3;
ctx.beginPath(); ctx.arc(425, 140, 22, Math.PI * 1.1, Math.PI * 1.8); ctx.stroke();
ctx.fillStyle = '#999999'; ctx.strokeStyle = '#1A1A1A';
ctx.beginPath(); ctx.arc(425, 140, 16, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
ctx.lineWidth = 4; ctx.beginPath(); ctx.moveTo(425, 140); ctx.lineTo(413, 128); ctx.stroke();
// Small Dial (Volume)
ctx.fillStyle = detailsColor; ctx.lineWidth = 4; ctx.strokeStyle = '#1A1A1A';
ctx.beginPath(); ctx.arc(425, 220, 20, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
ctx.strokeStyle = 'rgba(255,255,255,0.6)'; ctx.lineWidth = 2;
ctx.beginPath(); ctx.arc(425, 220, 16, Math.PI * 1.1, Math.PI * 1.8); ctx.stroke();
ctx.fillStyle = '#999999'; ctx.strokeStyle = '#1A1A1A';
ctx.beginPath(); ctx.arc(425, 220, 10, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
ctx.lineWidth = 3; ctx.beginPath(); ctx.moveTo(425, 220); ctx.lineTo(434, 211); ctx.stroke();
// Status LED Box Light
ctx.fillStyle = '#FF3333';
ctx.beginPath(); ctx.arc(425, 252, 4, 0, Math.PI * 2); ctx.fill();
const ledGlow = ctx.createRadialGradient(425, 252, 0, 425, 252, 10);
ledGlow.addColorStop(0, 'rgba(255, 51, 51, 0.8)');
ledGlow.addColorStop(1, 'rgba(255, 51, 51, 0)');
ctx.fillStyle = ledGlow;
ctx.beginPath(); ctx.arc(425, 252, 10, 0, Math.PI * 2); ctx.fill();
// Setting Switches Bottom Right
ctx.fillStyle = detailsColor; ctx.lineWidth = 4; ctx.strokeStyle = '#1A1A1A';
roundRect(ctx, 400, 275, 50, 16, 6, true, true);
roundRect(ctx, 400, 305, 50, 16, 6, true, true);
ctx.strokeStyle = 'rgba(255,255,255,0.5)'; ctx.lineWidth = 2;
ctx.beginPath(); ctx.moveTo(406, 279); ctx.lineTo(444, 279); ctx.stroke();
ctx.beginPath(); ctx.moveTo(406, 309); ctx.lineTo(444, 309); ctx.stroke();
// 10. Speaker Grills Lines
ctx.fillStyle = '#1A1A1A';
for(let i = 0; i < 5; i++) {
roundRect(ctx, 395, 350 + i * 16, 60, 6, 3, true, false);
}
return canvas;
}
Apply Changes