Please bookmark this page to avoid losing your image tool!

Image Wine Stain 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, stainColor = "100,20,50", strength = 0.6, darkenFactor = 0.15) {
    const canvas = document.createElement('canvas');
    // Use naturalWidth/Height for intrinsic image dimensions, fallback to width/height
    const W = originalImg.naturalWidth || originalImg.width;
    const H = originalImg.naturalHeight || originalImg.height;

    canvas.width = W;
    canvas.height = H;

    const ctx = canvas.getContext('2d');

    // If context cannot be obtained (highly unlikely for '2d')
    // an error will be thrown by subsequent ctx operations, which is acceptable.
    // Or, to be very robust and ensure a canvas is returned:
    if (!ctx) {
        console.error("Unable to get 2D context. Returning an empty canvas or a copy of the original.");
        // Fallback: try to return a canvas with the original image drawn,
        // or at least an empty canvas of the correct size.
        const fallbackCanvas = document.createElement('canvas');
        fallbackCanvas.width = W;
        fallbackCanvas.height = H;
        const fallbackCtx = fallbackCanvas.getContext('2d');
        if (fallbackCtx) {
            try {
                fallbackCtx.drawImage(originalImg, 0, 0, W, H);
                return fallbackCanvas;
            } catch (e) {
                // If drawing originalImg fails, return the empty fallback canvas
                console.error("Error drawing original image in fallback.", e);
                return fallbackCanvas;
            }
        }
        // If even creating a fallback context fails, return the first empty canvas
        return canvas;
    }

    ctx.drawImage(originalImg, 0, 0, W, H);

    let stainRGBArray;
    try {
        stainRGBArray = stainColor.split(',').map(c => {
            const val = parseInt(c.trim(), 10);
            if (isNaN(val) || val < 0 || val > 255) {
                throw new Error(`Invalid color component: ${c.trim()}`);
            }
            return val;
        });
        if (stainRGBArray.length !== 3) {
            throw new Error("Color string must have 3 components (R,G,B).");
        }
    } catch (e) {
        console.warn(`Invalid stainColor string: "${stainColor}". Using default "100,20,50". Error: ${e.message}`);
        stainRGBArray = [100, 20, 50]; // Default wine color (dark red-purple)
    }
    
    const [targetR, targetG, targetB] = stainRGBArray;

    // Clamp strength to [0, 1]
    const s = Math.max(0, Math.min(1, Number(strength)));
    // Clamp darkenFactor to [0, 1]
    const d = Math.max(0, Math.min(1, Number(darkenFactor)));

    if (W === 0 || H === 0) { // Handle 0-dimension images
        return canvas; // Return empty canvas
    }

    const imageData = ctx.getImageData(0, 0, W, H);
    const data = imageData.data;

    for (let i = 0; i < data.length; i += 4) {
        const r_orig = data[i];
        const g_orig = data[i + 1];
        const b_orig = data[i + 2];

        // Apply tint: linear interpolation from original color towards target stain color
        // strength (s) controls the mix: 0 = original, 1 = full targetColor
        let r_tinted = r_orig * (1 - s) + targetR * s;
        let g_tinted = g_orig * (1 - s) + targetG * s;
        let b_tinted = b_orig * (1 - s) + targetB * s;

        // Apply darkening: darkenFactor (d) reduces brightness
        // d = 0 means no darkening, d = 1 means fully black
        const darkeningMultiplier = (1 - d);
        r_tinted *= darkeningMultiplier;
        g_tinted *= darkeningMultiplier;
        b_tinted *= darkeningMultiplier;

        // Clamp values to the 0-255 range and round them
        data[i]   = Math.max(0, Math.min(255, Math.round(r_tinted)));
        data[i + 1] = Math.max(0, Math.min(255, Math.round(g_tinted)));
        data[i + 2] = Math.max(0, Math.min(255, Math.round(b_tinted)));
        // 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 Image Wine Stain Filter Effect Tool allows users to apply a wine stain filter effect to their images, simulating the appearance of a dark red-purple tint. The tool offers customization options for the stain color, strength of the effect, and the level of darkening applied to the image. This tool can be particularly useful for artists, graphic designers, or anyone looking to create vintage, artistic, or unique looks for their photos, making it ideal for social media posts, digital art projects, or personal photo editing.

Leave a Reply

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