Please bookmark this page to avoid losing your image tool!

Friday The 13th Photo Filter 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, theme = "night", darknessLevel = "0.4", contrastLevel = "1.5", noiseLevel = "0.15", maskOverlay = "center", bloodSplatter = "yes") {
    const canvas = document.createElement('canvas');
    const w = originalImg.width;
    const h = originalImg.height;
    canvas.width = w;
    canvas.height = h;
    const ctx = canvas.getContext('2d');
    
    // Draw original image
    ctx.drawImage(originalImg, 0, 0);

    // Filter Parameters
    const C = parseFloat(contrastLevel);
    const dark = parseFloat(darknessLevel);
    const effNoise = parseFloat(noiseLevel);
    const effC = isNaN(C) ? 1.5 : C;
    const effDark = isNaN(dark) ? 0.4 : dark;
    const noiseVal = isNaN(effNoise) ? 0.15 : effNoise;

    const adjustContrast = (c) => effC * (c - 128) + 128;

    // Slasher Film Color Grading via ImageData
    const imgData = ctx.getImageData(0, 0, w, h);
    const data = imgData.data;

    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i+1];
        let b = data[i+2];
        
        // 1. Contrast
        r = adjustContrast(r);
        g = adjustContrast(g);
        b = adjustContrast(b);
        
        // 2. Base desaturation to create a grim look
        const lum = 0.299 * r + 0.587 * g + 0.114 * b;
        const normalizedLum = Math.min(1, Math.max(0, lum / 255));
        
        r = r * 0.4 + lum * 0.6;
        g = g * 0.4 + lum * 0.6;
        b = b * 0.4 + lum * 0.6;

        // 3. Theme Tint (Night Moonlight vs Blood Red)
        if (theme === "blood") {
            // Blood tint: heavy reds in shadows, keeps highlights mostly intact
            r = r * (1.2 - 0.2 * normalizedLum);
            g = g * (0.4 + 0.4 * normalizedLum);
            b = b * (0.4 + 0.4 * normalizedLum);
        } else {
            // Night Camp Crystal Lake tint: cyan/blue shadows
            r = r * (0.5 + 0.5 * normalizedLum); 
            g = g * (0.8 + 0.2 * normalizedLum);
            b = b * (1.2 - 0.2 * normalizedLum);
        }
        
        // 4. Atmosphere Darkening
        r *= (1 - effDark);
        g *= (1 - effDark);
        b *= (1 - effDark);
        
        // 5. Film Grain / Noise
        if (noiseVal > 0) {
            const n = (Math.random() - 0.5) * 255 * noiseVal;
            r += n;
            g += n;
            b += n;
        }
        
        // Auto-clamping applies when setting back to Uint8ClampedArray
        data[i]   = r;
        data[i+1] = g;
        data[i+2] = b;
    }
    
    ctx.putImageData(imgData, 0, 0);

    // Helper: Draw Jason's Hockey Mask
    function drawHockeyMask(ctx, x, y, size) {
        ctx.save();
        ctx.translate(x, y);
        
        // Dirty Mask Base Gradient
        const grad = ctx.createRadialGradient(0, 0, size * 0.1, 0, 0, size * 0.6);
        grad.addColorStop(0, 'rgba(230, 225, 210, 1)'); // Bone white
        grad.addColorStop(1, 'rgba(60, 50, 40, 1)'); // Filthy edges
        ctx.fillStyle = grad;
        
        ctx.strokeStyle = 'rgba(0,0,0,0.8)';
        ctx.lineWidth = size * 0.01;
        ctx.lineJoin = 'round';
        
        ctx.beginPath();
        
        // Outer Face
        ctx.ellipse(0, 0, size * 0.45, size * 0.6, 0, 0, Math.PI * 2);
        
        // Left Eye Hole (drawn to intersect fill)
        let cxLeft = -size * 0.18, cyLeft = -size * 0.1, rx = size * 0.12, ry = size * 0.08, rotL = -0.2;
        ctx.moveTo(cxLeft + rx * Math.cos(rotL), cyLeft + rx * Math.sin(rotL));
        ctx.ellipse(cxLeft, cyLeft, rx, ry, rotL, 0, Math.PI * 2);
        
        // Right Eye Hole
        let cxRight = size * 0.18, cyRight = -size * 0.1, rotR = 0.2;
        ctx.moveTo(cxRight + rx * Math.cos(rotR), cyRight + rx * Math.sin(rotR));
        ctx.ellipse(cxRight, cyRight, rx, ry, rotR, 0, Math.PI * 2);
        
        // Breathing Holes
        const holes = [
            [0, size * 0.2],
            [-size * 0.1, size * 0.28], [size * 0.1, size * 0.28],
            [-size * 0.18, size * 0.38], [0, size * 0.38], [size * 0.18, size * 0.38],
            [-size * 0.1, -size * 0.45], [size * 0.1, -size * 0.45], [0, -size * 0.52]
        ];
        
        for (let i = 0; i < holes.length; i++) {
            const hr = size * 0.025;
            ctx.moveTo(holes[i][0] + hr, holes[i][1]);
            ctx.arc(holes[i][0], holes[i][1], hr, 0, Math.PI * 2);
        }
        
        ctx.fill("evenodd");  // Make eyes/breathing slots perfectly transparent holes!
        ctx.stroke(); 
        
        // Blood Red Chevrons
        ctx.fillStyle = 'rgba(120, 15, 15, 0.85)';
        
        // Forehead (pointing down towards nose)
        ctx.beginPath();
        ctx.moveTo(0, -size * 0.25);
        ctx.lineTo(-size * 0.06, -size * 0.4);
        ctx.lineTo(size * 0.06, -size * 0.4);
        ctx.closePath();
        ctx.fill();
        
        // Left Cheek (pointing towards left)
        ctx.beginPath();
        ctx.moveTo(-size * 0.28, size * 0.1);
        ctx.lineTo(-size * 0.18, size * 0.22);
        ctx.lineTo(-size * 0.35, size * 0.24);
        ctx.closePath();
        ctx.fill();

        // Right Cheek (pointing towards right)
        ctx.beginPath();
        ctx.moveTo(size * 0.28, size * 0.1);
        ctx.lineTo(size * 0.18, size * 0.22);
        ctx.lineTo(size * 0.35, size * 0.24);
        ctx.closePath();
        ctx.fill();

        ctx.restore();
    }

    // Ghost Center Mask Overlay
    if (maskOverlay === "center") {
        ctx.globalAlpha = 0.15;
        drawHockeyMask(ctx, w / 2, h / 2, Math.min(w, h) * 0.7);
        ctx.globalAlpha = 1.0;
    }

    // Claustrophobic Vignette
    const grad = ctx.createRadialGradient(
        w / 2, h / 2, Math.min(w, h) * 0.3,
        w / 2, h / 2, Math.min(w, h) * 0.85
    );
    grad.addColorStop(0, 'rgba(0,0,0,0)');
    grad.addColorStop(1, '#020202');
    ctx.fillStyle = grad;
    ctx.fillRect(0, 0, w, h);

    // Corner Watermark Mask Overlay
    if (maskOverlay === "corner") {
        ctx.globalAlpha = 0.8;
        const cornerSize = Math.min(w, h) * 0.25;
        drawHockeyMask(ctx, w - cornerSize * 0.6, h - cornerSize * 0.65, cornerSize);
        ctx.globalAlpha = 1.0;
    }

    // "Blood on the lens" Spratter Effect
    if (bloodSplatter === "yes" || bloodSplatter === "true") {
        ctx.fillStyle = 'rgba(180, 5, 5, 0.85)';
        for (let i = 0; i < 35; i++) {
            let bx, by;
            // Push splatters mostly towards the edges so we don't completely cover the main subject
            if (Math.random() > 0.5) {
                bx = Math.random() * w;
                by = Math.random() > 0.5 ? Math.random() * h * 0.15 : h - Math.random() * h * 0.15;
            } else {
                by = Math.random() * h;
                bx = Math.random() > 0.5 ? Math.random() * w * 0.15 : w - Math.random() * w * 0.15;
            }
            
            const radius = Math.random() * Math.min(w, h) * 0.015 + 2;
            ctx.beginPath();
            ctx.arc(bx, by, radius, 0, Math.PI * 2);
            ctx.fill();
            
            // Sub-splats
            for (let j = 0; j < 3; j++) {
                const sr = radius * Math.random();
                const sx = bx + (Math.random() - 0.5) * radius * 4;
                const sy = by + (Math.random() - 0.5) * radius * 4;
                ctx.beginPath();
                ctx.arc(sx, sy, sr, 0, Math.PI * 2);
                ctx.fill();
            }
            
            // Drips tapering off
            if (Math.random() > 0.6) {
                const dripLen = Math.random() * h * 0.1 + radius * 2;
                ctx.beginPath();
                ctx.moveTo(bx - radius * 0.6, by);
                ctx.quadraticCurveTo(bx, by + dripLen / 2, bx, by + dripLen);
                ctx.quadraticCurveTo(bx, by + dripLen / 2, bx + radius * 0.6, by);
                ctx.fill();
            }
        }
    }

    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 Friday the 13th Photo Filter Tool allows users to apply horror-themed cinematic effects to their images. It can transform photos with various color grading styles, such as a dark ‘night’ moonlight theme or a dramatic ‘blood’ red tint. The tool features adjustable settings for contrast, darkness, and film grain to create a gritty atmosphere, and offers special overlays like a hockey mask icon or blood splatter effects. This tool is ideal for fans of slasher films looking to create spooky social media content, themed party invitations, or atmospheric digital art.

Leave a Reply

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