Please bookmark this page to avoid losing your image tool!

Image Starry Night Sky 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,
    starDensity = 0.002, // Proportion of dark pixels that become stars
    starBrightnessMin = 200, // Minimum brightness of a star (0-255)
    starBrightnessMax = 255, // Maximum brightness of a star (0-255)
    nightEffectAmount = 0.6, // Strength of the night darkening and blue tint (0-1)
    darknessThresholdForStars = 70, // Luminance threshold (0-255) for original pixels to be considered for stars
    starColorVariation = 0.15 // Amount of color tint (yellowish/bluish) for stars (0 for white, up to 1 for strong color)
) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can potentially optimize getImageData/putImageData calls.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;

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

    if (imgWidth === 0 || imgHeight === 0) {
        // If the image has no dimensions, return an empty canvas.
        return canvas;
    }

    ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);

    const imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
    const data = imageData.data;

    // Store original luminance for star placement decisions, to avoid night tint affecting it.
    const originalLuminanceMap = new Float32Array(imgWidth * imgHeight);

    // Pass 1: Apply night effect and calculate original luminance
    for (let y = 0; y < imgHeight; y++) {
        for (let x = 0; x < imgWidth; x++) {
            const R_INDEX = (y * imgWidth + x) * 4;
            const G_INDEX = R_INDEX + 1;
            const B_INDEX = R_INDEX + 2;

            const r = data[R_INDEX];
            const g = data[G_INDEX];
            const b = data[B_INDEX];
            
            // Calculate original luminance (perceived brightness)
            const lum = 0.299 * r + 0.587 * g + 0.114 * b;
            originalLuminanceMap[y * imgWidth + x] = lum;

            // Apply Night Effect
            // 1. Darken based on nightEffectAmount
            const darkenFactor = 1.0 - (nightEffectAmount * 0.75); // Max 75% darkening
            let newR = r * darkenFactor;
            let newG = g * darkenFactor;
            let newB = b * darkenFactor;

            // 2. Add blue tint, also influenced by nightEffectAmount
            const blueBoost = 60 * nightEffectAmount;
            const redReduction = 25 * nightEffectAmount;
            const greenReduction = 15 * nightEffectAmount;

            newR = Math.max(0, newR - redReduction);
            newG = Math.max(0, newG - greenReduction);
            newB = Math.min(255, newB + blueBoost);
            
            data[R_INDEX] = Math.max(0, Math.min(255, newR));
            data[G_INDEX] = Math.max(0, Math.min(255, newG));
            data[B_INDEX] = Math.max(0, Math.min(255, newB));
        }
    }

    // Pass 2: Add Stars
    const crossGlowIntensity = 0.25; // Intensity of the glow on adjacent pixels for all stars

    for (let y = 0; y < imgHeight; y++) {
        for (let x = 0; x < imgWidth; x++) {
            const originalLum = originalLuminanceMap[y * imgWidth + x];

            if (originalLum < darknessThresholdForStars) {
                if (Math.random() < starDensity) {
                    const R_CENTER_INDEX = (y * imgWidth + x) * 4;
                    const G_CENTER_INDEX = R_CENTER_INDEX + 1;
                    const B_CENTER_INDEX = R_CENTER_INDEX + 2;
                    const A_CENTER_INDEX = R_CENTER_INDEX + 3;

                    // Star brightness (randomized within min/max)
                    const brightness = starBrightnessMin + Math.random() * (starBrightnessMax - starBrightnessMin);

                    // Star color initialization (white)
                    let starR = brightness;
                    let starG = brightness;
                    let starB = brightness;

                    // Apply color variation if specified
                    if (starColorVariation > 0 && Math.random() < 0.75) { // Apply color to ~75% of stars if variation is on
                        const colorRoll = Math.random();
                        // variationMagnitude scales with starColorVariation, from 0.5x to 1.0x of its value
                        const variationMagnitude = starColorVariation * (0.5 + Math.random() * 0.5); 

                        if (colorRoll < 0.5) { // Yellowish tint
                            starB *= (1 - variationMagnitude); // Reduce Blue
                            starG = Math.min(255, starG * (1 + variationMagnitude * 0.2)); // Slightly boost Green for more yellow
                        } else { // Bluish tint
                            starR *= (1 - variationMagnitude * 0.8); // Reduce Red significantly
                            starG *= (1 - variationMagnitude * 0.3); // Reduce Green less for blue
                        }
                    }
                    
                    starR = Math.max(0, Math.min(255, starR));
                    starG = Math.max(0, Math.min(255, starG));
                    starB = Math.max(0, Math.min(255, starB));

                    // Draw star center by overwriting pixel
                    data[R_CENTER_INDEX] = starR;
                    data[G_CENTER_INDEX] = starG;
                    data[B_CENTER_INDEX] = starB;
                    data[A_CENTER_INDEX] = 255; // Ensure star is opaque

                    // Add a subtle cross-shaped glow to ALL stars by additively blending with neighbors
                    const neighbors = [
                        { dx: -1, dy: 0 }, { dx: 1, dy: 0 },
                        { dx: 0, dy: -1 }, { dx: 0, dy: 1 }
                    ];
                    for (const n of neighbors) {
                        const nx = x + n.dx;
                        const ny = y + n.dy;
                        if (nx >= 0 && nx < imgWidth && ny >= 0 && ny < imgHeight) {
                            const R_NEIGHBOR_INDEX = (ny * imgWidth + nx) * 4;
                            const G_NEIGHBOR_INDEX = R_NEIGHBOR_INDEX + 1;
                            const B_NEIGHBOR_INDEX = R_NEIGHBOR_INDEX + 2;

                            data[R_NEIGHBOR_INDEX] = Math.min(255, data[R_NEIGHBOR_INDEX] + starR * crossGlowIntensity);
                            data[G_NEIGHBOR_INDEX] = Math.min(255, data[G_NEIGHBOR_INDEX] + starG * crossGlowIntensity);
                            data[B_NEIGHBOR_INDEX] = Math.min(255, data[B_NEIGHBOR_INDEX] + starB * crossGlowIntensity);
                        }
                    }
                }
            }
        }
    }

    ctx.putImageData(imageData, 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 Starry Night Sky Filter Effect Tool allows users to transform their images by applying a dreamy starry night sky filter effect. This includes darkening the original image and adding stars of varying brightness and colors, creating a night scene ambiance. The tool is useful for enhancing photos for social media, creating artistic backgrounds, or simply altering the mood of an image. Users can adjust parameters like star density, brightness, color variation, and the intensity of the night effect to achieve their desired look.

Leave a Reply

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