Please bookmark this page to avoid losing your image tool!

Realistic Driving License Photo And Data Generator

(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, 
    lastName = "PUBLIC",
    firstName = "JOHN Q",
    address = "100 N SENATE AVE, INDIANAPOLIS, IN 46204",
    dob = "05/10/1985",
    sex = "M",
    height = "5'-11\"",
    weight = "175",
    eyes = "BRO",
    hair = "BLK",
    dlNumber = "1234-56-7890",
    issueDate = "05/15/2022",
    expDate = "05/10/2028"
) {
    const canvas = document.createElement("canvas");
    canvas.width = 860;
    canvas.height = 540;
    const ctx = canvas.getContext("2d");

    // 1. Background Gradient
    let gradient = ctx.createLinearGradient(0, 0, 860, 540);
    gradient.addColorStop(0, "#ffffff");
    gradient.addColorStop(0.5, "#e6f0fa");
    gradient.addColorStop(1, "#f2e4e1");
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, 860, 540);

    // 2. Realistic Guilloche (micro-wave) Pattern
    ctx.save();
    ctx.lineWidth = 0.5;
    ctx.strokeStyle = "rgba(100, 130, 180, 0.15)";
    for(let i=0; i<540; i+=20) {
        ctx.beginPath();
        for(let x=0; x<=860; x+=10) {
            let y = i + Math.sin(x * 0.03) * 12 + Math.cos(x * 0.02 + i) * 6;
            if(x === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();
    }
    ctx.restore();

    // 3. Indiana Map Watermark
    ctx.save();
    ctx.translate(550, 270);
    ctx.scale(3, 3);
    ctx.fillStyle = "rgba(220, 200, 150, 0.25)";
    ctx.beginPath();
    ctx.moveTo(-20, -50); 
    ctx.lineTo(30, -50);
    ctx.lineTo(30, 50);
    ctx.bezierCurveTo(20, 55, 0, 70, -20, 60);
    ctx.bezierCurveTo(-25, 40, -35, 20, -30, -10);
    ctx.lineTo(-20, -50);
    ctx.fill();
    ctx.restore();

    // 4. Indy Race Car Watermark Background
    ctx.save();
    ctx.translate(620, 140); 
    ctx.scale(2.0, 2.0);
    ctx.globalAlpha = 0.2; 
    ctx.fillStyle = "#1e3a8a"; 
    
    // Draw Car Frame
    ctx.beginPath();
    ctx.moveTo(-60, 5); 
    ctx.lineTo(-50, 0);       // nose
    ctx.lineTo(-30, 0);       // front suspension
    ctx.lineTo(-10, -10);     // cockpit
    ctx.lineTo(20, -10);      // driver area
    ctx.lineTo(40, 5);        // engine cowl
    ctx.lineTo(60, 5);
    ctx.lineTo(60, -15);      // rear wing pillar
    ctx.lineTo(75, -15);      // rear wing
    ctx.lineTo(75, 10);
    ctx.lineTo(-60, 10);      // undertray
    ctx.fill();

    // Front wing
    ctx.fillRect(-65, 5, 15, 3); 

    // Wheels
    ctx.fillStyle = "#0f172a";
    ctx.beginPath(); ctx.arc(-40, 10, 8, 0, Math.PI*2); ctx.fill();
    ctx.beginPath(); ctx.arc(45, 10, 10, 0, Math.PI*2); ctx.fill();

    // Speed lines trailing the car
    ctx.strokeStyle = "#1e3a8a";
    ctx.lineWidth = 1.5;
    ctx.beginPath();
    ctx.moveTo(-90, 8); ctx.lineTo(-70, 8);
    ctx.moveTo(-80, 3); ctx.lineTo(-65, 3);
    ctx.moveTo(-100, 13); ctx.lineTo(-65, 13);
    ctx.stroke();
    ctx.restore();

    // 5. Header Details
    ctx.font = "italic bold 44px 'Times New Roman', Times, serif";
    ctx.fillStyle = "#1e3a8a";
    ctx.textAlign = "center";
    ctx.fillText("I N D I A N A", 430, 55);

    ctx.font = "bold 20px Arial";
    ctx.fillStyle = "#9f1239"; 
    ctx.fillText("DRIVER LICENSE", 430, 80);

    ctx.fillStyle = "rgba(250, 204, 21, 0.85)";
    ctx.fillRect(0, 95, 860, 18);
    
    ctx.font = "bold 12px Arial";
    ctx.fillStyle = "rgba(0,0,0,0.6)";
    ctx.textAlign = "right";
    ctx.fillText("USA", 840, 110);

    // 6. Draw Primary Cropped Photo
    let photoW = 200;
    let photoH = 260;
    let photoX = 40;
    let photoY = 135;

    ctx.save();
    ctx.beginPath();
    if(ctx.roundRect) {
        ctx.roundRect(photoX, photoY, photoW, photoH, 10);
    } else {
        ctx.rect(photoX, photoY, photoW, photoH);
    }
    ctx.clip();
    
    let imgRatio = originalImg.width / originalImg.height;
    let targetRatio = photoW / photoH;
    let drawW, drawH, drawX, drawY;
    if (imgRatio > targetRatio) {
        drawH = photoH;
        drawW = drawH * imgRatio;
        drawY = photoY;
        drawX = photoX - (drawW - photoW) / 2;
    } else {
        drawW = photoW;
        drawH = drawW / imgRatio;
        drawX = photoX;
        drawY = photoY - (drawH - photoH) / 2;
    }
    
    ctx.drawImage(originalImg, drawX, drawY, drawW, drawH);
    ctx.restore();
    
    // Primary photo border outline
    ctx.lineWidth = 1;
    ctx.strokeStyle = "rgba(30, 58, 138, 0.4)";
    ctx.stroke(); 

    // 7. Write Structured Data Fields
    let col1x = 260; 
    ctx.textAlign = "left";

    function addField(label, value, lx, ly, vx, vy, vSize="16px", vColor="#000000", lSize="11px") {
        ctx.font = `bold ${lSize} Arial`; 
        ctx.fillStyle = "#9f1239"; 
        ctx.fillText(label, lx, ly);
        ctx.font = `bold ${vSize} Arial`; 
        ctx.fillStyle = vColor;
        ctx.fillText(value, vx, vy);
    }

    addField("4d DLN", dlNumber, col1x, 145, col1x + 45, 146, "22px", "#000000");
    addField("3 DOB", dob, col1x + 280, 145, col1x + 325, 146, "18px", "#dc2626"); 
    addField("4b EXP", expDate, col1x + 450, 145, col1x + 495, 146, "18px", "#dc2626");

    addField("4a ISS", issueDate, col1x, 185, col1x + 45, 185, "16px", "#000000");

    addField("1", lastName.toUpperCase(), col1x, 225, col1x + 15, 225, "18px", "#000000");
    addField("2", firstName.toUpperCase(), col1x, 255, col1x + 15, 255, "18px", "#000000");

    ctx.font = "bold 11px Arial"; ctx.fillStyle = "#9f1239"; ctx.fillText("8", col1x, 295);
    const addrParts = address.split(',');
    ctx.font = "bold 16px Arial"; ctx.fillStyle = "#000000"; 
    ctx.fillText(addrParts[0].trim().toUpperCase(), col1x + 15, 295);
    if(addrParts.length > 1) {
        ctx.fillText(addrParts.slice(1).join(',').trim().toUpperCase(), col1x + 15, 315);
    }

    let statsY = 360;
    addField("15 SEX", sex.toUpperCase(), col1x, statsY, col1x, statsY + 18);
    addField("16 HGT", height.toUpperCase(), col1x + 65, statsY, col1x + 65, statsY + 18);
    addField("17 WGT", weight.toUpperCase(), col1x + 130, statsY, col1x + 130, statsY + 18);
    addField("18 EYES", eyes.toUpperCase(), col1x + 200, statsY, col1x + 200, statsY + 18);
    addField("19 HAIR", hair.toUpperCase(), col1x + 270, statsY, col1x + 270, statsY + 18);

    let classY = 420;
    addField("9 CLASS", "C", col1x, classY, col1x + 50, classY);
    addField("12 REST", "NONE", col1x + 85, classY, col1x + 140, classY);
    addField("13 END", "NONE", col1x + 200, classY, col1x + 250, classY);

    // Random DD (Document Discriminator) at bottom
    ctx.font = "10px Courier New";
    ctx.fillStyle = "#64748b";
    let randomDD = "DD " + Math.floor(Math.random()*10000000000000).toString().padStart(16, "0");
    ctx.fillText(randomDD, col1x, 460);

    // 8. Generate Laser Engraved Ghost Photo
    let ghostW = 100;
    let ghostH = 130;
    let ghostX = 720;
    let ghostY = 370; 

    // Create a temporary canvas directly mapped for the ghost filter effect
    const tCanvas = document.createElement("canvas");
    tCanvas.width = ghostW;
    tCanvas.height = ghostH;
    const tCtx = tCanvas.getContext("2d");
    
    tCtx.fillStyle = "#ffffff";
    tCtx.fillRect(0,0,ghostW,ghostH);

    // Keep aspect ratio matching entirely
    let gScale = ghostW / photoW;
    tCtx.save();
    tCtx.scale(gScale, gScale);
    tCtx.translate(-photoX, -photoY);
    tCtx.drawImage(originalImg, drawX, drawY, drawW, drawH);
    tCtx.restore();

    let idata = tCtx.getImageData(0, 0, ghostW, ghostH);
    let d = idata.data;
    for(let i=0; i<d.length; i+=4) {
        let r = d[i], g = d[i+1], b = d[i+2];
        let lum = 0.299 * r + 0.587 * g + 0.114 * b;
        
        // Boost contrast heavily to simulate engraving burn marks
        lum = (lum - 128) * 2.0 + 128;
        lum = Math.max(0, Math.min(255, lum));

        // Add subtle horizontal scanline texturing
        let row = Math.floor((i / 4) / ghostW);
        if(row % 2 === 0) {
            lum *= 0.8; 
        }

        // Output warm tinted monotone (laser burn characteristic)
        d[i] = lum * 0.90; 
        d[i+1] = lum * 0.95;
        d[i+2] = lum * 1.0; 
    }
    tCtx.putImageData(idata, 0, 0);

    // Draw the ghost back onto ID with a multiply blend to burn it in
    ctx.save();
    ctx.globalCompositeOperation = "multiply";
    ctx.globalAlpha = 0.8; 
    ctx.beginPath();
    ctx.roundRect ? ctx.roundRect(ghostX, ghostY, ghostW, ghostH, 8) : ctx.rect(ghostX, ghostY, ghostW, ghostH);
    ctx.clip();
    ctx.drawImage(tCanvas, ghostX, ghostY);
    ctx.restore();

    // 9. Fake Realistic Signature
    ctx.save();
    ctx.font = "italic 44px 'Brush Script MT', 'Bradley Hand', 'Comic Sans MS', cursive";
    ctx.fillStyle = "rgba(10, 10, 30, 0.85)"; 
    ctx.translate(140, 460);
    ctx.rotate(-0.06); // organic slant
    ctx.textAlign = "center";
    ctx.fillText(`${firstName.charAt(0).toUpperCase()}${firstName.slice(1).toLowerCase()} ${lastName.charAt(0).toUpperCase()}${lastName.slice(1).toLowerCase()}`, 0, 0);
    ctx.restore();

    ctx.strokeStyle = "#9f1239";
    ctx.lineWidth = 1;
    ctx.beginPath();
    ctx.moveTo(35, 475);
    ctx.lineTo(245, 475);
    ctx.stroke();

    // 10. Background Authenticity Seal
    ctx.save();
    ctx.translate(220, 250);
    ctx.globalAlpha = 0.15;
    ctx.beginPath(); ctx.arc(0, 0, 60, 0, Math.PI*2); 
    ctx.lineWidth = 6; ctx.strokeStyle = "#1e3a8a"; ctx.stroke();
    ctx.beginPath(); ctx.arc(0, 0, 52, 0, Math.PI*2);
    ctx.lineWidth = 1; ctx.stroke();
    ctx.fillStyle = "#1e3a8a";
    for(let i=0; i<12; i++) {
        ctx.rotate(Math.PI*2/12);
        ctx.beginPath();
        ctx.moveTo(0, -50);
        ctx.lineTo(5, -40);
        ctx.lineTo(-5, -40);
        ctx.fill();
    }
    ctx.restore();

    // 11. Fake Hologram Polish over standard components
    ctx.save();
    let holo = ctx.createLinearGradient(0, 0, 860, 540);
    holo.addColorStop(0, "rgba(255, 255, 255, 0.05)");
    holo.addColorStop(0.2, "rgba(255, 200, 200, 0.05)");
    holo.addColorStop(0.4, "rgba(200, 255, 200, 0.05)");
    holo.addColorStop(0.6, "rgba(200, 200, 255, 0.05)");
    holo.addColorStop(1, "rgba(255, 255, 255, 0.05)");
    ctx.globalCompositeOperation = "screen";
    ctx.fillStyle = holo;
    ctx.fillRect(0, 0, 860, 540);
    ctx.restore();

    // 12. Finalize Base Shape (Card Edges & Punchout)
    ctx.lineWidth = 4;
    ctx.strokeStyle = "#dddddd";
    ctx.beginPath();
    ctx.roundRect ? ctx.roundRect(0, 0, 860, 540, 16) : ctx.rect(0, 0, 860, 540);
    ctx.stroke();

    ctx.globalCompositeOperation = "destination-in";
    ctx.beginPath();
    ctx.fillStyle = "#000";
    if (ctx.roundRect) {
        ctx.roundRect(0, 0, 860, 540, 16);
    } else {
        ctx.rect(0, 0, 860, 540);
    }
    ctx.fill();

    return canvas;
}

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 generates a simulated driver’s license image by overlaying customizable personal data onto a background designed with security-style patterns, such as guilloche textures and watermarks. Users can input details including name, address, date of birth, physical characteristics, and license numbers, and upload a photo to be processed with effects like a ‘ghost’ laser-engraved image and a digital signature. It can be used for creative projects, graphic design mockups, or as a placeholder for testing user interface layouts in applications that require identity document visualizations.

Leave a Reply

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