Please bookmark this page to avoid losing your image tool!

Image Black And White Brush Effect Retoucher

(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 black and white "brush stroke" effect to an image.
 * This function simulates painting the image by applying thousands of
 * semi-transparent grayscale circular dabs, sampled from the original image's colors.
 *
 * @param {HTMLImageElement} originalImg The original image object to process.
 * @param {number} brushSize The base radius of the circular brush strokes in pixels. Default is 5.
 * @param {number} density A value that determines the number of strokes. Higher numbers create a denser, more detailed image. The total number of strokes is (width * height * density) / 100. Default is 4.
 * @param {number} brushAlpha The opacity (from 0.0 to 1.0) of each individual brush stroke. Lower values create a softer, more blended effect. Default is 0.5.
 * @returns {HTMLCanvasElement} A new canvas element with the black and white brush effect applied.
 */
function processImage(originalImg, brushSize = 5, density = 4, brushAlpha = 0.5) {
    const {
        width,
        height
    } = originalImg;

    // Create a hidden canvas to draw the original image for efficient pixel sampling.
    // Setting `willReadFrequently` can provide a performance boost in some browsers.
    const sourceCanvas = document.createElement('canvas');
    sourceCanvas.width = width;
    sourceCanvas.height = height;
    const sourceCtx = sourceCanvas.getContext('2d', {
        willReadFrequently: true
    });
    sourceCtx.drawImage(originalImg, 0, 0, width, height);

    // Get all pixel data from the source image at once to avoid slow `getImageData` calls inside the loop.
    const sourceImageData = sourceCtx.getImageData(0, 0, width, height).data;

    // Create the destination canvas where the final "painted" image will be rendered.
    const destCanvas = document.createElement('canvas');
    destCanvas.width = width;
    destCanvas.height = height;
    const destCtx = destCanvas.getContext('2d');

    // Fill the background with white. A different background color could be a parameter, but white is a safe default.
    destCtx.fillStyle = 'white';
    destCtx.fillRect(0, 0, width, height);

    // Calculate the total number of "brush strokes" to apply based on the image's area and the desired density.
    const numStrokes = Math.round((width * height * density) / 100);

    // Set the opacity for the strokes. This is clamped between 0 and 1 for safety.
    destCtx.globalAlpha = Math.max(0, Math.min(1, brushAlpha));

    for (let i = 0; i < numStrokes; i++) {
        // Pick a random position on the canvas to place a stroke.
        const x = Math.floor(Math.random() * width);
        const y = Math.floor(Math.random() * height);

        // Calculate the index in the 1D imageData array for the chosen (x, y) coordinate.
        // Each pixel takes up 4 array elements (R, G, B, A).
        const pixelIndex = (y * width + x) * 4;
        const r = sourceImageData[pixelIndex];
        const g = sourceImageData[pixelIndex + 1];
        const b = sourceImageData[pixelIndex + 2];

        // If the source pixel is undefined (which can happen at the edges of calculations), skip it.
        if (r === undefined) {
            continue;
        }

        // Convert the sampled color to its grayscale equivalent using the luminosity method, which better reflects human perception.
        const gray = Math.round(0.2126 * r + 0.7152 * g + 0.0722 * b);

        // Set the fill style for the brush dab to the calculated grayscale color.
        destCtx.fillStyle = `rgb(${gray}, ${gray}, ${gray})`;

        // Introduce randomness (jitter) to the stroke's position and size to create a more organic, less uniform look.
        const jitterX = x + (Math.random() - 0.5) * brushSize;
        const jitterY = y + (Math.random() - 0.5) * brushSize;
        // Randomly vary the stroke size between 75% and 125% of the base brushSize.
        const jitterSize = brushSize * (Math.random() * 0.5 + 0.75);

        // Draw a circle shape to represent a single dab of paint from a round brush.
        destCtx.beginPath();
        destCtx.arc(jitterX, jitterY, jitterSize, 0, Math.PI * 2, false);
        destCtx.fill();
    }

    // Return the completed canvas, which now holds the black and white "painted" image.
    return destCanvas;
}

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 Black and White Brush Effect Retoucher allows users to apply a unique black and white brush stroke effect to their images. By simulating the appearance of a painting, this tool uses thousands of semi-transparent gray circular strokes sampled from the original image to create a visually dynamic effect. It is useful for artists and photographers looking to add a creative touch to their images, as well as for anyone wanting to achieve a textured black and white aesthetic in their visuals.

Leave a Reply

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