Please bookmark this page to avoid losing your image tool!

Image Cyberpunk Neon 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.
async function processImage(originalImg, brightness = 10, contrast = 130, highlightColorStr = "#FF00FF", highlightIntensity = 0.5, shadowColorStr = "#00FFFF", shadowIntensity = 0.5, saturationBoost = 20) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true }); // Optimized for frequent getImageData

    // Ensure the image is loaded before trying to get its dimensions or draw it
    // This is more robust if originalImg might not be fully loaded yet,
    // though problem states it's an Image object, implying it might be.
    // However, naturalWidth/Height are best checks.
    const imgIsLoaded = originalImg.complete && originalImg.naturalWidth !== 0;

    if (!imgIsLoaded && originalImg.src) {
        // If not loaded, create a promise to wait for it
        await new Promise((resolve, reject) => {
            originalImg.onload = resolve;
            originalImg.onerror = reject;
            // If originalImg.src is already set and it failed, onerror might have fired.
            // If src not set, this won't help. The caller should provide a loaded image.
        });
    }

    canvas.width = originalImg.naturalWidth || originalImg.width;
    canvas.height = originalImg.naturalHeight || originalImg.height;
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    // Helper function to parse hex color string to RGB object
    function hexToRgb(hex) {
        let r = 0, g = 0, b = 0;
        hex = hex.replace(/^#/, ''); // Remove # if present

        if (hex.length === 3) { // #RGB shorthand
            r = parseInt(hex[0] + hex[0], 16);
            g = parseInt(hex[1] + hex[1], 16);
            b = parseInt(hex[2] + hex[2], 16);
        } else if (hex.length === 6) { // #RRGGBB
            r = parseInt(hex.substring(0, 2), 16);
            g = parseInt(hex.substring(2, 4), 16);
            b = parseInt(hex.substring(4, 6), 16);
        }
        return { r, g, b };
    }

    const parsedHighlightColor = hexToRgb(highlightColorStr);
    const parsedShadowColor = hexToRgb(shadowColorStr);

    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imageData.data;
    
    // Contrast: 100 means no change. 0 means total gray. 200 means double contrast.
    // (contrast / 100.0) gives a factor like 1.3 for contrast = 130.
    const contrastFactor = contrast / 100.0; 

    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];

        // 1. Apply Brightness
        // brightness is -100 to 100.
        r += brightness;
        g += brightness;
        b += brightness;

        // 2. Apply Contrast
        // Formula: NewColor = ((OldColor/255 - 0.5) * ContrastFactor + 0.5) * 255
        // Or simpler: Center around 127.5, scale, then shift back.
        r = ((r - 127.5) * contrastFactor) + 127.5;
        g = ((g - 127.5) * contrastFactor) + 127.5;
        b = ((b - 127.5) * contrastFactor) + 127.5;
        
        // Clamp after brightness/contrast before further processing
        r = Math.max(0, Math.min(255, r));
        g = Math.max(0, Math.min(255, g));
        b = Math.max(0, Math.min(255, b));

        // Store adjusted RGB for luminance calculation and tinting
        let adjR = r;
        let adjG = g;
        let adjB = b;

        // 3. Calculate Luminance (using Rec. 709 coefficients for perceived brightness)
        const lum = 0.2126 * adjR + 0.7152 * adjG + 0.0722 * adjB;

        // 4. Apply Split Toning (Neon Colors)
        let currentR = adjR;
        let currentG = adjG;
        let currentB = adjB;

        // Determine mix factor for highlights or shadows
        // highlightIntensity and shadowIntensity are 0 to 1
        if (lum > 128) { // Apply highlight tint to brighter pixels
            // blendFactor goes from 0 (at lum=128) to 1 (at lum=255)
            const blendFactor = (lum - 128) / 127.0; // Normalize to 0-1 range
            const mix = blendFactor * highlightIntensity;
            
            currentR = adjR * (1 - mix) + parsedHighlightColor.r * mix;
            currentG = adjG * (1 - mix) + parsedHighlightColor.g * mix;
            currentB = adjB * (1 - mix) + parsedHighlightColor.b * mix;
        } else { // Apply shadow tint to darker pixels
            // blendFactor goes from 0 (at lum=128) to 1 (at lum=0)
            const blendFactor = (128 - lum) / 128.0; // Normalize to 0-1 range
            const mix = blendFactor * shadowIntensity;

            currentR = adjR * (1 - mix) + parsedShadowColor.r * mix;
            currentG = adjG * (1 - mix) + parsedShadowColor.g * mix;
            currentB = adjB * (1 - mix) + parsedShadowColor.b * mix;
        }
        
        // 5. Saturation Boost
        // saturationBoost is 0 to 100 (0 = no change, 100 = significant boost like double)
        if (saturationBoost !== 0) {
            // satBoostFactor: 1.0 for 0 boost, 2.0 for 100 boost.
            const satBoostFactor = 1.0 + (saturationBoost / 100.0);
            // Calculate grayscale value of the current (tinted) pixel using Rec. 709
            const gray = currentR * 0.2126 + currentG * 0.7152 + currentB * 0.0722;
            
            // Interpolate towards/away from gray
            currentR = gray + (currentR - gray) * satBoostFactor;
            currentG = gray + (currentG - gray) * satBoostFactor;
            currentB = gray + (currentB - gray) * satBoostFactor;
        }

        // Clamp final RGB values to [0, 255]
        data[i] = Math.max(0, Math.min(255, Math.round(currentR)));
        data[i + 1] = Math.max(0, Math.min(255, Math.round(currentG)));
        data[i + 2] = Math.max(0, Math.min(255, Math.round(currentB)));
        // Alpha (data[i + 3]) remains unchanged
    }

    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 Cyberpunk Neon Filter Effect Tool allows users to transform their images with a vibrant cyberpunk neon aesthetic. It applies customizable adjustments including brightness, contrast, saturation, and unique highlight and shadow tinting using specified colors. This tool is ideal for creating visually striking images suitable for social media posts, digital art projects, and creative presentations, offering a way to enhance photos with an energetic and futuristic look.

Leave a Reply

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