Please bookmark this page to avoid losing your image tool!

Image Construction Site Filter Effect 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, saturationLevel = 0.6, contrastLevel = 1.3, tintColor = "#E09040", tintOpacity = 0.25, noiseIntensity = 15) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can sometimes optimize frequent getImageData/putImageData calls
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    // Ensure originalImg is loaded and has dimensions
    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;

    if (imgWidth === 0 || imgHeight === 0) {
        console.warn("Image has zero dimensions. Returning an empty canvas.");
        // Create a minimal canvas to avoid errors downstream if an empty one is not handled
        canvas.width = 1;
        canvas.height = 1;
        return canvas;
    }

    canvas.width = imgWidth;
    canvas.height = imgHeight;

    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

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

    // Helper function to parse hex color string (e.g., "#F00", "#FF0000") to {r, g, b}
    function hexToRgb(hex) {
        if (!hex || typeof hex !== 'string') return null;
        
        // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
        const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
        hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);

        const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        return result ? {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16)
        } : null;
    }

    let parsedTintColor = hexToRgb(tintColor);
    if (!parsedTintColor) {
        console.warn(`Invalid tintColor: "${tintColor}". Attempting to use default tint #E09040.`);
        // If the provided tintColor is invalid, try parsing the default value.
        // This makes the tint robustly applied unless the hardcoded default is also malformed.
        if (tintColor !== "#E09040") { // Avoid infinite loop if default itself is the problem
             parsedTintColor = hexToRgb("#E09040");
        }
        if (!parsedTintColor) {
            console.error("Default tintColor #E09040 could not be parsed. Tint will be skipped.");
        }
    }

    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];
        // Alpha channel (data[i+3]) is typically preserved

        // 1. Desaturation
        // saturationLevel = 1 means original color, 0 means grayscale.
        // Lerp: gray * (1 - saturationLevel) + colorComponent * saturationLevel
        const gray = 0.299 * r + 0.587 * g + 0.114 * b;
        r = gray * (1 - saturationLevel) + r * saturationLevel;
        g = gray * (1 - saturationLevel) + g * saturationLevel;
        b = b * (1 - saturationLevel) + b * saturationLevel;
        
        // Clamp values (though lerp with saturationLevel in [0,1] should keep them in [0,255] if originals are)
        r = Math.max(0, Math.min(255, r));
        g = Math.max(0, Math.min(255, g));
        b = Math.max(0, Math.min(255, b));

        // 2. Contrast
        // contrastLevel = 1.0 means no change.
        // Formula: NewValue = (((OldValue / 255.0) - 0.5) * contrastFactor) + 0.5) * 255.0;
        // This pushes values away from (contrastLevel > 1) or pulls them towards (contrastLevel < 1) the midpoint 128.
        if (contrastLevel !== 1.0) {
            r = ((r / 255.0 - 0.5) * contrastLevel + 0.5) * 255.0;
            g = ((g / 255.0 - 0.5) * contrastLevel + 0.5) * 255.0;
            b = ((b / 255.0 - 0.5) * contrastLevel + 0.5) * 255.0;
        }

        // Clamp values after contrast adjustment
        r = Math.max(0, Math.min(255, r));
        g = Math.max(0, Math.min(255, g));
        b = Math.max(0, Math.min(255, b));

        // 3. Tint
        // Blend current pixel color with parsedTintColor based on tintOpacity
        if (parsedTintColor && tintOpacity > 0) {
            r = r * (1 - tintOpacity) + parsedTintColor.r * tintOpacity;
            g = g * (1 - tintOpacity) + parsedTintColor.g * tintOpacity;
            b = b * (1 - tintOpacity) + parsedTintColor.b * tintOpacity;
        }
        
        // Clamp values after tinting
        r = Math.max(0, Math.min(255, r));
        g = Math.max(0, Math.min(255, g));
        b = Math.max(0, Math.min(255, b));

        // 4. Noise
        if (noiseIntensity > 0) {
            // Add noise symmetrically around 0; noiseIntensity defines the max deviation.
            // Math.random() gives [0, 1), so (Math.random() - 0.5) gives [-0.5, 0.5).
            // Multiply by 2 to get [-1, 1), then by noiseIntensity.
            const noise = (Math.random() - 0.5) * noiseIntensity * 2; 
            r += noise;
            g += noise;
            b += noise;
        }

        // Final clamp and round to integer for pixel data
        data[i] = Math.max(0, Math.min(255, Math.round(r)));
        data[i + 1] = Math.max(0, Math.min(255, Math.round(g)));
        data[i + 2] = Math.max(0, Math.min(255, Math.round(b)));
        // data[i+3] (alpha) remains unchanged
    }

    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 Construction Site Filter Effect Tool allows users to apply a unique filter effect to images, enhancing them with controls for saturation, contrast, tint color, tint opacity, and noise intensity. This tool is particularly useful for creative projects where a specific aesthetic is desired, such as in digital art, promotional materials, or social media content. Users can easily modify their images to reflect an industrial or construction-themed look, making it ideal for architects, designers, and anyone looking to add a distinctive flair to their visual content.

Leave a Reply

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