Please bookmark this page to avoid losing your image tool!

Image Red Filter Black And White 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, redHueCenterDegStr = "0", hueToleranceDegStr = "30", minSaturationStr = "0.2", minLightnessStr = "0.1") {
    // Parse parameters to numbers
    const targetHue = parseFloat(redHueCenterDegStr); // e.g., 0 for red
    const tolerance = parseFloat(hueToleranceDegStr); // e.g., 30, so 0 +/- 30 degrees
    const minSaturation = parseFloat(minSaturationStr); // e.g., 0.2 (0-1 range for saturation)
    const minLightness = parseFloat(minLightnessStr); // e.g., 0.1 (0-1 range for lightness)

    // Create a canvas element
    const canvas = document.createElement('canvas');
    // Use { willReadFrequently: true } for potential performance optimization
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    // Set canvas dimensions to the original image's dimensions
    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;

    // Handle cases where the image might not be fully loaded or has no dimensions
    if (canvas.width === 0 || canvas.height === 0) {
        console.warn("Original image has zero width or height. Ensure it is loaded before calling processImage.");
        // Return a small, empty canvas as a fallback
        canvas.width = 1; 
        canvas.height = 1;
        ctx.clearRect(0, 0, 1, 1); // Make it transparent
        return canvas; 
    }

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

    // Get the image data (pixel array) from the canvas
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    } catch (e) {
        console.error("Error getting image data for processing:", e);
        // If getImageData fails (e.g., cross-origin image without CORS), draw an error message on the canvas
        ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the drawn image
        ctx.font = "14px Arial";
        ctx.fillStyle = "black";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        let msg = "Error: Cannot process image.";
        if (e.name === 'SecurityError') {
            msg = "Error: Image source is cross-origin and not CORS-enabled.";
        }
        const lines = msg.split('\n');
        const lineHeight = 18;
        const startY = canvas.height / 2 - (lines.length -1) * lineHeight / 2;

        for(let k=0; k<lines.length; k++) {
            ctx.fillText(lines[k], canvas.width / 2, startY + k * lineHeight);
        }
        return canvas;
    }
    
    const data = imageData.data;

    // Helper function: Convert RGB to HSL
    // Input r, g, b are in [0, 255]
    // Output h is in [0, 359] degrees, s and l are in [0, 1]
    function rgbToHsl(r, g, b) {
        r /= 255; g /= 255; b /= 255;
        const max = Math.max(r, g, b);
        const min = Math.min(r, g, b);
        let h, s;
        const l = (max + min) / 2;

        if (max === min) {
            h = s = 0; // achromatic (grayscale)
        } else {
            const d = max - min;
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
            switch (max) {
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }
            h /= 6;
        }
        
        let finalH = Math.round(h * 360);
        // Ensure hue is in [0, 359]. If Math.round results in 360 (e.g. for 359.99...), map it to 0.
        finalH = finalH % 360;
        
        return [finalH, s, l];
    }

    // Normalize targetHue to be within [0, 359] degrees for consistent calculations
    const normalizedTargetHue = (targetHue % 360 + 360) % 360;

    // Calculate the hue range to be preserved. Handles wrapping around 360 degrees.
    const hueMin = (normalizedTargetHue - tolerance + 360) % 360;
    const hueMax = (normalizedTargetHue + tolerance + 360) % 360;

    // Iterate through the pixel data (each pixel has R, G, B, A components)
    for (let i = 0; i < data.length; i += 4) {
        const r_val = data[i];
        const g_val = data[i + 1];
        const b_val = data[i + 2];
        // Alpha component (data[i + 3]) is typically left unchanged

        const [h_pixel, s_pixel, l_pixel] = rgbToHsl(r_val, g_val, b_val);

        let isTargetHueRegion;
        if (hueMin <= hueMax) {
            // Normal hue range (e.g., min=60, max=120 for greens)
            isTargetHueRegion = (h_pixel >= hueMin && h_pixel <= hueMax);
        } else { 
            // Hue range wraps around 360 (e.g., min=330, max=30 for reds)
            isTargetHueRegion = (h_pixel >= hueMin || h_pixel <= hueMax);
        }
        
        // Determine if the pixel's color should be preserved
        // It must fall within the target hue range AND meet minimum saturation and lightness.
        // The saturation check is crucial: achromatic colors (s_pixel=0) have h_pixel=0.
        // If targetHue is red (0 deg), this check ensures grays don't get preserved as red.
        const preserveColor = isTargetHueRegion && (s_pixel >= minSaturation) && (l_pixel >= minLightness);

        if (!preserveColor) {
            // Convert to grayscale using the luminosity method (standard perceptual brightness)
            const gray = 0.299 * r_val + 0.587 * g_val + 0.114 * b_val;
            data[i] = gray;     // Red channel
            data[i + 1] = gray; // Green channel
            data[i + 2] = gray; // Blue channel
        }
        // If preserveColor is true, the original R, G, B values remain unchanged.
    }

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

    // Return the canvas element with the processed image
    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 Red Filter Black And White Effect Tool allows users to apply a unique filter to their images, creating a striking black and white effect while preserving specific red hues. This tool is useful for photographers and designers looking to emphasize red elements in their visuals, making them pop against a monochromatic background. It’s ideal for artistic projects, enhancing social media images, or creating distinctive graphics where a selective color effect is desired.

Leave a Reply

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