Please bookmark this page to avoid losing your image tool!

Image Moiré Pattern Filter

(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.
/**
 * Applies a Moiré pattern filter to an image.
 * The Moiré effect is generated by simulating the interference of two underlying patterns (gratings)
 * defined by their spatial frequencies (magnitude and orientation). The image brightness is modulated
 * by the resulting interference pattern.
 *
 * @param {Image} originalImg - The original JavaScript Image object. Assumed to be loaded.
 * @param {string} baseFrequencyStr - The base spatial frequency for the patterns, in radians per pixel. Default: "0.2".
 *                                   Higher values create denser base patterns (more lines per unit space).
 * @param {string} angle1Str - The orientation angle (in radians) of the first pattern. Default: "0".
 *                             0 corresponds to vertical lines (wave vector oriented along the x-axis). Pi/2 for horizontal.
 * @param {string} angle2Str - The orientation angle (in radians) of the second pattern. Default: "0.15".
 *                             The difference between angle1 and angle2 (approx 8.6 degrees for default 0.15 rad) is a key factor in Moiré formation.
 * @param {string} frequencyRatioStr - The ratio of the second pattern's spatial frequency to the base spatial frequency (k2_mag / k1_mag). Default: "1.0".
 *                                     If not 1.0, this difference in frequencies also contributes to the Moiré effect.
 * @param {string} amplitudeStr - The amplitude of the brightness modulation. Default: "0.2".
 *                                Controls the intensity of the Moiré effect. Recommended range: 0.0 to 1.0.
 *                                A value of 0.2 means pixel brightness can vary by +/- 20%.
 * @returns {HTMLCanvasElement} A canvas element displaying the image with the Moiré pattern filter applied.
 */
function processImage(originalImg, baseFrequencyStr = "0.2", angle1Str = "0", angle2Str = "0.15", frequencyRatioStr = "1.0", amplitudeStr = "0.2") {
    const baseFrequency = parseFloat(baseFrequencyStr);
    const angle1 = parseFloat(angle1Str); // in radians
    const angle2 = parseFloat(angle2Str); // in radians
    const frequencyRatio = parseFloat(frequencyRatioStr);
    const amplitude = parseFloat(amplitudeStr);

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

    const imgWidth = originalImg.width;
    const imgHeight = originalImg.height;

    // Ensure valid image dimensions. If not, return a small, empty canvas.
    if (imgWidth === 0 || imgHeight === 0) {
        canvas.width = 1; 
        canvas.height = 1;
        // Optionally: console.error("Image has zero width or height.");
        return canvas;
    }
    
    canvas.width = imgWidth;
    canvas.height = imgHeight;

    // Draw the original image onto the canvas
    ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);

    // If baseFrequency is 0, or amplitude is 0, no pattern will be applied.
    // The calculations below would result in patternSignal = 0 or modulation = 1.
    // So, the original image (already drawn) would effectively be returned.
    if (baseFrequency === 0 || amplitude === 0) {
        return canvas; 
    }

    const imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
    const data = imageData.data; // Pixel data array: [R, G, B, A, R, G, B, A, ...]

    // Calculate wave vector components for the two interfering patterns
    // Pattern 1:
    const k1_magnitude = baseFrequency;
    const k1x = k1_magnitude * Math.cos(angle1); // x-component of wave vector 1
    const k1y = k1_magnitude * Math.sin(angle1); // y-component of wave vector 1

    // Pattern 2:
    const k2_magnitude = baseFrequency * frequencyRatio;
    const k2x = k2_magnitude * Math.cos(angle2); // x-component of wave vector 2
    const k2y = k2_magnitude * Math.sin(angle2); // y-component of wave vector 2
    
    // Iterate over each pixel in the image
    for (let y = 0; y < imgHeight; y++) {
        for (let x = 0; x < imgWidth; x++) {
            const index = (y * imgWidth + x) * 4; // Calculate index for the current pixel's Red component

            // Calculate the value of each wave at the current pixel (x, y)
            // The dot product (k_vec . r_vec) gives the phase of the wave: kx*x + ky*y
            const wave1Value = Math.sin(k1x * x + k1y * y);
            const wave2Value = Math.sin(k2x * x + k2y * y);

            // The combined signal is the sum of the two waves. This creates the interference pattern.
            // The sum of two sine waves sin(A) + sin(B) results in a wave whose amplitude is modulated
            // (this is known as a beat phenomenon), creating the Moiré effect.
            // We normalize by 2.0 to keep patternSignal roughly in the [-1, 1] range.
            const patternSignal = (wave1Value + wave2Value) / 2.0;
            
            // Calculate the modulation factor for pixel brightness.
            // This factor will range from (1 - amplitude) to (1 + amplitude).
            const modulation = 1.0 + amplitude * patternSignal;

            // Apply the modulation to the Red, Green, and Blue channels of the pixel.
            // Alpha channel (data[index + 3]) remains unchanged.
            // Clamp values to stay within the valid [0, 255] range for colors.
            data[index]     = Math.max(0, Math.min(255, data[index]     * modulation)); // Red
            data[index + 1] = Math.max(0, Math.min(255, data[index + 1] * modulation)); // Green
            data[index + 2] = Math.max(0, Math.min(255, data[index + 2] * modulation)); // Blue
        }
    }

    // Put the modified pixel data back onto the canvas
    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 Moiré Pattern Filter is a tool designed to apply a Moiré pattern effect to images by simulating the interference of two underlying patterns. Users can control parameters such as the base frequency, orientation angles, and amplitude of the effect to customize the appearance of the Moiré pattern. This tool can be useful in various artistic applications, such as creating unique visual textures, enhancing images for design projects, or generating patterns for use in digital art. Additionally, it allows for the exploration of optical effects in photography and graphic design.

Leave a Reply

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