Please bookmark this page to avoid losing your image tool!

Image Asteroid Field Filter Effect 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.
function processImage(originalImg, asteroidCount = 50, minAsteroidSize = 5, maxAsteroidSize = 30, asteroidBaseColor = "#808080", asteroidColorVariation = 0.2, highlightFactor = 1.3, shadowFactor = 0.7) {

    // Helper function: parseHexColor
    // Parses a hex color string (e.g., #FF0000 or #F00) into an {r, g, b} object.
    // Defaults to black if parsing fails.
    function _parseHexColor(hex) {
        hex = String(hex).replace(/^#/, '');
        if (hex.length === 3) {
            hex = hex.split('').map(char => char + char).join('');
        }
        if (hex.length !== 6) {
            // console.warn("Invalid hex color for parsing:", hex, "- defaulting to black.");
            return { r: 0, g: 0, b: 0 };
        }
        const bigint = parseInt(hex, 16);
        if (isNaN(bigint)) {
            // console.warn("Invalid hex color value:", hex, "- defaulting to black.");
            return { r: 0, g: 0, b: 0 };
        }
        const r = (bigint >> 16) & 255;
        const g = (bigint >> 8) & 255;
        const b = bigint & 255;
        return { r, g, b };
    }

    // Helper function: componentToHex
    // Converts a single color component (0-255) to its 2-digit hex representation.
    function _componentToHex(c) {
        const hex = Math.round(c).toString(16);
        return hex.length == 1 ? "0" + hex : hex;
    }

    // Helper function: rgbToHex
    // Converts an {r, g, b} object back to a hex color string.
    function _rgbToHex(r, g, b) {
        return "#" + _componentToHex(r) + _componentToHex(g) + _componentToHex(b);
    }

    // Helper function: varyColor
    // Takes a base hex color and a variation factor (0-1).
    // Returns a new hex color with R, G, B components randomly shifted.
    function _varyColor(baseHexColor, variation) {
        const baseColor = _parseHexColor(baseHexColor);
        const v = Math.max(0, Math.min(1, Number(variation) || 0));

        const r = Math.max(0, Math.min(255, baseColor.r + (Math.random() - 0.5) * 2 * 255 * v));
        const g = Math.max(0, Math.min(255, baseColor.g + (Math.random() - 0.5) * 2 * 255 * v));
        const b = Math.max(0, Math.min(255, baseColor.b + (Math.random() - 0.5) * 2 * 255 * v));
        return _rgbToHex(r, g, b);
    }

    // Helper function: adjustBrightness
    // Takes a hex color and a brightness factor.
    // factor > 1 lightens, factor < 1 darkens.
    // Returns a new hex color with adjusted brightness.
    function _adjustBrightness(hexColor, factor) {
        const color = _parseHexColor(hexColor);
        const f = Number(factor) || 1.0;

        const r = Math.max(0, Math.min(255, color.r * f));
        const g = Math.max(0, Math.min(255, color.g * f));
        const b = Math.max(0, Math.min(255, color.b * f));
        return _rgbToHex(r, g, b);
    }

    const canvas = document.createElement('canvas');
    canvas.width = originalImg.naturalWidth || originalImg.width;
    canvas.height = originalImg.naturalHeight || originalImg.height;
    
    if (canvas.width === 0 || canvas.height === 0) {
        console.error("Image has zero width or height. Cannot process.");
        // Return an empty (but valid) canvas to avoid breaking downstream code
        const errorCtx = canvas.getContext('2d');
        if (errorCtx) { // Check if context can be obtained
             errorCtx.fillStyle = 'red';
             errorCtx.fillRect(0,0,1,1); // Make it 1x1 if it was 0x0
             if (canvas.width === 0) canvas.width = 1;
             if (canvas.height === 0) canvas.height = 1;
        }
        return canvas; 
    }

    const ctx = canvas.getContext('2d');

    // Draw original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    
    // Sanitize numerical parameters
    const numAsteroids = Math.max(0, parseInt(String(asteroidCount), 10) || 0);
    let minSize = Math.max(1, parseFloat(String(minAsteroidSize)) || 1);
    let maxSize = Math.max(minSize, parseFloat(String(maxAsteroidSize)) || minSize);
    
    const hFactor = Math.max(0, parseFloat(String(highlightFactor)) || 1.0);
    const sFactor = Math.max(0, parseFloat(String(shadowFactor)) || 1.0);
    const colorVar = Math.max(0, Math.min(1, parseFloat(String(asteroidColorVariation)) || 0));


    for (let i = 0; i < numAsteroids; i++) {
        const x = Math.random() * canvas.width;
        const y = Math.random() * canvas.height;
        
        const sizeRange = Math.max(0, maxSize - minSize);
        const currentSize = minSize + Math.random() * sizeRange;
        if (currentSize <= 0) continue; 

        const rotation = Math.random() * 2 * Math.PI;

        // Determine the asteroid's main color and its shaded variants
        const currentAsteroidMainColor = _varyColor(asteroidBaseColor, colorVar);
        const lighterColor = _adjustBrightness(currentAsteroidMainColor, hFactor);
        const darkerColor = _adjustBrightness(currentAsteroidMainColor, sFactor);

        // Generate vertices for an irregular polygon representing the asteroid
        const vertices = [];
        const numVertices = Math.floor(5 + Math.random() * 7); // 5 to 11 vertices
        let maxVertexRadius = 0;
        for (let j = 0; j < numVertices; j++) {
            const angle = (j / numVertices) * 2 * Math.PI;
            // Radius for each_vertex varies for irregular shape: 0.6 * currentSize to 1.4 * currentSize
            const radius = currentSize * (0.6 + Math.random() * 0.8); 
            if (radius > maxVertexRadius) maxVertexRadius = radius;
            vertices.push({
                x: radius * Math.cos(angle),
                y: radius * Math.sin(angle)
            });
        }

        if (vertices.length < 3) continue; 

        ctx.save();
        ctx.translate(x, y); // Move to asteroid's position
        ctx.rotate(rotation); // Apply random rotation

        // Create a linear gradient for a 3D effect
        // The gradient spans across the asteroid's maximum possible extent
        const gradRadius = maxVertexRadius; // Ensure gradient covers the entire shape
        const gradient = ctx.createLinearGradient(-gradRadius, -gradRadius, gradRadius, gradRadius);
        
        gradient.addColorStop(0, lighterColor);             // Highlight
        gradient.addColorStop(0.5, currentAsteroidMainColor); // Mid-tone
        gradient.addColorStop(1, darkerColor);              // Shadow
        ctx.fillStyle = gradient;

        // Draw the asteroid polygon
        ctx.beginPath();
        ctx.moveTo(vertices[0].x, vertices[0].y);
        for (let k = 1; k < numVertices; k++) {
            ctx.lineTo(vertices[k].x, vertices[k].y);
        }
        ctx.closePath();
        ctx.fill();
        
        ctx.restore(); // Restore context state (transformations)
    }

    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 Asteroid Field Filter Effect Tool allows users to add a visually appealing asteroid field effect to their images. By customizing parameters such as the number of asteroids, their sizes, and color variations, users can create unique artistic interpretations of their visuals. This tool is suitable for graphic designers, digital artists, or anyone looking to enhance images for personal projects or social media, enabling them to add a touch of creativity and space-themed aesthetics.

Leave a Reply

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