Please bookmark this page to avoid losing your image tool!

California Driver License Photorealistic Image 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.
async function processImage(
    originalImg, 
    dlNumber = "D7658681", 
    expDate = "03/30/2029", 
    dob = "03/30/1969", 
    lastName = "STEWART", 
    firstName = "RONALD", 
    address1 = "10 PELICAN CT", 
    address2 = "SACRAMENTO, CA 95833", 
    sex = "M", 
    hair = "BRN", 
    eyes = "BRO", 
    height = "5-06", 
    weight = "142", 
    dlClass = "C"
) {
    // 1. Setup Canvas (High-resolution, ~standard card aspect ratio 8:5)
    const cw = 1600;
    const ch = 1008;
    const canvas = document.createElement('canvas');
    canvas.width = cw;
    canvas.height = ch;
    const ctx = canvas.getContext('2d');

    // Polyfill roundRect for older canvas versions
    if (!ctx.roundRect) {
        ctx.roundRect = function (x, y, w, h, r) {
            this.beginPath();
            this.moveTo(x + r, y);
            this.arcTo(x + w, y, x + w, y + h, r);
            this.arcTo(x + w, y + h, x, y + h, r);
            this.arcTo(x, y + h, x, y, r);
            this.arcTo(x, y, x + w, y, r);
            this.closePath();
            return this;
        };
    }

    // 2. Dynamically Load Required Google Fonts
    const loadFonts = async () => {
        const link = document.createElement('link');
        link.href = 'https://fonts.googleapis.com/css2?family=Caveat:wght@700&family=Pacifico&display=swap';
        link.rel = 'stylesheet';
        document.head.appendChild(link);
        
        try {
            await document.fonts.load("100px 'Pacifico'");
            await document.fonts.load("80px 'Caveat'");
        } catch (error) {
            console.warn("Fonts loading failed or browser doesn't support API. Using fallbacks.");
        }
    };
    await loadFonts();

    // 3. Draw Background (Complex Wavy Guilloche Security Lines)
    const drawBackground = () => {
        // Base fill
        ctx.fillStyle = '#FDFDFD';
        ctx.fillRect(0, 0, cw, ch);

        ctx.lineWidth = 1.2;
        // Draw intersecting sine/bezier waves
        for (let i = 0; i < 90; i += 2) {
            ctx.beginPath();
            if (i % 3 === 0) ctx.strokeStyle = `rgba(254, 240, 138, 0.45)`;      // Yellow gradient mix
            else if (i % 2 === 0) ctx.strokeStyle = `rgba(135, 206, 235, 0.45)`; // Light blue gradient mix
            else ctx.strokeStyle = `rgba(255, 255, 255, 0.5)`;                   // White highlight

            for (let x = 0; x <= cw; x += 20) {
                let wave1 = Math.sin((x * 0.005) + i) * 200;
                let wave2 = Math.cos((x * 0.01) + (i * 0.5)) * 100;
                let y = (ch / 2) + wave1 + wave2;

                if (x === 0) ctx.moveTo(x, y);
                else ctx.lineTo(x, y);
            }
            ctx.stroke();
        }

        // Overlay faint gradient for photorealism
        const bGrad = ctx.createLinearGradient(0, 0, cw, ch);
        bGrad.addColorStop(0, 'rgba(255, 255, 255, 0.6)');
        bGrad.addColorStop(0.5, 'rgba(255, 248, 200, 0.2)');
        bGrad.addColorStop(1, 'rgba(200, 230, 245, 0.5)');
        ctx.fillStyle = bGrad;
        ctx.fillRect(0, 0, cw, ch);
    };

    // 4. Draw Header
    const drawHeader = () => {
        // USA and DRIVER LICENSE Text
        ctx.font = 'bold 28px Arial, sans-serif';
        ctx.fillStyle = '#1E3A8A';
        ctx.fillText("USA", 650, 70);
        
        ctx.font = 'bold 36px Arial, sans-serif';
        ctx.fillStyle = '#2563EB'; // lighter blue
        ctx.fillText("DRIVER LICENSE", 750, 70);

        // California Script Logo
        // Add white shadow to make script pop from background
        ctx.shadowColor = 'rgba(255,255,255,0.9)';
        ctx.shadowBlur = 10;
        ctx.font = '110px "Pacifico", cursive';
        ctx.fillStyle = '#1E3A8A'; // classic bold blue
        ctx.fillText("California", 80, 115);
        ctx.shadowBlur = 0; // reset shadow
    };

    // 5. Draw Golden Grizzly Bear with White Star
    const drawBear = () => {
        ctx.save();
        ctx.translate(1250, 20); // Top right position
        ctx.scale(1.4, 1.4);

        // Golden Gradients
        const goldGrad = ctx.createLinearGradient(0, 0, 180, 120);
        goldGrad.addColorStop(0, '#FDE047');
        goldGrad.addColorStop(0.5, '#CA8A04');
        goldGrad.addColorStop(1, '#A16207');

        ctx.fillStyle = goldGrad;
        ctx.beginPath();
        // Approximate vector shape of the California Grizzly Bear
        ctx.moveTo(10, 45); // nose
        ctx.lineTo(25, 30); // head
        ctx.lineTo(40, 15); // ear
        ctx.lineTo(55, 22); // back neck
        ctx.bezierCurveTo(75, 10, 110, 10, 130, 25); // back
        ctx.lineTo(150, 25); // hump
        ctx.bezierCurveTo(165, 30, 175, 60, 160, 85); // rump
        ctx.lineTo(155, 115); // back foot
        ctx.lineTo(135, 115);
        ctx.lineTo(135, 95);
        ctx.lineTo(120, 95); // under tail
        ctx.lineTo(115, 115);
        ctx.lineTo(95, 115); // front-back foot
        ctx.lineTo(95, 80); // belly
        ctx.lineTo(60, 75); // belly
        ctx.lineTo(45, 110); // front foot
        ctx.lineTo(25, 110); 
        ctx.lineTo(35, 75); // chest
        ctx.lineTo(15, 70);
        ctx.lineTo(8, 55);
        ctx.closePath();
        ctx.fill();

        // White cutout star in center
        ctx.globalCompositeOperation = 'destination-out';
        ctx.beginPath();
        ctx.translate(90, 45); // Center of body
        for (let i = 0; i < 5; i++) {
            ctx.lineTo(0, -16);
            ctx.translate(0, -16);
            ctx.rotate((Math.PI * 2) / 10);
            ctx.lineTo(0, 16);
            ctx.translate(0, 16);
            ctx.rotate(-(Math.PI * 6) / 10);
        }
        ctx.lineTo(0, -16);
        ctx.fill();

        // Re-draw star actual white to ensure it doesn't just cut to background lines
        ctx.globalCompositeOperation = 'source-over';
        ctx.fillStyle = '#FFFFFF';
        ctx.fill();

        ctx.restore();
    };

    // 6. Draw Photos
    const drawClippedPhoto = (img, x, y, w, h, opacity = 1.0) => {
        ctx.save();
        ctx.globalAlpha = opacity;
        
        ctx.beginPath();
        ctx.roundRect(x, y, w, h, 24); // smooth rounded corners
        ctx.clip();
        
        // Calculate dimensions to match aspect ratio (cover photo)
        const tgtAspect = w / h;
        const imgAspect = img.width / img.height;
        let sWidth = img.width, sHeight = img.height, sx = 0, sy = 0;
        
        if (imgAspect > tgtAspect) {
            sWidth = img.height * tgtAspect;
            sx = (img.width - sWidth) / 2;
        } else {
            sHeight = img.width / tgtAspect;
            sy = (img.height - sHeight) / 2;
        }
        
        ctx.drawImage(img, sx, sy, sWidth, sHeight, x, y, w, h);
        
        // Slight border line
        ctx.lineWidth = 4;
        ctx.lineJoin = "round";
        ctx.strokeStyle = "rgba(0,0,0,0.15)";
        ctx.stroke();
        
        ctx.restore();
    };

    // 7. Draw Texts Helper
    const drawLabel = (t, x, y, size = 18, align = "left", color = "#475569") => {
        ctx.font = `600 ${size}px Arial, sans-serif`;
        ctx.fillStyle = color;
        ctx.textAlign = align;
        ctx.fillText(t, x, y);
        ctx.textAlign = "left"; // reset
    };
    
    const drawValue = (t, x, y, size = 36, color = "#020617") => {
        ctx.font = `bold ${size}px Arial, sans-serif`;
        ctx.fillStyle = color;
        ctx.fillText(t, x, y);
    };

    // 8. Draw Linear Barcode
    const drawBarcode = (x, y, w, h) => {
        const seedStr = dlNumber + dob + lastName;
        ctx.fillStyle = '#0F172A';
        let cursor = x;
        for (let i = 0; i < seedStr.length * 9; i++) {
            let charC = seedStr.charCodeAt(i % seedStr.length);
            let barW = ((charC * (i + 1)) % 5) + 1;
            let gapW = ((charC * i) % 4) + 2;
            
            if (cursor + barW > x + w) break;
            ctx.fillRect(cursor, y, barW, h);
            cursor += barW + gapW;
        }
    };

    // Apply Drawing Commands
    drawBackground();
    drawHeader();
    drawBear();

    // Render Left Main Photo
    drawClippedPhoto(originalImg, 70, 180, 440, 586);

    // Render Bottom Right Ghost Photo (faded)
    drawClippedPhoto(originalImg, 1280, 580, 230, 306, 0.25);

    // Render Card Texts
    const startX = 550;
    const redColor = '#DC2626'; // Authentic red shade

    // Group 1: ID, EXP
    drawLabel("DL", startX, 210, 22);
    drawValue(dlNumber, startX + 45, 212, 46, redColor);

    drawLabel("EXP", startX + 400, 210, 22);
    drawValue(expDate, startX + 460, 212, 46, redColor);

    // Group 2: Name
    drawLabel("LN", startX, 300, 20);
    drawValue(lastName, startX, 345, 42);

    drawLabel("FN", startX, 400, 20);
    drawValue(firstName, startX, 445, 42);
    
    drawLabel("DOB", startX + 460, 400, 20);
    drawValue(dob, startX + 460, 445, 42, redColor);

    // Group 3: Address
    drawLabel("Address", startX, 510, 20);
    drawValue(address1, startX, 555, 36);
    drawValue(address2, startX, 600, 36);

    // Group 4: Physical Stats Array
    const statYLabel = 680;
    const statYVal = 720;
    const statW = 120; // column width spacing

    drawLabel("Class", startX, statYLabel, 18);
    drawValue(dlClass, startX, statYVal, 30);
    
    drawLabel("Sex", startX + statW, statYLabel, 18);
    drawValue(sex, startX + statW, statYVal, 30);
    
    drawLabel("Hair", startX + (statW * 2), statYLabel, 18);
    drawValue(hair, startX + (statW * 2), statYVal, 30);
    
    drawLabel("Eyes", startX + (statW * 3), statYLabel, 18);
    drawValue(eyes, startX + (statW * 3), statYVal, 30);
    
    drawLabel("Hgt", startX + (statW * 4.2), statYLabel, 18);
    drawValue(height, startX + (statW * 4.2), statYVal, 30);
    
    drawLabel("Wgt", startX + (statW * 5.6), statYLabel, 18);
    drawValue(weight, startX + (statW * 5.6), statYVal, 30);

    // 9. Render User Signature
    ctx.font = '80px "Caveat", cursive';
    ctx.fillStyle = '#0F172A';
    // Offset somewhat to simulate real handwritten positioning 
    ctx.fillText(`${firstName} ${lastName}`, startX, 830);

    // 10. Render Barcode at bottom middle
    drawBarcode(startX, 870, 700, 90);

    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 photorealistic digital representation of a California Driver License by overlaying user-provided images and personal data onto a high-resolution template. It features complex security design elements such as guilloche wavy lines, a golden grizzly bear icon, and a simulated barcode. Users can customize various fields including name, driver’s license number, expiration date, date of birth, address, and physical attributes. This utility can be used for creative projects, graphic design mockups, or as a placeholder in digital user interface prototyping.

Leave a Reply

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