Please bookmark this page to avoid losing your image tool!

Romantic 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, romanticFactor = 0.7, softness = 1.0, vignetteIntensity = 0.5) {
    // Validate and clamp parameters. parseFloat ensures string inputs are handled correctly.
    romanticFactor = Math.max(0, Math.min(1, parseFloat(romanticFactor)));
    softness = Math.max(0, Math.min(5, parseFloat(softness))); // Max blur 5px for a "soft" effect.
    vignetteIntensity = Math.max(0, Math.min(1, parseFloat(vignetteIntensity)));

    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can be an optimization hint for repeated getImageData/putImageData calls.
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    const w = originalImg.naturalWidth || originalImg.width;
    const h = originalImg.naturalHeight || originalImg.height;
    canvas.width = w;
    canvas.height = h;

    // 1. Apply Softness (Blur)
    // The canvas filter is applied when drawImage is called.
    // Only apply blur if softness is meaningfully greater than a very small threshold (e.g., 0.01).
    if (softness > 0.01) { 
        ctx.filter = `blur(${softness}px)`;
    }
    
    // Draw the original image onto the canvas. If a filter was set, it will be applied here.
    ctx.drawImage(originalImg, 0, 0, w, h);
    
    // Reset the filter on the context to 'none'. This ensures that subsequent drawing operations
    // (like the vignette) are not affected by the blur filter.
    if (softness > 0.01) {
        ctx.filter = 'none';
    }

    // 2. Apply Romantic Color Grading (Desaturation + Tint)
    // This pixel-level processing is done only if romanticFactor indicates an effect should be applied.
    if (romanticFactor > 0.01) { // Apply color grading if factor is meaningfully greater than a small threshold.
        // Get the pixel data from the canvas. At this point, the canvas contains the (potentially blurred) image.
        const imageData = ctx.getImageData(0, 0, w, h);
        const data = imageData.data; // This is a Uint8ClampedArray: [R,G,B,A, R,G,B,A, ...]

        // Define the target tint color (a soft, warm rose/peach hue).
        const tintR_val = 230; // Red component of the tint color
        const tintG_val = 200; // Green component of the tint color
        const tintB_val = 200; // Blue component of the tint color

        // Calculate the effective alpha for tinting, based on romanticFactor.
        // This determines how much the original pixel color blends with the tint color. Max 35% blend.
        const tintAlpha = 0.35 * romanticFactor; 
        
        // Calculate the desaturation level, also based on romanticFactor.
        // This imparts a slightly vintage or dreamy feel. Max 25% desaturation.
        const desaturationLevel = 0.25 * romanticFactor;

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

            // Apply Desaturation (if desaturationLevel is effective)
            // This blends the current color with its grayscale equivalent.
            if (desaturationLevel > 0) {
                const gray = 0.299 * r + 0.587 * g + 0.114 * b; // Standard luminance calculation for grayscale
                r = r * (1 - desaturationLevel) + gray * desaturationLevel;
                g = g * (1 - desaturationLevel) + gray * desaturationLevel;
                b = b * (1 - desaturationLevel) + gray * desaturationLevel;
            }

            // Apply Tint overlay
            // This blends the (now potentially desaturated) color with the defined tint color.
            data[i]   = Math.min(255, Math.max(0, r * (1 - tintAlpha) + tintR_val * tintAlpha));
            data[i+1] = Math.min(255, Math.max(0, g * (1 - tintAlpha) + tintG_val * tintAlpha));
            data[i+2] = Math.min(255, Math.max(0, b * (1 - tintAlpha) + tintB_val * tintAlpha));
            // The alpha channel (data[i+3]) is preserved from the original image.
        }
        // Write the modified pixel data back to the canvas.
        ctx.putImageData(imageData, 0, 0);
    }

    // 3. Apply Vignette
    // This adds a darkening effect to the corners and edges of the image.
    if (vignetteIntensity > 0.01) { // Apply vignette if intensity is meaningfully greater than a small threshold.
        const centerX = w / 2;
        const centerY = h / 2;
        
        // Calculate the radius to the furthest corner of the image. This ensures the vignette covers the entire image.
        const outerRadius = Math.sqrt(Math.pow(w / 2, 2) + Math.pow(h / 2, 2));
        
        // Determine the inner radius of the vignette (the central, fully transparent part).
        // This radius shrinks as vignetteIntensity increases, making the vignette effect more pronounced.
        // The 0.75 factor controls how rapidly the vignette "closes in" towards the center.
        const innerRadius = outerRadius * (1 - (vignetteIntensity * 0.75)); 

        // Create a radial gradient. The gradient transitions from transparent in the center to dark at the edges.
        const gradient = ctx.createRadialGradient(centerX, centerY, innerRadius, centerX, centerY, outerRadius);
        
        // Define the color stops for the gradient.
        gradient.addColorStop(0, 'rgba(0,0,0,0)'); // At the innerRadius, the gradient is fully transparent black.
        
        // Determine the opacity of the vignette at the extreme edges.
        // This is controlled by vignetteIntensity, with a maximum of 80% black opacity.
        const edgeOpacity = vignetteIntensity * 0.8; 
        gradient.addColorStop(1, `rgba(0,0,0,${edgeOpacity})`); // At the outerRadius, the gradient is semi-transparent black.

        ctx.fillStyle = gradient;
        // Draw the gradient rectangle over the entire canvas using the default 'source-over' compositing mode.
        // This overlays the semi-transparent gradient on top of the existing image content.
        ctx.fillRect(0, 0, w, h);
    }

    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 Romantic Photo Filter Tool enhances your images by applying a soft, romantic effect that can make your photos appear dreamy and warm. Users can customize the level of softness, color tint, and vignette intensity to create a unique look that suits their style. This tool is ideal for personalizing memories, creating stunning visuals for social media, and adding a touch of romance to portraits or landscape photography.

Leave a Reply

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