Please bookmark this page to avoid losing your image tool!

Realistic Driving Licence PDF Editor

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
function processImage(
    originalImg, 
    surname = "SMITH", 
    givenNames = "JOHN ARTHUR", 
    dob = "01-01-1990", 
    placeOfBirth = "LONDON", 
    issueDate = "15-05-2022", 
    expiryDate = "14-05-2032", 
    licenseNumber = "SMITH901010A99X", 
    address = "10 DOWNING STREET, WESTMINSTER, LONDON, SW1A 2AA"
) {
    // Create the container UI
    const container = document.createElement("div");
    container.style.display = "flex";
    container.style.flexDirection = "column";
    container.style.alignItems = "center";
    container.style.gap = "20px";
    container.style.fontFamily = "sans-serif";
    container.style.width = "100%";
    container.style.padding = "20px";
    container.style.boxSizing = "border-box";

    // Create the canvas for the realistic driving licence (Standard ID 856x539 px)
    const canvas = document.createElement("canvas");
    canvas.width = 856;
    canvas.height = 539;
    canvas.style.maxWidth = "100%";
    canvas.style.boxShadow = "0 8px 24px rgba(0,0,0,0.15)";
    canvas.style.borderRadius = "12px";
    const ctx = canvas.getContext("2d");

    // 1. Draw the gradient background (Realistic pink/purple/blue tones)
    const bgGradient = ctx.createLinearGradient(0, 0, 856, 539);
    bgGradient.addColorStop(0, "#f4dce9"); // Pinkish
    bgGradient.addColorStop(0.4, "#e0dcf4"); // Purplish
    bgGradient.addColorStop(1, "#cce8ea"); // Light Cyan
    ctx.fillStyle = bgGradient;
    ctx.fillRect(0, 0, 856, 539);

    // 2. Draw standard guilloche/security patterns (Sine waves)
    ctx.lineWidth = 0.5;
    for (let j = 0; j < 3; j++) {
        for (let i = 0; i < 40; i++) {
            ctx.beginPath();
            const yOffset = i * 15;
            ctx.moveTo(0, yOffset);
            for (let x = 0; x < 856; x += 5) {
                const y = yOffset + Math.sin(x / (20 + j * 10) + i) * (10 + j * 5);
                ctx.lineTo(x, y);
            }
            if (j === 0) ctx.strokeStyle = "rgba(180, 200, 230, 0.4)";
            if (j === 1) ctx.strokeStyle = "rgba(220, 180, 200, 0.3)";
            if (j === 2) ctx.strokeStyle = "rgba(230, 220, 180, 0.2)";
            ctx.stroke();
        }
    }

    // Central circular watermark (Steering wheel/crest illusion)
    ctx.globalAlpha = 0.08;
    ctx.beginPath();
    ctx.arc(520, 270, 120, 0, Math.PI * 2);
    ctx.lineWidth = 15;
    ctx.strokeStyle = "#333";
    ctx.stroke();
    ctx.moveTo(520, 150); ctx.lineTo(520, 390);
    ctx.moveTo(400, 270); ctx.lineTo(640, 270);
    ctx.stroke();
    ctx.globalAlpha = 1.0;

    // 3. Draw Flag Area (Generic UK flag representation)
    ctx.fillStyle = "#012169";
    ctx.fillRect(30, 30, 80, 56);
    ctx.strokeStyle = "#fff"; ctx.lineWidth = 6;
    ctx.beginPath(); ctx.moveTo(30, 30); ctx.lineTo(110, 86); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(110, 30); ctx.lineTo(30, 86); ctx.stroke();
    ctx.strokeStyle = "#C8102E"; ctx.lineWidth = 2;
    ctx.beginPath(); ctx.moveTo(30, 30); ctx.lineTo(110, 86); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(110, 30); ctx.lineTo(30, 86); ctx.stroke();
    ctx.strokeStyle = "#fff"; ctx.lineWidth = 12;
    ctx.beginPath(); ctx.moveTo(70, 30); ctx.lineTo(70, 86); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(30, 58); ctx.lineTo(110, 58); ctx.stroke();
    ctx.strokeStyle = "#C8102E"; ctx.lineWidth = 7;
    ctx.beginPath(); ctx.moveTo(70, 30); ctx.lineTo(70, 86); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(30, 58); ctx.lineTo(110, 58); ctx.stroke();
    ctx.strokeStyle = "rgba(0,0,0,0.1)"; ctx.lineWidth = 1;
    ctx.strokeRect(30, 30, 80, 56);

    // 4. Header Text
    ctx.fillStyle = "#8a5c73"; // Deep pinkish burgundy
    ctx.font = "bold 26px Arial, sans-serif";
    ctx.fillText("DRIVING LICENCE", 130, 50);
    ctx.fillStyle = "#333";
    ctx.font = "italic 16px Arial, sans-serif";
    ctx.fillText("UNITED KINGDOM", 130, 72);

    // 5. Draw the Main Portrait Photo (Original Image)
    const imgRatio = originalImg.width / originalImg.height;
    const targetRatio = 180 / 230;
    let sW = originalImg.width, sH = originalImg.height, sX = 0, sY = 0;
    if (imgRatio > targetRatio) {
        sW = originalImg.height * targetRatio;
        sX = (originalImg.width - sW) / 2;
    } else {
        sH = originalImg.width / targetRatio;
        sY = (originalImg.height - sH) / 2;
    }

    // Image Background + Render
    ctx.fillStyle = "#ffffff";
    ctx.fillRect(30, 115, 180, 230);
    ctx.drawImage(originalImg, sX, sY, sW, sH, 30, 115, 180, 230);
    ctx.strokeStyle = "rgba(0,0,0,0.4)";
    ctx.lineWidth = 1;
    ctx.strokeRect(30, 115, 180, 230);

    // Security Overlap Fade at bottom of image
    const imgGrad = ctx.createLinearGradient(0, 300, 0, 345);
    imgGrad.addColorStop(0, "rgba(255,255,255,0)");
    imgGrad.addColorStop(1, "rgba(240,245,250,0.6)");
    ctx.fillStyle = imgGrad;
    ctx.fillRect(30, 300, 180, 45);

    // 6. Draw the Ghost Portrait (Security Measure)
    ctx.globalAlpha = 0.25;
    ctx.drawImage(originalImg, sX, sY, sW, sH, 700, 360, 120, 153);
    ctx.globalAlpha = 1.0;

    // 7. Write the Fields
    function drawLabel(text, x, y) {
        ctx.fillStyle = "#996677";
        ctx.font = "italic 11px Arial, sans-serif";
        ctx.fillText(text, x, y);
    }
    
    function drawValue(text, x, y, size = 16) {
        ctx.fillStyle = "#111";
        ctx.font = `bold ${size}px Arial, sans-serif`;
        ctx.fillText(text, x, y);
    }

    // Line 1: Surname
    drawLabel("1. Surname", 230, 120);
    drawValue(surname.toUpperCase(), 245, 138);

    // Line 2: First names
    drawLabel("2. First names", 230, 170);
    drawValue(givenNames.toUpperCase(), 245, 188);

    // Line 3: DOB and Place
    drawLabel("3. Date and place of birth", 230, 220);
    drawValue(`${dob}    ${placeOfBirth.toUpperCase()}`, 245, 238);

    // Line 4a, 4b, 4c: Issue, Expiry, Authority
    drawLabel("4a. Date of issue", 230, 270);
    drawLabel("4b. Date of expiry", 400, 270);
    drawLabel("4c. Issuing authority", 570, 270);
    drawValue(issueDate, 245, 288);
    drawValue(expiryDate, 415, 288);
    drawValue("DVLA", 585, 288);

    // Line 5: Licence Number
    drawLabel("5. Licence number", 230, 320);
    drawValue(licenseNumber.toUpperCase(), 245, 342, 22); // Slightly larger font

    // Line 7: Signature
    drawLabel("7. Signature", 230, 390);
    ctx.fillStyle = "#000044"; // Dark blue ink look
    ctx.font = "32px 'Brush Script MT', 'Caveat', 'Segoe Script', cursive";
    const sigText = `${givenNames.split(" ")[0].charAt(0)}. ${surname}`;
    ctx.fillText(sigText, 250, 420);

    // Line 8: Address
    drawLabel("8. Address", 440, 390);
    const addrLines = address.split(',');
    for (let i = 0; i < addrLines.length && i < 4; i++) {
        drawValue(addrLines[i].trim().toUpperCase(), 455, 408 + (i * 18), 14);
    }

    // Line 9: Categories
    drawLabel("9. Categories", 230, 470);
    drawValue("AM / A / B1 / B", 245, 488);

    // Append Canvas to Container
    container.appendChild(canvas);

    // 8. Add the "Download/Print as PDF" button
    const btn = document.createElement("button");
    btn.textContent = "Download / Print as PDF";
    btn.style.padding = "12px 24px";
    btn.style.fontSize = "16px";
    btn.style.fontWeight = "bold";
    btn.style.cursor = "pointer";
    btn.style.border = "none";
    btn.style.borderRadius = "8px";
    btn.style.background = "#0056b3";
    btn.style.color = "#fff";
    btn.style.boxShadow = "0 4px 6px rgba(0,0,0,0.1)";
    btn.style.transition = "background 0.2s";

    btn.onmouseover = () => btn.style.background = "#004494";
    btn.onmouseout = () => btn.style.background = "#0056b3";

    // Handle PDF saving through Native Printing Dialogue
    btn.onclick = () => {
        try {
            const dataUrl = canvas.toDataURL("image/jpeg", 1.0);
            const iframe = document.createElement("iframe");
            iframe.style.display = "none";
            document.body.appendChild(iframe);
            
            iframe.contentDocument.write(`
                <html>
                <head>
                    <title>Driving Licence</title>
                    <style>
                        @page { size: landscape; margin: 0; }
                        body { margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background: #fff; }
                        img { max-width: 100%; max-height: 100%; object-fit: contain; }
                    </style>
                </head>
                <body>
                    <img src="${dataUrl}" />
                </body>
                </html>
            `);
            iframe.contentDocument.close();
            
            iframe.onload = () => {
                iframe.contentWindow.focus();
                iframe.contentWindow.print();
                setTimeout(() => document.body.removeChild(iframe), 2000); // Cleanup
            };
        } catch (e) {
            alert("Could not generate PDF. The original image must be securely hosted (CORS) to allow exporting.");
        }
    };

    container.appendChild(btn);

    return container;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

This tool allows users to generate a simulated driving licence layout by overlaying custom text and portrait images onto a stylized ID template. Users can input specific details such as name, date of birth, license number, and address to populate the fields. The tool incorporates design elements like background gradients, security patterns, and watermarks to create a realistic visual representation, which can then be downloaded or printed as a PDF. It is useful for graphic design mockups, educational demonstrations, or creative prototyping projects.

Leave a Reply

Your email address will not be published. Required fields are marked *