Please bookmark this page to avoid losing your image tool!

Image Background Reddening 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, toleranceStr = '45', hexColor = '#FF0000') {
    const tolerance = parseFloat(toleranceStr);
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    const width = originalImg.width;
    const height = originalImg.height;
    
    canvas.width = width;
    canvas.height = height;

    // 1. Fill canvas with the target background color first.
    // This elegantly handles images with a transparent background by turning 
    // the transparent areas red (and natively blending semi-transparent edge pixels).
    ctx.fillStyle = hexColor;
    ctx.fillRect(0, 0, width, height);

    // 2. Draw the original image on top.
    ctx.drawImage(originalImg, 0, 0);

    const imageData = ctx.getImageData(0, 0, width, height);
    const data = imageData.data;

    // Parse the replacement hex color
    let rFill = 255, gFill = 0, bFill = 0;
    const hexMatch = hexColor.match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
    if (hexMatch) {
        rFill = parseInt(hexMatch[1], 16);
        gFill = parseInt(hexMatch[2], 16);
        bFill = parseInt(hexMatch[3], 16);
    }

    // Prepare arrays for Flood Fill algorithm (replaces solid backgrounds like bright white)
    // Using typed arrays for stack avoids hitting max call stack size and saves memory/GC.
    const visited = new Uint8Array(width * height);
    const stackX = new Uint32Array(width * height);
    const stackY = new Uint32Array(width * height);
    
    const floodFill = (startX, startY) => {
        const startPos = startY * width + startX;
        if (visited[startPos]) return;

        const startIdx = startPos * 4;
        const targetR = data[startIdx];
        const targetG = data[startIdx + 1];
        const targetB = data[startIdx + 2];

        // If the starting corner is already exactly our fill color, there's nothing to change.
        if (targetR === rFill && targetG === gFill && targetB === bFill) {
            return;
        }

        const colorMatch = (idx) => {
            const r = data[idx];
            const g = data[idx + 1];
            const b = data[idx + 2];
            
            // Calculate color distance
            const dist = Math.sqrt(
                Math.pow(r - targetR, 2) +
                Math.pow(g - targetG, 2) +
                Math.pow(b - targetB, 2)
            );
            return dist <= tolerance;
        };

        visited[startPos] = 1;
        stackX[0] = startX;
        stackY[0] = startY;
        let stackPtr = 1;

        while (stackPtr > 0) {
            stackPtr--;
            const x = stackX[stackPtr];
            const y = stackY[stackPtr];
            const pos = y * width + x;
            const idx = pos * 4;
            
            // Color it red
            data[idx] = rFill;
            data[idx + 1] = gFill;
            data[idx + 2] = bFill;
            data[idx + 3] = 255;

            // Check Left neighbor
            if (x > 0 && !visited[pos - 1]) {
                visited[pos - 1] = 1;
                if (colorMatch((pos - 1) * 4)) {
                    stackX[stackPtr] = x - 1;
                    stackY[stackPtr] = y;
                    stackPtr++;
                }
            }
            // Check Right neighbor
            if (x < width - 1 && !visited[pos + 1]) {
                visited[pos + 1] = 1;
                if (colorMatch((pos + 1) * 4)) {
                    stackX[stackPtr] = x + 1;
                    stackY[stackPtr] = y;
                    stackPtr++;
                }
            }
            // Check Top neighbor
            if (y > 0 && !visited[pos - width]) {
                visited[pos - width] = 1;
                if (colorMatch((pos - width) * 4)) {
                    stackX[stackPtr] = x;
                    stackY[stackPtr] = y - 1;
                    stackPtr++;
                }
            }
            // Check Bottom neighbor
            if (y < height - 1 && !visited[pos + width]) {
                visited[pos + width] = 1;
                if (colorMatch((pos + width) * 4)) {
                    stackX[stackPtr] = x;
                    stackY[stackPtr] = y + 1;
                    stackPtr++;
                }
            }
        }
    };

    // Trigger flood fill from all 4 corners to capture typical exterior background regions.
    // If corners are connected, subsequent calls cleanly return as 'visited'.
    floodFill(0, 0);
    floodFill(width - 1, 0);
    floodFill(0, height - 1);
    floodFill(width - 1, height - 1);

    // Apply the manipulated pixels back onto the canvas
    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 Background Reddening Tool allows users to replace the background of an image with a red color. Utilizing a flood-fill algorithm, the tool can detect and change solid or near-solid background colors (like white) and also handle images with transparent backgrounds. This tool is useful for graphic designers, product photographers, or content creators who need to quickly standardize image backgrounds for e-commerce listings, marketing materials, or creative compositions.

Leave a Reply

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