Please bookmark this page to avoid losing your image tool!

Image Cave Interior 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, darknessLevel = 0.7, coolTintStrength = 0.5, vignetteStrength = 0.7, contrastFactor = 1.3) {
    const canvas = document.createElement('canvas');
    // Add { willReadFrequently: true } for potential performance optimization if available/supported
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    const imgWidth = originalImg.naturalWidth || originalImg.width || 0;
    const imgHeight = originalImg.naturalHeight || originalImg.height || 0;

    canvas.width = imgWidth;
    canvas.height = imgHeight;

    if (imgWidth === 0 || imgHeight === 0) {
        console.warn("Image has zero width or height. Returning an empty canvas.");
        return canvas; // Returns an empty canvas
    }

    try {
        ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
    } catch (e) {
        console.error("Error drawing image to canvas:", e);
        // Return a new empty canvas if drawing the original image fails
        const emptyCanvas = document.createElement('canvas');
        emptyCanvas.width = imgWidth; // Attempt to keep size, might be 0x0
        emptyCanvas.height = imgHeight;
        return emptyCanvas; 
    }

    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
    } catch (e) {
        console.error("Error getting ImageData (e.g., canvas tainted by cross-origin image). Returning canvas with original image.", e);
        // The canvas currently has the original image drawn on it.
        // Returning it as-is means returning the original image rendered on a canvas, without the filter.
        return canvas; 
    }
    
    const data = imageData.data;
    const width = imgWidth; // Use consistent variable names
    const height = imgHeight;
    const centerX = width / 2;
    const centerY = height / 2;
    
    // maxDist is the distance from the center to a corner.
    // This will be > 0 if width or height > 0.
    const maxDist = Math.sqrt(centerX * centerX + centerY * centerY);

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

        // 1. Base Darkening (0.0 = no change, 1.0 = black)
        // Make sure darknessLevel is clamped between 0 and 1
        const effectiveDarkness = Math.max(0, Math.min(1, darknessLevel));
        let rDark = r * (1 - effectiveDarkness);
        let gDark = g * (1 - effectiveDarkness);
        let bDark = b * (1 - effectiveDarkness);

        // 2. Cool Tint (0.0 = no tint, 1.0 = strong tint)
        // Make sure coolTintStrength is clamped between 0 and 1
        const effectiveCoolTint = Math.max(0, Math.min(1, coolTintStrength));
        let rTinted = rDark * (1 - effectiveCoolTint * 0.6); // Reduce red more significantly
        let gTinted = gDark * (1 - effectiveCoolTint * 0.3); // Reduce green less
        let bTinted = bDark * (1 + effectiveCoolTint * 0.1); // Slightly boost blue
        bTinted = Math.min(255, bTinted); // Cap blue boost

        r = rTinted;
        g = gTinted;
        b = bTinted;

        // 3. Vignette (0.0 = no vignette, 1.0 = edges are black)
        // Make sure vignetteStrength is clamped between 0 and 1
        const effectiveVignette = Math.max(0, Math.min(1, vignetteStrength));
        if (effectiveVignette > 0 && maxDist > 0) { // Only apply if strength > 0 and image has dimensions
            const x = (i / 4) % width;
            const y = Math.floor((i / 4) / width);
            const dist = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
            
            const normalizedDist = dist / maxDist; 
            
            // vignetteAmount is a multiplier from (1 - vignetteStrength) at edge to 1 at center.
            // Using a power of 2 for smoother falloff.
            let vignetteAmount = 1.0 - (effectiveVignette * Math.pow(normalizedDist, 2.0));
            vignetteAmount = Math.max(0, vignetteAmount); // Clamp to prevent negative values

            r *= vignetteAmount;
            g *= vignetteAmount;
            b *= vignetteAmount;
        }

        // 4. Contrast (1.0 = no change)
        // Ensure contrastFactor is not negative.
        const effectiveContrast = Math.max(0, contrastFactor);
        const midpoint = 128; // Midpoint for contrast calculation (0-255 range)
        r = effectiveContrast * (r - midpoint) + midpoint;
        g = effectiveContrast * (g - midpoint) + midpoint;
        b = effectiveContrast * (b - midpoint) + midpoint;

        // Clamp final values to [0, 255]
        data[i] = Math.max(0, Math.min(255, r));
        data[i + 1] = Math.max(0, Math.min(255, g));
        data[i + 2] = Math.max(0, Math.min(255, b));
        // Alpha channel (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 Image Cave Interior Filter Effect Tool allows users to apply a stylized effect to their images, enhancing them with a cave-like ambiance. This tool offers adjustments for darkness, color tinting with a cool vigor, vignette effects to draw focus towards the center, and contrast enhancements. It’s particularly useful for artists, photographers, or content creators looking to create atmospheric imagery, whether for social media posts, digital art, or enhancing personal photographs. Users can customize the intensity of each effect to achieve their desired look, making it a versatile addition to any image editing toolkit.

Leave a Reply

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