Please bookmark this page to avoid losing your image tool!

Image Fresco 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, levels = 4, saturationLevel = 1.0) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can optimize repeated getImageData/putImageData calls,
    // though for a single pass filter, its impact might be minor. It's good practice.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

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

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

    // Ensure 'levels' is at least 2, as 1 level would lead to division by zero or NaN.
    if (levels < 2) {
        levels = 2;
    }
    // Clamp saturationLevel to be non-negative. Values > 1.0 will boost saturation.
    if (saturationLevel < 0) {
        saturationLevel = 0;
    }

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

    // Calculate the step for color quantization
    // This determines the size of each color "band"
    const step = 255 / (levels - 1);

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

        // 1. Apply saturation adjustment (if saturationLevel is not 1.0)
        if (saturationLevel !== 1.0) {
            // Standard luma calculation (coefficients for RGB to perceived brightness)
            const luma = 0.299 * r + 0.587 * g + 0.114 * b;
            
            // Interpolate between luma (grayscale) and original color
            r = luma + (r - luma) * saturationLevel;
            g = luma + (g - luma) * saturationLevel;
            b = luma + (b - luma) * saturationLevel;

            // Clamp values to the 0-255 range before posterization
            // Storing them back into 'data' isn't done here to avoid premature rounding by Uint8ClampedArray.
            // We'll work with these potentially float, unclamped values and clamp before posterization.
            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. Apply posterization (color quantization)
        // For each color channel, map it to the nearest representative color level
        // The formula Math.round(value / step) determines which "level" the value falls into.
        // Multiplying by 'step' gives the actual color value for that level.
        // The final Math.round() ensures an integer result for the Uint8ClampedArray.
        data[i]   = Math.round(Math.round(r / step) * step);
        data[i+1] = Math.round(Math.round(g / step) * step);
        data[i+2] = Math.round(Math.round(b / step) * step);
        // Alpha channel (data[i + 3]) remains unchanged
    }

    // Put the modified image data 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 Fresco Filter Effect Tool allows users to apply a creative fresco filter effect to their images. This tool can effectively enhance the visual aesthetics of photos by adjusting the saturation levels and implementing color quantization, resulting in a stylized, artistic rendition of the original image. It is particularly useful for graphic designers, photographers, and social media enthusiasts looking to transform their images for artistic projects, digital artwork, or online sharing.

Leave a Reply

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