Please bookmark this page to avoid losing your image tool!

Photo Olympus Mju-II/Stylus Epic Filter Effect 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, vignetteStrength = 0.4, contrast = 1.3, saturation = 1.15, grainAmount = 8, shadowCoolness = 10, highlightWarmth = 5) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can be a performance hint for some browsers
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

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

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

    // Handle cases where image might not be fully loaded or has zero dimensions.
    if (width === 0 || height === 0) {
        // Return the empty (but correctly sized) canvas.
        // The caller might want to handle this by displaying an error or a placeholder.
        return canvas;
    }

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

    const imageData = ctx.getImageData(0, 0, width, height);
    const data = imageData.data;

    const centerX = width / 2;
    const centerY = height / 2;
    // Calculate distance to the furthest corner for vignette normalization
    const maxDist = Math.sqrt(centerX * centerX + centerY * centerY);

    function clamp(value, min = 0, max = 255) {
        return Math.max(min, Math.min(max, value));
    }

    for (let i = 0; i < data.length; i += 4) {
        let r = data[i];
        let g = data[i + 1];
        let b = data[i + 2];
        // Alpha channel (data[i+3]) is preserved

        // 1. Adjust Contrast
        // `contrast` = 1.0 means no change. Values > 1.0 increase contrast.
        if (contrast !== 1.0) {
            r = clamp(contrast * (r - 128) + 128);
            g = clamp(contrast * (g - 128) + 128);
            b = clamp(contrast * (b - 128) + 128);
        }

        // 2. Adjust Saturation
        // `saturation` = 1.0 means no change. Values > 1.0 increase saturation, < 1.0 decrease.
        if (saturation !== 1.0) {
            // Standard luminance constants for color manipulation
            const lumR = 0.299; // Or 0.2126 for Rec.709
            const lumG = 0.587; // Or 0.7152
            const lumB = 0.114; // Or 0.0722
            const currentPixelLuminance = lumR * r + lumG * g + lumB * b;
            
            r = clamp(currentPixelLuminance + (r - currentPixelLuminance) * saturation);
            g = clamp(currentPixelLuminance + (g - currentPixelLuminance) * saturation);
            b = clamp(currentPixelLuminance + (b - currentPixelLuminance) * saturation);
        }
        
        // 3. Apply Color Toning (Split Toning: Cool Shadows, Warm Highlights)
        // Calculate luminance of the current pixel (after contrast and saturation adjustments)
        const tonLuminance = 0.299 * r + 0.587 * g + 0.114 * b; // Range 0-255

        if (shadowCoolness > 0) {
            const shadowRegionMaxLuminance = 85; // Defines the upper limit of "shadows" (approx lower third)
            // Calculate how deep in shadows the pixel is (0 to 1)
            const shadowFactor = Math.max(0, (shadowRegionMaxLuminance - tonLuminance) / shadowRegionMaxLuminance);
            if (shadowFactor > 0) {
                 b = clamp(b + shadowCoolness * shadowFactor);
                 g = clamp(g + shadowCoolness * shadowFactor * 0.5); // Add a hint of cyan to green for coolness
            }
        }

        if (highlightWarmth > 0) {
            const highlightRegionMinLuminance = 170; // Defines the lower limit of "highlights" (approx upper third)
            const highlightRange = (255 - highlightRegionMinLuminance); // This is 85

            if (highlightRange > 0) { // Avoid division by zero if highlightRegionMinLuminance could be 255
                 // Calculate how deep in highlights the pixel is (0 to 1)
                 const highlightFactor = Math.max(0, (tonLuminance - highlightRegionMinLuminance) / highlightRange);
                 if (highlightFactor > 0) {
                    r = clamp(r + highlightWarmth * highlightFactor);
                    g = clamp(g + highlightWarmth * highlightFactor * 0.7); // Add a hint of yellow to green for warmth
                }
            } else if (tonLuminance === 255 && highlightRegionMinLuminance === 255) { 
                 // Edge case: tint pure white if highlightRegionMinLuminance is 255
                 r = clamp(r + highlightWarmth);
                 g = clamp(g + highlightWarmth * 0.7);
            }
        }

        // 4. Apply Vignette
        // vignetteStrength: 0 (none) to 1 (strongest darkening at edges)
        if (vignetteStrength > 0 && maxDist > 0) { // maxDist > 0 to avoid division by zero for tiny images
            const pixelX = (i / 4) % width;
            const pixelY = Math.floor((i / 4) / width);
            const dx = pixelX - centerX;
            const dy = pixelY - centerY;
            const dist = Math.sqrt(dx * dx + dy * dy);
            
            // Ratio of distance from center to max possible distance (0 at center, 1 at corners)
            const distRatio = dist / maxDist; 
            
            // vignetteEffect: 1.0 (no change) at center, down to (1.0 - vignetteStrength) at edges
            // Math.pow(distRatio, N), N controls the falloff (2.0 is a common quadratic falloff)
            const vignetteAmount = vignetteStrength * Math.pow(distRatio, 2.0);
            const vignetteEffect = 1.0 - vignetteAmount;
            
            r *= vignetteEffect;
            g *= vignetteEffect;
            b *= vignetteEffect;
            // Clamping is not strictly necessary if r,g,b were [0,255] as vignetteEffect is [0,1],
            // but Math.round will handle floats. Values are implicitly clamped by Math.round within data assignment anyway.
        }

        // 5. Add Film Grain
        // grainAmount: Controls the intensity of the noise
        if (grainAmount > 0) {
            // Generates noise approximately between -grainAmount/2 and +grainAmount/2
            const noise = (Math.random() - 0.5) * grainAmount; 
            r = clamp(r + noise);
            g = clamp(g + noise);
            b = clamp(b + noise);
        }
        
        // Assign final, rounded values to image data
        data[i] = Math.round(r);
        data[i + 1] = Math.round(g);
        data[i + 2] = Math.round(b);
        // data[i+3] (alpha channel) 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 Photo Olympus Mju-II/Stylus Epic Filter Effect Tool allows users to enhance their images by applying various artistic effects inspired by the classic Olympus Mju-II and Stylus Epic film cameras. Users can adjust parameters such as vignette strength, contrast, saturation, grain amount, and color toning for shadows and highlights. This tool is ideal for photographers and graphic designers looking to give their digital images a vintage or film-like appearance, making it perfect for personal projects, social media posts, and creative artwork.

Leave a Reply

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

Other Image Tools:

Image NiSi Nano IR ND Filter Effect Tool

Image Polaroid SX-70 Filter Effect Tool

Image Linhof Technika Filter Effect Tool

Image Lee Big Stopper 10-Stop ND Filter Effect Tool

Image Minolta X-700 Film Camera Render Effect Creator

Image ORWO UN54 Motion Picture Film Effect Applicator

Image Shen-Hao Large Format Filter Effect Tool

Image Impossible Project Polaroid Filter Effect Tool

Photo Foma Retropan 320 Film Filter Effect Tool

Image Fuji QuickSnap Disposable Filter Effect Application

Image 220 Film Format Filter Effect

Image Black and White with Green #61 Filter Effect Tool

Image 35mm Panoramic Camera Filter Effect Tool

Image Hitech Firecrest ND Filter Effect Formatter

Photo Rodenstock Digital Vario ND Filter Effect Tool

Image Leica Yellow Filter Effect Application

Image Argus C3 Vintage Camera Filter Effect

Image ORWO NP22 Film Filter Effect Application

Image Wratten #25 Red Filter Effect Tool

Image Helios 44-2 Swirly Bokeh Effect Filter

Image Fujifilm ETERNA Motion Picture Film Effect Applicator

Image Fujifilm FP-100C Instant Film Effect Filter

Image Canon AE-1 Film Camera Render Effect

Photo B+W Dark Red #29 Filter Effect Application

Image Toy Camera Effect Enhancer

Photo Graflex Speed Graphic Filter Effect Tool

Image Konica Hexar AF Filter Effect Application

Image Ricoh GR Film Camera Filter Effect Application

Image Kodak Disposable Camera Filter Effect

Image Hoya Pro ND Filter Effect Application

Image Wratten #12 Yellow Filter Effect Tool

Image AGFA APX 100 Film Filter Effect Tool

Image Singh-Ray Vari-ND Filter Effect Application

Image Rollei RPX 25 Film Filter Effect Tool

Image 35mm Half-frame Camera Filter Effect

Image Kodak Vision3 250D Motion Picture Film Effect Filter

See All →