You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(
originalImg,
state = 'California',
firstName = 'John',
lastName = 'Doe',
dob = '01/01/1990',
expDate = '01/01/2030',
issueDate = '01/02/2022',
address = '123 MAIN ST, ANYTOWN, USA 12345',
idNumber = 'D12345678',
sex = 'M',
height = '5-10',
eyes = 'BRN'
) {
// Dynamically load realistic ID fonts via Google Fonts
const loadFonts = async () => {
const fontId = 'id-generator-fonts';
if (!document.getElementById(fontId)) {
const link = document.createElement('link');
link.id = fontId;
link.href = 'https://fonts.googleapis.com/css2?family=Caveat:wght@600&family=Oswald:wght@500;700&family=Open+Sans:wght@400;700;800&display=swap';
link.rel = 'stylesheet';
document.head.appendChild(link);
await document.fonts.ready;
}
};
await loadFonts();
// Standard ID Card Dimensions (Scaled up for high-fidelity look: ~ 3.375 x 2.125 aspect ratio)
const canvas = document.createElement('canvas');
canvas.width = 1012;
canvas.height = 638;
const ctx = canvas.getContext('2d');
// Create a smooth border radius clipping path
const cornerRadius = 25;
ctx.beginPath();
ctx.moveTo(cornerRadius, 0);
ctx.lineTo(canvas.width - cornerRadius, 0);
ctx.quadraticCurveTo(canvas.width, 0, canvas.width, cornerRadius);
ctx.lineTo(canvas.width, canvas.height - cornerRadius);
ctx.quadraticCurveTo(canvas.width, canvas.height, canvas.width - cornerRadius, canvas.height);
ctx.lineTo(cornerRadius, canvas.height);
ctx.quadraticCurveTo(0, canvas.height, 0, canvas.height - cornerRadius);
ctx.lineTo(0, cornerRadius);
ctx.quadraticCurveTo(0, 0, cornerRadius, 0);
ctx.closePath();
ctx.clip();
// Determine state color theme
const sName = String(state).toLowerCase();
let bgGradientColors = ['#f8fafc', '#e2e8f0'];
let titleColor = '#0f172a';
let subTitleColor = '#334155';
let bannerColor = 'rgba(15, 23, 42, 0.08)';
if (sName.includes('california')) {
bgGradientColors = ['#fefce8', '#e0f2fe'];
titleColor = '#dc2626';
subTitleColor = '#1d4ed8';
bannerColor = 'rgba(220, 38, 38, 0.08)';
} else if (sName.includes('texas')) {
bgGradientColors = ['#eff6ff', '#f5f5f4'];
titleColor = '#1d4ed8';
subTitleColor = '#dc2626';
bannerColor = 'rgba(29, 78, 216, 0.12)';
} else if (sName.includes('new york')) {
bgGradientColors = ['#fffbeb', '#eff6ff'];
titleColor = '#111827';
subTitleColor = '#ca8a04';
bannerColor = 'rgba(202, 138, 4, 0.15)';
} else if (sName.includes('florida')) {
bgGradientColors = ['#f0fdf4', '#fefce8'];
titleColor = '#15803d';
subTitleColor = '#a16207';
bannerColor = 'rgba(21, 128, 61, 0.12)';
} else if (sName.includes('illinois')) {
bgGradientColors = ['#faf5ff', '#f3e5f5'];
titleColor = '#7e22ce';
subTitleColor = '#1d4ed8';
bannerColor = 'rgba(126, 34, 206, 0.1)';
}
// 1. Draw Background
const bgGradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
bgGradient.addColorStop(0, bgGradientColors[0]);
bgGradient.addColorStop(1, bgGradientColors[1]);
ctx.fillStyle = bgGradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 2. Draw Realistic Guilloche Pattern (Wavy Security Lines)
ctx.lineWidth = 1;
for (let j = 0; j < 5; j++) {
ctx.beginPath();
for (let i = 0; i <= canvas.width; i += 5) {
const y = 300 + j * 60 + Math.sin(i * 0.02 + j) * 40 + Math.cos(i * 0.01) * 30;
ctx.lineTo(i, y);
}
ctx.strokeStyle = `rgba(0, 0, 0, 0.04)`;
ctx.stroke();
}
// 3. Draw Header Banner
ctx.fillStyle = bannerColor;
ctx.fillRect(0, 0, canvas.width, 130);
// Header State Name
ctx.fillStyle = titleColor;
ctx.font = '700 56px "Oswald", sans-serif';
ctx.textAlign = 'center';
ctx.fillText(String(state).toUpperCase(), canvas.width / 2, 70);
// Header Subtitle
ctx.fillStyle = subTitleColor;
ctx.font = '700 24px "Open Sans", sans-serif';
ctx.fillText("USA DRIVER LICENSE / IDENTIFICATION CARD", canvas.width / 2, 110);
ctx.textAlign = 'left';
// 4. Draw Micro-printing (Background text repetitions)
ctx.globalAlpha = 0.08;
ctx.font = "10px sans-serif";
ctx.fillStyle = titleColor;
for (let i = 0; i < 40; i++) {
ctx.fillText((String(state).toUpperCase() + " ").repeat(20), -20, 150 + i * 15);
}
ctx.globalAlpha = 1.0;
// 5. Calculate & Draw Portrait Photo (3:4 ratio)
const boxW = 260;
const boxH = 346;
const imgRatio = originalImg.width / originalImg.height;
const boxRatio = boxW / boxH;
let sWidth = originalImg.width;
let sHeight = originalImg.height;
let sx = 0;
let sy = 0;
if (imgRatio > boxRatio) {
sWidth = originalImg.height * boxRatio;
sx = (originalImg.width - sWidth) / 2;
} else {
sHeight = originalImg.width / boxRatio;
sy = (originalImg.height - sHeight) / 2;
}
// Main Photo Border and Draw
const pX = 40, pY = 150;
ctx.fillStyle = '#fff';
ctx.fillRect(pX - 4, pY - 4, boxW + 8, boxH + 8);
ctx.strokeStyle = bannerColor;
ctx.lineWidth = 2;
ctx.strokeRect(pX - 4, pY - 4, boxW + 8, boxH + 8);
ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, pX, pY, boxW, boxH);
// 6. Ghost Photo (Security Feature)
ctx.globalAlpha = 0.3;
ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, 780, 310, 180, 240);
ctx.globalAlpha = 1.0;
// Simulated Holographic Seal overlapping portrait/ghost
const sealGradient = ctx.createRadialGradient(780, 280, 20, 780, 280, 120);
sealGradient.addColorStop(0, 'rgba(255, 215, 0, 0.4)');
sealGradient.addColorStop(1, 'rgba(255, 215, 0, 0)');
ctx.fillStyle = sealGradient;
ctx.beginPath();
ctx.arc(780, 280, 120, 0, Math.PI * 2);
ctx.fill();
// 7. Draw Data Fields
const drawField = (label, value, x, y) => {
ctx.fillStyle = '#b91c1c'; // Red-ish labels
ctx.font = '800 13px "Open Sans", sans-serif';
ctx.fillText(String(label), x, y);
ctx.fillStyle = '#111827'; // Dark values
ctx.font = '700 24px "Open Sans", sans-serif';
ctx.fillText(String(value).toUpperCase(), x, y + 26);
};
const rowX = 330;
drawField("4d DL/ID NUMBER", idNumber, rowX, 160);
drawField("3 DOB", dob, rowX, 225);
drawField("4b EXP", expDate, rowX + 210, 225);
drawField("4a ISS", issueDate, rowX + 420, 225);
drawField("1 LN", lastName, rowX, 290);
drawField("2 FN", firstName, rowX, 355);
drawField("8 ADDRESS", address, rowX, 420);
drawField("9 SEX", sex, rowX, 485);
drawField("10 HGT", height, rowX + 110, 485);
drawField("11 EYES", eyes, rowX + 220, 485);
// 8. Draw Digital Signature
ctx.fillStyle = '#0f172a';
ctx.font = '600 46px "Caveat", cursive';
ctx.fillText(`${firstName} ${lastName}`, rowX + 10, 560);
ctx.beginPath();
ctx.moveTo(rowX, 565);
ctx.lineTo(rowX + 320, 565);
ctx.lineWidth = 1;
ctx.strokeStyle = '#94a3b8';
ctx.stroke();
// 9. Draw Simulated Security 1D Barcode Pattern
ctx.fillStyle = '#000000';
let curX = 40;
const barcodeY = 585;
const barcodeHeight = 25;
while (curX < 970) {
let barW = Math.random() * 4 + 1;
let gap = Math.random() * 3 + 1;
if (curX + barW > 972) break;
ctx.fillRect(curX, barcodeY, barW, barcodeHeight);
curX += barW + gap;
}
return canvas;
}
Apply Changes