You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
state = "STATE OF JAVASCRIPT",
licenseNum = "DL-987654321",
fullName = "DOE, JOHN Q",
dob = "01/01/1995",
expDate = "12/31/2030",
address1 = "123 WEB API STREET",
address2 = "DOM CITY, JS 10101",
sex = "M",
height = "5'-11\"",
eyes = "BRN",
licenseClass = "C",
issueDate = "01/01/2023"
) {
// Create the canvas for the driver's license
const canvas = document.createElement('canvas');
const width = 850;
const height_canvas = 530;
canvas.width = width;
canvas.height = height_canvas;
const ctx = canvas.getContext('2d');
// 1. Draw Background
// A security-style gradient background typically found on IDs
const bgGrad = ctx.createLinearGradient(0, 0, width, height_canvas);
bgGrad.addColorStop(0, '#e0f2fe'); // Light blue
bgGrad.addColorStop(0.5, '#fce7f3'); // Pale pink
bgGrad.addColorStop(1, '#e0f2fe'); // Light blue
ctx.fillStyle = bgGrad;
ctx.fillRect(0, 0, width, height_canvas);
// Add decorative guilloche-like background curves
ctx.strokeStyle = '#bae6fd';
ctx.lineWidth = 1.5;
for (let i = 0; i < 50; i++) {
ctx.beginPath();
ctx.moveTo(0, i * 18);
ctx.bezierCurveTo(width / 3, i * 18 + 120, 2 * width / 3, i * 18 - 120, width, i * 18);
ctx.stroke();
}
// 2. Draw Header
// State Name block
ctx.fillStyle = '#0284c7';
ctx.fillRect(0, 0, width, 75);
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 36px "Arial", sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(state.toUpperCase(), width / 2, 38);
// Separator / "DRIVER LICENSE" bar
ctx.fillStyle = '#fde047'; // Yellow band
ctx.fillRect(0, 75, width, 30);
ctx.fillStyle = '#000000';
ctx.font = 'bold 18px "Arial", sans-serif';
ctx.fillText("DRIVER LICENSE", width / 2, 90);
// 3. Helper to draw data fields
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
function drawField(label, value, x, y, valueColor = '#000000') {
// Red Label
ctx.fillStyle = '#ef4444';
ctx.font = 'bold 11px "Arial", sans-serif';
ctx.fillText(label, x, y);
// Data Value
ctx.fillStyle = valueColor;
ctx.font = 'bold 18px "Arial", sans-serif';
ctx.fillText(value.toString(), x, y + 14);
}
// 4. Draw Layout and Data Fields
const startX = 300;
// Line 1
drawField("DL NO", licenseNum, startX, 125, '#0369a1');
drawField("EXP", expDate, startX + 250, 125, '#ef4444'); // Red expiration date
// Line 2
drawField("DOB", dob, startX, 180, '#ef4444');
drawField("CLASS", licenseClass, startX + 180, 180);
drawField("ISS", issueDate, startX + 320, 180);
// Line 3 (Name)
drawField("LN/FN", fullName, startX, 235);
// Line 4 (Address)
drawField("ADDRESS", address1, startX, 290);
ctx.fillStyle = '#000000';
ctx.font = 'bold 18px "Arial", sans-serif';
ctx.fillText(address2, startX, 324);
// Line 5 (Characteristics)
drawField("SEX", sex, startX, 380);
drawField("HGT", height, startX + 100, 380);
drawField("EYES", eyes, startX + 200, 380);
// Signature
ctx.fillStyle = '#000000';
ctx.font = 'italic 28px "Brush Script MT", "Cursive", "Arial"';
ctx.fillText(fullName, startX, 450);
// Draw signature underline
ctx.strokeStyle = '#000000';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(startX, 485);
ctx.lineTo(startX + 250, 485);
ctx.stroke();
// 5. Draw Portrait Image
const portX = 35;
const portY = 125;
const portW = 230;
const portH = 300;
// Calculate image crop to cover the portrait area nicely
const scale = Math.max(portW / originalImg.width, portH / originalImg.height);
const cw = portW / scale;
const ch = portH / scale;
const cx = (originalImg.width - cw) / 2;
const cy = (originalImg.height - ch) / 2;
// Portrait Border / Shadow
ctx.shadowColor = "rgba(0,0,0,0.3)";
ctx.shadowBlur = 5;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.fillStyle = '#ffffff';
ctx.fillRect(portX, portY, portW, portH);
ctx.shadowColor = "transparent"; // Reset shadow
// Draw main photo
ctx.drawImage(originalImg, cx, cy, cw, ch, portX, portY, portW, portH);
// 6. Draw "Ghost" Photo (Security feature)
const ghostW = portW * 0.45;
const ghostH = portH * 0.45;
const ghostX = width - ghostW - 35;
const ghostY = height_canvas - ghostH - 50;
ctx.save();
ctx.globalAlpha = 0.35; // Make it look somewhat washed out/translucent
ctx.drawImage(originalImg, cx, cy, cw, ch, ghostX, ghostY, ghostW, ghostH);
ctx.restore();
// 7. Draw Machine Readable Barcode Form (Fake generic barcode)
ctx.fillStyle = '#111827';
let curX = portX + 260; // Start right after portrait
const barcodeEnd = width - ghostW - 60; // End before ghost image
let seed = 12345; // Fixed seed-like logic for visual stability
while (curX < barcodeEnd) {
// Deterministic pseudo-random generation based on index
seed = (seed * 9301 + 49297) % 233280;
const pseudoRand = seed / 233280;
const barsWidth = Math.floor(pseudoRand * 4) + 1;
const space = Math.floor((pseudoRand * 10) % 3) + 2;
ctx.fillRect(curX, 445, barsWidth, 35);
curX += barsWidth + space;
}
return canvas;
}
Apply Changes