Please bookmark this page to avoid losing your image tool!

Image Background Remover And Transparent PNG Converter

(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, tolerance = 30, feathering = 15, method = "floodfill", bgColorHex = "auto") {
    const canvas = document.createElement('canvas');
    const width = originalImg.width;
    const height = originalImg.height;
    canvas.width = width;
    canvas.height = height;
    
    // Return empty canvas if dimension is 0
    if (width === 0 || height === 0) return canvas;
    
    const ctx = canvas.getContext('2d');
    ctx.drawImage(originalImg, 0, 0);
    
    const imgData = ctx.getImageData(0, 0, width, height);
    const data = imgData.data;

    // Determine the background color to be removed
    let bgR = 255, bgG = 255, bgB = 255;
    
    if (bgColorHex !== "auto" && /^#([0-9A-F]{3}){1,2}$/i.test(bgColorHex)) {
        // Parse from hex string if explicitly provided
        let hex = bgColorHex.replace('#', '');
        if (hex.length === 3) hex = hex.split('').map(c => c + c).join('');
        bgR = parseInt(hex.substring(0, 2), 16);
        bgG = parseInt(hex.substring(2, 4), 16);
        bgB = parseInt(hex.substring(4, 6), 16);
    } else {
        // Automatically determine background color by averaging the 4 corners of the image
        const corners = [
            0,
            (width - 1) * 4,
            ((height - 1) * width) * 4,
            ((height - 1) * width + width - 1) * 4
        ];
        let rSum = 0, gSum = 0, bSum = 0;
        for (let c of corners) {
            rSum += data[c];
            gSum += data[c+1];
            bSum += data[c+2];
        }
        bgR = Math.round(rSum / 4);
        bgG = Math.round(gSum / 4);
        bgB = Math.round(bSum / 4);
    }

    const tol = Math.max(0, tolerance);
    const fade = Math.max(1, feathering);

    // Calculate Euclidean color distance in RGB space
    function colorDist(r, g, b) {
        return Math.sqrt(
            (r - bgR) * (r - bgR) + 
            (g - bgG) * (g - bgG) + 
            (b - bgB) * (b - bgB)
        );
    }

    if (method === "chroma_key") {
        // Mode 1: Remove all pixels across the whole image matching the color
        for (let i = 0; i < data.length; i += 4) {
            const dist = colorDist(data[i], data[i+1], data[i+2]);
            if (dist <= tol) {
                // Perfect background match, make completely transparent
                data[i+3] = 0; 
            } else if (dist <= tol + fade) {
                // Feathering edge, make semi-transparent for anti-aliasing
                const alpha = Math.round(((dist - tol) / fade) * 255);
                data[i+3] = Math.min(data[i+3], alpha);
            }
        }
    } else {
        // Mode 2: Flood-fill to remove only the connected outer background (Leaves matching inner colors intact)
        const visited = new Uint8Array(width * height);
        // Pre-allocate a 1D array to act as a stack for maximum performance instead of JS Array .push() / .pop()
        const stack = new Int32Array(width * height);
        let stackPtr = 0;

        // Seed the outer edges of the image as the initial background area
        for (let x = 0; x < width; x++) {
            const topIdx = x;
            const bottomIdx = (height - 1) * width + x;
            if (colorDist(data[topIdx*4], data[topIdx*4+1], data[topIdx*4+2]) <= tol) {
                if (!visited[topIdx]) { stack[stackPtr++] = topIdx; visited[topIdx] = 1; }
            }
            if (colorDist(data[bottomIdx*4], data[bottomIdx*4+1], data[bottomIdx*4+2]) <= tol) {
                if (!visited[bottomIdx]) { stack[stackPtr++] = bottomIdx; visited[bottomIdx] = 1; }
            }
        }
        for (let y = 1; y < height - 1; y++) {
            const leftIdx = y * width;
            const rightIdx = y * width + width - 1;
            if (colorDist(data[leftIdx*4], data[leftIdx*4+1], data[leftIdx*4+2]) <= tol) {
                if (!visited[leftIdx]) { stack[stackPtr++] = leftIdx; visited[leftIdx] = 1; }
            }
            if (colorDist(data[rightIdx*4], data[rightIdx*4+1], data[rightIdx*4+2]) <= tol) {
                if (!visited[rightIdx]) { stack[stackPtr++] = rightIdx; visited[rightIdx] = 1; }
            }
        }

        // Neighborhood offsets for Flood-fill: Left, Right, Up, Down
        const dx = [-1, 1, 0, 0];
        const dy = [0, 0, -1, 1];

        // Process queue
        while (stackPtr > 0) {
            const current = stack[--stackPtr];
            const cx = current % width;
            const cy = Math.floor(current / width);

            // Set background pixel alpha to 0 (Transparent)
            const pIdx = current * 4;
            data[pIdx + 3] = 0;

            for (let i = 0; i < 4; i++) {
                const nx = cx + dx[i];
                const ny = cy + dy[i];

                if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                    const nPos = ny * width + nx;
                    if (!visited[nPos]) {
                        const nIdx = nPos * 4;
                        const dist = colorDist(data[nIdx], data[nIdx+1], data[nIdx+2]);
                        
                        if (dist <= tol) {
                            visited[nPos] = 1;
                            stack[stackPtr++] = nPos;
                        } else if (dist <= tol + fade) {
                            // Hit an object's boundary pixel. Stop traversing and feather the alpha.
                            visited[nPos] = 1;
                            const alpha = Math.round(((dist - tol) / fade) * 255);
                            data[nIdx+3] = Math.min(data[nIdx+3], alpha);
                        }
                    }
                }
            }
        }
    }

    // Apply the manipulated transparent pixels back to the Canvas
    ctx.putImageData(imgData, 0, 0);

    // Note: To obtain the transparent PNG out of this utility method outside the scope:
    // const dataUrl = canvas.toDataURL("image/png");
    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

This tool allows users to remove the background from an image and convert it into a transparent PNG. It features two distinct processing methods: a chroma key mode that removes specific colors throughout the entire image, and a flood-fill mode that intelligently removes only the connected background area while preserving similar colors within the main subject. Users can fine-tune the results using tolerance and feathering settings to ensure smooth, professional-looking edges. This utility is ideal for graphic designers, e-commerce merchants looking to create clean product photos, or anyone needing to isolate subjects for digital compositions and presentations.

Leave a Reply

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