Please bookmark this page to avoid losing your image tool!

Image Hero Character Identity Scanner

(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, themeColor = "#00ff00", language = "RU", scanSpeed = 3) {
    // Determine maximum dimensions to maintain performance
    const MAX_DIM = 800;
    let w = originalImg.width;
    let h = originalImg.height;
    
    if (w > MAX_DIM || h > MAX_DIM) {
        const ratio = Math.min(MAX_DIM / w, MAX_DIM / h);
        w = Math.floor(w * ratio);
        h = Math.floor(h * ratio);
    }

    const canvas = document.createElement('canvas');
    canvas.width = w;
    canvas.height = h;
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    // Draw the image first to gather seed data
    ctx.drawImage(originalImg, 0, 0, w, h);
    
    // Generate a pseudo-random seed based on image contents (so the same face gets the same stats)
    let seed = 0;
    try {
        const sampleSize = Math.min(w, 50);
        const imgData = ctx.getImageData(Array.from({length: 10}, () => Math.random() * (w - sampleSize))[0] || 0, 0, sampleSize, Math.min(h, 50)).data;
        for (let i = 0; i < imgData.length; i += 4) {
            seed += (imgData[i] + imgData[i + 1] * 2 + imgData[i + 2] * 3) * (i + 1);
        }
    } catch(e) {
        // Fallback if cross-origin image blocks getImageData
        seed = Math.random() * 999999;
    }

    // Pseudo-random number generator
    function random() {
        let x = Math.sin(seed++) * 10000;
        return x - Math.floor(x);
    }

    const isRU = language.toUpperCase() === "RU";

    // Data tables for Hero Identity
    const classesRU = ['ВОИН', 'МАГ', 'СНАЙПЕР', 'ПАЛАДИН', 'КИБЕР-НИНДЗЯ', 'БЕРСЕРК', 'ТЕХНОЖРЕЦ', 'АССАСИН', 'СТРАННИК'];
    const classesEN = ['WARRIOR', 'MAGE', 'SNIPER', 'PALADIN', 'CYBER-NINJA', 'BERSERKER', 'TECHNOPRIEST', 'ASSASSIN', 'ROVER'];
    const classes = isRU ? classesRU : classesEN;

    const alignsRU = ['ЗАКОНОПОСЛУШНЫЙ ДОБРЫЙ', 'ИСТИННО НЕЙТРАЛЬНЫЙ', 'ХАОТИЧНО ДОБРЫЙ', 'ХАОТИЧНО ЗЛОЙ', 'АНТИГЕРОЙ'];
    const alignsEN = ['LAWFUL GOOD', 'TRUE NEUTRAL', 'CHAOTIC GOOD', 'CHAOTIC EVIL', 'ANTIHERO'];
    const aligns = isRU ? alignsRU : alignsEN;

    // Assign stats
    const charClass = classes[Math.floor(random() * classes.length)];
    const align = aligns[Math.floor(random() * aligns.length)];
    const powerLvl = Math.floor(random() * 9000) + 1000;

    let threatLvl = "";
    let threatColor = themeColor;
    
    if (powerLvl >= 9000) {
        threatLvl = isRU ? "КРИТИЧЕСКАЯ (УРОВЕНЬ БОГА)" : "CRITICAL (GOD LEVEL)";
        threatColor = "#ff2222"; // Red
    } else if (powerLvl > 5000) {
        threatLvl = isRU ? "ВЫСОКАЯ" : "HIGH";
        threatColor = "#ffaa00"; // Orange
    } else {
        threatLvl = isRU ? "СРЕДНЯЯ" : "MODERATE";
    }

    const statsArray = isRU ? [
        "СИСТЕМА ИДЕНТИФИКАЦИИ ГЕРОЯ...",
        "------------------------------",
        `КЛАСС       : ${charClass}`,
        `МИРОВОЗЗР.  : ${align}`,
        `УРОВЕНЬ СИЛЫ: ${powerLvl}`,
        `ВЕРОЯТ.УГРОЗ: ${threatLvl}`
    ] : [
        "HERO IDENTITY SCANNER...",
        "------------------------------",
        `CLASS       : ${charClass}`,
        `ALIGNMENT   : ${align}`,
        `POWER LEVEL : ${powerLvl}`,
        `THREAT COEFF: ${threatLvl}`
    ];

    // Animation state
    let scanY = 0;
    let scanDir = 1;
    let frame = 0;
    let pConnected = false;

    function draw() {
        // Prevent memory leak if canvas is removed from the DOM
        if (canvas.isConnected) {
            pConnected = true;
        } else if (pConnected) {
            return; 
        }

        frame++;
        ctx.clearRect(0, 0, w, h);

        // Draw original base image
        ctx.drawImage(originalImg, 0, 0, w, h);

        // Apply dark overlay
        ctx.fillStyle = "rgba(0, 5, 0, 0.45)";
        ctx.fillRect(0, 0, w, h);

        // Animated grid background
        ctx.lineWidth = 1;
        ctx.strokeStyle = themeColor;
        ctx.globalAlpha = 0.15;
        const gridSize = 40;
        const yOffset = (frame * 0.5) % gridSize;
        ctx.beginPath();
        for (let x = 0; x < w; x += gridSize) {
            ctx.moveTo(x, 0); ctx.lineTo(x, h);
        }
        for (let y = 0; y < h + gridSize; y += gridSize) {
            ctx.moveTo(0, y - yOffset); ctx.lineTo(w, y - yOffset);
        }
        ctx.stroke();
        ctx.globalAlpha = 1.0;

        // HUD Corner brackets
        const cLen = Math.max(30, w * 0.05);
        ctx.lineWidth = 4;
        ctx.strokeStyle = themeColor;
        ctx.shadowColor = themeColor;
        ctx.shadowBlur = 8;
        const m = 20; // margin
        
        ctx.beginPath(); ctx.moveTo(m + cLen, m); ctx.lineTo(m, m); ctx.lineTo(m, m + cLen); ctx.stroke(); // Top Left
        ctx.beginPath(); ctx.moveTo(w - m - cLen, m); ctx.lineTo(w - m, m); ctx.lineTo(w - m, m + cLen); ctx.stroke(); // Top Right
        ctx.beginPath(); ctx.moveTo(m + cLen, h - m); ctx.lineTo(m, h - m); ctx.lineTo(m, h - m - cLen); ctx.stroke(); // Bottom Left
        ctx.beginPath(); ctx.moveTo(w - m - cLen, h - m); ctx.lineTo(w - m, h - m); ctx.lineTo(w - m, h - m - cLen); ctx.stroke(); // Bottom Right
        ctx.shadowBlur = 0;

        // Moving central target box
        const targetW = w * 0.4;
        const targetH = h * 0.4;
        const tX = (w - targetW) / 2 + Math.sin(frame * 0.04) * 8;
        const tY = (h - targetH) / 2 + Math.cos(frame * 0.03) * 6;

        ctx.lineWidth = 2;
        ctx.strokeStyle = "rgba(255, 255, 255, 0.4)";
        ctx.setLineDash([15, 10]);
        ctx.strokeRect(tX, tY, targetW, targetH);
        
        // Inner reticle crosshairs
        ctx.beginPath();
        ctx.moveTo(tX + targetW/2, tY - 10); ctx.lineTo(tX + targetW/2, tY + 10);
        ctx.moveTo(tX + targetW/2, tY + targetH - 10); ctx.lineTo(tX + targetW/2, tY + targetH + 10);
        ctx.moveTo(tX - 10, tY + targetH/2); ctx.lineTo(tX + 10, tY + targetH/2);
        ctx.moveTo(tX + targetW - 10, tY + targetH/2); ctx.lineTo(tX + targetW + 10, tY + targetH/2);
        ctx.stroke();
        ctx.setLineDash([]);

        // Main Sweep Scanline
        const sH = 3; 
        ctx.fillStyle = themeColor;
        ctx.shadowColor = themeColor;
        ctx.shadowBlur = 10;
        ctx.fillRect(0, scanY, w, sH);

        // Scanline gradient trail
        const gradient = ctx.createLinearGradient(0, scanY, 0, scanY - (40 * scanDir));
        gradient.addColorStop(0, themeColor);
        gradient.addColorStop(1, "transparent");
        ctx.fillStyle = gradient;
        ctx.globalAlpha = 0.25;
        ctx.fillRect(0, scanDir === 1 ? scanY - 40 : scanY, w, 40);
        
        ctx.globalAlpha = 1.0;
        ctx.shadowBlur = 0;

        // Move scanline
        scanY += scanSpeed * scanDir;
        if (scanY > h || scanY < 0) {
            scanDir *= -1;
        }

        // Render Text / Stats with Typewriter effect
        const fontSize = Math.max(14, Math.floor(Math.min(w, h) * 0.035));
        ctx.font = `bold ${fontSize}px "Courier New", Courier, monospace`;
        ctx.textAlign = "left";
        ctx.textBaseline = "top";

        const textX = m + 15;
        let textY = m + 15 + (frame % 10 < 5 ? Math.random() : 0); // slight glitch shake on text

        const charsPerFrame = 1.5;
        const maxChars = Math.floor(frame * charsPerFrame);
        let currentChars = 0;

        for (let i = 0; i < statsArray.length; i++) {
            const line = statsArray[i];
            if (currentChars >= maxChars) break;

            const charsToDraw = Math.min(line.length, maxChars - currentChars);
            const subLine = line.substring(0, charsToDraw);

            // Conditional styling for the "Threat" line
            if (i === statsArray.length - 1 && charsToDraw === line.length) {
                // Flash threat level if critical
                ctx.fillStyle = (frame % 30 < 15) ? threatColor : "#ffffff";
                ctx.shadowColor = threatColor;
                ctx.shadowBlur = 8;
            } else {
                ctx.fillStyle = themeColor;
                ctx.shadowColor = "#000000";
                ctx.shadowBlur = 4;
            }

            // Draw text background to ensure readability over bright images
            ctx.fillStyle = "rgba(0,0,0,0.4)";
            ctx.shadowBlur = 0;
            ctx.fillRect(textX - 5, textY - 2, ctx.measureText(subLine).width + 10, fontSize + 4);

            // Draw actual text
            ctx.fillStyle = (i === statsArray.length - 1 && charsToDraw === line.length) ? ((frame % 30 < 15) ? threatColor : "#ffffff") : themeColor;
            ctx.shadowColor = (i === statsArray.length - 1 && charsToDraw === line.length) ? threatColor : "#000";
            ctx.shadowBlur = (i === statsArray.length - 1 && charsToDraw === line.length) ? 8 : 4;
            ctx.fillText(subLine, textX, textY);
            
            textY += fontSize + 12;
            currentChars += line.length;
        }

        // Right side scrolling decorative binary
        ctx.shadowBlur = 0;
        ctx.fillStyle = themeColor;
        ctx.globalAlpha = 0.6;
        ctx.font = `${Math.max(10, fontSize * 0.75)}px "Courier New", Courier, monospace`;
        ctx.textAlign = "right";
        for (let i = 0; i < Math.floor(h / 25); i++) {
            if (Math.random() > 0.05) { // Occasional empty spots for glitchy look
                const bin = Math.random().toString(2).substr(2, 8);
                const yPos = h - m - 15 - (i * 20) + ((frame * 0.5) % 20);
                if (yPos > m && yPos < h - m) {
                    ctx.fillText(bin, w - m - 15, yPos);
                }
            }
        }
        ctx.globalAlpha = 1.0;

        requestAnimationFrame(draw);
    }

    draw();
    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 Image Hero Character Identity Scanner is a fun, interactive tool that transforms uploaded images into stylized, RPG-style hero profiles. Using an animated HUD (Heads-Up Display) effect with scanlines and digital overlays, the tool ‘scans’ an image to assign it a unique fantasy identity, including a character class (such as Mage, Warrior, or Cyber-Ninja), a moral alignment, a power level, and a threat coefficient. This tool is perfect for social media enthusiasts, gamers, and content creators looking to add a creative, cinematic flair to their profile pictures or character concepts.

Leave a Reply

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