Please bookmark this page to avoid losing your image tool!

Moody 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, saturationAdjustment = -0.4, contrastFactor = 1.3, brightnessOffset = -10, tintColorStr = "20,30,50", tintOpacity = 0.2) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

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

    if (!width || !height) {
        console.error("Image has zero width or height. Ensure the image is loaded properly before calling processImage.");
        // Return a small canvas with an error message
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = 300;
        errorCanvas.height = 100;
        const errorCtx = errorCanvas.getContext('2d');
        errorCtx.fillStyle = '#f0f0f0';
        errorCtx.fillRect(0, 0, errorCanvas.width, errorCanvas.height);
        errorCtx.fillStyle = 'red';
        errorCtx.font = '14px Arial';
        errorCtx.textAlign = 'center';
        errorCtx.fillText('Error: Invalid image dimensions.', errorCanvas.width / 2, errorCanvas.height / 2 - 10);
        errorCtx.fillText('Please ensure image is loaded.', errorCanvas.width / 2, errorCanvas.height / 2 + 10);
        return errorCanvas;
    }

    canvas.width = width;
    canvas.height = height;

    ctx.drawImage(originalImg, 0, 0, width, height);

    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, width, height);
    } catch (e) {
        console.error("Error getting image data: ", e);
        // This can happen due to CORS issues if the image is from another domain
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = width;
        errorCanvas.height = height;
        const errorCtx = errorCanvas.getContext('2d');
        errorCtx.fillStyle = '#f0f0f0';
        errorCtx.fillRect(0, 0, width, height);
        errorCtx.font = '16px Arial';
        errorCtx.fillStyle = 'red';
        errorCtx.textAlign = 'center';
        const errorMessage = `Error processing image.`;
        const corsMessage = `(Possibly CORS policy issue if image is cross-origin)`;
        errorCtx.fillText(errorMessage, width / 2, height / 2 - 10);
        if (height > 40) { // Only show second line if there's space
             errorCtx.fillText(corsMessage, width / 2, height / 2 + 10);
        }
        console.error("Failed to get ImageData, likely due to CORS policy. Image source: ", originalImg.src);
        return errorCanvas;
    }
    
    const data = imageData.data;

    const [tintR_str, tintG_str, tintB_str] = tintColorStr.split(',');
    const tr = parseInt(tintR_str, 10);
    const tg = parseInt(tintG_str, 10);
    const tb = parseInt(tintB_str, 10);
    const useTint = tintOpacity > 0 && !isNaN(tr) && !isNaN(tg) && !isNaN(tb);

    // Helper for clamping values to 0-255 range.
    // Uint8ClampedArray handles this automatically on assignment, but explicit clamping
    // is good practice if intermediate results are used in formulas expecting valid ranges.
    const clamp = (value) => Math.max(0, Math.min(255, value));

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

        // 1. Brightness adjustment (offset)
        if (brightnessOffset !== 0) {
            r += brightnessOffset;
            g += brightnessOffset;
            b += brightnessOffset;
        }
        // Clamp after brightness
        r = clamp(r);
        g = clamp(g);
        b = clamp(b);

        // 2. Contrast adjustment (factor)
        // Adjusts values relative to mid-gray (127.5)
        if (contrastFactor !== 1.0) {
            // Normalize to 0-1, shift center to 0, apply contrast, shift back, scale to 0-255
            r = ((r / 255.0 - 0.5) * contrastFactor + 0.5) * 255.0;
            g = ((g / 255.0 - 0.5) * contrastFactor + 0.5) * 255.0;
            b = ((b / 255.0 - 0.5) * contrastFactor + 0.5) * 255.0;
        }
        // Clamp after contrast
        r = clamp(r);
        g = clamp(g);
        b = clamp(b);
        
        // 3. Saturation adjustment
        // saturationAdjustment: -1 (grayscale) to 1 (super-saturated), 0 is original.
        // Convert to satFactor: 0 (grayscale) to 2 (super-saturated), 1 is original.
        if (saturationAdjustment !== 0) {
            const satFactor = saturationAdjustment + 1.0;
            // Luminance weights for grayscale conversion (Rec. 709, for sRGB/HDTV)
            const lumR = 0.2126;
            const lumG = 0.7152;
            const lumB = 0.0722;
            const gray = r * lumR + g * lumG + b * lumB;
            
            r = gray + satFactor * (r - gray);
            g = gray + satFactor * (g - gray);
            b = gray + satFactor * (b - gray);
        }
        // Clamp after saturation
        r = clamp(r);
        g = clamp(g);
        b = clamp(b);
        
        // 4. Tint
        if (useTint) {
            r = r * (1.0 - tintOpacity) + tr * tintOpacity;
            g = g * (1.0 - tintOpacity) + tg * tintOpacity;
            b = b * (1.0 - tintOpacity) + tb * tintOpacity;
        }

        // Final assignment to ImageData. Uint8ClampedArray handles clamping and rounding.
        data[i] = r;
        data[i + 1] = g;
        data[i + 2] = 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 Moody Photo Filter Tool enhances your images by applying a moody filter effect. Users can adjust various parameters to create a unique look, including saturation, contrast, brightness, and tint color with adjustable opacity. This tool is ideal for photographers, social media enthusiasts, and anyone looking to give their images a distinct atmosphere or artistic flair. It is useful for enhancing photos for online sharing, creating visually appealing graphics, or simply experimenting with different visual styles.

Leave a Reply

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