Please bookmark this page to avoid losing your image tool!

Image Cutout 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.
/**
 * Applies a cutout filter to an image.
 * This filter reduces the number of colors in the image by posterizing each color channel,
 * which can give the image an appearance similar to being made of cut-out pieces of paper.
 *
 * @param {Image} originalImg The original JavaScript Image object. It's assumed this image is loaded.
 * @param {number|string} levels The number of distinct color levels to use for each R, G, B channel.
 *                               This should be an integer between 2 and 256.
 *                               A lower number creates a more abstract, "cutout" effect.
 *                               Defaults to 5. If a string is provided, it will be parsed as an integer.
 * @returns {HTMLCanvasElement} A canvas element displaying the image with the cutout filter applied.
 *                               If the image cannot be processed (e.g., not loaded or CORS issue),
 *                               the canvas will display an error message.
 */
function processImage(originalImg, levels = 5) {
    // Validate and parse the 'levels' parameter
    let numLevels = parseInt(levels, 10);

    // Ensure numLevels is within a sensible range (2 to 256)
    if (isNaN(numLevels) || numLevels < 2) {
        numLevels = 2; // Minimum sensible level for posterization (e.g., two colors per channel)
    } else if (numLevels > 256) {
        numLevels = 256; // Maximum levels means minimal to no change (since 8-bit channels have 256 values)
    }

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

    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;

    if (imgWidth === 0 || imgHeight === 0) {
        // Handle cases where image dimensions are not available (e.g., image not loaded)
        canvas.width = 300; // Arbitrary small canvas size for error message
        canvas.height = 150;
        ctx.fillStyle = "lightgray";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "red";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.font = "16px Arial";
        ctx.fillText("Error: Image not loaded or has zero dimensions.", canvas.width / 2, canvas.height / 2, canvas.width * 0.9);
        return canvas;
    }
    
    canvas.width = imgWidth;
    canvas.height = imgHeight;

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

        // Get the pixel data from the canvas
        // This operation can throw a SecurityError if the image is cross-origin and taints the canvas
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imageData.data;

        // Calculate the quantization step.
        // If numLevels is 256, step will be 1 (255 / 255).
        // If numLevels is 2, step will be 255 (255 / 1).
        const step = 255 / (numLevels - 1);

        for (let i = 0; i < data.length; i += 4) {
            // Quantize R, G, B channels
            data[i] = Math.round(data[i] / step) * step;       // Red
            data[i + 1] = Math.round(data[i + 1] / step) * step; // Green
            data[i + 2] = Math.round(data[i + 2] / step) * step; // Blue
            // Alpha channel (data[i + 3]) is left unchanged
            // Note: The Uint8ClampedArray will automatically clamp values to 0-255 and round to nearest int.
        }

        // Put the modified pixel data back onto the canvas
        ctx.putImageData(imageData, 0, 0);

    } catch (e) {
        // console.error("Error processing image: ", e); // For debugging
        // Clear canvas (it might contain the original image) and draw an error message
        ctx.fillStyle = "lightgray";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "darkred";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.font = "bold 16px Arial";
        
        let message = "Error: Could not process image.";
        if (e.name === 'SecurityError') {
            message = "Error: Image from another domain (CORS issue).";
        }
        // Attempt to fit message within canvas width
        const maxMsgWidth = canvas.width * 0.9; 
        ctx.fillText(message, canvas.width / 2, canvas.height / 2, maxMsgWidth);
    }

    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 Cutout Filter Application allows users to apply a unique cutout filter effect to their images. This filter reduces the number of colors in an image, creating a stylized look reminiscent of paper cutouts by posterizing the RGB color channels. Users can specify the number of distinct color levels, with a lower number producing a more abstract appearance. This tool can be useful for artists, designers, and anyone looking to enhance their images with a creative aesthetic, perfect for creating distinctive graphics, posters, or digital art.

Leave a Reply

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