You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, name = "Cesar Rodriguez", dob = "11/2/1973", address = "890 SAWTELLE Ave San diego Ca 92114") {
const canvas = document.createElement('canvas');
const width = 600;
const height = 380;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// Helper: Clip a rounded rectangle path
function roundRectClip(ctx, x, y, w, h, r) {
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.lineTo(x + w - r, y);
ctx.quadraticCurveTo(x + w, y, x + w, y + r);
ctx.lineTo(x + w, y + h - r);
ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
ctx.lineTo(x + r, y + h);
ctx.quadraticCurveTo(x, y + h, x, y + h - r);
ctx.lineTo(x, y + r);
ctx.quadraticCurveTo(x, y, x + r, y);
ctx.closePath();
}
// Helper: Draw image with cover fill style
function customDrawImageCover(ctx, img, x, y, w, h) {
let imgRatio = img.width / img.height;
let targetRatio = w / h;
let srcX = 0, srcY = 0, srcW = img.width, srcH = img.height;
if (imgRatio > targetRatio) {
srcW = img.height * targetRatio;
srcX = (img.width - srcW) / 2;
} else {
srcH = img.width / targetRatio;
srcY = (img.height - srcH) / 2;
}
ctx.drawImage(img, srcX, srcY, srcW, srcH, x, y, w, h);
}
// Helper: Wrap text for Address
function wrapTextAndReturnY(ctx, text, x, y, maxWidth, lineHeight) {
let words = text.split(' ');
let line = '';
for (let n = 0; n < words.length; n++) {
let testLine = line + words[n] + ' ';
let metrics = ctx.measureText(testLine);
let testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
ctx.fillText(line.trim(), x, y);
line = words[n] + ' ';
y += lineHeight;
} else {
line = testLine;
}
}
ctx.fillText(line.trim(), x, y);
return y + lineHeight;
}
// Helper: Draw field with colored label
function drawField(label, value, xLinesUp, y) {
ctx.fillStyle = "#1b365d"; // Navy blue label
ctx.font = "bold 10px Arial, sans-serif";
ctx.textAlign = "right";
ctx.fillText(label, xLinesUp, y);
ctx.fillStyle = "black";
ctx.font = "bold 14px Arial, sans-serif";
ctx.textAlign = "left";
ctx.fillText(value, xLinesUp + 5, y);
}
// Helper: Draw geometric star
function drawStar(ctx, cx, cy, spikes, outerRadius, innerRadius) {
let rot = Math.PI / 2 * 3;
let x = cx, y = cy;
let step = Math.PI / spikes;
ctx.beginPath();
ctx.moveTo(cx, cy - outerRadius);
for (let i = 0; i < spikes; i++) {
x = cx + Math.cos(rot) * outerRadius;
y = cy + Math.sin(rot) * outerRadius;
ctx.lineTo(x, y);
rot += step;
x = cx + Math.cos(rot) * innerRadius;
y = cy + Math.sin(rot) * innerRadius;
ctx.lineTo(x, y);
rot += step;
}
ctx.lineTo(cx, cy - outerRadius);
ctx.closePath();
ctx.fill();
}
// Parse Name
let nameParts = name.trim().split(' ');
let lastName = nameParts.length > 1 ? nameParts.pop() : "";
let firstName = nameParts.join(' ');
if (!lastName) { lastName = firstName; firstName = ""; }
// 1. Draw Card Shape and Background
roundRectClip(ctx, 0, 0, width, height, 16);
ctx.clip(); // Limit drawing bounds to the rounded rectangle
let grd = ctx.createLinearGradient(0, 0, width, height);
grd.addColorStop(0, "#f9fcfc");
grd.addColorStop(0.5, "#e5f0f9");
grd.addColorStop(1, "#fcf7e8");
ctx.fillStyle = grd;
ctx.fillRect(0, 0, width, height);
// 2. Security Watermarks / Patterns
ctx.save();
ctx.translate(300, 190);
ctx.rotate(-Math.PI / 9);
ctx.font = "bold 110px Arial, sans-serif";
ctx.fillStyle = "rgba(255, 255, 255, 0.5)"; // Translucent white watermark
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("CALIFORNIA", 0, 0);
ctx.restore();
ctx.beginPath();
for (let x = 0; x < width; x += 5) {
ctx.lineTo(x, 220 + Math.sin(x / 15) * 8);
}
ctx.strokeStyle = "rgba(173, 216, 230, 0.3)";
ctx.lineWidth = 1;
ctx.stroke();
// 3. Top Header Divider Bar
ctx.fillStyle = "#8dc63f";
ctx.fillRect(0, 85, 200, 3);
ctx.fillStyle = "#fdb913";
ctx.fillRect(200, 85, 200, 3);
ctx.fillStyle = "#0072ce";
ctx.fillRect(400, 85, 200, 3);
// 4. Header Titles
ctx.font = "italic bold 45px 'Brush Script MT', 'Lucida Handwriting', 'Apple Chancery', cursive";
ctx.fillStyle = "#c72027"; // CA Red
ctx.textAlign = "center";
ctx.strokeStyle = "white";
ctx.lineWidth = 4;
ctx.strokeText("California", 300, 48);
ctx.fillText("California", 300, 48);
ctx.font = "bold 16px Arial, sans-serif";
ctx.fillStyle = "#1b365d";
ctx.fillText("DRIVER LICENSE", 300, 72);
ctx.font = "bold 12px Arial, sans-serif";
ctx.fillText("USA", 550, 25);
// 5. Real ID Star (Top Right)
ctx.fillStyle = "#d4af37"; // Gold
ctx.beginPath();
ctx.arc(550, 55, 16, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = "white";
drawStar(ctx, 550, 55, 5, 10, 4);
// 6. Draw Primary Portrait Images
const imgX = 20, imgY = 105, imgW = 130, imgH = 170;
ctx.save();
roundRectClip(ctx, imgX, imgY, imgW, imgH, 10);
ctx.clip();
customDrawImageCover(ctx, originalImg, imgX, imgY, imgW, imgH);
ctx.restore();
// Portrait border
ctx.strokeStyle = "rgba(27, 54, 93, 0.4)";
ctx.lineWidth = 2;
ctx.stroke();
// 7. Ghost Portrait
const gX = 480, gY = 240, gW = 90, gH = 115;
ctx.save();
ctx.globalAlpha = 0.35;
roundRectClip(ctx, gX, gY, gW, gH, 8);
ctx.clip();
customDrawImageCover(ctx, originalImg, gX, gY, gW, gH);
ctx.restore();
// 8. Text Fields Layout (Right-aligned guides at X = 195, 280, 380, etc.)
const startX = 195;
drawField("DL", "X" + Math.floor(1000000 + Math.random() * 9000000), startX, 115);
drawField("EXP", "11/02/2028", 345, 115);
drawField("CLASS", "C", 495, 115);
drawField("LN", lastName.toUpperCase(), startX, 140);
drawField("FN", firstName.toUpperCase(), startX, 165);
// Address handling
ctx.fillStyle = "black";
ctx.font = "bold 14px Arial, sans-serif";
ctx.textAlign = "left";
let yAfterAddress = wrapTextAndReturnY(ctx, address.toUpperCase(), startX + 5, 190, 275, 18);
// DOB
let dobY = yAfterAddress + 15;
ctx.fillStyle = "#1b365d";
ctx.font = "bold 10px Arial, sans-serif";
ctx.textAlign = "right";
ctx.fillText("DOB", startX, dobY);
ctx.fillStyle = "#c72027"; // Important fields in red
ctx.font = "bold 16px Arial, sans-serif";
ctx.textAlign = "left";
ctx.fillText(dob.toUpperCase(), startX + 5, dobY);
// Stats Section
let heightY = dobY + 28;
drawField("SEX", "M", startX, heightY);
drawField("HAIR", "BLK", 280, heightY);
drawField("EYES", "BRN", 380, heightY);
let infoY2 = heightY + 25;
drawField("HGT", "5'-08\"", startX, infoY2);
drawField("WGT", "165 lb", 280, infoY2);
drawField("ISS", "08/14/2023", 380, infoY2);
// 9. Signature
ctx.font = "32px 'Brush Script MT', 'Lucida Handwriting', 'Apple Chancery', cursive";
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// Place roughly between the portrait and the ghost image
ctx.fillText(name, 315, 350, 270);
return canvas;
}
Apply Changes