You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
titleText = "ID SCANNER",
bodyText = "STATUS: VERIFIED\nSUBJECT IDENTIFIED",
overlayColor = "#00FF41",
scanPercentage = "45"
) {
const canvas = document.createElement('canvas');
const w = canvas.width = originalImg.width;
const h = canvas.height = originalImg.height;
const ctx = canvas.getContext('2d');
// Draw the original image as base
ctx.drawImage(originalImg, 0, 0);
// Calculate dynamic scaling relative to image dimensions
const minDim = Math.min(w, h);
const marginX = w * 0.15;
const marginY = h * 0.15;
const rectW = w - marginX * 2;
const rectH = h - marginY * 2;
const cornerLen = minDim * 0.1;
const lineWidth = Math.max(2, minDim * 0.005);
// Draw HUD / Scanner Corners
ctx.strokeStyle = overlayColor;
ctx.lineWidth = lineWidth;
ctx.lineJoin = "miter";
ctx.beginPath();
// Top Left Corner
ctx.moveTo(marginX, marginY + cornerLen);
ctx.lineTo(marginX, marginY);
ctx.lineTo(marginX + cornerLen, marginY);
// Top Right Corner
ctx.moveTo(w - marginX - cornerLen, marginY);
ctx.lineTo(w - marginX, marginY);
ctx.lineTo(w - marginX, marginY + cornerLen);
// Bottom Right Corner
ctx.moveTo(w - marginX, h - marginY - cornerLen);
ctx.lineTo(w - marginX, h - marginY);
ctx.lineTo(w - marginX - cornerLen, h - marginY);
// Bottom Left Corner
ctx.moveTo(marginX, h - marginY - cornerLen);
ctx.lineTo(marginX, h - marginY);
ctx.lineTo(marginX + cornerLen, h - marginY);
ctx.stroke();
// Draw Scanner Crosshairs
const centerX = w / 2;
const centerY = h / 2;
const chSize = minDim * 0.05;
ctx.lineWidth = Math.max(1, lineWidth / 2);
ctx.beginPath();
ctx.moveTo(centerX - chSize, centerY);
ctx.lineTo(centerX + chSize, centerY);
ctx.moveTo(centerX, centerY - chSize);
ctx.lineTo(centerX, centerY + chSize);
ctx.stroke();
ctx.beginPath();
ctx.arc(centerX, centerY, chSize * 0.6, 0, Math.PI * 2);
ctx.stroke();
// Draw Laser Scan Line
const parsedPercentage = Math.max(0, Math.min(100, parseFloat(scanPercentage) || 45));
const scanY = marginY + (rectH * (parsedPercentage / 100));
ctx.shadowBlur = minDim * 0.02;
ctx.shadowColor = overlayColor;
ctx.fillStyle = overlayColor;
ctx.fillRect(marginX, scanY, rectW, Math.max(2, lineWidth));
// Scan area coloring (semi-transparent filled area above scan line)
ctx.globalAlpha = 0.15;
ctx.fillRect(marginX, marginY, rectW, scanY - marginY);
ctx.globalAlpha = 1.0;
ctx.shadowBlur = 0; // Reset shadow
// Process Textbox Overlay
const titleSize = Math.max(16, minDim * 0.035);
const bodySize = Math.max(12, minDim * 0.025);
const padding = Math.max(10, minDim * 0.02);
// Calculate dimensions
ctx.font = `bold ${titleSize}px monospace`;
const titleW = ctx.measureText(titleText).width;
ctx.font = `${bodySize}px monospace`;
const formattedBodyText = bodyText.replace(/\\n/g, '\n');
const bodyLines = formattedBodyText.split('\n');
let maxBodyW = 0;
bodyLines.forEach(line => {
const lineW = ctx.measureText(line).width;
if (lineW > maxBodyW) maxBodyW = lineW;
});
const boxW = Math.max(titleW, maxBodyW) + padding * 2;
const lineSpacing = bodySize * 1.5;
const boxH = padding * 2.5 + titleSize + (lineSpacing * bodyLines.length);
// Position of textbox (bottom right interior edge of scanner)
let boxX = w - marginX - boxW - (padding / 2);
let boxY = h - marginY - boxH - (padding / 2);
// Prevent clipping off screen if internal margin isn't wide enough
if (boxX < 0) boxX = padding;
if (boxY < 0) boxY = padding;
// Draw Textbox Background and Border
ctx.fillStyle = "rgba(0, 15, 5, 0.8)";
ctx.strokeStyle = overlayColor;
ctx.lineWidth = Math.max(1, lineWidth / 2);
// Slight shadow for the textbox
ctx.shadowBlur = 10;
ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
ctx.fillRect(boxX, boxY, boxW, boxH);
ctx.shadowBlur = 0; // Reset
ctx.strokeRect(boxX, boxY, boxW, boxH);
// Draw Text Inside Box
ctx.fillStyle = overlayColor;
ctx.textAlign = "left";
ctx.textBaseline = "top";
// Render Title
ctx.font = `bold ${titleSize}px monospace`;
ctx.fillText(titleText, boxX + padding, boxY + padding);
// Separator Line
ctx.beginPath();
ctx.moveTo(boxX + padding, boxY + padding + titleSize + (padding/4));
ctx.lineTo(boxX + boxW - padding, boxY + padding + titleSize + (padding/4));
ctx.stroke();
// Render Body text
ctx.font = `${bodySize}px monospace`;
bodyLines.forEach((line, index) => {
ctx.fillText(
line,
boxX + padding,
boxY + padding + titleSize + (padding/2) + (lineSpacing * index) + (padding/4)
);
});
// Decorative Data Blocks (Top Left internal corner)
const uiTextX = marginX + padding;
const uiTextY = marginY + padding;
ctx.font = `bold ${bodySize * 0.75}px monospace`;
ctx.fillText(`SYS: OK`, uiTextX, uiTextY);
ctx.fillText(`POS: ${Math.floor(Math.random() * 90) + 10}x-${Math.floor(Math.random() * 90) + 10}y`, uiTextX, uiTextY + bodySize);
ctx.fillText(`DAT: 0x${Math.floor(Math.random() * 0xFFFFFF).toString(16).toUpperCase()}`, uiTextX, uiTextY + bodySize * 2);
return canvas;
}
Apply Changes