You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, contrast = 20, desaturation = 0.25, warmTint = 0.2, vignette = 0.3) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.naturalWidth;
const height = originalImg.naturalHeight;
// Ensure width and height are positive to avoid errors with canvas/imageData
if (width <= 0 || height <= 0) {
// Or return a new empty canvas, or throw error
// For now, log error and return an empty canvas of minimal size
console.error("Original image has invalid dimensions.");
canvas.width = 1;
canvas.height = 1;
return canvas;
}
canvas.width = width;
canvas.height = height;
ctx.drawImage(originalImg, 0, 0, width, height);
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
// Convert parameters to numbers, ensuring they are treated correctly
const contrastValue = Number(contrast);
const desaturationLevel = Number(desaturation); // Expected 0 (no desat) to 1 (grayscale)
const warmTintStrength = Number(warmTint); // Expected 0 (no tint) to 1 (strong tint)
const vignetteStrength = Number(vignette); // Expected 0 (no vignette) to 1 (strong vignette)
// Pre-calculate contrast factor, avoid division by zero if contrastValue makes denominator zero
let TruncatedcontrastValue = Math.max(-255, Math.min(255, contrastValue)); // Clamp contrast to prevent issues
const contrastFactor = (259 * (TruncatedcontrastValue + 255)) / (255 * (259 - TruncatedcontrastValue));
const centerX = width / 2;
const centerY = height / 2;
// Max distance from center to a corner, for vignette normalization
const maxDist = Math.sqrt(centerX * centerX + centerY * centerY);
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i+1];
let b = data[i+2];
// 1. Apply Contrast
if (contrastValue !== 0) {
r = contrastFactor * (r - 128) + 128;
g = contrastFactor * (g - 128) + 128;
b = contrastFactor * (b - 128) + 128;
}
// Clamp after contrast. This is important as other filters expect 0-255 range.
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. Apply Desaturation
if (desaturationLevel > 0) {
const gray = 0.299 * r + 0.587 * g + 0.114 * b; // Luminosity method
// Linearly interpolate between original color and grayscale
r = r * (1 - desaturationLevel) + gray * desaturationLevel;
g = g * (1 - desaturationLevel) + gray * desaturationLevel;
b = b * (1 - desaturationLevel) + gray * desaturationLevel;
}
// 3. Apply Subtle Warm Tint
if (warmTintStrength > 0) {
// Multipliers for tinting: increase R&G, decrease B for warmth
// The effect strength is controlled by warmTintStrength (0 to 1)
const rMultiplier = 1 + (0.15 * warmTintStrength); // e.g., warmTint=0.2 -> 1.03
const gMultiplier = 1 + (0.08 * warmTintStrength); // e.g., warmTint=0.2 -> 1.016
const bMultiplier = 1 - (0.10 * warmTintStrength); // e.g., warmTint=0.2 -> 0.98
r *= rMultiplier;
g *= gMultiplier;
b *= bMultiplier;
}
// 4. Apply Vignette
if (vignetteStrength > 0 && maxDist > 0) { // maxDist can be 0 for 1x1 image
const pixelIndex = i / 4;
const x = pixelIndex % width;
const y = Math.floor(pixelIndex / width);
const dx = x - centerX;
const dy = y - centerY;
const dist = Math.sqrt(dx * dx + dy * dy);
// Normalized distance from center (0 at center, 1 at maxDist)
const vignetteAmount = dist / maxDist;
// Vignette factor: 1.0 at center, decreases towards edges.
// Math.pow(vignetteAmount, 1.5) gives a smooth radial gradient.
const currentVignetteFactor = 1.0 - vignetteStrength * Math.pow(vignetteAmount, 1.5);
r *= currentVignetteFactor;
g *= currentVignetteFactor;
b *= currentVignetteFactor;
}
// Clamp final values and assign back to image data
data[i] = Math.max(0, Math.min(255, Math.round(r)));
data[i+1] = Math.max(0, Math.min(255, Math.round(g)));
data[i+2] = Math.max(0, Math.min(255, Math.round(b)));
// Alpha channel (data[i+3]) remains unchanged
}
ctx.putImageData(imageData, 0, 0);
return canvas;
}
Apply Changes