You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, gameTitle = "Jaguar Karts") {
/**
* Dynamically loads a font from Google Fonts.
* @param {string} family The font-family name.
* @param {string} url The URL to the font file.
* @returns {Promise<void>} A promise that resolves when the font is loaded.
*/
const loadFont = async (family, url) => {
const font = new FontFace(family, `url(${url})`);
try {
await font.load();
document.fonts.add(font);
} catch (e) {
console.error(`Font ${family} failed to load:`, e);
}
};
// Load the classic "Press Start 2P" font for a retro gaming feel.
await loadFont('Press Start 2P', 'https://fonts.gstatic.com/s/pressstart2p/v15/e3t4euO8T-267oIAQAu6jDQyK3nVivM.woff2');
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 1000;
canvas.height = 850;
// --- Helper function for rounded rectangles ---
const drawRoundRect = (ctx, x, y, w, h, r) => {
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x + w, y, x + w, y + h, r);
ctx.arcTo(x + w, y + h, x, y + h, r);
ctx.arcTo(x, y + h, x, y, r);
ctx.arcTo(x, y, x + w, y, r);
ctx.closePath();
};
// --- Colors & Constants ---
const JAGUAR_RED = '#d42127';
const CONSOLE_BLACK = '#1c1c1c';
const CONSOLE_GRAY = '#2d2d2d';
const TV_BEZEL = '#353535';
const TV_SCREEN_BG = '#080808';
// --- Layout Constants ---
const tvWidth = 720, tvHeight = 560;
const tvX = (canvas.width - tvWidth) / 2, tvY = 50;
const screenWidth = 640, screenHeight = 480;
const screenX = tvX + (tvWidth - screenWidth) / 2;
const screenY = tvY + (tvHeight - screenHeight) / 2;
const consoleWidth = 900, consoleHeight = 110;
const consoleX = (canvas.width - consoleWidth) / 2, consoleY = tvY + tvHeight + 20;
// 1. Draw Background (Tabletop)
const bgGrad = ctx.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, 700);
bgGrad.addColorStop(0, '#555');
bgGrad.addColorStop(1, '#222');
ctx.fillStyle = bgGrad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 2. Draw CRT TV
ctx.save();
ctx.shadowColor = 'rgba(0,0,0,0.7)';
ctx.shadowBlur = 40;
ctx.shadowOffsetY = 25;
// TV Bezel
ctx.fillStyle = TV_BEZEL;
drawRoundRect(ctx, tvX, tvY, tvWidth, tvHeight, 30);
ctx.fill();
ctx.restore();
// TV Screen Bevel Effect
const tvGrad = ctx.createLinearGradient(tvX, tvY, tvX + tvWidth, tvY + tvHeight);
tvGrad.addColorStop(0, 'rgba(255,255,255,0.1)');
tvGrad.addColorStop(1, 'rgba(0,0,0,0.2)');
ctx.strokeStyle = tvGrad;
ctx.lineWidth = 2;
drawRoundRect(ctx, tvX, tvY, tvWidth, tvHeight, 30);
ctx.stroke();
// TV Screen background
ctx.fillStyle = TV_SCREEN_BG;
drawRoundRect(ctx, screenX, screenY, screenWidth, screenHeight, 5);
ctx.fill();
// 3. Draw originalImg onto the TV screen
ctx.save();
ctx.beginPath();
drawRoundRect(ctx, screenX, screenY, screenWidth, screenHeight, 5);
ctx.clip(); // Clip the image to the screen area
const imgRatio = originalImg.width / originalImg.height;
const screenRatio = screenWidth / screenHeight;
let dw, dh, dx, dy;
if (imgRatio > screenRatio) { // Image is wider
dw = screenWidth;
dh = dw / imgRatio;
dx = screenX;
dy = screenY + (screenHeight - dh) / 2;
} else { // Image is taller or same aspect
dh = screenHeight;
dw = dh * imgRatio;
dy = screenY;
dx = screenX + (screenWidth - dw) / 2;
}
ctx.drawImage(originalImg, dx, dy, dw, dh);
ctx.restore();
// 4. Add CRT Screen Effects (Scanlines & Vignette)
const screenGrad = ctx.createRadialGradient(screenX + screenWidth/2, screenY + screenHeight/2, 200, screenX + screenWidth/2, screenY + screenHeight/2, screenWidth/1.5);
screenGrad.addColorStop(0, 'rgba(0,0,0,0)');
screenGrad.addColorStop(1, 'rgba(0,0,0,0.4)');
ctx.fillStyle = screenGrad;
ctx.fillRect(screenX, screenY, screenWidth, screenHeight);
ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';
for (let y = screenY; y < screenY + screenHeight; y += 3) {
ctx.fillRect(screenX, y, screenWidth, 1);
}
// 5. Draw Atari Jaguar Console
ctx.save();
ctx.shadowColor = 'rgba(0,0,0,0.6)';
ctx.shadowBlur = 30;
ctx.shadowOffsetY = 20;
// Main body
ctx.fillStyle = CONSOLE_BLACK;
drawRoundRect(ctx, consoleX, consoleY, consoleWidth, consoleHeight, 15);
ctx.fill();
// Cartridge slot area (raised)
const slotAreaWidth = 350, slotAreaHeight = 60;
const slotAreaX = consoleX + (consoleWidth - slotAreaWidth) / 2;
const slotAreaY = consoleY - 10;
ctx.fillStyle = CONSOLE_GRAY;
drawRoundRect(ctx, slotAreaX, slotAreaY , slotAreaWidth, slotAreaHeight, 8);
ctx.fill();
// Cartridge
const cartWidth = 180, cartHeight = 40;
const cartX = slotAreaX + (slotAreaWidth - cartWidth) / 2;
const cartY = slotAreaY - 30;
ctx.fillStyle = '#666';
drawRoundRect(ctx, cartX, cartY, cartWidth, cartHeight, 4);
ctx.fill();
// Cartridge Label
ctx.fillStyle = '#ddd';
ctx.fillRect(cartX + 10, cartY + 5, cartWidth - 20, cartHeight - 15);
ctx.fillStyle = '#111';
ctx.font = '8px "Press Start 2P"';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(gameTitle.substring(0, 20), cartX + cartWidth / 2, cartY + 18);
ctx.restore(); // remove shadow for details
// ATARI Logo
ctx.fillStyle = JAGUAR_RED;
ctx.font = 'bold 24px "Arial Black", Gadget, sans-serif';
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
ctx.fillText('ATARI', consoleX + 40, consoleY + consoleHeight / 2 + 10);
// Power light
const lightX = consoleX + consoleWidth - 60;
const lightY = consoleY + consoleHeight / 2 + 10;
const lightGrad = ctx.createRadialGradient(lightX, lightY, 1, lightX, lightY, 8);
lightGrad.addColorStop(0, 'rgba(255, 50, 50, 1)');
lightGrad.addColorStop(0.3, 'rgba(255, 0, 0, 0.8)');
lightGrad.addColorStop(1, 'rgba(212, 33, 39, 0)');
ctx.fillStyle = lightGrad;
ctx.fillRect(lightX - 10, lightY - 10, 20, 20);
// "64 - BIT INTERACTIVE MULTIMEDIA SYSTEM" text
ctx.fillStyle = '#888';
ctx.font = '10px "Arial"';
ctx.textAlign = 'center';
ctx.fillText('64 - BIT INTERACTIVE MULTIMEDIA SYSTEM', canvas.width / 2, consoleY + consoleHeight - 20);
return canvas;
}
Apply Changes