Please bookmark this page to avoid losing your image tool!

Image To Oil Painting Converter

(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.
/**
 * Converts an image to an oil painting effect.
 * This function iterates over each pixel and replaces it with the most frequent color in its neighborhood,
 * creating a smeared, "painted" look.
 * @param {HTMLImageElement} originalImg The original image element.
 * @param {number} radius The radius of the neighborhood to consider for each pixel (e.g., brush size). A larger radius creates more smearing. Defaults to 4.
 * @param {number} intensityLevels The number of color intensity levels to quantize the image to. A lower number creates a more posterized, abstract look. Defaults to 50.
 * @returns {HTMLCanvasElement} A new canvas element with the oil painting effect applied.
 */
function processImage(originalImg, radius = 4, intensityLevels = 50) {
    // 1. Create a canvas and get its 2D context.
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Ensure parameters are valid numbers
    const safeRadius = Number(radius) || 4;
    const safeIntensityLevels = Math.max(1, Number(intensityLevels) || 50);

    // 2. Set canvas dimensions to match the image.
    const width = originalImg.naturalWidth;
    const height = originalImg.naturalHeight;
    canvas.width = width;
    canvas.height = height;

    // 3. Draw the original image onto the canvas to access its pixel data.
    ctx.drawImage(originalImg, 0, 0);

    // 4. Get the pixel data from the canvas.
    const originalImageData = ctx.getImageData(0, 0, width, height);
    const originalData = originalImageData.data;

    // 5. Create a new ImageData object to store the output pixels.
    const outputImageData = ctx.createImageData(width, height);
    const outputData = outputImageData.data;

    // 6. Iterate through each pixel of the image.
    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            const pixelIndex = (y * width + x) * 4;

            // Arrays to store histogram and average color data for the neighborhood.
            const intensityCount = new Array(safeIntensityLevels).fill(0);
            const avgR = new Array(safeIntensityLevels).fill(0);
            const avgG = new Array(safeIntensityLevels).fill(0);
            const avgB = new Array(safeIntensityLevels).fill(0);

            // Iterate through the neighborhood square defined by the radius.
            for (let ny = -safeRadius; ny <= safeRadius; ny++) {
                for (let nx = -safeRadius; nx <= safeRadius; nx++) {
                    // Calculate the coordinates of the neighboring pixel, clamping to image bounds.
                    const currentY = Math.max(0, Math.min(height - 1, y + ny));
                    const currentX = Math.max(0, Math.min(width - 1, x + nx));

                    const neighborIndex = (currentY * width + currentX) * 4;
                    const r = originalData[neighborIndex];
                    const g = originalData[neighborIndex + 1];
                    const b = originalData[neighborIndex + 2];

                    // Calculate the pixel's intensity and quantize it into one of the levels.
                    const currentIntensity = Math.floor((((r + g + b) / 3) * safeIntensityLevels) / 256);

                    // Update histogram and color sums for this intensity level.
                    intensityCount[currentIntensity]++;
                    avgR[currentIntensity] += r;
                    avgG[currentIntensity] += g;
                    avgB[currentIntensity] += b;
                }
            }

            // Find the intensity level that occurred most frequently in the neighborhood.
            let maxCount = 0;
            let maxIntensityIndex = 0;
            for (let i = 0; i < safeIntensityLevels; i++) {
                if (intensityCount[i] > maxCount) {
                    maxCount = intensityCount[i];
                    maxIntensityIndex = i;
                }
            }

            // Calculate the average color of the most frequent intensity.
            const finalR = avgR[maxIntensityIndex] / maxCount;
            const finalG = avgG[maxIntensityIndex] / maxCount;
            const finalB = avgB[maxIntensityIndex] / maxCount;

            // Set the output pixel's color.
            outputData[pixelIndex] = finalR;
            outputData[pixelIndex + 1] = finalG;
            outputData[pixelIndex + 2] = finalB;
            outputData[pixelIndex + 3] = 255; // Alpha channel (fully opaque).
        }
    }

    // 7. Put the processed pixel data back onto the canvas.
    ctx.putImageData(outputImageData, 0, 0);

    // 8. Return the canvas element.
    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 To Oil Painting Converter allows users to transform their images into an oil painting effect. By simulating the brush strokes and blending colors, this tool generates a visually appealing, textured appearance that resembles traditional oil paintings. Ideal for artists, designers, or anyone looking to create unique artwork from their photos, this tool offers customizable options such as the radius for brush size and the number of color intensity levels, allowing for a range of artistic interpretations. Whether for personal use, enhancing creative projects, or simply for fun, the converter provides an easy way to add an artistic flair to your images.

Leave a Reply

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