You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, heroName = "UNKNOWN SUBJECT", status = "HERO IDENTIFIED", scanColor = "#00FF00", scanPosition = 45) {
const canvas = document.createElement("canvas");
const w = originalImg.width;
const h = originalImg.height;
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext("2d");
// Helper to convert hex to rgba
function hexToRgba(hex, alpha) {
hex = hex.replace('#', '');
if (hex.length === 3) hex = hex.split('').map(x => x + x).join('');
let r = parseInt(hex.slice(0, 2), 16) || 0;
let g = parseInt(hex.slice(2, 4), 16) || 255;
let b = parseInt(hex.slice(4, 6), 16) || 0;
return `rgba(${r},${g},${b},${alpha})`;
}
// 1. Draw original image
ctx.drawImage(originalImg, 0, 0);
// 2. Apply dark UI tint to make HUD pop
ctx.fillStyle = "rgba(0, 15, 0, 0.4)";
ctx.fillRect(0, 0, w, h);
// 3. Draw CRT scanlines
ctx.fillStyle = "rgba(0, 0, 0, 0.2)";
const scanlineThickness = Math.max(1, h * 0.0025);
const scanlineSpacing = Math.max(2, h * 0.005);
for (let y = 0; y < h; y += scanlineSpacing) {
ctx.fillRect(0, y, w, scanlineThickness);
}
const margin = Math.min(w, h) * 0.05;
const cornerLen = Math.min(w, h) * 0.15;
// 4. Draw HUD corner brackets
ctx.lineWidth = Math.max(3, w * 0.005);
ctx.strokeStyle = scanColor;
ctx.beginPath();
// Top Left
ctx.moveTo(margin, margin + cornerLen);
ctx.lineTo(margin, margin);
ctx.lineTo(margin + cornerLen, margin);
// Top Right
ctx.moveTo(w - margin - cornerLen, margin);
ctx.lineTo(w - margin, margin);
ctx.lineTo(w - margin, margin + cornerLen);
// Bottom Right
ctx.moveTo(w - margin, h - margin - cornerLen);
ctx.lineTo(w - margin, h - margin);
ctx.lineTo(w - margin - cornerLen, h - margin);
// Bottom Left
ctx.moveTo(margin + cornerLen, h - margin);
ctx.lineTo(margin, h - margin);
ctx.lineTo(margin, h - margin - cornerLen);
ctx.stroke();
// 5. Center Crosshairs
const cx = w / 2;
const cy = h / 2;
const crossSize = Math.min(w, h) * 0.03;
ctx.lineWidth = Math.max(1, w * 0.002);
ctx.beginPath();
ctx.moveTo(cx - crossSize, cy);
ctx.lineTo(cx - crossSize / 3, cy);
ctx.moveTo(cx + crossSize / 3, cy);
ctx.lineTo(cx + crossSize, cy);
ctx.moveTo(cx, cy - crossSize);
ctx.lineTo(cx, cy - crossSize / 3);
ctx.moveTo(cx, cy + crossSize / 3);
ctx.lineTo(cx, cy + crossSize);
ctx.stroke();
ctx.beginPath();
ctx.arc(cx, cy, crossSize * 0.6, 0, Math.PI * 2);
ctx.stroke();
// 6. Active scan line
let scanPosNum = parseFloat(scanPosition);
if(isNaN(scanPosNum)) scanPosNum = 45;
const scanY = h * (scanPosNum / 100);
ctx.beginPath();
ctx.moveTo(0, scanY);
ctx.lineTo(w, scanY);
ctx.lineWidth = Math.max(2, h * 0.005);
ctx.strokeStyle = hexToRgba(scanColor, 0.8);
ctx.stroke();
// Scan line vertical glow
const glowH = h * 0.15;
const grd = ctx.createLinearGradient(0, scanY - glowH, 0, scanY);
grd.addColorStop(0, "rgba(0,0,0,0)");
grd.addColorStop(1, hexToRgba(scanColor, 0.3));
ctx.fillStyle = grd;
ctx.fillRect(0, scanY - glowH, w, glowH);
// 7. Text Overlay Setup
const fontSize = Math.max(12, h * 0.025);
ctx.font = `bold ${fontSize}px "Courier New", Courier, monospace`;
ctx.textBaseline = "top";
// Text block data
const textLines = [
"TARGET ACQUIRED",
"---------------------",
`IDENTITY : ${heroName}`,
`STATUS : ${status}`
];
let maxTextWidth = 0;
for (const text of textLines) {
const textWidth = ctx.measureText(text).width;
if (textWidth > maxTextWidth) maxTextWidth = textWidth;
}
// Draw text bounds box
const boxPad = fontSize;
const boxW = maxTextWidth + boxPad * 2;
const boxH = textLines.length * (fontSize * 1.5) + boxPad;
const boxX = margin + cornerLen * 0.3;
const boxY = margin + cornerLen * 0.3;
ctx.fillStyle = hexToRgba(scanColor, 0.15);
ctx.fillRect(boxX, boxY, boxW, boxH);
ctx.lineWidth = Math.max(1, w * 0.001);
ctx.strokeStyle = hexToRgba(scanColor, 0.5);
ctx.strokeRect(boxX, boxY, boxW, boxH);
// Draw identification text
ctx.fillStyle = scanColor;
ctx.textAlign = "left";
let currY = boxY + boxPad;
for (const text of textLines) {
ctx.fillText(text, boxX + boxPad, currY);
currY += fontSize * 1.5;
}
// Draw scanner brand top-right
ctx.textAlign = "right";
ctx.font = `bold ${fontSize}px "Courier New", Courier, monospace`;
ctx.fillText("HERO_ID_SCANNER_SYS", w - margin - cornerLen * 0.1, margin + cornerLen * 0.3);
// 8. Terminal data stream (Right side visual fluff)
const terminalLines = 10;
const termYStart = h - (terminalLines * fontSize * 1.3) - margin - cornerLen * 0.1;
const termX = w - margin - cornerLen * 0.2;
for(let i = 0; i < terminalLines; i++) {
let row = "";
for(let j = 0; j < 8; j++) {
row += Math.floor(Math.random() * 16).toString(16).toUpperCase();
}
row += " ";
for(let j = 0; j < 8; j++) {
row += Math.floor(Math.random() * 2).toString();
}
ctx.fillText(row, termX, termYStart + i * fontSize * 1.3);
}
return canvas;
}
Apply Changes