Please bookmark this page to avoid losing your image tool!

Image Petroglyph 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.
async function processImage(originalImg, edgeThreshold = 100, stoneColorStr = "210,200,190", carvingColorStr = "70,60,50") {

    // Helper function to parse color strings like "r,g,b"
    // Falls back to defaultRgbArray if parsing fails or format is incorrect.
    function parseColor(colorString, defaultRgbArray) {
        if (typeof colorString !== 'string') {
            return defaultRgbArray;
        }
        const parts = colorString.split(',').map(s => parseInt(s.trim(), 10));
        if (parts.length === 3 && parts.every(p => !isNaN(p) && p >= 0 && p <= 255)) {
            return parts;
        }
        return defaultRgbArray; // Fallback color
    }

    // Helper function to get grayscale pixel from grayscale data array.
    // Handles boundary conditions by clamping coordinates (edge pixel replication).
    function getPixelGray_internal(grayData, x, y, w, h) {
        const clampedX = Math.max(0, Math.min(x, w - 1));
        const clampedY = Math.max(0, Math.min(y, h - 1));
        return grayData[clampedY * w + clampedX];
    }

    const width = originalImg.width;
    const height = originalImg.height;

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


    if (width === 0 || height === 0) {
        return canvas; // Return empty canvas for zero-size image
    }

    // Parse the stone and carving colors using the helper.
    // The default values for stoneColorStr and carvingColorStr are valid and will be parsed correctly.
    // The fallbacks in parseColor are for cases where a user might provide an invalid string.
    const stoneColor = parseColor(stoneColorStr, [210, 200, 190]);
    const carvingColor = parseColor(carvingColorStr, [70, 60, 50]);

    ctx.drawImage(originalImg, 0, 0);
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, width, height);
    } catch (e) {
        // Handle potential security errors if image is cross-origin and canvas is tainted
        console.error("Error getting ImageData:", e);
        // Draw a simple error message on the canvas or return it as is
        ctx.clearRect(0, 0, width, height); // Clear any partial drawing
        ctx.fillStyle = "red";
        ctx.font = "16px Arial";
        ctx.textAlign = "center";
        ctx.fillText("Error processing image.", width / 2, height / 2);
        return canvas;
    }
    
    const originalData = imageData.data;

    // Create a 1D array to store grayscale values of the image
    const grayscaleData = new Uint8ClampedArray(width * height);
    for (let i = 0; i < originalData.length; i += 4) {
        const r = originalData[i];
        const g = originalData[i + 1];
        const b = originalData[i + 2];
        // Standard luminance calculation
        grayscaleData[i / 4] = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
    }

    const outputImageData = ctx.createImageData(width, height);
    const outputData = outputImageData.data;

    // Apply Sobel operator to detect edges
    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            // Sobel Gx kernel
            const gx = (
                -1 * getPixelGray_internal(grayscaleData, x - 1, y - 1, width, height) + 1 * getPixelGray_internal(grayscaleData, x + 1, y - 1, width, height) +
                -2 * getPixelGray_internal(grayscaleData, x - 1, y,     width, height) + 2 * getPixelGray_internal(grayscaleData, x + 1, y,     width, height) +
                -1 * getPixelGray_internal(grayscaleData, x - 1, y + 1, width, height) + 1 * getPixelGray_internal(grayscaleData, x + 1, y + 1, width, height)
            );

            // Sobel Gy kernel
            const gy = (
                -1 * getPixelGray_internal(grayscaleData, x - 1, y - 1, width, height) - 2 * getPixelGray_internal(grayscaleData, x, y - 1, width, height) - 1 * getPixelGray_internal(grayscaleData, x + 1, y - 1, width, height) +
                 1 * getPixelGray_internal(grayscaleData, x - 1, y + 1, width, height) + 2 * getPixelGray_internal(grayscaleData, x, y + 1, width, height) + 1 * getPixelGray_internal(grayscaleData, x + 1, y + 1, width, height)
            );

            const gradientMagnitude = Math.sqrt(gx * gx + gy * gy);
            const pixelIdx = (y * width + x) * 4;
            
            // If gradient magnitude is above threshold, it's an "edge" (carving)
            // Otherwise, it's "stone" (background)
            if (gradientMagnitude > edgeThreshold) {
                outputData[pixelIdx]     = carvingColor[0];
                outputData[pixelIdx + 1] = carvingColor[1];
                outputData[pixelIdx + 2] = carvingColor[2];
            } else {
                outputData[pixelIdx]     = stoneColor[0];
                outputData[pixelIdx + 1] = stoneColor[1];
                outputData[pixelIdx + 2] = stoneColor[2];
            }
            // Preserve original alpha channel
            outputData[pixelIdx + 3] = originalData[pixelIdx + 3];
        }
    }
    
    ctx.putImageData(outputImageData, 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 Image Petroglyph Filter Effect Tool allows users to transform their images into a stylized petroglyph-like appearance. By applying edge detection and customizable color settings, this tool enhances the edges of objects in the image to give them the look of carved stone engravings. Users can adjust the threshold for edge detection as well as the colors used for the stone and carvings, making it suitable for artistic endeavors such as creating unique graphics for digital art, enhancing photos for educational materials, or crafting visuals for creative projects. This effect can be particularly useful for designers, educators, or artists seeking to create visually striking representations or simulations of ancient art styles.

Leave a Reply

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