Please bookmark this page to avoid losing your image tool!

Photo Cinematic Mood Filter

(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, tintColor = "rgba(40, 60, 100, 0.25)", contrast = 1.2, saturation = 0.85, grain = 0.05, vignetteDarkness = 0.7, vignetteClearRadius = 0.4) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

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

    // 1. Apply contrast and saturation filters, then draw image
    // These filters are applied to the drawing operation itself.
    let filterString = "";
    if (typeof contrast === 'number' && contrast !== 1) {
        filterString += `contrast(${contrast * 100}%) `;
    }
    if (typeof saturation === 'number' && saturation !== 1) {
        filterString += `saturate(${saturation * 100}%)`;
    }

    if (filterString.trim() !== "") {
        ctx.filter = filterString.trim();
    }
    
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    
    // Reset filter for subsequent operations on the canvas
    if (ctx.filter !== 'none' && ctx.filter !== "") {
        ctx.filter = 'none';
    }

    // 2. Apply Color Tint
    // The 'color' composite mode takes the hue and saturation of the source (fillStyle)
    // and the luma of the destination (current canvas content).
    // The alpha of fillStyle moderates the effect.
    if (typeof tintColor === 'string' && tintColor.trim() !== "") {
        let applyTint = true;
        // Check if tintColor is explicitly transparent or has alpha <= 0
        if (tintColor.toLowerCase() === 'transparent') {
            applyTint = false;
        } else if (tintColor.startsWith('rgba(')) {
            try {
                const parts = tintColor.substring(tintColor.indexOf('(') + 1, tintColor.lastIndexOf(')')).split(',');
                if (parts.length === 4) {
                    const alpha = parseFloat(parts[3].trim());
                    if (!isNaN(alpha) && alpha <= 0) {
                        applyTint = false;
                    }
                }
            } catch (e) {
                // Issue parsing rgba, proceed with caution or log warning
                console.warn("Could not parse alpha from tintColor:", tintColor, e);
            }
        }
        
        if (applyTint) {
            ctx.globalCompositeOperation = 'color';
            ctx.fillStyle = tintColor;
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            ctx.globalCompositeOperation = 'source-over'; // Reset composite operation
        }
    }

    // 3. Apply Film Grain
    if (typeof grain === 'number' && grain > 0 && grain <= 1) {
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const pixels = imageData.data;
        // Adjust noiseFactor: e.g. grain * 25 gives noise range roughly +/-12.5 for grain=1
        const noiseFactor = grain * 25; 

        for (let i = 0; i < pixels.length; i += 4) {
            // Add independent noise to R, G, B channels
            // Math.random() gives [0, 1), so (Math.random() - 0.5) is [-0.5, 0.5)
            const rNoise = (Math.random() - 0.5) * noiseFactor;
            const gNoise = (Math.random() - 0.5) * noiseFactor;
            const bNoise = (Math.random() - 0.5) * noiseFactor;

            pixels[i]     = Math.max(0, Math.min(255, pixels[i] + rNoise));
            pixels[i + 1] = Math.max(0, Math.min(255, pixels[i + 1] + gNoise));
            pixels[i + 2] = Math.max(0, Math.min(255, pixels[i + 2] + bNoise));
            // Alpha (pixels[i+3]) remains unchanged
        }
        ctx.putImageData(imageData, 0, 0);
    }

    // 4. Apply Vignette
    // vignetteDarkness: 0 (no darkening) to 1 (edges are black).
    // vignetteClearRadius: 0 (starts darkening from center) to 1 (no vignette).
    if (typeof vignetteDarkness === 'number' && vignetteDarkness > 0 &&
        typeof vignetteClearRadius === 'number' && vignetteClearRadius >= 0 && vignetteClearRadius < 1) {
        
        ctx.globalCompositeOperation = 'multiply'; // Use multiply to darken the image

        const centerX = canvas.width / 2;
        const centerY = canvas.height / 2;
        
        // The outer radius of the gradient should cover the corners of the image
        const outerActualRadius = Math.sqrt(centerX * centerX + centerY * centerY);
        
        // The inner radius where the vignette effect begins (still white for multiply)
        const innerClearActualRadius = outerActualRadius * vignetteClearRadius;

        const gradient = ctx.createRadialGradient(
            centerX, centerY, innerClearActualRadius,
            centerX, centerY, outerActualRadius
        );

        // Determine the color for the edge of the vignette
        // For 'multiply' mode: white (255,255,255) means no change.
        // Darker colors will darken the image.
        // vignetteDarkness = 1 means black (0,0,0).
        // vignetteDarkness = 0 means white (255,255,255).
        const edgeColorVal = Math.max(0, Math.min(255, Math.round(255 * (1 - vignetteDarkness))));
        const vignetteEdgeRgbColor = `rgb(${edgeColorVal},${edgeColorVal},${edgeColorVal})`;

        gradient.addColorStop(0, 'white'); // Center of gradient (up to innerClearActualRadius) is white
        gradient.addColorStop(1, vignetteEdgeRgbColor); // Edge of gradient (at outerActualRadius) is the vignette color

        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.globalCompositeOperation = 'source-over'; // Reset composite operation
    }

    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 Cinematic Mood Filter is an online tool designed to enhance your images by applying a variety of cinematic effects. Users can adjust contrast, saturation, and apply a color tint to create a specific mood or atmosphere in their photos. Additionally, the tool allows for the addition of film grain for a textured feel and a vignette effect that darkens the edges of the image, drawing the viewer’s focus to the center. This utility is ideal for photographers, graphic designers, or anyone looking to add a professional and artistic touch to their images before sharing them on social media, using them in presentations, or printing.

Leave a Reply

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