Please bookmark this page to avoid losing your image tool!

California State ID Card Generator For Ronald Sanchez

(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, firstName = "RONALD", lastName = "SANCHEZ", dob = "08/15/1985", address1 = "123 MAIN ST", address2 = "SACRAMENTO, CA 95814", idNumber = "I1234567", expDate = "08/15/2026", sex = "M", hair = "BLK", eyes = "BRN", height = "5'-10\"", weight = "175 lb") {
    
    // Create base canvas representing a standard ID size
    // Renamed local dimension variables to avoid regex-based sandbox conflicts with parameter names
    const canvas = document.createElement('canvas');
    const targetW = 856;
    const targetH = 540;
    
    // Use bracket notation to prevent naive sandbox regexes from extracting "height" as a duplicate declaration 
    canvas['width'] = targetW;
    canvas['height'] = targetH;
    
    const ctx = canvas.getContext('2d');

    // 1. Background Fill with soft distinct gradient
    const grad = ctx.createLinearGradient(0, 0, targetW, targetH);
    grad.addColorStop(0, '#e5f3fa');
    grad.addColorStop(0.5, '#fffdef');
    grad.addColorStop(1, '#e5f3fa');
    ctx.fillStyle = grad;
    ctx.fillRect(0, 0, targetW, targetH);

    // 2. Security Guilloche Pattern (wavy lines)
    ctx.lineWidth = 1;
    ctx.globalAlpha = 0.4;
    for (let i = 0; i < 40; i++) {
        ctx.beginPath();
        ctx.strokeStyle = i % 2 === 0 ? '#ffcce6' : '#cce6ff';
        for (let posX = 0; posX < targetW; posX += 10) {
            let posY = (i * 15) + Math.sin(posX * 0.02 + i) * 20;
            if (posX === 0) ctx.moveTo(posX, posY);
            else ctx.lineTo(posX, posY);
        }
        ctx.stroke();
    }
    
    // 3. Holographic repeating background text
    ctx.globalAlpha = 0.07;
    ctx.fillStyle = '#cc8800';
    ctx.font = 'bold 36px Arial';
    ctx.rotate(-Math.PI / 6);
    for (let bgX = -500; bgX < targetW * 2; bgX += 250) {
        for (let bgY = -500; bgY < targetH * 2; bgY += 100) {
            ctx.fillText('CALIFORNIA', bgX, bgY);
        }
    }
    ctx.rotate(Math.PI / 6);
    ctx.globalAlpha = 1.0;

    // Helper to carefully crop/fit user portraits
    function drawCoverImage(img, cropX, cropY, cropW, cropH) {
        // Obscured the property names via bracket notation to prevent regex-based false matches
        const imgRatio = img['width'] / img['height'];
        const boxRatio = cropW / cropH;
        let sourceW = img['width'];
        let sourceH = img['height'];
        let sx = 0;
        let sy = 0;

        if (imgRatio > boxRatio) {
            sourceW = img['height'] * boxRatio;
            sx = (img['width'] - sourceW) / 2;
        } else {
            sourceH = img['width'] / boxRatio;
            sy = (img['height'] - sourceH) / 5; // offset slightly top for portraits
        }
        ctx.drawImage(img, sx, sy, sourceW, sourceH, cropX, cropY, cropW, cropH);
    }

    // 4. Ghost Portrait (on the lower right)
    ctx.globalAlpha = 0.3;
    drawCoverImage(originalImg, 660, 280, 140, 190);
    ctx.globalAlpha = 1.0;

    // 5. Header Area Elements
    ctx.fillStyle = '#0a2351';
    ctx.font = 'italic bold 55px Georgia, "Times New Roman", serif';
    ctx.fillText('California', 280, 65);

    ctx.fillStyle = '#cc0000';
    ctx.font = '30px Arial';
    ctx.fillText('★', 540, 60);

    ctx.fillStyle = '#0a2351';
    ctx.font = 'bold 16px Arial';
    ctx.fillText('IDENTIFICATION CARD', 285, 95);

    // Render Real-ID Golden Pill graphic
    function drawPill(px, py, pw, ph) {
        ctx.beginPath();
        ctx.moveTo(px + ph/2, py);
        ctx.lineTo(px + pw - ph/2, py);
        ctx.arcTo(px + pw, py, px + pw, py + ph/2, ph/2);
        ctx.arcTo(px + pw, py + ph, px + pw - ph/2, py + ph, ph/2);
        ctx.lineTo(px + ph/2, py + ph);
        ctx.arcTo(px, py + ph, px, py + ph/2, ph/2);
        ctx.arcTo(px, py, px + ph/2, py, ph/2);
        ctx.closePath();
        ctx.fill();
    }
    ctx.fillStyle = 'rgba(218, 165, 32, 0.9)';
    drawPill(720, 25, 100, 60);
    ctx.fillStyle = '#ffffff';
    ctx.font = '28px Arial';
    ctx.fillText('★', 756, 66);

    // 6. Detailed Text Fields mapping over identity data
    // Row 1: ID details
    ctx.fillStyle = '#000000';
    ctx.font = '14px Arial';
    ctx.fillText('ID', 285, 135);
    ctx.font = 'bold 24px Arial';
    ctx.fillStyle = '#cc0000';
    ctx.fillText(idNumber, 310, 135);

    // Exp Details
    ctx.fillStyle = '#0a2351';
    ctx.font = '14px Arial';
    ctx.fillText('EXP', 520, 135);
    ctx.font = 'bold 22px Arial';
    ctx.fillStyle = '#cc0000';
    ctx.fillText(expDate, 560, 135);

    // Stats Section (Y=175)
    const statsY = 175;
    ctx.fillStyle = '#000000';
    ctx.font = '14px Arial';
    ctx.fillText('DOB', 285, statsY);
    ctx.font = 'bold 20px Arial';
    ctx.fillStyle = '#cc0000';
    ctx.fillText(dob, 330, statsY);

    // Physical Stats Labels (Y=215)
    const physY = 215;
    ctx.font = '12px Arial';
    ctx.fillStyle = '#555555';
    ctx.fillText('SEX', 285, physY);
    ctx.fillText('HAIR', 335, physY);
    ctx.fillText('EYES', 385, physY);
    ctx.fillText('HGT', 435, physY);
    ctx.fillText('WGT', 495, physY);

    // Physical Stats Values (Y=235)
    ctx.font = 'bold 16px Arial';
    ctx.fillStyle = '#000000';
    ctx.fillText(sex, 285, physY + 20);
    ctx.fillText(hair, 335, physY + 20);
    ctx.fillText(eyes, 385, physY + 20);
    ctx.fillText(height, 435, physY + 20);
    ctx.fillText(weight, 495, physY + 20);

    // VETERAN marker
    ctx.fillStyle = '#008000';
    ctx.font = 'bold 16px Arial';
    ctx.fillText('VETERAN', 720, 160);

    // Pink Donor Dot marker
    ctx.fillStyle = '#ff66b2';
    ctx.beginPath();
    ctx.arc(770, 220, 16, 0, Math.PI * 2);
    ctx.fill();
    ctx.fillStyle = '#ffffff';
    ctx.font = 'bold 12px Arial';
    ctx.fillText('DONOR', 748, 224);

    // Main Names section (Y=285)
    const nameY = 285;
    ctx.font = '12px Arial';
    ctx.fillStyle = '#555555';
    ctx.fillText('LN', 285, nameY);
    ctx.font = 'bold 24px Arial';
    ctx.fillStyle = '#000000';
    ctx.fillText(lastName, 310, nameY + 5);

    ctx.font = '12px Arial';
    ctx.fillStyle = '#555555';
    ctx.fillText('FN', 285, nameY + 35);
    ctx.font = 'bold 24px Arial';
    ctx.fillStyle = '#000000';
    ctx.fillText(firstName, 310, nameY + 40);

    // Formatted Address block
    const addressY = 365;
    ctx.font = 'bold 18px Arial';
    ctx.fillText(address1, 285, addressY);
    ctx.fillText(address2, 285, addressY + 25);

    // Signature Rendering Base
    ctx.font = '36px "Brush Script MT", "Lucida Handwriting", cursive';
    ctx.fillStyle = '#000000';
    ctx.fillText(`${firstName} ${lastName}`, 285, 450);
    
    // Draw solid guide line underneath signature
    ctx.beginPath();
    ctx.moveTo(280, 455);
    ctx.lineTo(600, 455);
    ctx.lineWidth = 1;
    ctx.strokeStyle = '#888888';
    ctx.stroke();

    // Bottom administrative details
    ctx.fillStyle = '#0a2351';
    ctx.font = 'bold 14px Arial';
    ctx.fillText('CLASS', 40, 510);
    ctx.font = 'bold 22px Arial';
    ctx.fillText('C', 95, 512);

    ctx.font = '10px Arial';
    ctx.fillStyle = '#000000';
    ctx.fillText('END', 150, 500);
    ctx.fillText('NONE', 150, 515);

    ctx.fillText('HAZMAT', 220, 500);
    ctx.fillText('NONE', 220, 515);

    ctx.font = 'bold 14px Arial';
    ctx.fillStyle = '#0a2351';
    ctx.fillText('ISS', 370, 510);
    ctx.font = '16px Arial';
    ctx.fillStyle = '#000000';
    // Just mapping issue date to roughly ~ 5 years before exp
    const issYear = parseInt(expDate.split('/')[2], 10) - 5;
    const issStr = `${expDate.substring(0,6)}${issYear}`;
    ctx.fillText(issStr, 400, 510);

    // 7. Full Main Portrait Render
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(36, 126, 228, 308);
    drawCoverImage(originalImg, 40, 130, 220, 300);

    // DOB overlaid under the portrait with outline
    ctx.font = 'bold 22px Arial';
    ctx.fillStyle = '#cc0000';
    ctx.strokeStyle = '#ffffff';
    ctx.lineWidth = 3;
    ctx.strokeText(dob, 70, 465);
    ctx.fillText(dob, 70, 465);

    // Phantom signature gently flowing over portrait side
    ctx.globalAlpha = 0.5;
    ctx.fillStyle = '#ffffff';
    ctx.font = '24px "Brush Script MT", "Lucida Handwriting", cursive';
    ctx.fillText(`${firstName} ${lastName}`, 45, 410);
    ctx.globalAlpha = 1.0;

    // 8. Mask the card to have natural rounded corners
    ctx.globalCompositeOperation = 'destination-in';
    ctx.beginPath();
    const r = 25; // Corner radius
    ctx.moveTo(r, 0);
    ctx.lineTo(targetW - r, 0);
    ctx.arcTo(targetW, 0, targetW, r, r);
    ctx.lineTo(targetW, targetH - r);
    ctx.arcTo(targetW, targetH, targetW - r, targetH, r);
    ctx.lineTo(r, targetH);
    ctx.arcTo(0, targetH, 0, targetH - r, r);
    ctx.lineTo(0, r);
    ctx.arcTo(0, 0, r, 0, r);
    ctx.closePath();
    ctx.fill();
    ctx.globalCompositeOperation = 'source-over';

    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 allows users to generate a customized identification card layout by combining a portrait image with various personal details. It overlays text information such as name, date of birth, address, and physical characteristics onto a stylized background that includes security-inspired design elements like gradients, patterns, and watermark effects. This tool can be used for creative projects, role-playing game assets, or as a template for designing novelty membership or identification cards.

Leave a Reply

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