Please bookmark this page to avoid losing your image tool!

Image Effects Video Editor For Android

(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 various "video editor" style effects to an image.
 * This function emulates effects often found in mobile video editing apps.
 *
 * @param {Image} originalImg The original JavaScript Image object.
 * @param {string} effectType The type of effect to apply.
 *   Available effects: 'glitch', 'vhs', 'scanlines', 'posterize', 'grayscale', 'sepia', 'invert'.
 *   Defaults to 'glitch'.
 * @param {number} intensity A value from 0.0 to 1.0 that controls the strength of the effect.
 *   Defaults to 0.5.
 * @returns {HTMLCanvasElement} A new canvas element with the applied effect.
 */
function processImage(originalImg, effectType = 'glitch', intensity = 0.5) {
    // 1. Setup Canvas
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true });
    const width = originalImg.naturalWidth;
    const height = originalImg.naturalHeight;
    canvas.width = width;
    canvas.height = height;

    // Draw the original image onto the canvas to start with
    ctx.drawImage(originalImg, 0, 0, width, height);

    // Clamp intensity to a valid 0-1 range
    const clampedIntensity = Math.max(0, Math.min(1, intensity));

    // Helper function to get a pixel's starting index in the ImageData array
    const getIndex = (x, y, w) => (y * w + x) * 4;

    // 2. Apply Effects based on effectType
    switch (effectType.toLowerCase()) {
        case 'grayscale': {
            const imageData = ctx.getImageData(0, 0, width, height);
            const data = imageData.data;
            for (let i = 0; i < data.length; i += 4) {
                const r = data[i];
                const g = data[i + 1];
                const b = data[i + 2];
                const gray = 0.299 * r + 0.587 * g + 0.114 * b;
                // Blend original color with grayscale based on intensity
                data[i] = (1 - clampedIntensity) * r + clampedIntensity * gray;
                data[i + 1] = (1 - clampedIntensity) * g + clampedIntensity * gray;
                data[i + 2] = (1 - clampedIntensity) * b + clampedIntensity * gray;
            }
            ctx.putImageData(imageData, 0, 0);
            break;
        }

        case 'sepia': {
            const imageData = ctx.getImageData(0, 0, width, height);
            const data = imageData.data;
            for (let i = 0; i < data.length; i += 4) {
                const r = data[i];
                const g = data[i + 1];
                const b = data[i + 2];
                const sr = Math.min(255, r * 0.393 + g * 0.769 + b * 0.189);
                const sg = Math.min(255, r * 0.349 + g * 0.686 + b * 0.168);
                const sb = Math.min(255, r * 0.272 + g * 0.534 + b * 0.131);

                // Blend original color with sepia based on intensity
                data[i] = (1 - clampedIntensity) * r + clampedIntensity * sr;
                data[i + 1] = (1 - clampedIntensity) * g + clampedIntensity * sg;
                data[i + 2] = (1 - clampedIntensity) * b + clampedIntensity * sb;
            }
            ctx.putImageData(imageData, 0, 0);
            break;
        }

        case 'invert': {
            const imageData = ctx.getImageData(0, 0, width, height);
            const data = imageData.data;
            for (let i = 0; i < data.length; i += 4) {
                const r = data[i];
                const g = data[i + 1];
                const b = data[i + 2];
                // Blend original color with inverted color based on intensity
                data[i] = (1 - clampedIntensity) * r + clampedIntensity * (255 - r);
                data[i + 1] = (1 - clampedIntensity) * g + clampedIntensity * (255 - g);
                data[i + 2] = (1 - clampedIntensity) * b + clampedIntensity * (255 - b);
            }
            ctx.putImageData(imageData, 0, 0);
            break;
        }

        case 'posterize': {
            // Intensity controls the number of color levels (from 2 to 16)
            const levels = Math.round(clampedIntensity * 14) + 2;
            const step = 255 / (levels - 1);
            const imageData = ctx.getImageData(0, 0, width, height);
            const data = imageData.data;
            for (let i = 0; i < data.length; i += 4) {
                data[i] = Math.round(data[i] / step) * step;
                data[i + 1] = Math.round(data[i + 1] / step) * step;
                data[i + 2] = Math.round(data[i + 2] / step) * step;
            }
            ctx.putImageData(imageData, 0, 0);
            break;
        }

        case 'scanlines': {
            // This effect just draws lines over the existing image.
            ctx.fillStyle = `rgba(0, 0, 0, ${clampedIntensity * 0.3})`;
            for (let y = 0; y < height; y += 3) {
                ctx.fillRect(0, y, width, 1);
            }
            break;
        }

        case 'vhs': {
            // 1. Chromatic Aberration
            const originalData = ctx.getImageData(0, 0, width, height).data;
            const newData = ctx.createImageData(width, height);
            const offset = Math.floor(clampedIntensity * 15);

            for (let y = 0; y < height; y++) {
                for (let x = 0; x < width; x++) {
                    const i = getIndex(x, y, width);
                    // R from left, G from center, B from right
                    const rIndex = getIndex(Math.max(0, x - offset), y, width);
                    const bIndex = getIndex(Math.min(width - 1, x + offset), y, width);
                    
                    newData.data[i] = originalData[rIndex];        // Red
                    newData.data[i + 1] = originalData[i + 1];      // Green
                    newData.data[i + 2] = originalData[bIndex + 2]; // Blue
                    newData.data[i + 3] = 255;                      // Alpha
                }
            }
            ctx.putImageData(newData, 0, 0);

            // 2. Noise
            const vhsImageData = ctx.getImageData(0, 0, width, height);
            const data = vhsImageData.data;
            const noiseAmount = clampedIntensity * 40;
            for (let i = 0; i < data.length; i += 4) {
                const randomNoise = (Math.random() - 0.5) * noiseAmount;
                data[i] = Math.max(0, Math.min(255, data[i] + randomNoise));
                data[i + 1] = Math.max(0, Math.min(255, data[i + 1] + randomNoise));
                data[i + 2] = Math.max(0, Math.min(255, data[i + 2] + randomNoise));
            }
            ctx.putImageData(vhsImageData, 0, 0);

            // 3. Scanlines on top
            ctx.fillStyle = `rgba(0, 0, 0, ${clampedIntensity * 0.15})`;
            for (let y = 0; y < height; y += 4) {
                ctx.fillRect(0, y, width, 2);
            }
            break;
        }

        case 'glitch':
        default: {
            // Intensity controls the number of glitch slices and their max offset
            const numSlices = Math.floor(clampedIntensity * 40);
            const maxOffsetX = width * 0.15 * clampedIntensity;

            for (let i = 0; i < numSlices; i++) {
                const startY = Math.random() * height;
                const sliceHeight = Math.random() * (height / 15) + 1;
                const offsetX = (Math.random() - 0.5) * 2 * maxOffsetX;
                
                if (startY + sliceHeight > height) continue;

                // Grab a slice of the canvas and draw it back with an offset
                const sliceData = ctx.getImageData(0, startY, width, sliceHeight);
                ctx.putImageData(sliceData, offsetX, startY);
            }
            break;
        }
    }

    // 3. Return the modified canvas
    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 Effects Video Editor for Android allows users to apply various styling effects to images, similar to those used in mobile video editing applications. This tool offers multiple effects such as ‘glitch’, ‘vhs’, ‘scanlines’, ‘posterize’, ‘grayscale’, ‘sepia’, and ‘invert’, enabling users to creatively enhance their images. The intensity of each effect can be adjusted, allowing for subtle to dramatic changes, making it suitable for enhancing photography, creating digital art, or adding unique visuals for social media posts.

Leave a Reply

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