You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
ID = "847664094",
Name = " Abdulwahab Taofeeq",
Address = "9586 Atlantic Avenue, United Kingdom",
DOB = "19/5/1948",
Class = "A",
Sex = "F",
ISS = "7/8/2023",
EXP = "7/8/2028"
) {
// 1. Setup Canvas (Standard ID ratio ~ 85.6mm x 53.98mm)
const canvas = document.createElement("canvas");
const width = 856;
const height = 540;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
// Clean up input parameters
const clnName = Name.trim();
const clnAddress = Address.trim();
// Splitting Name into Surname (1) and Given Names (2)
const spaceIdx = clnName.lastIndexOf(" ");
let surname = clnName;
let firstNames = "";
if (spaceIdx > -1) {
surname = clnName.slice(spaceIdx + 1).toUpperCase();
firstNames = clnName.slice(0, spaceIdx);
} else {
surname = clnName.toUpperCase();
}
// 2. Define Card Path (Rounded Corners)
const radius = 30;
ctx.beginPath();
ctx.moveTo(radius, 0);
ctx.lineTo(width - radius, 0);
ctx.quadraticCurveTo(width, 0, width, radius);
ctx.lineTo(width, height - radius);
ctx.quadraticCurveTo(width, height, width - radius, height);
ctx.lineTo(radius, height);
ctx.quadraticCurveTo(0, height, 0, height - radius);
ctx.lineTo(0, radius);
ctx.quadraticCurveTo(0, 0, radius, 0);
ctx.closePath();
ctx.clip(); // Restrict all drawing to card boundaries
// 3. Draw Background Gradient
const bgGrad = ctx.createLinearGradient(0, 0, width, height);
bgGrad.addColorStop(0, "#f7d9e8"); // Pinkish top left
bgGrad.addColorStop(0.5, "#dff0e4"); // Pale green middle
bgGrad.addColorStop(1, "#f4cce0"); // Pinkish bottom right
ctx.fillStyle = bgGrad;
ctx.fillRect(0, 0, width, height);
// 4. Draw Guilloche Pattern (Security Waves)
ctx.lineWidth = 1;
ctx.strokeStyle = "rgba(183, 0, 80, 0.15)";
for (let i = -200; i < height + 200; i += 18) {
ctx.beginPath();
ctx.moveTo(0, i);
ctx.bezierCurveTo(width / 3, i + 80, (2 * width) / 3, i - 80, width, i);
ctx.stroke();
}
// 5. Draw Header
ctx.fillStyle = "#b70050"; // Official magenta style color
ctx.font = "bold 32px Arial";
ctx.fillText("DRIVING LICENCE", 40, 50);
ctx.fillStyle = "#b70050";
ctx.font = "bold 11px Arial";
ctx.fillText("UNITED KINGDOM", 40, 68);
// UK Flag Placeholder
ctx.fillStyle = "#003399";
ctx.fillRect(width - 110, 20, 70, 50);
ctx.fillStyle = "#FFFFFF";
ctx.font = "bold 24px Arial";
ctx.textAlign = "center";
ctx.fillText("UK", width - 75, 54);
ctx.textAlign = "left";
// 6. Large Watermark
ctx.save();
ctx.translate(width / 2, height / 2);
ctx.rotate(-Math.PI / 8);
ctx.fillStyle = "rgba(255, 255, 255, 0.6)";
ctx.font = "bold 180px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("DVLA", 0, 0);
ctx.restore();
// 7. Draw Primary Photo (Left Side)
// Target constraints: x=40, y=90, w=160, h=200 (Ratio 4:5)
let photoX = 40, photoY = 90, photoW = 160, photoH = 200;
const aspect = photoW / photoH; // 0.8
let sWidth = originalImg.width;
let sHeight = originalImg.height;
let sx = 0, sy = 0;
// Crop center to maintain 4:5 ratio
if (sWidth / sHeight > aspect) {
let newWidth = sHeight * aspect;
sx = (sWidth - newWidth) / 2;
sWidth = newWidth;
} else {
let newHeight = sWidth / aspect;
sy = (sHeight - newHeight) / 2;
sHeight = newHeight;
}
ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, photoX, photoY, photoW, photoH);
// Add border to photo
ctx.lineWidth = 1;
ctx.strokeStyle = "rgba(0, 0, 0, 0.5)";
ctx.strokeRect(photoX, photoY, photoW, photoH);
// Add Hologram overlay on primary photo
ctx.beginPath();
ctx.arc(photoX + photoW - 20, photoY + photoH - 40, 35, 0, 2 * Math.PI);
ctx.lineWidth = 2;
ctx.strokeStyle = "rgba(255, 215, 0, 0.6)"; // Gold circle
ctx.stroke();
// 8. Draw Ghost Photo (Bottom Right Security)
ctx.globalAlpha = 0.4;
let ghostW = 100, ghostH = 125;
ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, width - 130, height - 165, ghostW, ghostH);
ctx.globalAlpha = 1.0;
// 9. Text Elements Layout Setup
const startX = 220;
const lblFont = "bold 13px Arial";
const valFont = "bold 18px Arial";
const highlightColor = "#b70050";
const textColor = "#1a1a1a";
// Helper to draw numbered fields
const drawField = (num, val, y, x = startX, sizeOffset = 0, isBoldLabel = true) => {
if (num) {
ctx.font = isBoldLabel ? lblFont : "13px Arial";
ctx.fillStyle = highlightColor;
ctx.fillText(num + ".", x, y);
}
if (val) {
ctx.font = sizeOffset ? `bold ${18 + sizeOffset}px Arial` : valFont;
ctx.fillStyle = textColor;
ctx.fillText(val, x + 25, y);
}
};
// Rendering Data Fields
drawField("1", surname, 110);
drawField("2", firstNames, 145);
drawField("3", DOB, 180);
// Incorporate Sex nicely beside DOB
ctx.font = lblFont;
ctx.fillStyle = highlightColor;
ctx.fillText("Sex:", startX + 180, 180);
ctx.font = valFont;
ctx.fillStyle = textColor;
ctx.fillText(Sex, startX + 215, 180);
// Dates & Issuing Authority
drawField("4a", ISS, 220, startX);
drawField("4b", EXP, 220, startX + 150);
drawField("4c", "DVLA", 220, startX + 300);
// Driver Number (License ID)
drawField("5", ID.toUpperCase(), 270, startX, 4);
// Address lines rendering
drawField("8", "", 320); // Label only
ctx.font = "16px Arial";
ctx.fillStyle = textColor;
let addrY = 320;
const addrLines = clnAddress.split(",");
addrLines.forEach((line) => {
ctx.fillText(line.trim(), startX + 25, addrY);
addrY += 22;
});
// Class / Categories
drawField("9", Class, addrY + 20);
// 10. Signature Area (Field 7)
const sigY = 320;
drawField("7", "", sigY, 40); // Label only
// Signature Background Box
ctx.fillStyle = "rgba(255, 255, 255, 0.9)";
ctx.fillRect(40, sigY + 5, 160, 45);
// Fake Signature Rendering
ctx.fillStyle = "#000033"; // very dark blue ink
ctx.textAlign = "center";
ctx.font = "italic 26px cursive, 'Brush Script MT', 'Times New Roman'"; // Fallbacks mimic script
ctx.fillText(firstNames + " " + surname, 120, sigY + 38, 150);
ctx.textAlign = "left";
// 11. Add Border Line representing card boundary over everything
ctx.beginPath();
ctx.moveTo(radius, 0);
ctx.lineTo(width - radius, 0);
ctx.quadraticCurveTo(width, 0, width, radius);
ctx.lineTo(width, height - radius);
ctx.quadraticCurveTo(width, height, width - radius, height);
ctx.lineTo(radius, height);
ctx.quadraticCurveTo(0, height, 0, height - radius);
ctx.lineTo(0, radius);
ctx.quadraticCurveTo(0, 0, radius, 0);
ctx.closePath();
ctx.lineWidth = 4;
ctx.strokeStyle = "#cccccc"; // gray outer edge
ctx.stroke();
return canvas;
}
Apply Changes