Please bookmark this page to avoid losing your image tool!

Photo Polished Stone 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, applyGrayscaleStr = "true", contrastVal = 1.2, numLevels = 4, noiseAmt = 0.05, blurRadiusParam = 0) {
    // Parameter parsing and validation
    const applyGrayscale = String(applyGrayscaleStr).toLowerCase() === "true";

    let contrast = Number(contrastVal);
    if (isNaN(contrast)) {
        contrast = 1.2; // Default contrast
    }

    let levels = Number(numLevels);
    if (isNaN(levels) || levels < 1) {
        levels = 4; // Default levels
    }
    levels = Math.floor(levels); // Ensure integer

    let noiseIntensity = Number(noiseAmt);
    if (isNaN(noiseIntensity)) {
        noiseIntensity = 0.05; // Default noise intensity
    }
    noiseIntensity = Math.max(0, Math.min(1, noiseIntensity)); // Clamp between 0 and 1

    let blurRadius = Number(blurRadiusParam);
    if (isNaN(blurRadius) || blurRadius < 0) {
        blurRadius = 0; // Default blur radius (no blur)
    }
    blurRadius = Math.floor(blurRadius); // Ensure integer

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    canvas.width = originalImg.naturalWidth || originalImg.width;
    canvas.height = originalImg.naturalHeight || originalImg.height;

    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    // Optional Blur Pass
    if (blurRadius > 0) {
        const M = canvas.width;
        const N = canvas.height;
        const sourceImageData = ctx.getImageData(0, 0, M, N);
        const sourceData = sourceImageData.data;
        const outputPixelData = new Uint8ClampedArray(sourceData.length);

        for (let y = 0; y < N; y++) {
            for (let x = 0; x < M; x++) {
                let r_sum = 0, g_sum = 0, b_sum = 0;
                let count = 0;
                for (let dy = -blurRadius; dy <= blurRadius; dy++) {
                    for (let dx = -blurRadius; dx <= blurRadius; dx++) {
                        const nx = x + dx;
                        const ny = y + dy;
                        if (nx >= 0 && nx < M && ny >= 0 && ny < N) {
                            const offset = (ny * M + nx) * 4;
                            r_sum += sourceData[offset];
                            g_sum += sourceData[offset + 1];
                            b_sum += sourceData[offset + 2];
                            count++;
                        }
                    }
                }
                const K = (y * M + x) * 4;
                outputPixelData[K]     = r_sum / count;
                outputPixelData[K + 1] = g_sum / count;
                outputPixelData[K + 2] = b_sum / count;
                outputPixelData[K + 3] = sourceData[K + 3]; // Preserve alpha
            }
        }
        const blurredImageData = new ImageData(outputPixelData, M, N);
        ctx.putImageData(blurredImageData, 0, 0);
    }

    // Main Pixel Processing
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imageData.data;

    const quantize = (value, numQuantLevels) => {
        if (numQuantLevels <= 1) {
            return Math.round(value / 255) * 255; // Results in 0 or 255
        }
        const step = 255 / (numQuantLevels - 1);
        return Math.round(value / step) * step;
    };

    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];

        // 1. Grayscale (operates on potentially blurred data)
        if (applyGrayscale) {
            const gray = 0.299 * r + 0.587 * g + 0.114 * b;
            r = g = b = gray;
        }

        // 2. Contrast
        if (contrast !== 1.0) { // Apply contrast if it's not neutral
            r = contrast * (r - 128) + 128;
            g = contrast * (g - 128) + 128;
            b = contrast * (b - 128) + 128;
        }
        
        // Clamp after contrast and ensure integer values for posterization
        r = Math.max(0, Math.min(255, Math.round(r)));
        g = Math.max(0, Math.min(255, Math.round(g)));
        b = Math.max(0, Math.min(255, Math.round(b)));
        
        // 3. Posterization
        r = quantize(r, levels);
        g = quantize(g, levels);
        b = quantize(b, levels);
        // quantize function should already keep values within 0-255 if input is.

        // 4. Noise
        if (noiseIntensity > 0) {
            // Generate noise between -128*intensity and +128*intensity
            const noiseVal = (Math.random() - 0.5) * 2 * noiseIntensity * 128;
            r += noiseVal;
            g += noiseVal;
            b += noiseVal;
        }
        
        // Final Clamp and store
        data[i] = Math.max(0, Math.min(255, Math.round(r)));
        data[i + 1] = Math.max(0, Math.min(255, Math.round(g)));
        data[i + 2] = Math.max(0, Math.min(255, Math.round(b)));
        // Alpha (data[i+3]) remains unchanged
    }

    ctx.putImageData(imageData, 0, 0);
    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 Photo Polished Stone Filter Effect Tool allows users to enhance their images by applying a polished stone effect. This tool can transform photographs by converting them into grayscale, adjusting contrast, posterizing them to a specified number of levels, adding noise, and applying a blur effect. It is useful for artists, designers, and photographers looking to create unique, stylized images for digital art, social media posts, or personal projects. Users can customize the strength of effects to achieve the desired aesthetic.

Leave a Reply

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