Please bookmark this page to avoid losing your image tool!

Image Cyberpunk Filter Application

(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, primaryColor = "#ff00ff", secondaryColor = "#002288", contrastFactor = 1.5, aberrationAmount = 3, vignetteAmount = 0.4, scanlinesOpacity = 0.1) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true }); // willReadFrequently for performance with getImageData/putImageData

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

    // Helper function to parse hex color string to an {r, g, b} object
    function hexToRgb(hex) {
        hex = hex.replace(/^#/, '');
        if (hex.length === 3) {
            hex = hex.split('').map(char => char + char).join('');
        }
        const num = parseInt(hex, 16);
        if (isNaN(num)) { // Fallback for invalid hex
            return { r: 255, g: 20, b: 147 }; // Default to a pink color
        }
        return { r: (num >> 16) & 255, g: (num >> 8) & 255, b: num & 255 };
    }

    const pColorRGB = hexToRgb(primaryColor); // Highlight color (e.g., magenta/pink)
    const sColorRGB = hexToRgb(secondaryColor); // Shadow color (e.g., dark blue/purple)

    // --- Step 1: Draw original image ---
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    // --- Step 2: Get image data ---
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    } catch (e) {
        console.error("Error getting image data (possibly tainted canvas):", e);
        // Return original image on a new canvas if processing fails
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = canvas.width;
        errorCanvas.height = canvas.height;
        const errorCtx = errorCanvas.getContext('2d');
        errorCtx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
        return errorCanvas;
    }
    
    let data = imageData.data;

    // --- Step 3: Pixel manipulation (Contrast & Color Grading) ---
    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];

        // 3.1 Contrast
        if (contrastFactor !== 1.0) {
            r = (r / 255 - 0.5) * contrastFactor + 0.5;
            g = (g / 255 - 0.5) * contrastFactor + 0.5;
            b = (b / 255 - 0.5) * contrastFactor + 0.5;
            r = Math.max(0, Math.min(1, r)) * 255;
            g = Math.max(0, Math.min(1, g)) * 255;
            b = Math.max(0, Math.min(1, b)) * 255;
        }
        
        // 3.2 Cyberpunk Color Grading
        // Calculate luminance (0-1) using current r,g,b after contrast
        const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;

        // Mix current color with primary (highlights) and secondary (shadows) colors
        const mixStrength = 0.65; // How much of the target colors to mix in

        let finalR = r * (1 - mixStrength) + (sColorRGB.r * (1 - luminance) + pColorRGB.r * luminance) * mixStrength;
        let finalG = g * (1 - mixStrength) + (sColorRGB.g * (1 - luminance) + pColorRGB.g * luminance) * mixStrength;
        let finalB = b * (1 - mixStrength) + (sColorRGB.b * (1 - luminance) + pColorRGB.b * luminance) * mixStrength;

        // Additional common cyberpunk adjustments: slightly reduce green, boost blue
        finalG *= 0.9; 
        finalB = Math.min(255, finalB * 1.1); 
        
        data[i]   = Math.max(0, Math.min(255, finalR));
        data[i+1] = Math.max(0, Math.min(255, finalG));
        data[i+2] = Math.max(0, Math.min(255, finalB));
    }

    // --- Step 4: Chromatic Aberration ---
    if (aberrationAmount > 0) {
        const shiftedData = new Uint8ClampedArray(data.length);
        const offset = Math.round(aberrationAmount);
        
        for (let y = 0; y < canvas.height; y++) {
            for (let x = 0; x < canvas.width; x++) {
                const i = (y * canvas.width + x) * 4;

                const rX = Math.max(0, Math.min(canvas.width - 1, x - offset));
                const bX = Math.max(0, Math.min(canvas.width - 1, x + offset));
                
                const rIndex = (y * canvas.width + rX) * 4;
                const gIndex = i; 
                const bIndex = (y * canvas.width + bX) * 4;

                shiftedData[i]     = data[rIndex];     // Red channel from left-shifted pixel
                shiftedData[i + 1] = data[gIndex + 1]; // Green channel from current pixel
                shiftedData[i + 2] = data[bIndex + 2]; // Blue channel from right-shifted pixel
                shiftedData[i + 3] = data[i + 3];     // Alpha
            }
        }
        // Update data with aberrated data
        data.set(shiftedData);
    }

    // --- Step 5: Vignette ---
    if (vignetteAmount > 0) {
        const centerX = canvas.width / 2;
        const centerY = canvas.height / 2;
        // Use the largest dimension for a more circular vignette, or maxDist for elliptical
        const radius = Math.max(centerX, centerY); 

        for (let y = 0; y < canvas.height; y++) {
            for (let x = 0; x < canvas.width; x++) {
                const i = (y * canvas.width + x) * 4;
                const dx = x - centerX;
                const dy = y - centerY;
                const dist = Math.sqrt(dx * dx + dy * dy);
                
                // Calculate vignette factor (0 to 1, where 1 is full intensity, 0 is no darkening)
                // Smootherstep or power curve for falloff
                const vignetteEffect = Math.pow(dist / radius, 2) * vignetteAmount;
                const factor = Math.max(0, 1 - vignetteEffect);

                data[i]   *= factor;
                data[i+1] *= factor;
                data[i+2] *= factor;
            }
        }
    }

    // --- Put final pixel data back ---
    ctx.putImageData(imageData, 0, 0);

    // --- Step 6: Scanlines ---
    if (scanlinesOpacity > 0 && scanlinesOpacity <= 1) {
        ctx.fillStyle = `rgba(0, 0, 0, ${scanlinesOpacity})`;
        for (let y = 0; y < canvas.height; y += 4) { // 2px lines with 2px gap
            ctx.fillRect(0, y, canvas.width, 2);
        }
    }
    
    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 Filter Application is a tool designed to enhance your images with a futuristic cyberpunk aesthetic. You can apply striking color grading by using primary and secondary colors, adjust the contrast of the image, and introduce stylistic effects such as chromatic aberration, vignetting, and scanlines. This tool is perfect for digital artists, photographers, and anyone looking to give their images a unique and vibrant look reminiscent of cyberpunk themes. Whether for social media posts, graphics design, or personal artwork, this application allows users to transform images to evoke a high-energy, urban vibe.

Leave a Reply

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