You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, pageTitle = "Scanned Entity", description = "This article is about a recently scanned identification entity. The subject's characteristics and biometric records have been cataloged into the database. Further observation is mandated by standard protocol. Please refer to the infobox for verified credentials and scanner identification status.", idNumber = "8X-491-002", scanColor = "#00ff00") {
// Create canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Define fixed canvas dimensions for the Wikipedia page template
const width = 1000;
const height = 800;
canvas.width = width;
canvas.height = height;
// 1. Fill page background
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, width, height);
// 2. Draw Left Sidebar (Wiki Vector legacy skin style)
ctx.fillStyle = '#f6f6f6';
ctx.fillRect(0, 0, 160, height);
// Sidebar border
ctx.strokeStyle = '#a2a9b1';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(160, 0);
ctx.lineTo(160, height);
ctx.stroke();
// Fake Wikipedia Logo in sidebar
ctx.textAlign = 'center';
ctx.fillStyle = '#000000';
ctx.font = '22px "Linux Libertine", Georgia, Times, serif';
ctx.fillText("WIKIPEDIA", 80, 50);
ctx.font = '10px Arial, sans-serif';
ctx.fillText("The Free Encyclopedia", 80, 65);
// Sidebar Fake Links
const links = [
"Main page", "Contents", "Current events", "Random article",
"About Wikipedia", "Contact us", "Donate"
];
ctx.textAlign = 'left';
ctx.font = '12px Arial, sans-serif';
ctx.fillStyle = '#0645ad'; // Classic Wikipedia link blue
links.forEach((link, index) => {
ctx.fillText(link, 15, 120 + (index * 22));
});
// 3. Top Tabs Area
ctx.fillStyle = '#ffffff';
ctx.fillRect(160, 0, width - 160, 30);
ctx.fillStyle = '#0645ad';
ctx.font = '13px Arial, sans-serif';
ctx.fillText("Article", 180, 20);
ctx.fillText("Talk", 230, 20);
// 4. Main Page Title
ctx.fillStyle = '#000000';
ctx.font = '32px "Linux Libertine", Georgia, Times, serif';
ctx.fillText(pageTitle, 180, 70);
// Page Title Underline Divider
ctx.strokeStyle = '#a2a9b1';
ctx.beginPath();
ctx.moveTo(180, 80);
ctx.lineTo(950, 80);
ctx.stroke();
// Subtitle note
ctx.font = '12px Arial, sans-serif';
ctx.fillStyle = '#54595d';
ctx.fillText("From Wikipedia, the free encyclopedia", 180, 98);
// 5. Draw Infobox (Right side)
const infoWidth = 300;
const infoX = 650;
const infoY = 93;
const infoHeight = 550;
ctx.fillStyle = '#f8f9fa';
ctx.fillRect(infoX, infoY, infoWidth, infoHeight);
ctx.strokeStyle = '#a2a9b1';
ctx.strokeRect(infoX, infoY, infoWidth, infoHeight);
// Infobox Header
ctx.fillStyle = '#eaecf0';
ctx.fillRect(infoX + 1, infoY + 1, infoWidth - 2, 35);
ctx.fillStyle = '#000000';
ctx.textAlign = 'center';
ctx.font = 'bold 14px Arial, sans-serif';
ctx.fillText(pageTitle, infoX + infoWidth / 2, infoY + 23);
// Image Placement inside InfoBox
const imgMaxWidth = 270;
const imgMaxHeight = 270;
const scale = Math.min(imgMaxWidth / originalImg.width, imgMaxHeight / originalImg.height);
const dw = originalImg.width * scale;
const dh = originalImg.height * scale;
const dx = infoX + (infoWidth - dw) / 2;
const dy = infoY + 45;
ctx.drawImage(originalImg, dx, dy, dw, dh);
// Image Border
ctx.strokeStyle = '#c8ccd1';
ctx.strokeRect(dx, dy, dw, dh);
// ID Scanner Overlay on Image
ctx.fillStyle = scanColor;
// Scanner area (semi-transparent)
ctx.globalAlpha = 0.15;
ctx.fillRect(dx, dy, dw, dh * 0.4);
// Scan line (solid)
ctx.globalAlpha = 0.8;
ctx.fillRect(dx, dy + dh * 0.4 - 2, dw, 4);
// Reset alpha
ctx.globalAlpha = 1.0;
// Infobox Data Table
ctx.textAlign = 'left';
let rowY = dy + dh + 25;
const infoData = [
{ label: "Status", value: "Verified Identity" },
{ label: "ID Code", value: idNumber },
{ label: "Scan Time", value: new Date().toISOString().split('T')[0] },
{ label: "Clearance", value: "Level 1" },
{ label: "Threat Lvl", value: "Nominal" }
];
infoData.forEach((data) => {
// Row background for label
ctx.fillStyle = '#eaecf0';
ctx.fillRect(infoX + 2, rowY - 14, 100, 24);
// Label Text
ctx.fillStyle = '#000000';
ctx.font = 'bold 12px Arial, sans-serif';
ctx.fillText(data.label, infoX + 8, rowY + 3);
// Value Text
ctx.font = '12px Arial, sans-serif';
ctx.fillText(data.value, infoX + 110, rowY + 3);
// Subtle Row Divider
ctx.strokeStyle = '#eaecf0';
ctx.beginPath();
ctx.moveTo(infoX + 2, rowY + 11);
ctx.lineTo(infoX + infoWidth - 2, rowY + 11);
ctx.stroke();
rowY += 25;
});
// Fake Barcode for Scanner Vibe
const barcodeY = rowY + 15;
const barcodeWidth = infoWidth - 40;
const barcodeHeight = 40;
const barcodeX = infoX + 20;
ctx.fillStyle = '#000000';
let currentX = 0;
// Simple seeded barcode generation
while (currentX < barcodeWidth) {
let barWidth = (Math.sin(currentX * 123.456) * 0.5 + 0.5) * 4 + 1;
if (currentX + barWidth > barcodeWidth) barWidth = barcodeWidth - currentX;
let isBlack = (Math.cos(currentX * 321.654) > 0);
if (isBlack) {
ctx.fillRect(barcodeX + currentX, barcodeY, barWidth, barcodeHeight);
}
currentX += barWidth;
}
// Barcode subtext
ctx.textAlign = 'center';
ctx.font = '11px monospace';
ctx.fillText("|| | | || || | | | || | " + idNumber + " ||| |", infoX + infoWidth / 2, barcodeY + barcodeHeight + 15);
// 6. Main Text / Description Area wrapping
const textX = 180;
const textY = 130;
const maxTextWidth = infoX - textX - 30; // Space between left margin and infobox
ctx.fillStyle = '#202122'; // Wikipedia modern text color
ctx.font = '14px Arial, sans-serif';
ctx.textAlign = 'left';
// Basic word wrapper function
function wrapText(context, text, x, y, maxWidth, lineHeight) {
const paragraphs = text.split('\n');
let currentY = y;
paragraphs.forEach(paragraph => {
const words = paragraph.split(' ');
let line = '';
for(let n = 0; n < words.length; n++) {
const testLine = line + words[n] + ' ';
const metrics = context.measureText(testLine);
const testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
context.fillText(line, x, currentY);
line = words[n] + ' ';
currentY += lineHeight;
} else {
line = testLine;
}
}
context.fillText(line, x, currentY);
currentY += lineHeight + 10; // Extra spacing after paragraph
});
}
// Render description text
wrapText(ctx, description, textX, textY, maxTextWidth, 22);
return canvas;
}
Apply Changes