Please bookmark this page to avoid losing your image tool!

Image Gas Giant Atmosphere Filter Effect

(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, primaryColorStr = "rgb(200,150,100)", secondaryColorStr = "rgb(150,100,80)", tintStrength = 0.6, bandStrength = 0.4, swirlStrength = 15, patternScale = 0.03) {

    // Helper function to parse color strings (hex, rgb, named) to {r, g, b}
    function parseColor(colorStr) {
        if (typeof colorStr !== 'string' || !colorStr) {
            // Default to black if colorStr is not a valid string or is empty
           return { r: 0, g: 0, b: 0 };
        }
        // For robust color parsing, use a temporary canvas
        const canvas = document.createElement('canvas');
        canvas.width = 1;
        canvas.height = 1;
        // Use willReadFrequently for potential performance optimization if available
        const ctx = canvas.getContext('2d', { willReadFrequently: true });
        
        if (!ctx) { // Fallback in case context cannot be created
            console.warn("Failed to create 2D context for color parsing.");
            return { r:0, g:0, b:0 };
        }

        ctx.fillStyle = colorStr; // Assign the color string
        ctx.fillRect(0, 0, 1, 1); // Draw a 1x1 pixel of this color

        // Get the color data of this pixel. getImageData returns [R, G, B, A]
        const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data;
        
        return { r, g, b };
    }

    const parsedPrimaryColor = parseColor(primaryColorStr);
    const parsedSecondaryColor = parseColor(secondaryColorStr);

    const canvas = document.createElement('canvas');
    // Use willReadFrequently for potential performance optimization
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    if (!originalImg || !(originalImg.naturalWidth || originalImg.width) || !(originalImg.naturalHeight || originalImg.height)) {
        // Return an empty or minimal canvas if image is invalid or not loaded
        canvas.width = 100; // Default small size
        canvas.height = 100;
        ctx.fillStyle = 'gray';
        ctx.fillRect(0,0,canvas.width,canvas.height);
        ctx.fillStyle = 'black';
        ctx.fillText("Invalid Image", 10, 50);
        console.error("Original image is invalid, not loaded, or has zero dimensions.");
        return canvas;
    }

    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;
    canvas.width = width;
    canvas.height = height;

    // Draw the original image to the canvas
    ctx.drawImage(originalImg, 0, 0, width, height);

    // --- Pass 1: Swirl Distortion ---
    if (swirlStrength > 0 && patternScale > 0) { // Only run if effect is active
        const sourceImageData = ctx.getImageData(0, 0, width, height);
        const sourceData = sourceImageData.data;
        const distortedImageData = ctx.createImageData(width, height);
        const distortedData = distortedImageData.data;

        for (let y = 0; y < height; y++) {
            for (let x = 0; x < width; x++) {
                // Complex sinusoidal displacement for a more "fluid" swirl
                const angleX = x * patternScale * 1.5 + y * patternScale * 0.05;
                const angleY = y * patternScale * 2.0 + x * patternScale * 0.1;

                const offsetX = Math.sin(angleY) * swirlStrength +
                                Math.cos(angleX) * swirlStrength * 0.7; // Added 0.7 factor for variation
                const offsetY = Math.cos(angleX) * swirlStrength +
                                Math.sin(angleY) * swirlStrength * 0.7; // Added 0.7 factor for variation

                let srcX = x + offsetX;
                let srcY = y + offsetY;

                // Clamp coordinates to be within bounds and round them
                srcX = Math.round(Math.max(0, Math.min(width - 1, srcX)));
                srcY = Math.round(Math.max(0, Math.min(height - 1, srcY)));

                const Nsrc = (srcY * width + srcX) * 4;
                const Ndst = (y * width + x) * 4;

                distortedData[Ndst]     = sourceData[Nsrc];
                distortedData[Ndst + 1] = sourceData[Nsrc + 1];
                distortedData[Ndst + 2] = sourceData[Nsrc + 2];
                distortedData[Ndst + 3] = sourceData[Nsrc + 3]; // Alpha
            }
        }
        // Put the distorted image data back onto the canvas for the next pass
        ctx.putImageData(distortedImageData, 0, 0);
    }
    // If swirlStrength is 0 or patternScale is 0, canvas still contains the original image.

    // --- Pass 2: Color Tinting and Banding ---
    // Get image data (which is now the distorted image, or original if swirl was skipped)
    const currentImageData = ctx.getImageData(0, 0, width, height);
    const data = currentImageData.data;

    const effectiveTintStrength = Math.max(0, Math.min(1, tintStrength));
    const effectiveBandStrength = Math.max(0, Math.min(1, bandStrength));


    for (let i = 0; i < data.length; i += 4) {
        const x = (i / 4) % width;
        const y = Math.floor((i / 4) / width);

        let r = data[i];
        let g = data[i+1];
        let b = data[i+2];

        // 1. Apply primary color tint
        if (effectiveTintStrength > 0) {
            r = r * (1 - effectiveTintStrength) + parsedPrimaryColor.r * effectiveTintStrength;
            g = g * (1 - effectiveTintStrength) + parsedPrimaryColor.g * effectiveTintStrength;
            b = b * (1 - effectiveTintStrength) + parsedPrimaryColor.b * effectiveTintStrength;
        }

        // 2. Apply banding with secondary color
        if (effectiveBandStrength > 0 && patternScale > 0) {
            // A more complex band pattern, involving x and y for waviness & varied intensity
            const bandNoiseVal1 = Math.sin(y * patternScale * 5 + x * patternScale * 0.3);
            const bandNoiseVal2 = Math.cos(x * patternScale * 0.8 + y * patternScale * 0.1); // Different frequencies
            // Combine and normalize to roughly 0-1 range
            const bandNoise = (bandNoiseVal1 + bandNoiseVal2 * 0.5 + 1.5) / (1 + 0.5 + 1.5); // Sum of amplitudes + offset / Max possible value
            
            const currentPixelBandStrength = bandNoise * effectiveBandStrength;

            r = r * (1 - currentPixelBandStrength) + parsedSecondaryColor.r * currentPixelBandStrength;
            g = g * (1 - currentPixelBandStrength) + parsedSecondaryColor.g * currentPixelBandStrength;
            b = b * (1 - currentPixelBandStrength) + parsedSecondaryColor.b * currentPixelBandStrength;
        }
        
        // Clamp final colors to 0-255 range and assign
        data[i]   = Math.max(0, Math.min(255, Math.floor(r)));
        data[i+1] = Math.max(0, Math.min(255, Math.floor(g)));
        data[i+2] = Math.max(0, Math.min(255, Math.floor(b)));
        // data[i+3] (alpha) remains unchanged from the (potentially distorted) source
    }

    // Put the final processed image data back
    ctx.putImageData(currentImageData, 0, 0);

    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 Gas Giant Atmosphere Filter Effect tool allows users to apply a unique filter effect to their images that mimics the appearance of gas giant atmospheres. By utilizing various parameters, users can introduce swirling distortions, color tints, and banding effects to create visually striking images reminiscent of planetary atmospheres. This tool can be particularly useful for artists, graphic designers, and hobbyists looking to enhance their digital artwork, create atmospheric backgrounds, or simply experiment with creative image transformations.

Leave a Reply

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