Please bookmark this page to avoid losing your image tool!

Virginia Drivers License Photo Utility

(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,
    lastName = "DOE",
    firstName = "JANE",
    address = "123 MAIN ST\nANYTOWN, VA 23220",
    dob = "01-01-1990",
    iss = "01-01-2024",
    exp = "01-01-2032",
    dd = "A12-34-5678",
    sex = "F",
    height = "5-09",
    eyes = "BRO",
    signature = "Jane Doe"
) {
    // 1. Setup Canvas
    const canvas = document.createElement('canvas');
    const CARD_WIDTH = 856;
    const CARD_HEIGHT = 540;
    canvas.width = CARD_WIDTH;
    canvas.height = CARD_HEIGHT;
    const ctx = canvas.getContext('2d');

    // 2. Load Resources (Fonts & SVGs)
    const loadFont = async (name, url) => {
        if (document.fonts.check(`12px ${name}`)) {
            return;
        }
        const font = new FontFace(name, `url(${url})`);
        try {
            await font.load();
            document.fonts.add(font);
        } catch (e) {
            console.error(`Font ${name} failed to load:`, e);
        }
    };

    await Promise.all([
        loadFont('Oswald', 'https://fonts.gstatic.com/s/oswald/v49/TK3_WkUHHAIjg75cFRf3bXL8LICs1_FvgUE.woff2'),
        loadFont('RobotoCondensed', 'https://fonts.gstatic.com/s/robotocondensed/v25/ieVi2ZhZI2eCN5jzbjEETS9weq8-33mZKCMS1upZQ_cehA.woff2'),
        loadFont('DancingScript', 'https://fonts.gstatic.com/s/dancingscript/v24/If2SXTr6YS-zF4S-kcSWSVi_szLviuEViw.woff2')
    ]);

    const loadImageFromSVG = async (svgString) => {
        const img = new Image();
        const svgBlob = new Blob([svgString], {
            type: 'image/svg+xml;charset=utf-8'
        });
        const url = URL.createObjectURL(svgBlob);
        return new Promise((resolve, reject) => {
            img.onload = () => {
                URL.revokeObjectURL(url);
                resolve(img);
            };
            img.onerror = () => {
                URL.revokeObjectURL(url);
                reject(new Error('Failed to load image from SVG string'));
            };
            img.src = url;
        });
    };

    const realIdStarSVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="49" fill="#000"/><path fill="#f0c400" d="M50 10l12 25 27 4 -20 19 5 27 -24 -13 -24 13 5 -27 -20 -19 27 -4z"/></svg>`;
    const starImage = await loadImageFromSVG(realIdStarSVG);


    // 3. Draw Background
    const gradient = ctx.createLinearGradient(0, 0, 0, CARD_HEIGHT);
    gradient.addColorStop(0, '#e0f4ff');
    gradient.addColorStop(1, '#ffffff');
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, CARD_WIDTH, CARD_HEIGHT);

    // Draw faint background seal
    ctx.save();
    ctx.globalAlpha = 0.08;
    ctx.strokeStyle = '#000000';
    ctx.lineWidth = 10;
    const sealX = CARD_WIDTH / 2;
    const sealY = CARD_HEIGHT / 2 + 30;
    const sealR = 180;
    ctx.beginPath();
    ctx.arc(sealX, sealY, sealR, 0, Math.PI * 2);
    ctx.stroke();

    ctx.font = 'bold 36px Oswald';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillStyle = '#000000';
    ctx.fillText('COMMONWEALTH OF VIRGINIA', sealX, sealY);
    ctx.restore();


    // 4. Draw Header
    ctx.fillStyle = '#003366'; // Dark blue
    ctx.font = 'bold 44px Oswald';
    ctx.textAlign = 'center';
    ctx.fillText('VIRGINIA', CARD_WIDTH / 2, 60);

    ctx.fillStyle = '#000000';
    ctx.font = '22px Oswald';
    ctx.fillText('DRIVER\'S LICENSE', CARD_WIDTH / 2, 90);

    ctx.drawImage(starImage, CARD_WIDTH - 80, 20, 60, 60);

    // 5. Draw Photos
    const PHOTO_X = 40;
    const PHOTO_Y = 130;
    const PHOTO_W = 250;
    const PHOTO_H = 300;

    // Main Photo with crop-to-fit (cover)
    ctx.save();
    ctx.beginPath();
    ctx.rect(PHOTO_X, PHOTO_Y, PHOTO_W, PHOTO_H);
    ctx.clip();
    const hRatio = PHOTO_W / originalImg.width;
    const vRatio = PHOTO_H / originalImg.height;
    const ratio = Math.max(hRatio, vRatio);
    const centerShiftX = (PHOTO_W - originalImg.width * ratio) / 2;
    const centerShiftY = (PHOTO_H - originalImg.height * ratio) / 2;
    ctx.drawImage(originalImg, 0, 0, originalImg.width, originalImg.height,
        PHOTO_X + centerShiftX, PHOTO_Y + centerShiftY, originalImg.width * ratio, originalImg.height * ratio);
    ctx.restore();

    ctx.strokeStyle = '#333';
    ctx.lineWidth = 1;
    ctx.strokeRect(PHOTO_X, PHOTO_Y, PHOTO_W, PHOTO_H);

    // Ghost Photo
    ctx.globalAlpha = 0.3;
    ctx.drawImage(originalImg, 320, 280, 125, 150);
    ctx.globalAlpha = 1.0;


    // 6. Draw Text Data
    ctx.textAlign = 'left';
    ctx.font = 'bold 20px RobotoCondensed';

    const drawDataField = (label, value, x, y, options = {}) => {
        const labelWidth = options.labelWidth || 70;
        const color = options.color || '#000000';

        ctx.fillStyle = '#a00000';
        ctx.fillText(label, x, y);
        ctx.fillStyle = color;

        const lines = value.split('\n');
        lines.forEach((line, index) => {
            ctx.fillText(line.toUpperCase(), x + labelWidth, y + (index * 25));
        });
    };

    let yPos = 150;
    const xPos = 320;
    const yStep = 35;

    drawDataField('DD', dd, xPos, yPos, { color: '#a00000' }); yPos += yStep;
    drawDataField('EXP', exp, xPos, yPos); yPos += yStep;
    yPos += 10;
    
    drawDataField('LN', lastName, xPos, yPos); yPos += yStep;
    drawDataField('FN', firstName, xPos, yPos); yPos += yStep;
    yPos += 10;

    const addressLines = address.split('\n');
    drawDataField('ADR', address, xPos, yPos);
    yPos += 25 * addressLines.length + 10;

    const bottomFieldsY = yPos;
    drawDataField('DOB', dob, xPos, bottomFieldsY);
    drawDataField('ISS', iss, xPos, bottomFieldsY + yStep);

    // Right-side data column
    const xPos2 = 600;
    let yPos2 = bottomFieldsY;
    drawDataField('HGT', height, xPos2, yPos2, { labelWidth: 60 }); yPos2 += yStep;
    drawDataField('SEX', sex, xPos2, yPos2, { labelWidth: 60 }); yPos2 += yStep;
    drawDataField('EYES', eyes, xPos2, yPos2, { labelWidth: 60 });

    // 7. Draw Signature
    ctx.strokeStyle = '#555';
    ctx.lineWidth = 1;
    ctx.beginPath();
    ctx.moveTo(40, CARD_HEIGHT - 60);
    ctx.lineTo(290, CARD_HEIGHT - 60);
    ctx.stroke();

    ctx.fillStyle = '#002244';
    ctx.font = '36px DancingScript';
    ctx.fillText(signature, 50, CARD_HEIGHT - 70);

    // 8. Draw decorative barcode
    ctx.fillStyle = '#000';
    for (let i = 0; i < 200; i++) {
        const x_bar = 320 + i * 2.5;
        const width_bar = Math.random() > 0.5 ? 1 : 2;
        ctx.fillRect(x_bar, CARD_HEIGHT - 40, width_bar, 30);
    }

    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

The Virginia Drivers License Photo Utility is an online tool designed to create a digital representation of a Virginia driver’s license. Users can upload their photographs and provide personal details such as name, address, date of birth, and other relevant information. The tool generates a customizable driver’s license image that includes the user’s photo, a unique license number, address, and other identifying features. This tool is particularly useful for individuals who need a visual representation of their driver’s license for educational, creative, or organizational purposes.

Leave a Reply

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