Please bookmark this page to avoid losing your image tool!

Image Alien Transformation Tool

(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, skinColorParam = "AAD0AA", eyeScleraColorParam = "FF0000", brainColorParam = "F5C6C6", domeOpacityParam = 0.2) {

    // --- Helper Functions ---
    function hexToRgb(hex) {
        const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        return result ? {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16)
        } : { r: 0, g: 0, b: 0 }; // Default to black if invalid
    }

    function rgbToHsl(r, g, b) {
        r /= 255; g /= 255; b /= 255;
        const max = Math.max(r, g, b), min = Math.min(r, g, b);
        let h, s, l = (max + min) / 2;

        if (max === min) {
            h = s = 0; // achromatic
        } else {
            const d = max - min;
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
            switch (max) {
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }
            h /= 6;
        }
        return [h, s, l];
    }

    function hslToRgb(h, s, l) {
        let r, g, b;
        if (s === 0) {
            r = g = b = l; // achromatic
        } else {
            const hue2rgb = (p, q, t) => {
                if (t < 0) t += 1;
                if (t > 1) t -= 1;
                if (t < 1 / 6) return p + (q - p) * 6 * t;
                if (t < 1 / 2) return q;
                if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
                return p;
            };
            const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
            const p = 2 * l - q;
            r = hue2rgb(p, q, h + 1 / 3);
            g = hue2rgb(p, q, h);
            b = hue2rgb(p, q, h - 1 / 3);
        }
        return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
    }

    function componentToHex(c) {
        const hex = c.toString(16);
        return hex.length == 1 ? "0" + hex : hex;
    }

    function rgbToHex(r, g, b) {
        return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
    }
    
    function adjustColorLightness(hexColor, percent) {
        const rgb = hexToRgb(hexColor);
        let hsl = rgbToHsl(rgb.r, rgb.g, rgb.b);
        hsl[2] = Math.max(0, Math.min(1, hsl[2] + (percent / 100)));
        const newRgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
        return rgbToHex(newRgb[0], newRgb[1], newRgb[2]);
    }
    // --- End Helper Functions ---

    const skinMainRgb = hexToRgb(skinColorParam);
    const brainMainRgb = hexToRgb(brainColorParam);

    const CW = 500; // Canvas Width
    const CH = 650; // Canvas Height

    const canvas = document.createElement('canvas');
    canvas.width = CW;
    canvas.height = CH;
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, CW, CH);
    ctx.fillStyle = "white"; // Optional: background for testing
    ctx.fillRect(0,0,CW,CH);


    // 1. Draw Alien Head Base (Brain and Face Area Shapes)
    ctx.fillStyle = `#${brainColorParam}`;
    ctx.beginPath();
    ctx.ellipse(CW / 2, CH * 0.35, CW * 0.45, CH * 0.30, 0, 0, 2 * Math.PI);
    ctx.fill();

    ctx.fillStyle = `#${skinColorParam}`;
    ctx.beginPath();
    // Start from top-left of face area, under the brain
    ctx.moveTo(CW * 0.28, CH * 0.55); 
    // Left cheek/jaw slope down to chin
    ctx.bezierCurveTo(CW * 0.25, CH * 0.75, CW * 0.4, CH * 0.86, CW / 2, CH * 0.87);
    // Chin to right cheek/jaw slope up
    ctx.bezierCurveTo(CW * 0.6, CH * 0.86, CW * 0.75, CH * 0.75, CW * 0.72, CH * 0.55);
    // Connect to bottom of brain smoothly (create a slight overlap area)
    ctx.lineTo(CW * 0.75, CH * 0.40); // Upper right of face area
    ctx.arcTo(CW / 2, CH * 0.35, CW * 0.25, CH * 0.40, CW * 0.3); // Curve along bottom of brain
    ctx.lineTo(CW * 0.25, CH * 0.40); // Upper left of face area
    ctx.closePath();
    ctx.fill();

    // 2. Draw Brain Texture
    const brainHsl = rgbToHsl(brainMainRgb.r, brainMainRgb.g, brainMainRgb.b);
    const textureLightnessAdjust = brainHsl[2] < 0.5 ? 20 : -20;
    const brainTextureColor = adjustColorLightness(brainColorParam, textureLightnessAdjust);
    ctx.strokeStyle = brainTextureColor;
    ctx.lineWidth = Math.max(1.5, CW / 250);
    
    // More structured convolutions for brain texture
    const numConvolutions = 6;
    const brainTopY = CH * 0.05; // Top of brain ellipse
    const brainBottomY = CH * 0.60; // Bottom of brain ellipse
    const brainCenterX = CW / 2;
    const brainRadiusX = CW * 0.45;

    for (let i = 0; i < numConvolutions; i++) {
        ctx.beginPath();
        // Start on left side of brain
        let startY = brainTopY + (brainBottomY - brainTopY) * (Math.random() * 0.4 + i * 0.1);
        let startX = brainCenterX - Math.sqrt(1 - Math.pow((startY - CH * 0.35) / (CH * 0.30), 2)) * brainRadiusX * (0.8 + Math.random()*0.2) ;
        if (isNaN(startX)) startX = brainCenterX - brainRadiusX * (0.8 + Math.random()*0.2);
        ctx.moveTo(startX, startY);

        // Random curves across the brain
        ctx.bezierCurveTo(
            brainCenterX - brainRadiusX * (Math.random() * 0.5), startY + (Math.random() - 0.5) * CH * 0.1, // CP1
            brainCenterX + brainRadiusX * (Math.random() * 0.5), startY + (Math.random() - 0.5) * CH * 0.1, // CP2
            startX + brainRadiusX * 2 * (0.8 + Math.random()*0.2), startY + (Math.random() - 0.5) * CH * 0.05 // End point (roughly other side)
        );
        ctx.stroke();
    }


    // 3. Process and Place Original Face
    const faceCanvas = document.createElement('canvas');
    const faceCtx = faceCanvas.getContext('2d');
    const faceProcessSize = 200; // Process face at this resolution
    faceCanvas.width = faceProcessSize;
    faceCanvas.height = faceProcessSize;

    let cropInputX, cropInputY, cropInputSize;
    if (originalImg.width / originalImg.height > 1) { // Landscape or square
        cropInputSize = originalImg.height;
        cropInputX = (originalImg.width - cropInputSize) / 2;
        cropInputY = 0;
    } else { // Portrait
        cropInputSize = originalImg.width;
        cropInputX = 0;
        cropInputY = (originalImg.height - cropInputSize) / 3; // Try to get upper part
    }
    cropInputX = Math.max(0, cropInputX);
    cropInputY = Math.max(0, cropInputY);
    
    faceCtx.drawImage(originalImg, cropInputX, cropInputY, cropInputSize, cropInputSize, 0, 0, faceProcessSize, faceProcessSize);

    const imgData = faceCtx.getImageData(0, 0, faceProcessSize, faceProcessSize);
    const pixels = imgData.data;
    const targetSkinHsl = rgbToHsl(skinMainRgb.r, skinMainRgb.g, skinMainRgb.b);

    for (let i = 0; i < pixels.length; i += 4) {
        let r = pixels[i], g = pixels[i+1], b = pixels[i+2];
        let hsl = rgbToHsl(r, g, b);
        hsl[0] = targetSkinHsl[0]; 
        hsl[1] = Math.max(0.05, hsl[1] * 0.6); // Desaturate
        hsl[2] = hsl[2] * 0.95; // Slightly darken
        let newRgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
        pixels[i] = newRgb[0];
        pixels[i+1] = newRgb[1];
        pixels[i+2] = newRgb[2];
    }
    faceCtx.putImageData(imgData, 0, 0);

    const facePlaceWidth = CW * 0.40;
    const facePlaceHeight = facePlaceWidth; 
    const facePlaceX = CW / 2 - facePlaceWidth / 2;
    const facePlaceY = CH * 0.60 - facePlaceHeight / 2; 

    ctx.save();
    ctx.beginPath();
    ctx.ellipse(facePlaceX + facePlaceWidth/2, facePlaceY + facePlaceHeight/2, facePlaceWidth/2 * 0.90, facePlaceHeight/2 * 0.85, 0, 0, 2 * Math.PI);
    ctx.clip();
    ctx.drawImage(faceCanvas, facePlaceX, facePlaceY, facePlaceWidth, facePlaceHeight);
    ctx.restore();

    // 4. Add Alien Eyes (on top of the tinted face)
    const eyeRadiusX = facePlaceWidth * 0.22;
    const eyeRadiusY = facePlaceHeight * 0.25; 
    const eyeVerticalPos = facePlaceY + facePlaceHeight * 0.40;

    // Left Eye
    const leftEyeX = facePlaceX + facePlaceWidth * 0.28;
    ctx.fillStyle = `#${eyeScleraColorParam}`;
    ctx.beginPath();
    ctx.ellipse(leftEyeX, eyeVerticalPos, eyeRadiusX, eyeRadiusY, -0.1, 0, 2 * Math.PI); // Slight tilt
    ctx.fill();
    ctx.fillStyle = "black"; // Pupil
    ctx.beginPath();
    ctx.ellipse(leftEyeX, eyeVerticalPos, eyeRadiusX * 0.5, eyeRadiusY * 0.5, -0.1, 0, 2 * Math.PI);
    ctx.fill();
    ctx.fillStyle = "rgba(255,255,255,0.7)"; // Highlight
    ctx.beginPath();
    ctx.ellipse(leftEyeX + eyeRadiusX * 0.25, eyeVerticalPos - eyeRadiusY * 0.25, eyeRadiusX * 0.2, eyeRadiusY * 0.2, -0.1, 0, Math.PI * 2);
    ctx.fill();

    // Right Eye
    const rightEyeX = facePlaceX + facePlaceWidth * 0.72;
    ctx.fillStyle = `#${eyeScleraColorParam}`;
    ctx.beginPath();
    ctx.ellipse(rightEyeX, eyeVerticalPos, eyeRadiusX, eyeRadiusY, 0.1, 0, 2 * Math.PI); // Slight tilt
    ctx.fill();
    ctx.fillStyle = "black"; // Pupil
    ctx.beginPath();
    ctx.ellipse(rightEyeX, eyeVerticalPos, eyeRadiusX * 0.5, eyeRadiusY * 0.5, 0.1, 0, 2 * Math.PI);
    ctx.fill();
    ctx.fillStyle = "rgba(255,255,255,0.7)"; // Highlight
    ctx.beginPath();
    ctx.ellipse(rightEyeX + eyeRadiusX * 0.25, eyeVerticalPos - eyeRadiusY * 0.25, eyeRadiusX * 0.2, eyeRadiusY * 0.2, 0.1, 0, Math.PI * 2);
    ctx.fill();

    // 5. Optional: Transparent Dome
    if (domeOpacityParam > 0 && domeOpacityParam <=1) {
        ctx.fillStyle = `rgba(190, 210, 255, ${domeOpacityParam})`;
        ctx.beginPath();
        // Path for dome starting from bottom-left, over the top, to bottom-right
        const domeBaseY = CH * 0.50; 
        const domePeakY = CH * -0.05; // Control point for peak
        ctx.moveTo(CW * 0.03, domeBaseY); 
        ctx.bezierCurveTo(
            CW * 0.1, domePeakY,  // CP1 (high left)
            CW * 0.9, domePeakY,  // CP2 (high right)
            CW * 0.97, domeBaseY   // End point (bottom-right)
        );
        ctx.fill();

        // Dome highlights
        ctx.strokeStyle = `rgba(255, 255, 255, ${Math.min(1.0, domeOpacityParam * 2.5)})`;
        ctx.lineWidth = Math.max(2, CW / 150);
        ctx.beginPath();
        ctx.arc(CW * 0.4, CH * 0.15, CW * 0.15, Math.PI * 1.35, Math.PI * 1.65);
        ctx.stroke();
        ctx.beginPath();
        ctx.arc(CW * 0.65, CH * 0.1, CW * 0.08, Math.PI * 1.25, Math.PI * 1.75);
        ctx.stroke();
    }

    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 Alien Transformation Tool allows users to transform an uploaded image into an alien-like rendition. Users can customize various aspects of the transformation, such as the skin color, eye color, brain color, and the opacity of a transparent dome effect. This tool is suitable for creative projects, social media content, or any artistic endeavor where a playful and imaginative representation of a human face is desired. It seamlessly blends image processing with artistic design, making it perfect for those looking to add a fantastical or otherworldly touch to their photography.

Leave a Reply

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