Please bookmark this page to avoid losing your image tool!

Image Color Distortion And Audio Effects Video Editor

(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.
/**
 * Creates a video-like effect with color distortion and audio from a static image.
 * This simulates a 'glitchy' or 'datamoshed' video aesthetic.
 *
 * @param {Image} originalImg The input Image object.
 * @param {number} distortionAmount A number from 0 to 1 controlling the intensity of visual glitches. Defaults to 0.3.
 * @param {number} basePitch The base frequency (in Hz) for the generated audio. Defaults to 200.
 * @param {number} pitchModulation The range (in Hz) by which the audio pitch will fluctuate. Defaults to 100.
 * @param {string} audioType The type of audio waveform. Can be 'noise', 'sine', 'square', 'sawtooth', or 'triangle'. Defaults to 'noise'.
 * @returns {HTMLElement} A div element containing the animated canvas and a play button.
 */
async function processImage(originalImg, distortionAmount = 0.3, basePitch = 200, pitchModulation = 100, audioType = 'noise') {
    // Clamp distortionAmount to be between 0 and 1 for predictable results.
    const clampedDistortion = Math.max(0, Math.min(1, distortionAmount));

    // Create the main container and canvas elements.
    const container = document.createElement('div');
    const canvas = document.createElement('canvas');
    // Use a backing canvas for the original image data to improve performance.
    const sourceCanvas = document.createElement('canvas');

    const ctx = canvas.getContext('2d', {
        willReadFrequently: true
    });
    const sourceCtx = sourceCanvas.getContext('2d');

    // Set canvas dimensions to the original image's natural size.
    canvas.width = sourceCanvas.width = originalImg.naturalWidth;
    canvas.height = sourceCanvas.height = originalImg.naturalHeight;

    // Draw the original image to the backing canvas and store its pixel data.
    sourceCtx.drawImage(originalImg, 0, 0);
    const originalImageData = sourceCtx.getImageData(0, 0, canvas.width, canvas.height);

    // Perform an initial draw on the visible canvas.
    ctx.drawImage(originalImg, 0, 0);

    // Create a "Play" button to initiate the effects, respecting browser autoplay policies.
    const playButton = document.createElement('button');
    playButton.textContent = '▶';

    container.appendChild(canvas);
    container.appendChild(playButton);

    let audioContext;
    let animationFrameId;

    const startEffect = async () => {
        playButton.style.display = 'none';

        // Initialize the Web Audio API context.
        audioContext = new(window.AudioContext || window.webkitAudioContext)();
        if (audioContext.state === 'suspended') {
            await audioContext.resume();
        }

        const masterGain = audioContext.createGain();
        masterGain.gain.setValueAtTime(0.25, audioContext.currentTime); // Keep volume reasonable.
        masterGain.connect(audioContext.destination);

        // Audio graph setup based on the 'audioType' parameter.
        const validWaveforms = ['sine', 'square', 'sawtooth', 'triangle'];
        if (audioType === 'noise') {
            const bufferSize = audioContext.sampleRate * 2; // 2 seconds of noise buffer.
            const noiseBuffer = audioContext.createBuffer(1, bufferSize, audioContext.sampleRate);
            const output = noiseBuffer.getChannelData(0);
            for (let i = 0; i < bufferSize; i++) {
                output[i] = Math.random() * 2 - 1;
            }
            const noiseSource = audioContext.createBufferSource();
            noiseSource.buffer = noiseBuffer;
            noiseSource.loop = true;

            const filter = audioContext.createBiquadFilter();
            filter.type = 'bandpass';
            filter.frequency.setValueAtTime(basePitch, audioContext.currentTime);
            filter.Q.setValueAtTime(10, audioContext.currentTime);

            const lfo = audioContext.createOscillator();
            lfo.type = 'sine';
            lfo.frequency.setValueAtTime(5, audioContext.currentTime);
            const lfoGain = audioContext.createGain();
            lfoGain.gain.setValueAtTime(pitchModulation, audioContext.currentTime);

            lfo.connect(lfoGain);
            lfoGain.connect(filter.frequency);
            noiseSource.connect(filter);
            filter.connect(masterGain);
            noiseSource.start();
            lfo.start();
        } else if (validWaveforms.includes(audioType)) {
            const oscillator = audioContext.createOscillator();
            oscillator.type = audioType;
            oscillator.frequency.setValueAtTime(basePitch, audioContext.currentTime);

            const lfo = audioContext.createOscillator();
            lfo.type = 'sine';
            lfo.frequency.setValueAtTime(8, audioContext.currentTime);
            const lfoGain = audioContext.createGain();
            lfoGain.gain.setValueAtTime(pitchModulation, audioContext.currentTime);

            lfo.connect(lfoGain);
            lfoGain.connect(oscillator.frequency);
            oscillator.connect(masterGain);
            oscillator.start();
            lfo.start();
        }

        // Animation loop for visual effects.
        let time = 0;

        function animate() {
            time += 0.05;

            const imageData = ctx.createImageData(originalImageData.width, originalImageData.height);
            const data = imageData.data;
            const sourceData = originalImageData.data;
            const {
                width,
                height
            } = imageData;

            // Calculate glitch parameters for the current frame.
            const splitOffset = Math.round(Math.sin(time) * 15 * clampedDistortion);
            const numBlocks = 3 + Math.floor(clampedDistortion * 25);
            const glitchBlocks = [];
            for (let i = 0; i < numBlocks; i++) {
                glitchBlocks.push({
                    y: Math.floor(Math.random() * height),
                    h: Math.floor(Math.random() * height * 0.1),
                    offset: Math.floor((Math.random() - 0.5) * width * 0.2 * clampedDistortion)
                });
            }

            // Process each pixel to apply combined glitch effects.
            for (let y = 0; y < height; y++) {
                let horizontalOffset = 0;
                for (const block of glitchBlocks) {
                    if (y >= block.y && y < block.y + block.h) {
                        horizontalOffset = block.offset;
                        break;
                    }
                }
                for (let x = 0; x < width; x++) {
                    const destIndex = (y * width + x) * 4;
                    const sourceX = (x - horizontalOffset + width) % width;

                    // Apply RGB split to the glitched coordinates.
                    const rIndex = (y * width + (sourceX - splitOffset + width) % width) * 4;
                    const gIndex = (y * width + sourceX) * 4;
                    const bIndex = (y * width + (sourceX + splitOffset + width) % width) * 4;

                    data[destIndex] = sourceData[rIndex];
                    data[destIndex + 1] = sourceData[gIndex + 1];
                    data[destIndex + 2] = sourceData[bIndex + 2];
                    data[destIndex + 3] = 255;
                }
            }

            ctx.putImageData(imageData, 0, 0);
            animationFrameId = requestAnimationFrame(animate);
        }
        animate();
    };

    playButton.onclick = startEffect;

    // Set up a MutationObserver to clean up resources when the element is removed from the DOM.
    const observer = new MutationObserver((mutationsList) => {
        for (const mutation of mutationsList) {
            if (mutation.removedNodes) {
                mutation.removedNodes.forEach(node => {
                    if (node === container) {
                        if (animationFrameId) cancelAnimationFrame(animationFrameId);
                        if (audioContext && audioContext.state !== 'closed') audioContext.close();
                        observer.disconnect();
                    }
                });
            }
        }
    });

    playButton.addEventListener('click', () => {
        // Once interaction starts, observe the container's parent for removal.
        setTimeout(() => {
            if (container.parentNode) {
                observer.observe(container.parentNode, {
                    childList: true
                });
            }
        }, 0);
    }, {
        once: true
    });

    // Apply styles for proper layout and appearance.
    container.style.position = 'relative';
    container.style.display = 'inline-block';
    container.style.width = `${canvas.width}px`;
    container.style.height = `${canvas.height}px`;
    canvas.style.display = 'block';
    canvas.style.maxWidth = '100%';
    canvas.style.height = 'auto';

    playButton.style.position = 'absolute';
    playButton.style.top = '50%';
    playButton.style.left = '50%';
    playButton.style.transform = 'translate(-50%, -50%)';
    playButton.style.fontSize = '48px';
    playButton.style.width = '80px';
    playButton.style.height = '80px';
    playButton.style.paddingLeft = '5px';
    playButton.style.cursor = 'pointer';
    playButton.style.border = '3px solid white';
    playButton.style.background = 'rgba(0,0,0,0.6)';
    playButton.style.color = 'white';
    playButton.style.borderRadius = '50%';
    playButton.style.textShadow = '0 0 5px black';
    playButton.style.transition = 'background 0.2s';
    playButton.onmouseover = () => {
        playButton.style.background = 'rgba(0,0,0,0.8)';
    };
    playButton.onmouseout = () => {
        playButton.style.background = 'rgba(0,0,0,0.6)';
    };

    return container;
}

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 Color Distortion and Audio Effects Video Editor is a creative tool that allows users to transform static images into dynamic visual experiences. By applying various levels of color distortion effects and generating corresponding audio, it simulates a glitchy or datamoshed video aesthetic. This tool is ideal for artists, video creators, and hobbyists looking to create unique visual content, engage in multimedia projects, or enhance their social media posts with eye-catching effects.

Leave a Reply

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