Please bookmark this page to avoid losing your image tool!

Image Hair Smoothing Enhancer

(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.
/**
 * Smoothes an image using a bilateral filter, which is effective at reducing fine texture
 * like frizzy hair while preserving important edges. The function can be computationally
 * intensive on large images or with large radius values.
 *
 * @param {Image} originalImg The original Image object to process.
 * @param {number} radius The radius of the filter neighborhood in pixels. A larger radius smooths more but is slower. Default is 5.
 * @param {number} sigmaI The "intensity" or "color" sigma. It defines how much color difference is tolerated for smoothing. Larger values mean more colors are averaged together, resulting in stronger smoothing. Default is 50.
 * @param {number} sigmaS The "spatial" sigma. It defines the influence of pixels based on their distance from the center pixel. Default is 50.
 * @returns {Promise<HTMLCanvasElement>} A promise that resolves with a new canvas element containing the smoothed image.
 */
async function processImage(originalImg, radius = 5, sigmaI = 50, sigmaS = 50) {
    // This is a computationally expensive operation, wrapping it in a Promise
    // allows the UI to remain responsive.
    return new Promise((resolve) => {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d', { willReadFrequently: true });

        canvas.width = originalImg.naturalWidth;
        canvas.height = originalImg.naturalHeight;

        // Draw the original image to the canvas
        ctx.drawImage(originalImg, 0, 0);

        // Get the pixel data from the canvas
        const originalData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const outputData = new ImageData(canvas.width, canvas.height);
        const src = originalData.data;
        const dst = outputData.data;
        const width = canvas.width;
        const height = canvas.height;

        // Helper function for the Gaussian distribution
        const gaussian = (x, sigma) => Math.exp(-(x * x) / (2 * sigma * sigma));

        // Pre-calculate Gaussian lookup tables for optimization
        const intensityWeights = new Float32Array(256);
        for (let i = 0; i < 256; i++) {
            intensityWeights[i] = gaussian(i, sigmaI);
        }

        const spatialWeights = new Float32Array(2 * radius + 1);
         for (let i = -radius; i <= radius; i++) {
            spatialWeights[i + radius] = gaussian(i, sigmaS);
        }

        // Process the image
        // Use a slight delay with setTimeout to avoid completely blocking the main thread,
        // allowing for UI updates if necessary (e.g., a progress bar).
        setTimeout(() => {
            for (let y = 0; y < height; y++) {
                for (let x = 0; x < width; x++) {
                    const centerIndex = (y * width + x) * 4;
                    const rC = src[centerIndex];
                    const gC = src[centerIndex + 1];
                    const bC = src[centerIndex + 2];

                    let totalR = 0,
                        totalG = 0,
                        totalB = 0;
                    let totalWeight = 0;

                    // Iterate over the neighborhood defined by the radius
                    for (let ny = -radius; ny <= radius; ny++) {
                        for (let nx = -radius; nx <= radius; nx++) {
                            const currentY = y + ny;
                            const currentX = x + nx;

                            // Check if the neighbor pixel is within the image bounds
                            if (currentY >= 0 && currentY < height && currentX >= 0 && currentX < width) {
                                const neighborIndex = (currentY * width + currentX) * 4;
                                const rN = src[neighborIndex];
                                const gN = src[neighborIndex + 1];
                                const bN = src[neighborIndex + 2];

                                // Calculate the color difference (absolute difference in RGB channels)
                                const dr = rC - rN;
                                const dg = gC - gN;
                                const db = bC - bN;
                                const intensityDiff = Math.sqrt(dr*dr + dg*dg + db*db);

                                // Look up pre-calculated weights
                                const colorWeight = intensityWeights[Math.round(intensityDiff)] || 0;
                                const spatialWeight = spatialWeights[nx + radius] * spatialWeights[ny + radius];

                                const weight = spatialWeight * colorWeight;

                                totalR += rN * weight;
                                totalG += gN * weight;
                                totalB += bN * weight;
                                totalWeight += weight;
                            }
                        }
                    }

                    dst[centerIndex] = totalR / totalWeight;
                    dst[centerIndex + 1] = totalG / totalWeight;
                    dst[centerIndex + 2] = totalB / totalWeight;
                    dst[centerIndex + 3] = src[centerIndex + 3]; // Keep original alpha
                }
            }

            // Put the processed pixel data back onto the canvas
            ctx.putImageData(outputData, 0, 0);
            resolve(canvas);
        }, 0);
    });
}

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 Hair Smoothing Enhancer is a web-based tool designed to reduce frizzy or coarse hair textures in images while preserving essential edges and details. Utilizing a bilateral filter, this tool effectively smoothens the appearance of hair in photos, making it ideal for portrait editing, fashion photography, and social media images. Users can customize the level of smoothing by adjusting parameters like radius and sigma values, allowing for tailored enhancements to suit individual preferences. Whether you’re a professional photographer or simply looking to touch up personal photos, this tool offers an efficient solution for creating smoother hair appearances.

Leave a Reply

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