You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, sepiaLevel = 0.7, noiseStrength = 20, brightnessAdj = -15, contrastMul = 0.9, vignetteIntensity = 0.5) {
// Ensure parameters are numbers and clamp them to sensible ranges
sepiaLevel = Math.max(0, Math.min(1, Number(sepiaLevel)));
noiseStrength = Math.max(0, Math.min(100, Number(noiseStrength))); // Max 100 for noise is quite high
brightnessAdj = Math.max(-255, Math.min(255, Number(brightnessAdj)));
contrastMul = Math.max(0, Math.min(5, Number(contrastMul))); // Contrast factor
vignetteIntensity = Math.max(0, Math.min(1, Number(vignetteIntensity)));
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.naturalWidth;
const height = originalImg.naturalHeight;
canvas.width = width;
canvas.height = height;
// If image is not loaded or has no dimensions, return an empty canvas of correct size (or draw nothing)
if (width === 0 || height === 0) {
// Optionally fill with a placeholder color if desired, or just return
// ctx.fillStyle = 'grey';
// ctx.fillRect(0,0,width,height);
return canvas;
}
ctx.drawImage(originalImg, 0, 0, width, height);
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
const centerX = width / 2;
const centerY = height / 2;
// Max distance from center to a corner, for vignette calculations
const maxDistCorner = (width > 0 && height > 0) ? Math.sqrt(centerX * centerX + centerY * centerY) : 0;
for (let i = 0; i < data.length; i += 4) {
let r_orig = data[i];
let g_orig = data[i + 1];
let b_orig = data[i + 2];
let r = r_orig;
let g = g_orig;
let b = b_orig;
// 1. Apply Sepia
if (sepiaLevel > 0) {
// Standard sepia weights
const sr = (r_orig * 0.393) + (g_orig * 0.769) + (b_orig * 0.189);
const sg = (r_orig * 0.349) + (g_orig * 0.686) + (b_orig * 0.168);
const sb = (r_orig * 0.272) + (g_orig * 0.534) + (b_orig * 0.131);
// Blend original with sepia based on sepiaLevel
r = r_orig * (1 - sepiaLevel) + sr * sepiaLevel;
g = g_orig * (1 - sepiaLevel) + sg * sepiaLevel;
b = b_orig * (1 - sepiaLevel) + sb * sepiaLevel;
}
// 2. Apply Brightness Adjustment
r += brightnessAdj;
g += brightnessAdj;
b += brightnessAdj;
// 3. Apply Contrast Adjustment
// Adjust contrast by stretching/compressing values around midpoint (128)
r = (r - 128) * contrastMul + 128;
g = (g - 128) * contrastMul + 128;
b = (b - 128) * contrastMul + 128;
// Intermediate clamping after tonal adjustments
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. Apply Noise
if (noiseStrength > 0) {
// Generate noise between -noiseStrength and +noiseStrength
const noise = (Math.random() - 0.5) * 2 * noiseStrength;
r += noise;
g += noise;
b += noise;
}
// Clamp again after noise
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. Apply Vignette
if (vignetteIntensity > 0 && maxDistCorner > 0) {
const currentX = (i / 4) % width;
const currentY = Math.floor((i / 4) / width);
const dx = currentX - centerX;
const dy = currentY - centerY;
const dist = Math.sqrt(dx * dx + dy * dy);
// vignetteFactor goes from 1 (center) to (1 - vignetteIntensity) at corners
let vignetteFactor = 1.0 - (dist / maxDistCorner) * vignetteIntensity;
vignetteFactor = Math.max(0, Math.min(1, vignetteFactor)); // Ensure factor is [0, 1]
r *= vignetteFactor;
g *= vignetteFactor;
b *= vignetteFactor;
}
// Final Clamp for all combined effects
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]) remains unchanged
}
ctx.putImageData(imageData, 0, 0);
return canvas;
}
Apply Changes