You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, sepiaStrength = 0.7, noiseStrength = 0.05, desaturation = 0.2, vignetteIntensity = 0.3) {
const canvas = document.createElement('canvas');
// Using { willReadFrequently: true } can be a performance hint for browsers
const ctx = canvas.getContext('2d', { willReadFrequently: true });
const w = originalImg.naturalWidth || originalImg.width;
const h = originalImg.naturalHeight || originalImg.height;
canvas.width = w;
canvas.height = h;
if (w === 0 || h === 0) {
// If image dimensions are zero (e.g., not loaded or invalid image),
// return an empty canvas to prevent errors.
console.warn("Image has zero width or height. Returning an empty canvas.");
return canvas;
}
ctx.drawImage(originalImg, 0, 0, w, h);
const imageData = ctx.getImageData(0, 0, w, h);
const data = imageData.data;
const len = data.length;
// Max noise deviation: e.g. if noiseStrength is 1, noise can shift a channel by +/-32
// Default (0.05) means +/- 1.6, a very subtle noise.
const noisePixelShift = noiseStrength * 32;
for (let i = 0; i < len; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
// Alpha channel data[i+3] is preserved by default
// 1. Desaturation
// Desaturation = 0 means original color, Desaturation = 1 means grayscale.
if (desaturation > 0) {
const gray = 0.299 * r + 0.587 * g + 0.114 * b; // Standard luminance calculation
r = r * (1 - desaturation) + gray * desaturation;
g = g * (1 - desaturation) + gray * desaturation;
b = b * (1 - desaturation) + gray * desaturation;
}
// 2. Sepia Tone
// sepiaStrength = 0 means no sepia, sepiaStrength = 1 means full sepia.
if (sepiaStrength > 0) {
// Standard sepia matrix values
const sr = (r * 0.393) + (g * 0.769) + (b * 0.189);
const sg = (r * 0.349) + (g * 0.686) + (b * 0.168);
const sb = (r * 0.272) + (g * 0.534) + (b * 0.131);
r = r * (1 - sepiaStrength) + sr * sepiaStrength;
g = g * (1 - sepiaStrength) + sg * sepiaStrength;
b = b * (1 - sepiaStrength) + sb * sepiaStrength;
}
// 3. Noise
// Adds monochromatic noise.
if (noisePixelShift > 0) {
const randomNoise = (Math.random() - 0.5) * noisePixelShift;
r += randomNoise;
g += randomNoise;
b += randomNoise;
}
// Clamp values to the 0-255 range for each channel
data[i] = Math.max(0, Math.min(255, r));
data[i + 1] = Math.max(0, Math.min(255, g));
data[i + 2] = Math.max(0, Math.min(255, b));
}
ctx.putImageData(imageData, 0, 0);
// 4. Vignette Effect
// Clamp vignetteIntensity to a practical [0, 1] range.
const effectiveVignetteIntensity = Math.max(0, Math.min(1, vignetteIntensity));
if (effectiveVignetteIntensity > 0) {
ctx.save(); // Save current canvas state
const centerX = w / 2;
const centerY = h / 2;
// Spread Factor: Controls how far the transparent center of the vignette extends.
// Ranges from ~0.1 (for intensity 1, small center) to ~0.9 (for intensity 0, large center).
const spreadFactor = 0.1 + (1 - effectiveVignetteIntensity) * 0.8;
// Define the inner and outer radii for the radial gradient.
// Inner radius is based on the smaller dimension of the image and the spread factor.
const innerRadius = (Math.min(w, h) / 2) * spreadFactor;
// Outer radius extends to the corners of the image.
const outerRadius = Math.sqrt(centerX * centerX + centerY * centerY);
const gradient = ctx.createRadialGradient(
centerX, centerY, innerRadius,
centerX, centerY, outerRadius
);
// Edge Opacity: Controls darkness of the vignette at the edges.
// Max opacity of ~0.8 for black at full intensity to avoid pure black.
const edgeOpacity = effectiveVignetteIntensity * 0.8;
gradient.addColorStop(0, "rgba(0,0,0,0)"); // Transparent black at the inner radius
gradient.addColorStop(1, `rgba(0,0,0,${edgeOpacity})`); // Semi-transparent black at the outer radius
ctx.globalCompositeOperation = 'source-over'; // Draw new shapes on top of existing content
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, w, h); // Apply the gradient over the entire canvas
ctx.restore(); // Restore canvas state
}
return canvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
Photo Old Filter Application is a web-based tool that allows users to apply vintage photo effects to their images. Users can adjust the strength of sepia toning, add noise for a grainy texture, desaturate colors for a faded look, and create vignette effects to enhance the nostalgic feel of photographs. This tool is ideal for anyone looking to give their photos an artistic, retro aesthetic, whether for personal projects, social media sharing, or creative design.