Please bookmark this page to avoid losing your image tool!

Photo 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 a photo image to an oil painting effect using a pixel-based algorithm.
 * This function analyzes neighborhoods of pixels to simplify colors and create a painterly, textured look.
 *
 * @param {HTMLImageElement} originalImg The original image to be converted.
 * @param {number} radius The radius of the "brush stroke". A larger radius creates larger, more abstract strokes. Defaults to 4. Recommended range: 1-10.
 * @param {number} intensity The number of color intensity levels. A lower value simplifies the palette more, creating a more stylized effect. Defaults to 20. Recommended range: 1-255.
 * @returns {HTMLCanvasElement} A new canvas element displaying the oil painting version of the image.
 */
function processImage(originalImg, radius = 4, intensity = 20) {
    // --- 1. Sanitize Parameters and Setup ---

    // Coerce parameters to numbers and clamp them to reasonable values for performance and quality.
    const r = Math.max(1, Math.min(10, Number(radius)));
    const i = Math.max(1, Math.min(255, Number(intensity)));

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

    // Create a canvas to draw the original image and get its pixel data.
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d', { willReadFrequently: true });
    ctx.drawImage(originalImg, 0, 0);

    const originalImageData = ctx.getImageData(0, 0, width, height);
    const originalData = originalImageData.data;

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

    // --- 2. Main Algorithm: Iterate Through Pixels ---

    // Iterate over 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 data about the neighborhood pixels.
            const intensityCount = new Array(i + 1).fill(0);
            const rSum = new Array(i + 1).fill(0);
            const gSum = new Array(i + 1).fill(0);
            const bSum = new Array(i + 1).fill(0);

            // --- 2a. Analyze the Neighborhood ---

            // Iterate over a square neighborhood around the current pixel defined by the radius.
            for (let ny = -r; ny <= r; ny++) {
                for (let nx = -r; nx <= r; nx++) {
                    const currentY = y + ny;
                    const currentX = x + nx;

                    // Check if the neighbor pixel is within the image bounds.
                    if (currentY >= 0 && currentY < height && currentX >= 0 && currentX < width) {
                        const neighborIndex = (currentY * width + currentX) * 4;
                        const nr = originalData[neighborIndex];
                        const ng = originalData[neighborIndex + 1];
                        const nb = originalData[neighborIndex + 2];

                        // Calculate the luminance (brightness) of the neighbor pixel.
                        const currentIntensity = Math.round((nr * 0.299 + ng * 0.587 + nb * 0.114));

                        // Quantize the intensity into a limited number of bins.
                        const intensityBin = Math.floor(currentIntensity * i / 255);

                        // Keep a running count and sum of colors for each intensity level.
                        intensityCount[intensityBin]++;
                        rSum[intensityBin] += nr;
                        gSum[intensityBin] += ng;
                        bSum[intensityBin] += nb;
                    }
                }
            }

            // --- 2b. Determine the Dominant Color ---

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

            // Calculate the average color of the pixels that had the dominant intensity.
            const avgR = rSum[maxIndex] / maxCount;
            const avgG = gSum[maxIndex] / maxCount;
            const avgB = bSum[maxIndex] / maxCount;
            
            // --- 2c. Set the Output Pixel ---

            // Set the output pixel color to this average dominant color.
            outputData[pixelIndex] = avgR;
            outputData[pixelIndex + 1] = avgG;
            outputData[pixelIndex + 2] = avgB;
            outputData[pixelIndex + 3] = 255; // Set alpha to fully opaque.
        }
    }

    // --- 3. Finalize and Return ---

    // Create a new canvas to return the final result.
    const resultCanvas = document.createElement('canvas');
    resultCanvas.width = width;
    resultCanvas.height = height;
    const resultCtx = resultCanvas.getContext('2d');
    resultCtx.putImageData(outputImageData, 0, 0);

    return resultCanvas;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Photo To Oil Painting Converter transforms your photos into an oil painting style using a pixel-based algorithm. By adjusting parameters such as brush stroke radius and color intensity levels, users can create artwork that emulates a traditional painting effect. This tool is ideal for artists, designers, and anyone looking to enhance their images with a creative touch, making it suitable for personal projects, social media posts, or to add a unique aesthetic to photos for galleries or exhibits.

Leave a Reply

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