You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, darknessLevel = 0.7, coolTintStrength = 0.5, vignetteStrength = 0.7, contrastFactor = 1.3) {
const canvas = document.createElement('canvas');
// Add { willReadFrequently: true } for potential performance optimization if available/supported
const ctx = canvas.getContext('2d', { willReadFrequently: true });
const imgWidth = originalImg.naturalWidth || originalImg.width || 0;
const imgHeight = originalImg.naturalHeight || originalImg.height || 0;
canvas.width = imgWidth;
canvas.height = imgHeight;
if (imgWidth === 0 || imgHeight === 0) {
console.warn("Image has zero width or height. Returning an empty canvas.");
return canvas; // Returns an empty canvas
}
try {
ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
} catch (e) {
console.error("Error drawing image to canvas:", e);
// Return a new empty canvas if drawing the original image fails
const emptyCanvas = document.createElement('canvas');
emptyCanvas.width = imgWidth; // Attempt to keep size, might be 0x0
emptyCanvas.height = imgHeight;
return emptyCanvas;
}
let imageData;
try {
imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
} catch (e) {
console.error("Error getting ImageData (e.g., canvas tainted by cross-origin image). Returning canvas with original image.", e);
// The canvas currently has the original image drawn on it.
// Returning it as-is means returning the original image rendered on a canvas, without the filter.
return canvas;
}
const data = imageData.data;
const width = imgWidth; // Use consistent variable names
const height = imgHeight;
const centerX = width / 2;
const centerY = height / 2;
// maxDist is the distance from the center to a corner.
// This will be > 0 if width or height > 0.
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. Base Darkening (0.0 = no change, 1.0 = black)
// Make sure darknessLevel is clamped between 0 and 1
const effectiveDarkness = Math.max(0, Math.min(1, darknessLevel));
let rDark = r * (1 - effectiveDarkness);
let gDark = g * (1 - effectiveDarkness);
let bDark = b * (1 - effectiveDarkness);
// 2. Cool Tint (0.0 = no tint, 1.0 = strong tint)
// Make sure coolTintStrength is clamped between 0 and 1
const effectiveCoolTint = Math.max(0, Math.min(1, coolTintStrength));
let rTinted = rDark * (1 - effectiveCoolTint * 0.6); // Reduce red more significantly
let gTinted = gDark * (1 - effectiveCoolTint * 0.3); // Reduce green less
let bTinted = bDark * (1 + effectiveCoolTint * 0.1); // Slightly boost blue
bTinted = Math.min(255, bTinted); // Cap blue boost
r = rTinted;
g = gTinted;
b = bTinted;
// 3. Vignette (0.0 = no vignette, 1.0 = edges are black)
// Make sure vignetteStrength is clamped between 0 and 1
const effectiveVignette = Math.max(0, Math.min(1, vignetteStrength));
if (effectiveVignette > 0 && maxDist > 0) { // Only apply if strength > 0 and image has dimensions
const x = (i / 4) % width;
const y = Math.floor((i / 4) / width);
const dist = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
const normalizedDist = dist / maxDist;
// vignetteAmount is a multiplier from (1 - vignetteStrength) at edge to 1 at center.
// Using a power of 2 for smoother falloff.
let vignetteAmount = 1.0 - (effectiveVignette * Math.pow(normalizedDist, 2.0));
vignetteAmount = Math.max(0, vignetteAmount); // Clamp to prevent negative values
r *= vignetteAmount;
g *= vignetteAmount;
b *= vignetteAmount;
}
// 4. Contrast (1.0 = no change)
// Ensure contrastFactor is not negative.
const effectiveContrast = Math.max(0, contrastFactor);
const midpoint = 128; // Midpoint for contrast calculation (0-255 range)
r = effectiveContrast * (r - midpoint) + midpoint;
g = effectiveContrast * (g - midpoint) + midpoint;
b = effectiveContrast * (b - midpoint) + midpoint;
// Clamp final values to [0, 255]
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