Please bookmark this page to avoid losing your image tool!

Image Metronome Tick 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, tickWidth = 10, tickSpacing = 50, effectType = "grayscale", effectStrength = 0.5, orientation = "vertical") {
    // Parameter parsing and validation
    let pTickWidth = Number(tickWidth);
    pTickWidth = (Number.isFinite(pTickWidth) && pTickWidth >= 1) ? Math.floor(pTickWidth) : 10;

    let pTickSpacing = Number(tickSpacing);
    pTickSpacing = (Number.isFinite(pTickSpacing) && pTickSpacing >= 1) ? Math.floor(pTickSpacing) : 50;
    
    let pEffectStrength = Number(effectStrength);
    pEffectStrength = Number.isFinite(pEffectStrength) ? pEffectStrength : 0.5;
    pEffectStrength = Math.min(1, Math.max(0, pEffectStrength)); // Clamp to [0, 1]

    const pEffectType = String(effectType || "grayscale").toLowerCase();
    const pOrientation = String(orientation || "vertical").toLowerCase();

    // Canvas setup
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Determine image 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 || !imgHeight || imgWidth <= 0 || imgHeight <= 0) {
        // Handle invalid or non-loaded image object gracefully
        // console.warn("Metronome Tick Filter: Invalid image dimensions. Returning 1x1 canvas.");
        canvas.width = 1;
        canvas.height = 1;
        ctx.clearRect(0,0,1,1); // Make it blank
        return canvas;
    }

    canvas.width = imgWidth;
    canvas.height = imgHeight;
    
    ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);

    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
    } catch (e) {
        // console.error("Metronome Tick Filter: Error getting ImageData (possibly cross-origin issue):", e);
        // Return the canvas with the original image drawn, as processing is not possible.
        return canvas;
    }
    
    const data = imageData.data;

    // Pixel iteration
    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];
        // Alpha channel data[i+3] is not modified

        const pixelIndex = i / 4;
        const x = pixelIndex % imgWidth;
        const y = Math.floor(pixelIndex / imgWidth);

        let isInTick = false;
        if (pOrientation === "vertical") {
            const posInCycle = x % pTickSpacing;
            if (posInCycle < pTickWidth) {
                isInTick = true;
            }
        } else if (pOrientation === "horizontal") {
            const posInCycle = y % pTickSpacing;
            if (posInCycle < pTickWidth) {
                isInTick = true;
            }
        }
        // If orientation is not vertical or horizontal, isInTick remains false, so no effect is applied in bands.

        if (isInTick) {
            let r = r_orig, g = g_orig, b = b_orig; // Start with original values for current pixel

            if (pEffectType === "grayscale") {
                const gray = (r_orig * 0.299 + g_orig * 0.587 + b_orig * 0.114);
                r = r_orig * (1 - pEffectStrength) + gray * pEffectStrength;
                g = g_orig * (1 - pEffectStrength) + gray * pEffectStrength;
                b = b_orig * (1 - pEffectStrength) + gray * pEffectStrength;
            } else if (pEffectType === "darken") {
                r = r_orig * (1 - pEffectStrength);
                g = g_orig * (1 - pEffectStrength);
                b = b_orig * (1 - pEffectStrength);
            } else if (pEffectType === "lighten") {
                r = r_orig + (255 - r_orig) * pEffectStrength;
                g = g_orig + (255 - g_orig) * pEffectStrength;
                b = b_orig + (255 - b_orig) * pEffectStrength;
            } else if (pEffectType === "sepia") {
                 // Standard sepia weights
                 let tr = 0.393*r_orig + 0.769*g_orig + 0.189*b_orig;
                 let tg = 0.349*r_orig + 0.686*g_orig + 0.168*b_orig;
                 let tb = 0.272*r_orig + 0.534*g_orig + 0.131*b_orig;
                 
                 // Apply strength (interpolation between original and sepia)
                 r = r_orig * (1 - pEffectStrength) + tr * pEffectStrength;
                 g = g_orig * (1 - pEffectStrength) + tg * pEffectStrength;
                 b = b_orig * (1 - pEffectStrength) + tb * pEffectStrength;
            }
            // If effectType is unknown, r,g,b remain as r_orig,g_orig,b_orig, so no change in the tick band.

            data[i]   = Math.min(255, Math.max(0, r));
            data[i+1] = Math.min(255, Math.max(0, g));
            data[i+2] = Math.min(255, Math.max(0, b));
        }
    }

    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 Metronome Tick Filter Effect Tool allows users to apply a visually appealing tick effect to images, creating alternating bands with specific styles and spacing. Users can customize the tick width, spacing, and choose from various effects such as grayscale, darken, lighten, and sepia. This tool is ideal for artists, designers, and anyone looking to enhance their images for presentations, social media posts, or creative projects by adding a unique and stylistic filter.

Leave a Reply

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