Please bookmark this page to avoid losing your image tool!

Photo Instagram-Style Filter Application 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, filterName = "None") {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Ensure the original image's dimensions are used.
    // It's assumed that originalImg is a loaded HTMLImageElement.
    // If naturalWidth/Height are 0, the canvas will be 0x0, which is generally problematic.
    // Robust error handling for unloaded images is outside typical scope of a processing function.
    canvas.width = originalImg.naturalWidth;
    canvas.height = originalImg.naturalHeight;

    // Default filter definition structure.
    // Properties are defined here to ensure they exist when merging with specific filter specs.
    const defaultFilterSpec = { 
        cssFilter: 'none', 
        overlay: null, // Example: { color: "rgba(R,G,B,A)", mode: "blend-mode" }
        vignette: null // Example: { type: "dark"|"light"|"custom", intensity: 0-1 (for dark/light), innerRadiusFactor:0-1, outerRadiusFactor:0-1, color1:"rgba(...)", color2:"rgba(...)", blendMode:"..." (for custom) }
    };

    // Filter definitions
    // These are approximations of popular Instagram-style filters.
    // - cssFilter: Uses CanvasRenderingContext2D.filter property, similar to CSS filters.
    // - overlay: Applies a solid color layer over the image using a specified blend mode.
    // - vignette: Adds a radial gradient vignette effect.
    const filters = {
        "None": {}, // Will effectively use defaultFilterSpec
        "Clarendon": { 
            cssFilter: "brightness(1.15) contrast(1.1) saturate(1.3)" 
        },
        "Gingham": { 
            cssFilter: "brightness(1.05) saturate(0.7) contrast(0.9) sepia(0.05)", 
            overlay: { color: "rgba(230, 220, 225, 0.15)", mode: "lighten" } 
        },
        "Moon": { 
            cssFilter: "grayscale(1) contrast(1.3) brightness(1.05)" 
        },
        "Lark": { 
            cssFilter: "brightness(1.1) contrast(0.9) saturate(1.2) sepia(0.05)"
        },
        "Reyes": { 
            cssFilter: "sepia(0.3) brightness(1.1) contrast(0.85) saturate(0.75)",
            overlay: { color: "rgba(240, 230, 200, 0.1)", mode: "lighten"}
        },
        "Juno": { 
            cssFilter: "contrast(1.2) saturate(1.4) brightness(1.05) hue-rotate(-8deg) sepia(0.1)" 
        },
        "Slumber": { 
            cssFilter: "saturate(0.6) brightness(1.05) contrast(0.9) sepia(0.1)",
            overlay: { color: "rgba(200, 200, 220, 0.1)", mode: "soft-light" }
        },
        "Crema": { 
            cssFilter: "sepia(0.25) contrast(1.1) saturate(0.8) brightness(1.15) hue-rotate(-4deg)" 
        },
        "Ludwig": { 
            cssFilter: "brightness(1.05) contrast(1.05) saturate(0.7) sepia(0.15)" 
        },
        "Aden": { 
            cssFilter: "hue-rotate(-20deg) contrast(0.9) saturate(0.85) brightness(1.2) sepia(0.1)" 
        },
        "Perpetua": { 
            cssFilter: "contrast(1.1) brightness(1.1) saturate(1.25) hue-rotate(5deg) sepia(0.05)" 
        },
        "Inkwell": { 
            cssFilter: "grayscale(1) contrast(1.2) brightness(0.95) sepia(0.05)"
        },
        "Willow": {
            cssFilter: "grayscale(0.7) contrast(0.9) brightness(1.1) sepia(0.05) hue-rotate(320deg)",
            vignette: { type: "dark", intensity: 0.2, innerRadiusFactor: 0.5, outerRadiusFactor: 0.9 }
        },
        "Lo-Fi": { 
            cssFilter: "saturate(1.4) contrast(1.3) hue-rotate(-5deg) sepia(0.05)" 
        },
        "X-Pro II": { 
            cssFilter: "contrast(1.3) saturate(1.25) sepia(0.3) hue-rotate(-7deg) brightness(0.95)", 
            vignette: { type: "dark", intensity: 0.5, innerRadiusFactor: 0.3, outerRadiusFactor: 0.75 } 
        },
        "Nashville": { 
            cssFilter: "sepia(0.25) contrast(1.2) brightness(1.05) saturate(1.2) hue-rotate(-3deg)",
            overlay: { color: "rgba(240, 200, 180, 0.08)", mode: "screen" }
        },
        "1977": { 
            cssFilter: "contrast(1.1) brightness(1.1) saturate(1.2) sepia(0.35) hue-rotate(-7deg)",
            overlay: { color: "rgba(230, 100, 80, 0.1)", mode: "screen" } // Reddish overlay
        },
        "Earlybird": { 
            cssFilter: "sepia(0.35) contrast(1.1) brightness(0.95) saturate(1.1) hue-rotate(-5deg)", 
            vignette: { type: "dark", intensity: 0.4, innerRadiusFactor: 0.4, outerRadiusFactor: 0.8 } 
        },
        "Brannan": {
            cssFilter: "contrast(1.35) sepia(0.45) hue-rotate(-2deg) saturate(0.9)", // sepia gives strong tint
            overlay: { color: "rgba(180, 190, 170, 0.1)", mode: "lighten"} // Greyish-green tint
        },
        "Sutro": {
            cssFilter: "brightness(0.75) contrast(1.25) saturate(0.7) sepia(0.35) hue-rotate(15deg) grayscale(0.1)",
            vignette: { type: "dark", intensity: 0.6, innerRadiusFactor: 0.3, outerRadiusFactor: 0.7 }
        },
        "Toaster": { // Aims for a "scorched" look with warm, dark vignette
            cssFilter: "sepia(0.3) saturate(1.5) contrast(1.2) hue-rotate(-15deg) brightness(0.9)",
            vignette: { type: "custom", color1: "rgba(128,70,0,0.15)", color2: "rgba(50,10,0,0.4)", blendMode: 'multiply', innerRadiusFactor: 0.3, outerRadiusFactor: 0.75 }
        },
        "Walden": { 
            cssFilter: "brightness(1.15) hue-rotate(-12deg) sepia(0.25) saturate(1.5)",
            overlay: { color: "rgba(255, 255, 180, 0.1)", mode: "screen" } // Light yellow overlay
        },
        "Hefe": { 
            cssFilter: "contrast(1.25) saturate(1.35) sepia(0.2) hue-rotate(-7deg) brightness(1.05)",
            vignette: { type: "dark", intensity: 0.3, innerRadiusFactor: 0.4, outerRadiusFactor: 0.8 }
        },
        "Valencia": { 
            cssFilter: "contrast(1.1) brightness(1.1) sepia(0.1) saturate(1.1) hue-rotate(-3deg)",
            overlay: { color: "rgba(240, 220, 180, 0.05)", mode: "lighten" } // Very subtle warm overlay
        },
        "Kelvin": {
            cssFilter: "sepia(0.45) saturate(1.7) contrast(1.35) brightness(1.15) hue-rotate(-15deg)",
            overlay: { color: "rgba(255,180,0,0.1)", mode:"overlay" } // Strong warm/orange overlay
        }
    };

    // Get the definition for the selected filter, or "None" if not found.
    const selectedFilterSpec = filters[filterName] || filters["None"];
    // Merge the selected filter's specifics with the default structure.
    // This ensures `filterDef` object has all keys (cssFilter, overlay, vignette).
    const filterDef = { ...defaultFilterSpec, ...selectedFilterSpec };

    // Step 1: Apply the base CSS-like filter
    if (filterDef.cssFilter && filterDef.cssFilter !== 'none') {
        ctx.filter = filterDef.cssFilter;
    }
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    
    // Reset ctx.filter before drawing overlay or vignette, so they aren't affected by the CSS filter.
    ctx.filter = 'none'; 

    // Step 2: Apply color overlay if defined
    if (filterDef.overlay && filterDef.overlay.color && filterDef.overlay.mode) {
        ctx.globalCompositeOperation = filterDef.overlay.mode;
        ctx.fillStyle = filterDef.overlay.color;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.globalCompositeOperation = 'source-over'; // Reset blend mode to default
    }

    // Step 3: Apply vignette if defined
    if (filterDef.vignette) {
        const v = filterDef.vignette;
        const centerX = canvas.width / 2;
        const centerY = canvas.height / 2;
        
        // Radii are based on the shorter dimension of the canvas to maintain a more circular vignette.
        const shorterDim = Math.min(canvas.width, canvas.height);
        const innerR = shorterDim * (v.innerRadiusFactor !== undefined ? v.innerRadiusFactor : 0.3);
        const outerR = shorterDim * (v.outerRadiusFactor !== undefined ? v.outerRadiusFactor : 0.9);

        const gradient = ctx.createRadialGradient(centerX, centerY, innerR, centerX, centerY, outerR);
        
        let vignetteBlendMode = 'multiply'; // Default for dark vignette
        let vignetteColorStop1 = 'rgba(0,0,0,0)'; // Default: transparent center
        let vignetteIntensity = v.intensity !== undefined ? v.intensity : 0.5;
        let vignetteColorStop2 = `rgba(0,0,0,${vignetteIntensity})`; // Default: dark edge

        if (v.type === 'light') {
            vignetteBlendMode = 'screen'; // Or 'lighten' could be used
            vignetteColorStop1 = 'rgba(255,255,255,0)'; // Transparent center
            vignetteColorStop2 = `rgba(255,255,255,${vignetteIntensity})`; // Light edge
        } else if (v.type === 'custom' && v.color1 && v.color2) {
            // Custom vignette allows specific inner/outer colors and blend mode
            vignetteBlendMode = v.blendMode || 'multiply';
            vignetteColorStop1 = v.color1;
            vignetteColorStop2 = v.color2;
        }
        
        gradient.addColorStop(0, vignetteColorStop1);
        gradient.addColorStop(1, vignetteColorStop2);
        
        ctx.globalCompositeOperation = vignetteBlendMode;
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.globalCompositeOperation = 'source-over'; // Reset blend mode
    }

    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 Instagram-Style Filter Application Tool allows users to apply a variety of Instagram-style filters to their images. By selecting from a range of effects such as brightness adjustments, color overlays, and vignette effects, users can enhance their photos to achieve the desired aesthetic. This tool is ideal for social media enthusiasts looking to beautify their images before sharing, photographers wanting to create specific atmospheres in their work, or anyone interested in adding a creative touch to their pictures.

Leave a Reply

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