You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, saturationBoost = 70, contrastBoost = 20, tintColor = "rgba(255, 223, 186, 0.15)", vignetteStrength = 0.3) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const imgWidth = originalImg.naturalWidth || originalImg.width;
const imgHeight = originalImg.naturalHeight || originalImg.height;
canvas.width = imgWidth;
canvas.height = imgHeight;
// If the image has no dimensions (e.g., not loaded or invalid), return an empty canvas.
if (imgWidth === 0 || imgHeight === 0) {
console.warn("Original image has zero dimensions. Returning empty canvas.");
return canvas;
}
// Sanitize numeric parameters:
// Coerce to number, if NaN, use the default value from the function signature.
const saneSaturationBoost = Number.isFinite(Number(saturationBoost)) ? Number(saturationBoost) : 70;
const saneContrastBoost = Number.isFinite(Number(contrastBoost)) ? Number(contrastBoost) : 20;
let saneVignetteStrength = Number.isFinite(Number(vignetteStrength)) ? Number(vignetteStrength) : 0.3;
saneVignetteStrength = Math.max(0, Math.min(1, saneVignetteStrength)); // Clamp to [0, 1]
// 1. Construct filter string for saturation, contrast, brightness, and hue rotation
let filterString = "";
// Apply saturation: (100 + boost)% means 170% for boost = 70.
filterString += `saturate(${100 + saneSaturationBoost}%) `;
// Apply contrast: (100 + boost)% means 120% for boost = 20.
filterString += `contrast(${100 + saneContrastBoost}%) `;
// Apply a fixed brightness boost for a "playful" feel
filterString += `brightness(105%) `;
// Apply a fixed subtle hue rotation for "playful" character
filterString += `hue-rotate(5deg) `;
ctx.filter = filterString.trim();
// 2. Draw the image; filters are applied at draw time
ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
// Reset filter before drawing overlay effects (tint, vignette)
ctx.filter = 'none';
// 3. Apply tintColor overlay
// User can pass "" or null to disable tint.
// If tintColor is not a string (e.g. undefined was passed, so default applies), it will be string.
// If null is passed, typeof === 'object'.
if (typeof tintColor === 'string' && tintColor.trim() !== "") {
ctx.fillStyle = tintColor;
ctx.fillRect(0, 0, imgWidth, imgHeight);
} else if (tintColor === null) {
// Explicitly passed null means no tint, do nothing.
}
// 4. Apply vignette
if (saneVignetteStrength > 0) {
const centerX = imgWidth / 2;
const centerY = imgHeight / 2;
// Inner radius of the vignette (fully transparent part).
// Relative to the smaller dimension of the image for better proportions.
const innerRadius = Math.min(imgWidth, imgHeight) * 0.3;
// Outer radius of the vignette (where it reaches maximum darkness).
// Calculated to extend to the corners of the image.
const outerRadius = Math.sqrt(Math.pow(centerX, 2) + Math.pow(centerY, 2));
const gradient = ctx.createRadialGradient(
centerX, centerY, innerRadius, // Inner circle (x, y, radius)
centerX, centerY, outerRadius // Outer circle (x, y, radius)
);
// Vignette fades from transparent center to dark edges
gradient.addColorStop(0, `rgba(0,0,0,0)`); // Transparent at innerRadius
gradient.addColorStop(1, `rgba(0,0,0,${saneVignetteStrength})`); // Max darkness at outerRadius
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, imgWidth, imgHeight);
}
return canvas;
}
Apply Changes