Please bookmark this page to avoid losing your image tool!

Image Color Pop Filter 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, targetColor = "red", tolerance = 50) {
    // Validate the input image
    // An HTMLImageElement is an Image object.
    // Check if it's loaded and has dimensions.
    if (!originalImg || !(originalImg instanceof HTMLImageElement) || !originalImg.complete || originalImg.naturalWidth === 0) {
        console.error("processImage Error: The provided image is invalid, not fully loaded, or has no dimensions.");
        // Return a very small canvas to indicate an error.
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = 1;
        errorCanvas.height = 1;
        // Optionally, you could draw a small error indicator on this canvas:
        // const errCtx = errorCanvas.getContext('2d');
        // if (errCtx) { errCtx.fillStyle = 'red'; errCtx.fillRect(0,0,1,1); }
        return errorCanvas;
    }

    // Helper function to parse a color string (e.g., "red", "#FF0000", "rgb(255,0,0)")
    // into an RGB object {r, g, b}.
    function parseColor(colorStr) {
        // Use a temporary 2D context to parse the color.
        // The fillStyle property an handle various color formats and normalizes them.
        const tempCtx = document.createElement('canvas').getContext('2d');
        if (!tempCtx) { // Should not happen in a browser environment
            console.error("processImage Error: Failed to create a 2D rendering context for color parsing. Defaulting to black.");
            return { r: 0, g: 0, b: 0 };
        }

        // Set fillStyle to black first (default for canvas).
        tempCtx.fillStyle = '#000000';
        // Attempt to set the user-provided color string.
        // If colorStr is invalid, fillStyle typically doesn't change or defaults to black.
        tempCtx.fillStyle = colorStr;
        const computedColor = tempCtx.fillStyle; // This will be a string like '#RRGGBB' or 'rgb(...)' or 'rgba(...)'

        // Try to parse hex color (e.g., #RRGGBB or #RGB)
        if (computedColor.startsWith('#')) {
            let hex = computedColor;
            if (hex.length === 4) { // #RGB shorthand (e.g., #F00 becomes #FF0000)
                hex = '#' + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3];
            }
            if (hex.length === 7) { // #RRGGBB (e.g., #FF0000)
                return {
                    r: parseInt(hex.substring(1, 3), 16),
                    g: parseInt(hex.substring(3, 5), 16),
                    b: parseInt(hex.substring(5, 7), 16)
                };
            }
        }

        // Try to parse rgb/rgba color (e.g., rgb(255,0,0) or rgba(255,0,0,1))
        const rgbMatch = computedColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d\.]+)?\)/);
        if (rgbMatch) {
            return {
                r: parseInt(rgbMatch[1]),
                g: parseInt(rgbMatch[2]),
                b: parseInt(rgbMatch[3])
            };
        }

        // Fallback if parsing failed (should be rare with fillStyle normalization)
        // This implies colorStr was invalid and resulted in computedColor being black (which is parsable),
        // or fillStyle returned an unexpected format.
        console.warn(`processImage Warning: Could not parse color string: "${colorStr}". Computed as: "${computedColor}". Defaulting to black for color pop effect.`);
        return { r: 0, g: 0, b: 0 }; // Default to black
    }

    const targetRgb = parseColor(targetColor);

    // Create a canvas element
    const canvas = document.createElement('canvas');
    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;
    
    const ctx = canvas.getContext('2d');
    if (!ctx) {
        console.error("processImage Error: Failed to get 2D rendering context from canvas.");
        const errorCanvas = document.createElement('canvas'); errorCanvas.width = 1; errorCanvas.height = 1;
        return errorCanvas;
    }
    
    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    // Get the image data from the canvas
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    } catch (e) {
        // This can happen due to tainted canvas (e.g., image loaded from a different origin without CORS headers)
        console.error("processImage Error: Failed to get ImageData from canvas. The canvas may be tainted by cross-origin data.", e);
        // Return a small error canvas. Could also return the canvas with the original image,
        // but failing explicitly shows the processing couldn't be done.
        const errorCanvas = document.createElement('canvas'); errorCanvas.width = 1; errorCanvas.height = 1;
        return errorCanvas;
    }
    
    const data = imageData.data; // Uint8ClampedArray: [R, G, B, A, R, G, B, A, ...]

    // Iterate through each pixel of the image data (4 values per pixel: R, G, B, A)
    for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i + 1];
        const b = data[i + 2];
        // Alpha channel (data[i+3]) is preserved by not modifying it.

        // Calculate the Euclidean distance in RGB space between current pixel color and target color
        const distR = r - targetRgb.r;
        const distG = g - targetRgb.g;
        const distB = b - targetRgb.b;
        // Squared distance is often used to avoid sqrt, but for comparison with `tolerance`, sqrt is needed for intuitive scale.
        const distance = Math.sqrt(distR * distR + distG * distG + distB * distB);

        // If the distance is greater than the tolerance, convert the pixel to grayscale.
        // Otherwise (distance <= tolerance), keep the original color of the pixel.
        if (distance > tolerance) {
            // Convert to grayscale using the luminance formula (perceived brightness)
            const gray = 0.299 * r + 0.587 * g + 0.114 * b;
            data[i] = gray;     // Red channel
            data[i + 1] = gray; // Green channel
            data[i + 2] = gray; // Blue channel
        }
        // If distance <= tolerance, the pixel's original color (data[i], data[i+1], data[i+2]) is preserved.
    }

    // Put the modified image data back onto the canvas
    ctx.putImageData(imageData, 0, 0);

    // Return the canvas element with the color pop effect
    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 Color Pop Filter Tool allows users to enhance their images by isolating a specific color and converting the rest of the image to grayscale. This tool is useful for creating striking visual effects where a targeted color stands out against a muted background. It can be applied in various scenarios such as photography, graphic design, or social media post enhancement, allowing users to draw attention to specific elements in their images.

Leave a Reply

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