You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, grainAmount = 0.2, vignetteStrength = 0.6, warmth = 0.15, contrastFactor = 1.1, saturationFactor = 0.9, brightness = 5) {
const canvas = document.createElement('canvas');
// using { willReadFrequently: true } can optimize repeated getImageData/putImageData calls,
// though for a single pass filter it might not have a huge impact.
const ctx = canvas.getContext('2d', { willReadFrequently: true });
const w = originalImg.naturalWidth || originalImg.width;
const h = originalImg.naturalHeight || originalImg.height;
if (w === 0 || h === 0) {
// Avoid errors with zero-dimension images
canvas.width = 1;
canvas.height = 1;
console.warn("Image has zero width or height. Returning a 1x1 canvas.");
return canvas;
}
canvas.width = w;
canvas.height = h;
ctx.drawImage(originalImg, 0, 0, w, h);
let imageData;
try {
imageData = ctx.getImageData(0, 0, w, h);
} catch (e) {
// This can happen if the image is from a different origin (CORS)
// and the canvas becomes tainted.
console.error("Could not get image data. Canvas may be tainted by cross-origin data.", e);
// In this case, we return the canvas with the original image drawn, without filters.
return canvas;
}
const data = imageData.data;
const centerX = w / 2;
const centerY = h / 2;
const maxDist = Math.sqrt(centerX * centerX + centerY * centerY);
// Constants for effect strengths based on parameters
const warmthRMultiplier = 60;
const warmthGMultiplier = 30;
const warmthBSubtractor = 15; // Blue is reduced to make it warmer
const grainScaleFactor = 50; // Scales grainAmount (0-1) to pixel intensity
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
// 1. Contrast & Brightness
// Adjust contrast: f(v) = factor * (v - 128) + 128
// Then add brightness
r = contrastFactor * (r - 128) + 128 + brightness;
g = contrastFactor * (g - 128) + 128 + brightness;
b = contrastFactor * (b - 128) + 128 + brightness;
// Clamp after contrast/brightness
r = Math.max(0, Math.min(255, r));
g = Math.max(0, Math.min(255, g));
b = Math.max(0, Math.min(255, b));
// 2. Warmth (Color Tint)
// Apply warmth by boosting red/green and slightly reducing blue
r += warmthRMultiplier * warmth;
g += warmthGMultiplier * warmth;
b -= warmthBSubtractor * warmth;
// Clamp after warmth
r = Math.max(0, Math.min(255, r));
g = Math.max(0, Math.min(255, g));
b = Math.max(0, Math.min(255, b));
// 3. Saturation
// Formula: C' = L * (1 - sat) + C * sat
// where L is luminance, C is color component, sat is saturationFactor
const L = 0.299 * r + 0.587 * g + 0.114 * b; // Calculate luminance from current r,g,b
r = L * (1 - saturationFactor) + r * saturationFactor;
g = L * (1 - saturationFactor) + g * saturationFactor;
b = L * (1 - saturationFactor) + b * saturationFactor;
// Clamp after saturation
r = Math.max(0, Math.min(255, r));
g = Math.max(0, Math.min(255, g));
b = Math.max(0, Math.min(255, b));
// 4. Grain
// Add random noise to each channel. grainAmount (0-1) controls intensity.
const grain = (Math.random() - 0.5) * (grainAmount * grainScaleFactor);
r += grain;
g += grain;
b += grain;
// Clamp after grain
r = Math.max(0, Math.min(255, r));
g = Math.max(0, Math.min(255, g));
b = Math.max(0, Math.min(255, b));
// 5. Vignette
// Darken pixels towards the edges of the image
if (vignetteStrength > 0 && maxDist > 0) {
const x = (i / 4) % w;
const y = Math.floor((i / 4) / w);
const dx = x - centerX;
const dy = y - centerY;
const dist = Math.sqrt(dx * dx + dy * dy);
const vignettePower = 1.5; // Controls the falloff curve of the vignette
const normalizedDist = dist / maxDist;
// Calculate vignette effect: 1 at center, decreases towards edges
const vignetteEffect = 1 - Math.pow(normalizedDist, vignettePower) * vignetteStrength;
r *= vignetteEffect;
g *= vignetteEffect;
b *= vignetteEffect;
}
// Final assignment to pixel data
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));
// Alpha channel (data[i+3]) is preserved
}
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 Kodak Disposable Camera Filter Effect tool allows users to apply a vintage filter reminiscent of disposable camera photographs to their images. By adjusting various parameters such as grain amount, vignette strength, warmth, contrast, saturation, and brightness, users can create nostalgic, warm-toned images with a unique character. This tool is ideal for photography enthusiasts and social media users who want to enhance their photos with a classic, artistic touch, making them stand out with a retro aesthetic.