Please bookmark this page to avoid losing your image tool!

Image Gothic 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,
    desaturationLevel = 0.85,
    contrastAmount = 1.5,
    darknessMultiplier = 0.75,
    tintColorHex = "151025", // A dark, desaturated purple-blue: R=21, G=16, B=37
    tintStrength = 0.25,
    vignetteStrength = 0.4
) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can optimize repeated getImageData/putImageData calls
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    // Ensure the image has valid dimensions
    if (originalImg.naturalWidth === 0 || originalImg.naturalHeight === 0) {
        // Return a minimal 1x1 canvas if the image is not loaded or has no dimensions
        // This prevents errors in getImageData for 0-width/height canvases
        canvas.width = 1;
        canvas.height = 1;
        // Optionally, you could fill it with a transparent or black pixel
        // ctx.fillStyle = 'rgba(0,0,0,0)';
        // ctx.fillRect(0,0,1,1);
        return canvas;
    }

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

    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    // Get image data to manipulate pixels
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imageData.data;

    // Parse tintColorHex to R, G, B components
    // Handles potentially malformed hex strings by defaulting components to 0 if parsing fails
    const parseHexComponent = (hexString) => parseInt(hexString, 16) || 0;
    const tintR = parseHexComponent(tintColorHex.substring(0, 2));
    const tintG = parseHexComponent(tintColorHex.substring(2, 4));
    const tintB = parseHexComponent(tintColorHex.substring(4, 6));

    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    // Calculate maximum distance from center to a corner (for vignette normalization)
    const maxDist = Math.sqrt(centerX * centerX + centerY * centerY);

    // Process each pixel
    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];
        // Alpha channel (data[i+3]) is preserved

        // 1. Desaturation
        // Calculate luminance (perceived brightness)
        const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
        // Mix original color with luminance based on desaturationLevel
        r = r * (1 - desaturationLevel) + luminance * desaturationLevel;
        g = g * (1 - desaturationLevel) + luminance * desaturationLevel;
        b = b * (1 - desaturationLevel) + luminance * desaturationLevel;

        // 2. Contrast
        if (contrastAmount !== 1.0) { // Apply contrast only if contrastAmount is not neutral
            // Adjust contrast: map values to [-0.5, 0.5], scale, then map back to [0, 255]
            r = ((r / 255 - 0.5) * contrastAmount + 0.5) * 255;
            g = ((g / 255 - 0.5) * contrastAmount + 0.5) * 255;
            b = ((b / 255 - 0.5) * contrastAmount + 0.5) * 255;
        }

        // 3. Darkness
        // Apply overall darkness multiplier
        r *= darknessMultiplier;
        g *= darknessMultiplier;
        b *= darknessMultiplier;

        // 4. Tint
        if (tintStrength > 0) {
            // Blend current color with tint color
            r = r * (1 - tintStrength) + tintR * tintStrength;
            g = g * (1 - tintStrength) + tintG * tintStrength;
            b = b * (1 - tintStrength) + tintB * tintStrength;
        }
        
        // 5. Vignette
        if (vignetteStrength > 0 && maxDist > 0) { // maxDist check for 1x1 or degenerate cases
            // Calculate current pixel's coordinates
            const x = (i / 4) % canvas.width;
            const y = Math.floor((i / 4) / canvas.width);
            
            // Calculate distance from center
            const dx = x - centerX;
            const dy = y - centerY;
            const distNormalized = Math.sqrt(dx * dx + dy * dy) / maxDist; // Normalized distance (0 at center, 1 at corners)

            // Calculate vignette effect (stronger further from center)
            // Using Math.pow(distNormalized, 2) for a smoother, quadratic falloff
            const vignetteEffect = 1.0 - Math.pow(distNormalized, 2) * vignetteStrength;
            
            r *= vignetteEffect;
            g *= vignetteEffect;
            b *= vignetteEffect;
        }

        // Clamp RGB values to [0, 255] range
        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));
    }

    // Put the modified image data back onto the canvas
    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 Gothic Filter Effect Tool allows users to apply a unique gothic aesthetic to their images. By adjusting various parameters such as desaturation, contrast, darkness, tint color, and vignette strength, users can transform their images to achieve a moody and atmospheric appearance. This tool can be particularly useful for photographers, graphic designers, or social media enthusiasts looking to create striking visuals, adding a dramatic flair to portraits, landscapes, or any images intended for artistic or thematic presentations.

Leave a Reply

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