You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(
originalImg,
licenseNumber = "S98765432",
lastName = "DOE",
firstName = "JANE",
middleName = "A",
address = "123 MAIN ST",
cityStateZip = "ANYTOWN, OK 73003",
dob = "01-01-1995",
issueDate = "08-15-2021",
expiresDate = "08-15-2029",
sex = "F",
height = "5-06",
eyes = "BLU",
hair = "BRN",
restrictions = "NONE",
endorsements = "NONE",
signature = "Jane A. Doe",
organDonor = "YES"
) {
const canvasWidth = 856;
const canvasHeight = 540;
const canvas = document.createElement('canvas');
canvas.width = canvasWidth;
canvas.height = canvasHeight;
const ctx = canvas.getContext('2d');
// Dynamically load necessary fonts from Google Fonts
const oswaldFont = new FontFace('Oswald', 'url(https://fonts.gstatic.com/s/oswald/v49/TK3_WkUHHAIjg75cFRf3bXL8LICs1_FvsUtiZSSU.woff2)');
const latoFont = new FontFace('Lato', 'url(https://fonts.gstatic.com/s/lato/v23/S6uyw4BMUTPHjx4wXg.woff2)');
const dancingScriptFont = new FontFace('Dancing Script', 'url(https://fonts.gstatic.com/s/dancingscript/v24/If2RFXBG5qsbfGfk4uRONFib-v2rsget.woff2)');
await Promise.all([oswaldFont.load(), latoFont.load(), dancingScriptFont.load()]);
document.fonts.add(oswaldFont);
document.fonts.add(latoFont);
document.fonts.add(dancingScriptFont);
// --- Helper to draw an SVG path ---
const drawPath = (pathData, color, alpha = 1.0) => {
const path = new Path2D(pathData);
ctx.fillStyle = color;
ctx.globalAlpha = alpha;
ctx.fill(path);
ctx.globalAlpha = 1.0;
};
// --- Asset Data (SVG Paths) ---
// Oklahoma State Outline Path
const okPath = "M843.2,166.5V2.9h-212V166.5h-298v77.2h-152V411H2.4v22.4h178.2v103.7h46.7V411h270.8v126.1h20v-56.5h77.2v-10.7h118v-87.9h4.3v-4.3h44.3v-23.7h4.3v-4.3h10.3V170.8h-10.3v-4.3H843.2z";
// Simplified Scissor-tailed Flycatcher silhouette path
const birdPath = "M 5,10 C 15,0 25,0 35,10 L 30,15 L 40,25 L 25,20 L 20,35 L 15,20 L 0,25 L 10,15 Z M 19,34 L 10,70 L 21,34 L 30,70 L 19,34 Z";
// --- Drawing Start ---
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
// 1. Background Elements
const bgGrad = ctx.createLinearGradient(0, 0, canvasWidth, canvasHeight);
bgGrad.addColorStop(0, '#eaf4ff');
bgGrad.addColorStop(0.5, '#ffffff');
bgGrad.addColorStop(1, '#ffeaf4');
ctx.fillStyle = bgGrad;
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
// Large, faint state outline
ctx.save();
ctx.translate(-150, -10);
ctx.scale(0.8, 0.8);
drawPath(okPath, '#0072c6', 0.08);
ctx.restore();
// Large, faint bird silhouette
ctx.save();
ctx.translate(canvasWidth - 320, canvasHeight - 250);
ctx.scale(5, 5);
ctx.rotate(-0.2);
drawPath(birdPath, '#ff7f50', 0.12);
ctx.restore();
// 2. Header
ctx.font = 'bold 36px Oswald';
ctx.fillStyle = '#003366';
ctx.fillText('OKLAHOMA', 250, 50);
ctx.font = '24px Oswald';
ctx.fillStyle = '#003366';
ctx.fillText('DRIVER LICENSE', 253, 80);
// REAL ID Star
const starX = 790, starY = 65, starRadius = 40;
ctx.fillStyle = '#DAA520'; // Gold
ctx.beginPath();
ctx.arc(starX, starY, starRadius, 0, 2 * Math.PI);
ctx.fill();
ctx.fillStyle = '#000000';
ctx.font = '60px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('★', starX, starY + 5);
ctx.textAlign = 'left';
ctx.textBaseline = 'alphabetic';
// 3. User Photos
// Main Photo
const photoX = 30, photoY = 100, photoW = 180, photoH = 230;
ctx.drawImage(originalImg, photoX, photoY, photoW, photoH);
ctx.strokeStyle = '#003366';
ctx.lineWidth = 2;
ctx.strokeRect(photoX, photoY, photoW, photoH);
// Ghost Photo
ctx.globalAlpha = 0.25;
ctx.drawImage(originalImg, 260, 250, 150, 190);
ctx.globalAlpha = 1.0;
// 4. Main data fields
const fieldStartX = 250;
const labelColor = '#d35d6e';
const valueColor = '#000000';
let currentY;
const drawField = (label, value, x, y, valueFont = 'bold 20px Lato') => {
ctx.font = '14px Lato';
ctx.fillStyle = labelColor;
ctx.fillText(label, x, y - 5);
ctx.font = valueFont;
ctx.fillStyle = valueColor;
ctx.fillText(value.toUpperCase(), x, y + 20);
};
// License Number (special styling)
ctx.fillStyle = '#d35d6e';
ctx.fillRect(250, 95, 250, 30);
ctx.font = 'bold 22px Lato';
ctx.fillStyle = '#FFFFFF';
ctx.fillText(`DL ${licenseNumber}`, 260, 118);
currentY = 175;
drawField('1b CLASS', 'D', fieldStartX, currentY);
drawField('4f END', endorsements.toUpperCase(), fieldStartX + 120, currentY);
currentY += 55;
drawField('1 LN', lastName, fieldStartX, currentY, 'bold 28px Lato');
currentY += 55;
drawField('2 FN', `${firstName} ${middleName}`, fieldStartX, currentY, 'bold 28px Lato');
currentY += 55;
drawField('8 ADDR', address, fieldStartX, currentY);
currentY += 55;
drawField('', cityStateZip, fieldStartX, currentY);
// Smaller data fields on the left
const smallFieldX1 = 30;
const smallFieldX2 = 130;
let smallFieldY = 350;
const drawSmallField = (label, value, x, y) => {
ctx.font = '12px Lato';
ctx.fillStyle = labelColor;
ctx.fillText(label, x, y);
ctx.font = 'bold 16px Lato';
ctx.fillStyle = valueColor;
ctx.fillText(value.toUpperCase(), x, y + 18);
};
drawSmallField('3 DOB', dob, smallFieldX1, smallFieldY);
smallFieldY += 45;
drawSmallField('4a ISS', issueDate, smallFieldX1, smallFieldY);
drawSmallField('4b EXP', expiresDate, smallFieldX2, smallFieldY);
smallFieldY += 45;
drawSmallField('4c SEX', sex, smallFieldX1, smallFieldY);
drawSmallField('HGT', height, smallFieldX2, smallFieldY);
smallFieldY += 45;
drawSmallField('EYES', eyes, smallFieldX1, smallFieldY);
drawSmallField('HAIR', hair, smallFieldX2, smallFieldY);
// Right-side fields
drawField('RSTR', restrictions.toUpperCase(), 600, 175);
drawField('DONOR', organDonor.toUpperCase() === "YES" ? "ORGAN DONOR" : "NONE", 600, 230);
if(organDonor.toUpperCase() === "YES") {
ctx.fillStyle = 'red';
ctx.font = '28px Arial';
ctx.fillText('❤', 740, 250);
}
// Signature
ctx.font = '14px Lato';
ctx.fillStyle = labelColor;
ctx.fillText('SIGNATURE', 250, 480);
ctx.strokeStyle = '#000000';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(250, 510);
ctx.lineTo(550, 510);
ctx.stroke();
ctx.fillStyle = '#000033';
ctx.font = '32px "Dancing Script"';
ctx.fillText(signature, 260, 505);
// Duplicate number bottom right
ctx.font = 'bold 16px Lato';
ctx.fillStyle = '#d35d6e';
ctx.fillText(licenseNumber, 750, 520);
// Specimen Watermark for safety and to prevent misuse
ctx.save();
ctx.translate(canvasWidth / 2, canvasHeight / 2);
ctx.rotate(-0.3);
ctx.font = 'bold 90px Arial';
ctx.fillStyle = 'red';
ctx.globalAlpha = 0.4;
ctx.textAlign = 'center';
ctx.fillText('SPECIMEN', 0, 30);
ctx.restore();
return canvas;
}
Apply Changes