Please bookmark this page to avoid losing your image tool!

Image Dark Matter Visualization 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, thresholdLevel = 0.5, particleColorStr = "255,255,255", particleStrength = 0.8, darkMatterBaseColorStr = "10,10,30", darkMatterTintStrength = 0.2, noiseIntensity = 15) {
    
    // Helper function to parse color strings (e.g., "255,100,50")
    // It's defined inside `processImage` to keep it self-contained.
    function parseColor(colorStr, defaultArr) {
        // Ensure colorStr is a string before attempting to split
        if (typeof colorStr !== 'string') {
            return defaultArr;
        }
        try {
            const parts = colorStr.split(',').map(s => parseInt(s.trim(), 10));
            if (parts.length === 3 && parts.every(p => !isNaN(p) && p >= 0 && p <= 255)) {
                return parts;
            }
            return defaultArr; // Return default if parsing fails or format is incorrect
        } catch (e) {
            // In case of unexpected errors during parsing, return default
            return defaultArr;
        }
    }

    const canvas = document.createElement('canvas');
    // { willReadFrequently: true } can be a performance hint for getImageData/putImageData operations
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    // Use naturalWidth/Height for intrinsic dimensions, fallback to width/height if needed
    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;

    // Handle cases where image dimensions are not available
    if (imgWidth === 0 || imgHeight === 0) {
        console.error("Image has zero width or height. Cannot process.");
        // Return a minimal empty canvas as per guideline of returning a canvas
        const emptyCanvas = document.createElement('canvas');
        emptyCanvas.width = 1; 
        emptyCanvas.height = 1;
        return emptyCanvas;
    }

    canvas.width = imgWidth;
    canvas.height = imgHeight;

    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);

    let imageData;
    try {
        // Get pixel data from the canvas
        imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    } catch (e) {
        console.error("Could not getImageData (e.g., cross-origin issue if image source is external and server lacks CORS headers):", e);
        // If getImageData fails (e.g. tainted canvas), we can't process pixels.
        // Return the canvas with the original image drawn on it, or an empty one.
        // For this filter, pixel processing is essential, so returning the image unmodified on canvas is a fallback.
        return canvas; 
    }
    
    const data = imageData.data;
    // Create new ImageData for the output pixels.
    const outputImageData = ctx.createImageData(canvas.width, canvas.height);
    const outputData = outputImageData.data;

    // Parse color parameters
    const [pcR, pcG, pcB] = parseColor(particleColorStr, [255, 255, 255]); // Default: white
    const [dmR_base, dmG_base, dmB_base] = parseColor(darkMatterBaseColorStr, [10, 10, 30]); // Default: dark blue/purple

    // Calculate the actual luminance threshold
    const actualThreshold = thresholdLevel * 255;

    // Sanitize strength/tint/intensity parameters to ensure they are within reasonable bounds
    const pStrength = Math.max(0, Math.min(1, particleStrength)); // Clamp to [0, 1]
    const dmTintStrength = Math.max(0, Math.min(1, darkMatterTintStrength)); // Clamp to [0, 1]
    const nIntensity = Math.max(0, noiseIntensity); // Ensure non-negative


    for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i+1];
        const b = data[i+2];
        const a = data[i+3]; // Original alpha component

        // Calculate luminance (brightness) of the pixel
        const luminance = 0.299 * r + 0.587 * g + 0.114 * b;

        let outR, outG, outB;

        if (luminance > actualThreshold) { // This pixel becomes a "particle"
            // Brighten the original color: component-wise, push towards 255 by 50% of the remaining distance.
            // This enhances brightness while retaining some original hue.
            const brightR = r + (255 - r) * 0.5;
            const brightG = g + (255 - g) * 0.5;
            const brightB = b + (255 - b) * 0.5;
            
            // Interpolate between the brightened original color and the target particleColor,
            // controlled by particleStrength.
            outR = brightR * (1 - pStrength) + pcR * pStrength;
            outG = brightG * (1 - pStrength) + pcG * pStrength;
            outB = brightB * (1 - pStrength) + pcB * pStrength;

        } else { // This pixel becomes part of "dark matter"
            // Use a significantly darkened version of the original color for tinting calculation.
            const origDarkR = r * 0.2; 
            const origDarkG = g * 0.2;
            const origDarkB = b * 0.2;

            // Blend the darkened original color with the darkMatterBaseColor,
            // controlled by darkMatterTintStrength.
            let dmR_tinted = origDarkR * dmTintStrength + dmR_base * (1 - dmTintStrength);
            let dmG_tinted = origDarkG * dmTintStrength + dmG_base * (1 - dmTintStrength);
            let dmB_tinted = origDarkB * dmTintStrength + dmB_base * (1 - dmTintStrength);
            
            // Add random noise to the dark matter areas for texture.
            // Noise ranges from -nIntensity to +nIntensity.
            const noise = (Math.random() - 0.5) * 2 * nIntensity; 
            outR = dmR_tinted + noise;
            outG = dmG_tinted + noise;
            outB = dmB_tinted + noise;
        }

        // Clamp final RGB values to the valid [0, 255] range and floor them.
        outputData[i]   = Math.max(0, Math.min(255, Math.floor(outR)));
        outputData[i+1] = Math.max(0, Math.min(255, Math.floor(outG)));
        outputData[i+2] = Math.max(0, Math.min(255, Math.floor(outB)));
        // Preserve the original alpha value. For a fully opaque effect, this could be set to 255.
        outputData[i+3] = a; 
    }

    // Put the processed pixel data back onto the canvas
    ctx.putImageData(outputImageData, 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 Dark Matter Visualization Filter Effect is a creative image processing tool that enhances images by applying a unique filter to simulate a cosmic dark matter effect. Users can customize the visualization with adjustable parameters such as threshold levels, particle color and strength, as well as the base color and tint strength for the dark matter effect. This tool is suitable for artists, graphic designers, and enthusiasts looking to create visually striking images for various applications, including digital art, presentations, social media, and educational materials.

Leave a Reply

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