Please bookmark this page to avoid losing your image tool!

Image Vaporwave Effect 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.
function processImage(originalImg, aberrationAmount = 3, pinkTint = 0.3, cyanTint = 0.2, scanlineIntensity = 0.2, scanlineHeight = 2, scanlineGap = 2) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can optimize repeated getImageData/putImageData calls
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

    const originalWidth = originalImg.naturalWidth;
    const originalHeight = originalImg.naturalHeight;

    // Handle cases where image might not be loaded or is invalid
    if (originalWidth === 0 || originalHeight === 0) {
        canvas.width = 1; // Avoid 0x0 canvas
        canvas.height = 1;
        console.warn("Image Vaporwave Effect Filter: Original image has zero width or height. Ensure the image is loaded before processing.");
        return canvas;
    }

    canvas.width = originalWidth;
    canvas.height = originalHeight;

    // --- 1. Draw original image ---
    ctx.drawImage(originalImg, 0, 0, originalWidth, originalHeight);

    // --- 2. Chromatic Aberration ---
    // Ensure aberrationAmount is an integer for pixel offsets
    const caAmount = Math.floor(aberrationAmount);

    if (caAmount !== 0) { // Apply if caAmount is non-zero (positive or negative)
        const srcData = ctx.getImageData(0, 0, originalWidth, originalHeight);
        const dstData = ctx.createImageData(originalWidth, originalHeight); // Create new ImageData for the output
        const srcPixels = srcData.data;
        const dstPixels = dstData.data;

        for (let y = 0; y < originalHeight; y++) {
            for (let x = 0; x < originalWidth; x++) {
                const i = (y * originalWidth + x) * 4;

                // Red channel from x - caAmount (clamped to image bounds)
                const rX = Math.max(0, Math.min(originalWidth - 1, x - caAmount));
                const rIndex = (y * originalWidth + rX) * 4;

                // Green channel from original x (no shift)
                const gIndex = i;

                // Blue channel from x + caAmount (clamped to image bounds)
                const bX = Math.max(0, Math.min(originalWidth - 1, x + caAmount));
                const bIndex = (y * originalWidth + bX) * 4;

                dstPixels[i]     = srcPixels[rIndex];       // Red
                dstPixels[i + 1] = srcPixels[gIndex + 1];   // Green
                dstPixels[i + 2] = srcPixels[bIndex + 2];   // Blue
                dstPixels[i + 3] = srcPixels[gIndex + 3];   // Alpha
            }
        }
        ctx.putImageData(dstData, 0, 0); // Apply aberration to canvas
    }

    // --- 3. Get image data (potentially with CA applied) for color tinting and scanlines ---
    let imageData = ctx.getImageData(0, 0, originalWidth, originalHeight);
    let data = imageData.data;

    // Ensure scanline parameters are reasonable
    const sHeight = Math.max(0, scanlineHeight); // Allow 0 for no scanlines
    const sGap = Math.max(0, scanlineGap);
    const sCycle = sHeight + sGap; // Total height of one scanline + gap cycle

    // Clamp scanlineIntensity between 0 and 1
    const clampedScanlineIntensity = Math.max(0, Math.min(1, scanlineIntensity));

    // --- 4. Color Tinting & Scanlines (Combined loop for efficiency) ---
    for (let y = 0; y < originalHeight; y++) {
        // Determine if the current row is part of a scanline
        const isScanlineRow = (clampedScanlineIntensity > 0 && sHeight > 0 && sCycle > 0) && ((y % sCycle) < sHeight);
        
        for (let x = 0; x < originalWidth; x++) {
            const i = (y * originalWidth + x) * 4;

            let r = data[i];
            let g = data[i+1];
            let b = data[i+2];

            // Vaporwave Color Tinting:
            // These factors are heuristic, aiming for a pink/magenta and cyan/blue shift,
            // while typically reducing the green channel.
            let newR = r * (1 + pinkTint * 0.5) + b * (pinkTint * 0.3);
            let newG = g * (1 - (pinkTint + cyanTint) * 0.6); // Green is often de-emphasized
            let newB = b * (1 + cyanTint * 0.5) + r * (cyanTint * 0.3);

            // Clamp color values to the valid 0-255 range
            data[i]   = Math.min(255, Math.max(0, newR));
            data[i+1] = Math.min(255, Math.max(0, newG));
            data[i+2] = Math.min(255, Math.max(0, newB));

            // Apply Scanlines on the (now tinted) pixel
            if (isScanlineRow) {
                const factor = (1 - clampedScanlineIntensity); // Darken pixels for scanline effect
                data[i]   = Math.max(0, data[i]   * factor);
                data[i+1] = Math.max(0, data[i+1] * factor);
                data[i+2] = Math.max(0, data[i+2] * factor);
            }
        }
    }

    // --- 5. Put modified data back to 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 Vaporwave Effect Filter allows users to apply a vaporwave aesthetic to their images by adding chromatic aberration, color tinting with pink and cyan hues, and optional scanline effects. This tool is ideal for artists, designers, and social media enthusiasts looking to create unique and retro-inspired visuals. Whether for personal projects, online posts, or creative presentations, the filter enhances images with a distinctive nostalgic flair.

Leave a Reply

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