Please bookmark this page to avoid losing your image tool!

Image Red-eye Removal 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.
/**
 * Removes red-eye effect from an image using a pixel-based heuristic.
 *
 * @param {Image} originalImg The original HTMLImageElement. It's assumed this image is loaded
 *                            and has `naturalWidth` and `naturalHeight` > 0.
 * @param {number} [minRedValue=70] The minimum value for the red channel (0-255) for a pixel
 *                                  to be considered as potential red-eye. Higher values are stricter.
 * @param {number} [redDominanceFactor=1.5] How much the red channel must dominate the green and
 *                                          blue channels (e.g., R > G * factor && R > B * factor).
 *                                          A factor of 1.0 means red just needs to be greater.
 *                                          Higher values mean red must be much stronger.
 * @returns {HTMLCanvasElement} A canvas element with the red-eye effect reduced or removed.
 *                               In case of errors (e.g., invalid image dimensions, CORS restrictions),
 *                               it returns a canvas displaying an error message.
 */
function processImage(originalImg, minRedValue = 70, redDominanceFactor = 1.5) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can be an optimization hint for the browser
    // for contexts where getImageData/putImageData are used often.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    const imgWidth = originalImg.naturalWidth;
    const imgHeight = originalImg.naturalHeight;

    // Validate image dimensions first
    if (imgWidth === 0 || imgHeight === 0) {
        // Setup a canvas to display an error message for invalid image dimensions
        canvas.width = 300; // Arbitrary small size for the error message canvas
        canvas.height = 80;
        ctx.font = "bold 14px Arial";
        ctx.fillStyle = "#700"; // Dark red color for the text
        ctx.textAlign = "center";
        ctx.textBaseline = "middle"; // Vertically center text
        ctx.fillText("Error: Image dimensions are invalid (0x0).", canvas.width / 2, canvas.height / 2);
        console.error("processImage: Original image dimensions are 0x0.");
        return canvas;
    }
    
    // Set canvas dimensions to match the original image
    canvas.width = imgWidth;
    canvas.height = imgHeight;

    try {
        // Draw the original image onto the canvas
        ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);

        // Get the pixel data from the canvas. This can throw a security error for cross-origin images.
        const imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
        const data = imageData.data; // This is a Uint8ClampedArray: [R, G, B, A, R, G, B, A, ...]

        // Although dimensions are checked, imageData.data could theoretically be null
        // (e.g., out of memory for extremely large canvases), though rare.
        if (!data) {
             console.error("processImage: Failed to retrieve ImageData.data (is null).");
             ctx.font = "bold 16px Arial";
             // Draw a semi-transparent background for the error text for better visibility
             ctx.fillStyle = "rgba(128, 0, 0, 0.75)"; // Dark red, semi-transparent
             ctx.fillRect(0, canvas.height / 2 - 20, canvas.width, 40); // Background rectangle
             ctx.fillStyle = "white"; // Text color
             ctx.textAlign = "center";
             ctx.textBaseline = "middle";
             ctx.fillText("Error: Could not retrieve pixel data.", canvas.width / 2, canvas.height / 2);
             return canvas; // Return canvas (original image may be drawn) with error message
        }

        // Iterate over each pixel (each pixel consists of 4 components: R, G, B, A)
        for (let i = 0; i < data.length; i += 4) {
            const r = data[i];   // Red channel value
            const g = data[i+1]; // Green channel value
            const b = data[i+2]; // Blue channel value
            // const alpha = data[i+3]; // Alpha channel, preserved

            // Red-eye detection heuristic:
            // 1. The red component must be above a minimum threshold.
            // 2. The red component must be significantly stronger than both green and blue components.
            if (r > minRedValue && 
                r > (g * redDominanceFactor) && 
                r > (b * redDominanceFactor)) {
                
                // This pixel is identified as part of a red-eye.
                // Correct it by converting the pixel to a grayscale value.
                // The gray value is derived from the average of the green and blue components,
                // which are assumed to be less affected by the red-eye phenomenon.
                const gray = Math.floor((g + b) / 2);
                
                data[i]   = gray; // Set Red component to the new gray value
                data[i+1] = gray; // Set Green component to the new gray value
                data[i+2] = gray; // Set Blue component to the new gray value
                // The alpha channel (data[i+3]) remains unchanged.
            }
        }

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

    } catch (e) {
        // Catch errors, most commonly SecurityError due to CORS restrictions on getImageData
        console.error("processImage: Error during image processing:", e.message, e);
        
        // Display an error message on the canvas.
        // If ctx.drawImage succeeded, the original image is on the canvas under this message.
        ctx.font = "bold 16px Arial";
        ctx.fillStyle = "rgba(128, 0, 0, 0.75)"; // Dark red, semi-transparent background
        ctx.fillRect(0, canvas.height / 2 - 20, canvas.width, 40); // Background rectangle for text
        ctx.fillStyle = "white"; // Text color
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        let errorMessage = "Error: Pixel access denied.";
        if (e.name === 'SecurityError') {
            errorMessage += " (CORS issue?)";
        }
        ctx.fillText(errorMessage, canvas.width / 2, canvas.height / 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 Red-eye Removal Tool provides a simple and effective way to eliminate red-eye effects from photographs. This tool is particularly useful for improving the appearance of portraits where flash photography has caused red-eye, making the eyes appear unnatural. By analyzing the pixel data of an image, it identifies and adjusts the red-eye pixels, converting them to a more natural gray tone. This tool can be beneficial for personal photo touch-ups, professional editing, or preparing images for social media sharing, ensuring your photos look polished and aesthetically pleasing.

Leave a Reply

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