Please bookmark this page to avoid losing your image tool!

Image Pointillist 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, dotRadius = 5, samplingDensity = 10) {
    // Sanitize parameters: ensure they are numbers and fall back to defaults if parsing fails
    let numDotRadius = parseFloat(dotRadius);
    if (isNaN(numDotRadius)) {
        numDotRadius = 5; // Default dotRadius if provided value is not a valid number
    }

    let numSamplingDensity = parseFloat(samplingDensity);
    if (isNaN(numSamplingDensity)) {
        numSamplingDensity = 10; // Default samplingDensity if provided value is not a valid number
    }

    // Ensure radius and density have sensible minimum values
    const R = Math.max(0.5, numDotRadius); // Minimum dot radius of 0.5px
    const D = Math.max(1, numSamplingDensity); // Minimum sampling distance (grid step) of 1px

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

    // If image has no dimensions, return an empty canvas
    if (width === 0 || height === 0) {
        const emptyCanvas = document.createElement('canvas');
        emptyCanvas.width = width;
        emptyCanvas.height = height;
        return emptyCanvas;
    }

    // Create an offscreen canvas to draw the original image.
    // This allows us to get its pixel data.
    const offscreenCanvas = document.createElement('canvas');
    offscreenCanvas.width = width;
    offscreenCanvas.height = height;
    const offscreenCtx = offscreenCanvas.getContext('2d', { willReadFrequently: true });
    
    offscreenCtx.drawImage(originalImg, 0, 0, width, height);
    
    // Get all pixel data from the offscreen canvas at once for performance.
    let originalImageData;
    try {
        originalImageData = offscreenCtx.getImageData(0, 0, width, height);
    } catch (e) {
        // Handle potential security errors if image is cross-origin and canvas is tainted
        console.error("Error getting image data: ", e);
        // Return a simple canvas indicating the error or an empty one
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = width;
        errorCanvas.height = height;
        const errCtx = errorCanvas.getContext('2d');
        errCtx.fillStyle = 'red';
        errCtx.fillRect(0,0,width,height);
        errCtx.fillStyle = 'white';
        errCtx.textAlign = 'center';
        errCtx.fillText("Error processing image (cross-origin?)", width/2, height/2);
        return errorCanvas;
    }
    const data = originalImageData.data;

    // Create the output canvas where the pointillist effect will be drawn
    const outputCanvas = document.createElement('canvas');
    outputCanvas.width = width;
    outputCanvas.height = height;
    const outputCtx = outputCanvas.getContext('2d');

    // Fill the output canvas with a white background, typical for pointillism
    outputCtx.fillStyle = 'white';
    outputCtx.fillRect(0, 0, width, height);

    // Helper function to get the color of a pixel from the image data array.
    // x and y are the coordinates to sample from.
    function getPixelColor(x, y, imgWidth, imgHeight, pixelData) {
        // Clamp coordinates to be within image boundaries and floor them to get integer indices
        const clampedX = Math.max(0, Math.min(Math.floor(x), imgWidth - 1));
        const clampedY = Math.max(0, Math.min(Math.floor(y), imgHeight - 1));
        
        const index = (clampedY * imgWidth + clampedX) * 4; // 4 components: R, G, B, A
        return {
            r: pixelData[index],
            g: pixelData[index + 1],
            b: pixelData[index + 2],
            a: pixelData[index + 3],
        };
    }

    // Iterate over the image in a grid, with steps defined by D (samplingDensity)
    for (let y = 0; y < height; y += D) {
        for (let x = 0; x < width; x += D) {
            // Determine the center of the current grid cell.
            // This point will be used for color sampling and as the center of the dot.
            const cellCenterX = x + D / 2;
            const cellCenterY = y + D / 2;

            // Get the color from the original image at the center of the cell
            const color = getPixelColor(cellCenterX, cellCenterY, width, height, data);

            // Set the fill style for the_dot using the sampled color (including alpha)
            outputCtx.fillStyle = `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a / 255})`;
            
            // Draw the dot (a circle)
            outputCtx.beginPath();
            outputCtx.arc(cellCenterX, cellCenterY, R, 0, Math.PI * 2, true); // Math.PI * 2 for a full circle
            outputCtx.fill();
        }
    }

    return outputCanvas;
}

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 Pointillist Filter Effect Tool allows users to apply a pointillism effect to images, transforming them into artworks that mimic the style of pointillist painting. Users can adjust parameters such as the size of the dots and the sampling density to create varying artistic effects. This tool is useful for artists, graphic designers, and anyone looking to enhance their images with a unique stylistic touch, perfect for social media posts, digital art projects, or personal creations.

Leave a Reply

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