You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, pinkGlow = 0.2, bloomAmount = 10, grainAmount = 25, saturation = 140, contrast = 120, vignette = 0.3) {
// Create a canvas element
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Set canvas dimensions to match the image
const w = originalImg.width;
const h = originalImg.height;
canvas.width = w;
canvas.height = h;
// --- Step 1: Apply base color grading (Saturation & Contrast) ---
// The filter property is a powerful way to apply multiple effects at once.
ctx.filter = `saturate(${saturation}%) contrast(${contrast}%)`;
ctx.drawImage(originalImg, 0, 0, w, h);
// Reset filter to apply next effects cleanly
ctx.filter = 'none';
// --- Step 2: Add a dreamy bloom effect ---
// This is done by drawing the image on top of itself with a blur,
// increased brightness, and a 'screen' composite operation which adds the colors together.
if (bloomAmount > 0) {
ctx.globalCompositeOperation = 'screen';
ctx.globalAlpha = 0.5; // Controls the intensity of the bloom
ctx.filter = `blur(${bloomAmount}px) brightness(120%)`;
ctx.drawImage(originalImg, 0, 0, w, h);
// Reset canvas state for the next step
ctx.filter = 'none';
ctx.globalAlpha = 1.0;
ctx.globalCompositeOperation = 'source-over';
}
// --- Step 3: Add a pink/magenta color overlay ---
// 'overlay' or 'color-dodge' gives a classic Y2K color tint.
if (pinkGlow > 0) {
ctx.globalCompositeOperation = 'overlay';
ctx.fillStyle = '#ff69b4'; // A vibrant magenta/pink
ctx.globalAlpha = pinkGlow;
ctx.fillRect(0, 0, w, h);
// Reset canvas state
ctx.globalAlpha = 1.0;
ctx.globalCompositeOperation = 'source-over';
}
// --- Step 4: Add a vignette ---
// This darkens the corners, focusing the eye and adding a retro camera feel.
if (vignette > 0) {
const gradient = ctx.createRadialGradient(w / 2, h / 2, Math.max(w, h) / 4, w / 2, h / 2, Math.max(w, h) / 2);
gradient.addColorStop(0, 'rgba(0,0,0,0)');
gradient.addColorStop(1, `rgba(0,0,0,${vignette})`);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, w, h);
}
// --- Step 5: Add film/digital grain ---
// This is done by manipulating the pixel data directly to add random noise.
if (grainAmount > 0) {
const imageData = ctx.getImageData(0, 0, w, h);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
// Add a random value (noise) to each color channel
const noise = (Math.random() - 0.5) * grainAmount;
data[i] = Math.max(0, Math.min(255, data[i] + noise)); // Red
data[i + 1] = Math.max(0, Math.min(255, data[i + 1] + noise)); // Green
data[i + 2] = Math.max(0, Math.min(255, data[i + 2] + noise)); // Blue
// Alpha channel (data[i + 3]) is left unchanged
}
ctx.putImageData(imageData, 0, 0);
}
return canvas;
}
Apply Changes