Please bookmark this page to avoid losing your image tool!

Image HDR Filter Application

(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, sharpenAmount = 1.0, sharpenRadius = 2, contrastLevel = 20, saturationFactor = 1.2) {
    // Ensure originalImg is loaded and has valid dimensions.
    // This is a basic check; robust error handling might be more complex.
    if (!originalImg || typeof originalImg.naturalWidth === 'undefined' || !originalImg.complete || originalImg.naturalWidth === 0 || originalImg.naturalHeight === 0) {
        console.error("Image is not fully loaded, invalid, or has zero dimensions.");
        // Return a minimal canvas or throw an error.
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = 1;
        errorCanvas.height = 1;
        const errorCtx = errorCanvas.getContext('2d');
        if (errorCtx) {
            errorCtx.fillStyle = 'red';
            errorCtx.fillRect(0,0,1,1); // Mark error
        }
        return errorCanvas;
    }

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

    // 1. Create main canvas for final output and intermediate steps
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');

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

    // --- Step 1: Unsharp Masking (Detail Enhancement) ---
    // Only apply if sharpenAmount is effective and radius is positive
    if (sharpenAmount > 0 && sharpenRadius > 0) {
        // Create a temporary canvas for the blurred version
        const blurCanvas = document.createElement('canvas');
        blurCanvas.width = width;
        blurCanvas.height = height;
        // Add willReadFrequently hint for potential performance improvement
        const blurCtx = blurCanvas.getContext('2d', { willReadFrequently: true });

        // Apply CSS blur filter to the temporary canvas context
        // Ensure sharpenRadius is non-negative for the blur filter
        blurCtx.filter = `blur(${Math.max(0, sharpenRadius)}px)`;
        blurCtx.drawImage(originalImg, 0, 0, width, height); // Draw image to apply filter
        blurCtx.filter = 'none'; // Reset filter on the temporary context

        // Get pixel data from the original image (on the main canvas)
        // and the blurred image (on the temporary canvas)
        const originalImageData = ctx.getImageData(0, 0, width, height);
        const blurredImageData = blurCtx.getImageData(0, 0, width, height);
        
        // We will modify the pixel data of the main canvas (originalImageData.data)
        const data = originalImageData.data;

        for (let i = 0; i < data.length; i += 4) {
            // Process R, G, B channels
            for (let j = 0; j < 3; j++) {
                const originalPixel = data[i + j]; // Current pixel value from main canvas
                const blurredPixel = blurredImageData.data[i + j];
                
                const detail = originalPixel - blurredPixel;
                let sharpenedPixel = originalPixel + sharpenAmount * detail;

                // Clamp the pixel value to the 0-255 range
                sharpenedPixel = Math.max(0, Math.min(255, sharpenedPixel));
                data[i + j] = sharpenedPixel;
            }
            // Alpha channel (data[i + 3]) remains unchanged from originalImageData
        }
        // Put the modified (sharpened) image data back onto the main canvas
        ctx.putImageData(originalImageData, 0, 0);
    }

    // --- Step 2: Contrast Adjustment ---
    // The image on `canvas` is now the (potentially) sharpened version.
    // contrastLevel = 0 means no change.
    if (contrastLevel !== 0) { 
        const imageData = ctx.getImageData(0, 0, width, height); // Get current state of canvas
        const data = imageData.data;
        
        // Map contrastLevel (e.g., -100 to 100) to C_internal for the formula
        // A common range for C_internal in the formula is -255 to 255.
        // Let's map -100..100 to -128..128 so 100 gives a strong but not extreme effect.
        const C_internal = (contrastLevel / 100) * 128; 
        const factor = (259 * (C_internal + 255)) / (255 * (259 - C_internal));

        for (let i = 0; i < data.length; i += 4) {
            // Adjust R, G, B channels
            data[i]     = factor * (data[i]     - 128) + 128;
            data[i + 1] = factor * (data[i + 1] - 128) + 128;
            data[i + 2] = factor * (data[i + 2] - 128) + 128;

            // Clamp values
            data[i]     = Math.max(0, Math.min(255, data[i]));
            data[i + 1] = Math.max(0, Math.min(255, data[i + 1]));
            data[i + 2] = Math.max(0, Math.min(255, data[i + 2]));
        }
        // Put the modified (contrasted) data back
        ctx.putImageData(imageData, 0, 0);
    }

    // --- Step 3: Saturation Adjustment ---
    // The image on `canvas` is now sharpened + contrasted.
    // saturationFactor = 1.0 means no change.
    if (saturationFactor !== 1.0) { 
        const imageData = ctx.getImageData(0, 0, width, height); // Get current state of canvas
        const data = imageData.data;

        for (let i = 0; i < data.length; i += 4) {
            const r = data[i];
            const g = data[i + 1];
            const b = data[i + 2];

            // Luminance calculation (standard coefficients for sRGB/Rec.709 primaries are often used,
            // but 0.299, 0.587, 0.114 are common for NTSC/Rec.601 and widely used in image editors)
            const gray = 0.299 * r + 0.587 * g + 0.114 * b;

            // Adjust saturation for R, G, B channels
            data[i]     = gray + saturationFactor * (r - gray);
            data[i + 1] = gray + saturationFactor * (g - gray);
            data[i + 2] = gray + saturationFactor * (b - gray);

            // Clamp values
            data[i]     = Math.max(0, Math.min(255, data[i]));
            data[i + 1] = Math.max(0, Math.min(255, data[i + 1]));
            data[i + 2] = Math.max(0, Math.min(255, data[i + 2]));
        }
        // Put the modified (saturated) data back
        ctx.putImageData(imageData, 0, 0);
    }
    
    // Return the canvas 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 HDR Filter Application enhances images by applying high dynamic range (HDR) effects, which include sharpening, contrast adjustment, and saturation modification. Users can upload an image and customize the level of sharpening, the radius for detail enhancement, as well as the degree of contrast and saturation adjustments. This tool is useful for photographers and graphic designers looking to improve their images for better visual appeal, enhance details, or create striking visuals for presentations, social media, or professional portfolios.

Leave a Reply

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