Please bookmark this page to avoid losing your image tool!

Serene Photo 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, desaturationAmount = 0.3, contrastAdjust = 0.8, brightnessAdjust = 1.05, sereneColorTintStr = "200,220,240", tintStrength = 0.15) {
    // 1. Parse sereneColorTintStr into R, G, B values
    let R_tint = 200, G_tint = 220, B_tint = 240; // Default serene color
    if (typeof sereneColorTintStr === 'string') {
        const parsedRGB = sereneColorTintStr.split(',').map(Number);
        if (parsedRGB.length === 3 && parsedRGB.every(num => !isNaN(num) && num >= 0 && num <= 255)) {
            [R_tint, G_tint, B_tint] = parsedRGB;
        } else {
            console.warn("Invalid sereneColorTintStr format or values. Using default tint: " + sereneColorTintStr);
        }
    } else {
         console.warn("sereneColorTintStr is not a string. Using default tint.");
    }


    // 2. Create a canvas
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true }); // willReadFrequently for performance with getImageData/putImageData

    // 3. Set canvas dimensions
    // Use naturalWidth/Height for intrinsic dimensions, fallback to width/height
    const imgWidth = originalImg.naturalWidth || originalImg.width;
    const imgHeight = originalImg.naturalHeight || originalImg.height;
    
    if (imgWidth === 0 || imgHeight === 0) {
        console.error("Image has zero dimensions. Ensure the image is loaded and valid.");
        // Return a small error canvas or throw an error
        canvas.width = 100;
        canvas.height = 50;
        ctx.fillStyle = 'red';
        ctx.font = '12px Arial';
        ctx.fillText('Invalid Image', 10, 30);
        return canvas;
    }

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

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

    // 5. Get the image data
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    } catch (e) {
        console.error("Could not get image data, possibly due to cross-origin restrictions:", e);
        // Create an error message canvas
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = Math.max(200, canvas.width); // Use canvas dimensions if available
        errorCanvas.height = Math.max(100, canvas.height);
        const errorCtx = errorCanvas.getContext('2d');
        errorCtx.fillStyle = 'lightgray';
        errorCtx.fillRect(0, 0, errorCanvas.width, errorCanvas.height);
        errorCtx.fillStyle = 'red';
        errorCtx.font = '16px Arial';
        errorCtx.textAlign = 'center';
        errorCtx.textBaseline = 'middle';
        const lines = ["Error processing image.", "(Cross-origin issue?)"];
        lines.forEach((line, index) => {
            errorCtx.fillText(line, errorCanvas.width / 2, errorCanvas.height / 2 + (index * 20) - (lines.length-1)*10 );
        });
        return errorCanvas;
    }
    const data = imageData.data;

    // 6. Iterate through the pixels and apply the filter
    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];

        // a. Apply brightness adjustment
        if (brightnessAdjust !== 1.0) {
            r *= brightnessAdjust;
            g *= brightnessAdjust;
            b *= brightnessAdjust;
        }

        // b. Apply contrast adjustment
        if (contrastAdjust !== 1.0) {
            const mid = 127.5; // Midpoint for 0-255 range
            r = (r - mid) * contrastAdjust + mid;
            g = (g - mid) * contrastAdjust + mid;
            b = (b - mid) * contrastAdjust + mid;
        }
        
        // c. Apply desaturation
        if (desaturationAmount > 0.0 && desaturationAmount <= 1.0) {
            // Luminance calculation (standard Rec. 601)
            const gray = 0.299 * r + 0.587 * g + 0.114 * b;
            r = r * (1 - desaturationAmount) + gray * desaturationAmount;
            g = g * (1 - desaturationAmount) + gray * desaturationAmount;
            b = b * (1 - desaturationAmount) + gray * desaturationAmount;
        }

        // d. Apply serene color tint (blend)
        if (tintStrength > 0.0 && tintStrength <= 1.0) {
            r = r * (1 - tintStrength) + R_tint * tintStrength;
            g = g * (1 - tintStrength) + G_tint * tintStrength;
            b = b * (1 - tintStrength) + B_tint * tintStrength;
        }
        
        // e. Clamp 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
    }

    // 7. Put the modified image data back onto the canvas
    ctx.putImageData(imageData, 0, 0);

    // 8. Return the canvas
    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

Serene Photo Filter is a powerful online image processing tool that allows users to enhance their photos by applying a serene color tint, adjusting brightness, contrast, and desaturation levels. This tool is particularly useful for photographers and social media enthusiasts who wish to create calming and visually appealing images. By customizing the tint and intensity of the effects, users can easily transform their images into soothing artworks suitable for sharing, printing, or personal use.

Leave a Reply

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