You can edit the below JavaScript code to customize the image tool.
function processImage(
originalImg,
aberrationAmount = 3, // Pixels for R/B channel horizontal offset
pinkBoostAmount = 30, // Amount to add to the Red channel (0-255 range)
blueBoostAmount = 25, // Amount to add to the Blue channel (0-255 range)
greenSuppressionFactor = 0.8, // Factor to multiply the Green channel by (e.g., 0.8 for 20% suppression)
scanlineIntervalPx = 4, // Total period of the scanline pattern (e.g., every 4th row group starts a scanline)
scanlineThicknessPx = 1, // Thickness of each scanline in pixels (how many consecutive rows are darkened)
scanlineStrengthFactor = 0.8 // How dark scanlines are (0.0 = black, 1.0 = no change)
) {
const canvas = document.createElement('canvas');
// Use willReadFrequently hint for performance with repeated getImageData/putImageData calls
const ctx = canvas.getContext('2d', { willReadFrequently: true });
const w = originalImg.naturalWidth || originalImg.width;
const h = originalImg.naturalHeight || originalImg.height;
if (w === 0 || h === 0) {
console.error("Image has zero width or height.");
// Return an empty canvas or one with specific dimensions if preferred for error handling
canvas.width = w; // will be 0
canvas.height = h; // will be 0
return canvas;
}
canvas.width = w;
canvas.height = h;
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0, w, h);
let imageData;
try {
// Get the pixel data from the canvas
imageData = ctx.getImageData(0, 0, w, h);
} catch (e) {
console.error("Could not get image data (possibly due to tainted canvas from cross-origin image):", e);
// If getImageData fails, we can't process. Return the canvas with the original image drawn.
return canvas;
}
const data = imageData.data;
// Create a copy of the original pixel data for sampling during chromatic aberration
// This ensures that aberration samples from the pristine image, not already modified pixels
const originalData = new Uint8ClampedArray(data);
// --- Apply Chromatic Aberration and Color Adjustments ---
for (let y = 0; y < h; y++) {
for (let x = 0; x < w; x++) {
const i = (y * w + x) * 4; // Index for the current pixel in the 'data' array
// Chromatic Aberration: Sample R, G, B channels from slightly different locations
// Red channel: sample from 'aberrationAmount' pixels to the left
const rX = Math.max(0, x - aberrationAmount);
const rIndex = (y * w + rX) * 4;
const rOrig = originalData[rIndex];
// Green channel & Alpha: sample from the current pixel (center)
const gIndex = i; // (y * w + x) * 4
const gOrig = originalData[gIndex + 1];
const alpha = originalData[gIndex + 3]; // Preserve original alpha
// Blue channel: sample from 'aberrationAmount' pixels to the right
const bX = Math.min(w - 1, x + aberrationAmount);
const bIndex = (y * w + bX) * 4;
const bOrig = originalData[bIndex + 2];
// Vaporwave Color Adjustments on the (potentially aberrated) R, G, B values
let finalR = rOrig + pinkBoostAmount;
let finalG = gOrig * greenSuppressionFactor;
let finalB = bOrig + blueBoostAmount;
// Clamp color values to the valid 0-255 range
data[i] = Math.max(0, Math.min(255, finalR));
data[i + 1] = Math.max(0, Math.min(255, finalG));
data[i + 2] = Math.max(0, Math.min(255, finalB));
data[i + 3] = alpha; // Set the alpha for the modified pixel
}
}
// Write the modified pixel data (with aberration and color changes) back to the canvas
ctx.putImageData(imageData, 0, 0);
// --- (Optional) Apply Scanlines ---
// Apply scanlines if strength is less than 1 (meaning some darkening) and geometry is valid
if (scanlineStrengthFactor < 1.0 && scanlineStrengthFactor >= 0.0 && scanlineIntervalPx > 0 && scanlineThicknessPx > 0) {
// Get the image data again, this time it includes the color/aberration changes
imageData = ctx.getImageData(0, 0, w, h);
const scanlineData = imageData.data; // Use a new variable for clarity, refers to same underlying buffer for modification
for (let y = 0; y < h; y++) {
// Determine if the current row 'y' should be part of a scanline band
// It's part of a scanline if 'y' modulo 'scanlineIntervalPx' is less than 'scanlineThicknessPx'
if ((y % scanlineIntervalPx) < scanlineThicknessPx) {
for (let x = 0; x < w; x++) {
const i = (y * w + x) * 4;
// Darken the R, G, B components by the 'scanlineStrengthFactor'
scanlineData[i] = scanlineData[i] * scanlineStrengthFactor;
scanlineData[i + 1] = scanlineData[i + 1] * scanlineStrengthFactor;
scanlineData[i + 2] = scanlineData[i + 2] * scanlineStrengthFactor;
// Alpha channel remains unchanged by scanlines
}
}
}
// Write the pixel data (now with scanlines) 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!
The Image Retro Vaporwave Filter tool allows users to apply a distinct vaporwave aesthetic to their images. By adjusting color channels and introducing chromatic aberration, users can enhance the red and blue hues while suppressing the green, resulting in a vivid retro look. The tool also features options for adding scanline patterns to further evoke a nostalgic feel. This tool is ideal for artists, graphic designers, and social media users looking to transform images for creative projects, profile pictures, or any visual content that benefits from a unique, stylized appearance.