Please bookmark this page to avoid losing your image tool!

Image Zig-Zag Filter Application

(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, amplitudeParam = 10, frequencyParam = 50) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

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

    if (width === 0 || height === 0) {
        // If image is not loaded or has no dimensions, return a small, empty canvas.
        // This helps prevent errors with zero-size canvas operations.
        console.error("Image has zero dimensions or is not fully loaded.");
        canvas.width = 1; 
        canvas.height = 1;
        return canvas;
    }

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

    let amplitude = Number(amplitudeParam);
    // Validate amplitude: if not a number, use default.
    if (isNaN(amplitude)) {
        amplitude = 10; // Default amplitude
    }

    let frequency = Number(frequencyParam);
    // Validate frequency: if not a number or non-positive, use default.
    // A frequency of 0 or negative is meaningless for a period length.
    if (isNaN(frequency) || frequency <= 0) { 
        frequency = 50; // Default frequency
    }
    
    // If amplitude is 0, no displacement occurs.
    // Draw the original image and return, as there's no filtering to apply.
    if (amplitude === 0) {
        ctx.drawImage(originalImg, 0, 0, width, height);
        return canvas;
    }

    // Draw the original image onto the canvas. This allows us to get its pixel data.
    ctx.drawImage(originalImg, 0, 0, width, height);
    const sourceImageData = ctx.getImageData(0, 0, width, height);
    const sourceData = sourceImageData.data;

    // Create a new ImageData object to hold the modified pixel data.
    const outputImageData = ctx.createImageData(width, height);
    const outputData = outputImageData.data;

    // Iterate over each row (y-coordinate) of the image.
    for (let y = 0; y < height; y++) {
        // Calculate the normalized position within the wave cycle for the current row y.
        // period_val will range from 0.0 up to (but not including) 1.0.
        const period_val = (y % frequency) / frequency;

        let displacement_factor;
        // Calculate the displacement factor based on a triangle wave.
        // The wave pattern is: (0,0) -> (0.25,1) -> (0.5,0) -> (0.75,-1) -> (1,0)
        // This factor determines the proportion of 'amplitude' to apply.
        // It oscillates between -1 and 1.
        if (period_val < 0.25) {
            // Rising edge: factor goes from 0 to 1 as period_val goes from 0 to 0.25
            displacement_factor = period_val * 4;
        } else if (period_val < 0.75) {
            // Falling edge: factor goes from 1 to -1 as period_val goes from 0.25 to 0.75
            // This segment passes through 0 when period_val is 0.5
            displacement_factor = 1 - (period_val - 0.25) * 4;
        } else {
            // Rising edge: factor goes from -1 to 0 as period_val goes from 0.75 to 1.0
            displacement_factor = -1 + (period_val - 0.75) * 4;
        }

        // Calculate the actual horizontal pixel offset for this row.
        // Math.round is used to get an integer offset.
        const dx_offset = Math.round(amplitude * displacement_factor);

        // Iterate over each column (x-coordinate) in the current row.
        for (let x = 0; x < width; x++) {
            // Determine the source x-coordinate from which to pick the pixel.
            // This is the destination x shifted by the calculated offset.
            let src_x_float = x - dx_offset;

            // Clamp the source x-coordinate to be within the image boundaries [0, width-1].
            // This handles cases where the offset would point outside the image.
            src_x_float = Math.max(0, Math.min(width - 1, src_x_float));
            
            // Convert the (potentially floating-point) source x-coordinate to an integer pixel index.
            // Math.floor is a common choice for this.
            const src_x_int = Math.floor(src_x_float);
            // The source y-coordinate is the same as the destination y-coordinate for this filter.
            const src_y_int = y;

            // Calculate array indices for destination and source pixels.
            // Each pixel consists of 4 bytes (R, G, B, A).
            const dest_idx = (y * width + x) * 4;
            const src_idx = (src_y_int * width + src_x_int) * 4;

            // Copy pixel data (R, G, B, A components) from source to destination.
            outputData[dest_idx]     = sourceData[src_idx];     // Red
            outputData[dest_idx + 1] = sourceData[src_idx + 1]; // Green
            outputData[dest_idx + 2] = sourceData[src_idx + 2]; // Blue
            outputData[dest_idx + 3] = sourceData[src_idx + 3]; // Alpha
        }
    }

    // Write the modified pixel data from outputImageData back to the canvas.
    ctx.putImageData(outputImageData, 0, 0);

    // Return the canvas element with the filtered image.
    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 Zig-Zag Filter Application allows users to apply a zig-zag distortion effect to their images. By adjusting the amplitude and frequency parameters, users can customize the intensity and pattern of the distortion, creating artistic and unique visual effects. This tool is ideal for graphic designers, digital artists, or anyone looking to enhance their images with creative filters for personal projects, social media posts, or digital art. It can also be useful for creating eye-catching graphics that stand out in various digital platforms.

Leave a Reply

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