Please bookmark this page to avoid losing your image tool!

Image Gouache 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.
/**
 * Applies a pseudo-gouache effect to an image.
 * This effect is achieved by first blurring the image and then posterizing it
 * to reduce the number of colors, creating flat color areas with soft transitions.
 *
 * @param {Image} originalImg The original image object (HTMLImageElement or compatible).
 *                            Ensure the image is fully loaded so that naturalWidth/naturalHeight are available.
 * @param {number} [blurRadius=2] The radius for the Gaussian blur effect in pixels.
 *                                  A larger radius creates softer transitions. Set to 0 for no blur.
 *                                  The value is clamped to be non-negative.
 * @param {number} [levels=4] The number of color levels per channel for posterization.
 *                            Must be an integer >= 2. Fewer levels result in a more abstract, flatter look.
 *                            The value is clamped to be an integer and at least 2.
 * @returns {HTMLCanvasElement} A new canvas element displaying the image with the gouache effect.
 */
function processImage(originalImg, blurRadius = 2, levels = 4) {
    // Validate and sanitize parameters
    levels = Math.max(2, Math.floor(Number(levels)));
    blurRadius = Math.max(0, Number(blurRadius));

    const originalWidth = originalImg.naturalWidth;
    const originalHeight = originalImg.naturalHeight;

    // Determine canvas dimensions. Prioritize natural dimensions of the image.
    // Fallback to element's width/height if natural dimensions are 0 (e.g., SVG or not fully loaded raster).
    const width = originalWidth > 0 ? originalWidth : originalImg.width;
    const height = originalHeight > 0 ? originalHeight : originalImg.height;

    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');

    if (width === 0 || height === 0) {
        // If dimensions are zero, drawing operations would fail or be meaningless.
        // Return the empty (0x0 or 0-width/height) canvas.
        return canvas;
    }

    // Create a temporary canvas for intermediate operations (e.g., blurring).
    // This avoids issues with applying filters and then immediately getting pixel data from the same context.
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = width;
    tempCanvas.height = height;
    const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true });


    // Step 1: Apply blur (if blurRadius > 0) and draw to tempCanvas
    if (blurRadius > 0) {
        tempCtx.filter = `blur(${blurRadius}px)`;
    }
    
    // Draw the original image onto the tempCanvas. 
    // If a filter is set on tempCtx, it will be applied during this drawing operation.
    tempCtx.drawImage(originalImg, 0, 0, width, height);
    
    // Reset the filter on tempCtx if it was applied, so it doesn't affect subsequent operations on this context (if any).
    if (blurRadius > 0) {
        tempCtx.filter = 'none'; 
    }
    // Now, tempCanvas contains the (potentially) blurred image.

    // Step 2: Posterization
    // Get the pixel data from the (blurred) image on tempCanvas
    const imageData = tempCtx.getImageData(0, 0, width, height);
    const data = imageData.data;
    
    // Calculate factor for posterization.
    // `levels` is the number of distinct output values for each color channel.
    // Example: if levels = 4, output values for a channel could be 0, 85, 170, 255.
    // The formula aims to map the input range [0, 255] to `levels` discrete values.
    // levels must be >= 2, so (levels - 1) is >= 1, avoiding division by zero.
    const quantMultiplier = 255 / (levels - 1);
    
    for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i+1];
        const b = data[i+2];
        // Alpha (data[i+3]) remains unchanged

        // Posterize each color channel (R, G, B)
        // This formula divides the 0-255 range into `levels` segments.
        // `Math.floor(colorValue * levels / 256)` maps the colorValue to an index [0, levels-1].
        // Then this index is scaled back to the 0-255 range using `quantMultiplier`.
        data[i]   = Math.round(Math.floor(r * levels / 256) * quantMultiplier);
        data[i+1] = Math.round(Math.floor(g * levels / 256) * quantMultiplier);
        data[i+2] = Math.round(Math.floor(b * levels / 256) * quantMultiplier);
    }

    // Draw the processed (posterized) image data onto the main output 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 Gouache Filter Effect Tool allows users to apply a pseudo-gouache artistic effect to their images. This effect combines blurring and posterization to create flat color areas with soft transitions, reminiscent of traditional gouache painting techniques. Users can adjust the blur radius for softer transitions and specify the number of color levels to achieve a more abstract or vivid result. This tool is ideal for artists, graphic designers, or anyone looking to stylize their images for creative projects, social media posts, or unique presentations.

Leave a Reply

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