You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(
originalImg,
lastName = "DOE",
firstName = "JANE",
middleInitial = "A",
address = "123 MAIN ST\nANYTOWN, MN 55401",
dob = "01-01-1990",
issueDate = "08-15-2022",
expiresDate = "08-15-2030",
licenseNumber = "A12345678901",
sex = "F",
height = "5-05",
eyes = "BLU",
dlClass = "D",
restrictions = "NONE",
endorsements = "NONE"
) {
// Standard ID-1 card size in pixels at ~250 DPI
const canvasWidth = 856;
const canvasHeight = 540;
const canvas = document.createElement('canvas');
canvas.width = canvasWidth;
canvas.height = canvasHeight;
const ctx = canvas.getContext('2d');
// Dynamically load a cursive font for the signature
// This ensures the font is available before we try to use it on the canvas
const fontName = 'Dancing Script';
try {
if (!document.fonts.check(`1em "${fontName}"`)) {
const fontFace = new FontFace(fontName, `url(https://fonts.gstatic.com/s/dancingscript/v24/If2cXTr6YS-zF4S-kcSWSVi_sxjsohD9F50Ruu7BMSo3Rep8ltA.woff2)`);
await fontFace.load();
document.fonts.add(fontFace);
}
} catch (e) {
console.error("Font could not be loaded. A default font will be used for the signature.", e);
}
// --- Draw Background ---
// A simplified, abstract representation of the Minnesota license background (lakes/trees)
const bgGradient = ctx.createLinearGradient(0, 0, 0, canvasHeight);
bgGradient.addColorStop(0, '#aaccff'); // Light sky blue
bgGradient.addColorStop(0.45, '#d0e0f0');
bgGradient.addColorStop(0.5, '#b0c0a0'); // Muted green for land/trees
bgGradient.addColorStop(1, '#c0d0e0'); // Water
ctx.fillStyle = bgGradient;
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
// Add some "tree" shapes for texture
ctx.fillStyle = 'rgba(100, 120, 100, 0.15)';
for (let i = 0; i < 50; i++) {
const x = Math.random() * canvasWidth;
const y = canvasHeight * 0.45 + Math.random() * 40;
const width = 15 + Math.random() * 20;
const height = 40 + Math.random() * 60;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + width / 2, y - height);
ctx.lineTo(x + width, y);
ctx.closePath();
ctx.fill();
}
// --- Draw Header ---
ctx.fillStyle = '#002664'; // Dark Blue
ctx.fillRect(0, 0, canvasWidth, 75);
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 32px Arial, sans-serif';
ctx.textAlign = 'center';
ctx.fillText('MINNESOTA', canvasWidth / 2, 35);
ctx.font = 'bold 18px Arial, sans-serif';
ctx.fillText('DRIVER LICENSE', canvasWidth / 2, 60);
// REAL ID Star (gold circle with a star cutout)
ctx.save();
ctx.translate(790, 40);
ctx.fillStyle = '#DAA520'; // Gold
ctx.beginPath();
ctx.arc(0, 0, 22, 0, 2 * Math.PI);
ctx.fill();
ctx.fillStyle = '#002664'; // Cutout color same as header
ctx.beginPath();
for (let i = 0; i < 5; i++) {
ctx.lineTo(Math.cos((18 + i * 72) * Math.PI / 180) * 20, -Math.sin((18 + i * 72) * Math.PI / 180) * 20);
ctx.lineTo(Math.cos((54 + i * 72) * Math.PI / 180) * 8, -Math.sin((54 + i * 72) * Math.PI / 180) * 8);
}
ctx.closePath();
ctx.fill();
ctx.restore();
// --- Draw Photos ---
const photoX = 40;
const photoY = 100;
const photoWidth = 240;
const photoHeight = 310;
ctx.fillStyle = '#ffffff';
ctx.fillRect(photoX - 2, photoY - 2, photoWidth + 4, photoHeight + 4); // White border
ctx.drawImage(originalImg, photoX, photoY, photoWidth, photoHeight);
// Ghost Photo
ctx.globalAlpha = 0.15;
ctx.drawImage(originalImg, 450, 180, 300, 388);
ctx.globalAlpha = 1.0;
// --- Minnesota State Outline (simplified) ---
ctx.strokeStyle = 'rgba(0, 38, 100, 0.4)';
ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(350, 450); ctx.lineTo(350, 500); ctx.lineTo(440, 500); ctx.lineTo(440, 480);
ctx.lineTo(460, 460); ctx.lineTo(460, 400); ctx.lineTo(430, 350); ctx.lineTo(410, 320);
ctx.lineTo(420, 280); ctx.lineTo(380, 250); ctx.lineTo(380, 200); ctx.lineTo(400, 180);
ctx.lineTo(350, 180); ctx.closePath();
ctx.fill();
ctx.stroke();
// --- Draw Text Data ---
ctx.textAlign = 'left';
const dataX = 320;
const drawField = (label, value, x, y, valueFont = 'bold 20px "Courier New", monospace') => {
ctx.font = '14px "Courier New", monospace';
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
ctx.fillText(label, x, y - 5);
ctx.font = valueFont;
ctx.fillStyle = '#000000';
// Handle multi-line address
if (value.includes('\n')) {
const lines = value.split('\n');
lines.forEach((line, index) => {
ctx.fillText(line.toUpperCase(), x, y + 20 + (index * 22));
});
} else {
ctx.fillText(value.toUpperCase(), x, y + 18);
}
}
drawField("DL NO.", licenseNumber, dataX, 100);
drawField("LN", lastName, dataX, 150);
drawField("FN", `${firstName} ${middleInitial}`.trim(), dataX, 200);
drawField("DOB", dob, dataX, 250);
drawField("ISS", issueDate, 650, 100);
drawField("EXP", expiresDate, 650, 150);
drawField("ADD", address, dataX, 300);
const bottomRowY = 470;
const bottomRowFont = 'bold 18px "Courier New", monospace';
drawField("SEX", sex, dataX, bottomRowY, bottomRowFont);
drawField("HGT", height, dataX + 100, bottomRowY, bottomRowFont);
drawField("EYES", eyes, dataX + 250, bottomRowY, bottomRowFont);
drawField("CLASS", dlClass, dataX + 410, bottomRowY, bottomRowFont);
// --- Draw Signature ---
ctx.strokeStyle = '#000000';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(photoX, photoY + photoHeight + 45);
ctx.lineTo(photoX + photoWidth, photoY + photoHeight + 45);
ctx.stroke();
ctx.fillStyle = '#000050';
ctx.font = `36px "${fontName}", cursive`;
ctx.fillText(`${firstName} ${lastName}`, photoX + 10, photoY + photoHeight + 40);
return canvas;
}
Apply Changes