You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg,
state = "CALIFORNIA",
licenseNumber = "D1234567",
fullName = "JOHN DOE",
address = "123 MAIN ST",
cityStateZip = "ANYTOWN, CA 90210",
dob = "01/01/1990",
sex = "M",
height = "5'-10\"",
eyes = "BRN",
hair = "BLK",
issueDate = "01/01/2020",
expDate = "01/01/2025") {
const canvas = document.createElement('canvas');
canvas.width = 860;
canvas.height = 540;
const ctx = canvas.getContext('2d');
// Helper for drawing rounded rectangles (safer cross-browser compatibility)
function drawRoundRectPath(ctx, x, y, width, height, radius) {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
}
// 1. Clip the main card canvas to have rounded corners
ctx.save();
drawRoundRectPath(ctx, 0, 0, 860, 540, 25);
ctx.clip();
// 2. Background Base (Subtle Radial/Linear Gradient)
const bgGrad = ctx.createLinearGradient(0, 0, 860, 540);
bgGrad.addColorStop(0, '#e8f4f8');
bgGrad.addColorStop(0.5, '#fdfbfb');
bgGrad.addColorStop(1, '#e2ebf0');
ctx.fillStyle = bgGrad;
ctx.fillRect(0, 0, 860, 540);
// 3. Decorative wavy background lines (security feature mockup)
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgba(30, 144, 255, 0.12)';
for (let j = 0; j < 25; j++) {
ctx.beginPath();
ctx.moveTo(0, j * 25);
for (let i = 0; i <= 860; i += 20) {
ctx.lineTo(i, j * 25 + Math.sin(i / 60) * 15);
}
ctx.stroke();
}
// 4. Header Bar
ctx.fillStyle = '#0033a0'; // Deep blue
ctx.fillRect(0, 0, 860, 95);
// Golden Divider Line
ctx.fillStyle = '#fdb927';
ctx.fillRect(0, 95, 860, 10);
// Header Text
ctx.fillStyle = '#ffffff';
ctx.textAlign = 'center';
ctx.font = 'bold 46px "Times New Roman", Georgia, serif';
ctx.fillText(state.toUpperCase(), 430, 55);
ctx.font = 'bold 18px Arial, sans-serif';
ctx.fillText('DRIVER LICENSE', 430, 82);
ctx.textAlign = 'left';
// 5. Giant Watermark (State Name)
ctx.save();
ctx.translate(430, 320);
ctx.rotate(-0.4);
ctx.fillStyle = 'rgba(0, 0, 0, 0.04)';
ctx.font = 'bold 130px Arial, sans-serif';
ctx.textAlign = 'center';
ctx.fillText(state.toUpperCase(), 0, 0);
ctx.restore();
// 6. Calculate aspect ratio crop for the Portrait Photo
const targetW = 200;
const targetH = 260;
const imgRatio = originalImg.width / originalImg.height;
const targetRatio = targetW / targetH;
let sX, sY, sW, sH;
if (imgRatio > targetRatio) {
sH = originalImg.height;
sW = sH * targetRatio;
sX = (originalImg.width - sW) / 2;
sY = 0;
} else {
sW = originalImg.width;
sH = sW / targetRatio;
sX = 0;
sY = (originalImg.height - sH) / 2;
}
// Draw Main Photo
ctx.save();
drawRoundRectPath(ctx, 40, 130, targetW, targetH, 12);
ctx.clip();
ctx.drawImage(originalImg, sX, sY, sW, sH, 40, 130, targetW, targetH);
ctx.restore();
// Stroke Main Photo
drawRoundRectPath(ctx, 40, 130, targetW, targetH, 12);
ctx.lineWidth = 3;
ctx.strokeStyle = '#999999';
ctx.stroke();
// 7. Ghost Photo (Semi-transparent mini version)
ctx.save();
ctx.globalAlpha = 0.25;
drawRoundRectPath(ctx, 690, 310, 110, 143, 8);
ctx.clip();
ctx.drawImage(originalImg, sX, sY, sW, sH, 690, 310, 110, 143);
ctx.restore();
// 8. Fake Gold State Seal over photo corner
ctx.save();
ctx.globalAlpha = 0.65;
ctx.translate(225, 380);
const sealGrad = ctx.createRadialGradient(0, 0, 0, 0, 0, 42);
sealGrad.addColorStop(0, '#fff5cc');
sealGrad.addColorStop(1, '#ffc200');
ctx.fillStyle = sealGrad;
ctx.beginPath();
ctx.arc(0, 0, 42, 0, Math.PI * 2);
ctx.fill();
ctx.lineWidth = 2;
ctx.strokeStyle = '#cc9900';
ctx.stroke();
ctx.setLineDash([4, 4]);
ctx.beginPath();
ctx.arc(0, 0, 34, 0, Math.PI * 2);
ctx.stroke();
ctx.setLineDash([]);
ctx.font = 'bold 8px Arial';
ctx.fillStyle = '#664d00';
ctx.textAlign = 'center';
ctx.fillText('SEAL OF THE STATE', 0, -5);
ctx.fillText('OFFICIAL MOCKUP', 0, 5);
ctx.restore();
// 9. Data Fields Layout
const labelColor = '#c62828'; // Crimson Red
const valColor = '#111111'; // Pure Black
// DL NUMBER
ctx.fillStyle = labelColor;
ctx.font = 'bold 22px Arial, sans-serif';
ctx.fillText('DL', 270, 155);
ctx.fillStyle = valColor;
ctx.font = 'bold 32px Arial, sans-serif';
ctx.fillText(licenseNumber, 310, 155);
// EXP & ISS DATE
ctx.fillStyle = labelColor;
ctx.font = 'bold 16px Arial, sans-serif';
ctx.fillText('EXP', 580, 140);
ctx.fillStyle = valColor;
ctx.font = 'bold 22px Arial, sans-serif';
ctx.fillText(expDate, 625, 140);
ctx.fillStyle = labelColor;
ctx.font = 'bold 14px Arial, sans-serif';
ctx.fillText('ISS', 580, 170);
ctx.fillStyle = valColor;
ctx.font = 'bold 18px Arial, sans-serif';
ctx.fillText(issueDate, 625, 170);
// NAME & ADDRESS
ctx.fillStyle = labelColor;
ctx.font = 'bold 14px Arial, sans-serif';
ctx.fillText('NM', 270, 205);
ctx.fillStyle = valColor;
ctx.font = 'bold 24px Arial, sans-serif';
ctx.fillText(fullName.toUpperCase(), 310, 205);
ctx.fillStyle = labelColor;
ctx.font = 'bold 14px Arial, sans-serif';
ctx.fillText('DA', 270, 245);
ctx.fillStyle = valColor;
ctx.font = 'bold 20px Arial, sans-serif';
ctx.fillText(address.toUpperCase(), 310, 245);
ctx.fillText(cityStateZip.toUpperCase(), 310, 270);
// DOB
ctx.fillStyle = labelColor;
ctx.font = 'bold 22px Arial, sans-serif';
ctx.fillText('DOB', 270, 320);
ctx.fillStyle = valColor;
ctx.font = 'bold 30px Arial, sans-serif';
ctx.fillText(dob, 330, 320);
// Physical characteristics (SEX, HAIR, EYES, HGT)
const statY = 375;
function drawStat(label, value, x) {
ctx.fillStyle = labelColor;
ctx.font = 'bold 14px Arial, sans-serif';
ctx.fillText(label, x, statY);
ctx.fillStyle = valColor;
ctx.font = 'bold 18px Arial, sans-serif';
ctx.fillText(value, x, statY + 22);
}
drawStat('SEX', sex, 270);
drawStat('HAIR', hair, 340);
drawStat('EYES', eyes, 420);
drawStat('HGT', height, 500);
// 10. MRZ (Machine Readable Zone) Mockup Strip at bottom
ctx.fillStyle = '#b71c1c';
ctx.fillRect(0, 500, 860, 40);
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 18px "Courier New", Courier, monospace';
const fillerCode = "<<<<<<<<<<<<<<<<<<<<<<<<";
const mrzText = `<<MOCKUP<DRIVER<LICENSE<${licenseNumber}<<${fullName.replace(/\s+/g, '<')} ${fillerCode}`.slice(0, 60);
ctx.fillText(mrzText, 25, 526);
// 11. Fake Signature (Using built-in Cursive/Script fonts)
ctx.fillStyle = '#0a0a0a';
ctx.font = '40px "Brush Script MT", "Snell Roundhand", "Zapf Chancery", cursive, sans-serif';
ctx.save();
ctx.translate(450, 465);
ctx.rotate(-0.06); // Slight natural tilt
ctx.fillText(fullName, 0, 0);
ctx.restore();
// 12. Draw physical card edge (Outline)
ctx.restore(); // Restore from main clip
drawRoundRectPath(ctx, 0, 0, 860, 540, 25);
ctx.lineWidth = 4;
ctx.strokeStyle = '#bbbbbb';
ctx.stroke();
return canvas;
}
Apply Changes