You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, desaturation = 0.8, contrast = 70, redTintFactor = 0.9, greenTintFactor = 1.05, blueTintFactor = 1.15, vignetteStrength = 0.6, grainAmount = 15) {
function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
canvas.width = originalImg.naturalWidth || originalImg.width;
canvas.height = originalImg.naturalHeight || originalImg.height;
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
const width = canvas.width;
const height = canvas.height;
const centerX = width / 2;
const centerY = height / 2;
// Maximum distance from center to any corner
const maxDist = Math.sqrt(Math.pow(centerX, 2) + Math.pow(centerY, 2));
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
// 1. Desaturation
if (desaturation > 0) {
const gray = 0.299 * r + 0.587 * g + 0.114 * b;
r = r * (1 - desaturation) + gray * desaturation;
g = g * (1 - desaturation) + gray * desaturation;
b = b * (1 - desaturation) + gray * desaturation;
}
// 2. Contrast
if (contrast !== 0) {
const contrastFactor = (259 * (contrast + 255)) / (255 * (259 - contrast));
r = contrastFactor * (r - 128) + 128;
g = contrastFactor * (g - 128) + 128;
b = contrastFactor * (b - 128) + 128;
}
// Clamp after desaturation and contrast
r = clamp(r, 0, 255);
g = clamp(g, 0, 255);
b = clamp(b, 0, 255);
// 3. Color Tinting (Metropolis specific)
r *= redTintFactor;
g *= greenTintFactor;
b *= blueTintFactor;
// Clamp after tinting
r = clamp(r, 0, 255);
g = clamp(g, 0, 255);
b = clamp(b, 0, 255);
// 4. Vignetting
if (vignetteStrength > 0 && maxDist > 0) { // maxDist check for 1x1 images
const x = (i / 4) % width;
const y = Math.floor((i / 4) / width);
const dx = x - centerX;
const dy = y - centerY;
const dist = Math.sqrt(dx * dx + dy * dy);
let reduction = (dist / maxDist) * vignetteStrength;
reduction = Math.min(reduction, 1.0); // Ensure reduction doesn't exceed 1
r *= (1 - reduction);
g *= (1 - reduction);
b *= (1 - reduction);
// Clamp after vignette
r = clamp(r, 0, 255);
g = clamp(g, 0, 255);
b = clamp(b, 0, 255);
}
// 5. Film Grain
if (grainAmount > 0) {
const noise = (Math.random() - 0.5) * grainAmount;
r += noise;
g += noise;
b += noise;
// Clamp after grain
r = clamp(r, 0, 255);
g = clamp(g, 0, 255);
b = clamp(b, 0, 255);
}
data[i] = Math.round(r);
data[i + 1] = Math.round(g);
data[i + 2] = Math.round(b);
}
ctx.putImageData(imageData, 0, 0);
return canvas;
}
Apply Changes