You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, focusPosition = 0.5, focusRange = 0.2, blurAmount = 5, gradientType = "linear", angle = 0, saturation = 1.2, contrast = 1.1, transitionWidth = 0.15) {
const width = originalImg.naturalWidth || originalImg.width;
const height = originalImg.naturalHeight || originalImg.height;
// Ensure parameters are numbers
focusPosition = Number(focusPosition);
focusRange = Number(focusRange);
blurAmount = Number(blurAmount);
angle = Number(angle);
saturation = Number(saturation);
contrast = Number(contrast);
transitionWidth = Number(transitionWidth);
// 1. Create sharpImageCanvas (with saturation/contrast)
// This canvas will hold the original image modified by saturation and contrast.
const sharpCanvas = document.createElement('canvas');
sharpCanvas.width = width;
sharpCanvas.height = height;
const sharpCtx = sharpCanvas.getContext('2d');
let sharpFilterString = '';
if (saturation !== 1) sharpFilterString += `saturate(${saturation}) `;
if (contrast !== 1) sharpFilterString += `contrast(${contrast})`;
if (sharpFilterString) sharpCtx.filter = sharpFilterString.trim();
sharpCtx.drawImage(originalImg, 0, 0, width, height);
sharpCtx.filter = 'none'; // Reset filter
// 2. Create blurredImageCanvas
// This canvas will hold the version of the image that is blurred, saturated, and contrasted.
const blurCanvas = document.createElement('canvas');
blurCanvas.width = width;
blurCanvas.height = height;
const blurCtx = blurCanvas.getContext('2d');
if (blurAmount > 0) {
let blurFilterString = `blur(${blurAmount}px) `;
if (saturation !== 1) blurFilterString += `saturate(${saturation}) `;
if (contrast !== 1) blurFilterString += `contrast(${contrast})`;
blurCtx.filter = blurFilterString.trim();
blurCtx.drawImage(originalImg, 0, 0, width, height); // Draw original, filters apply
blurCtx.filter = 'none'; // Reset filter
} else {
// If no blur, the "blurred" version is just the sharp (saturated/contrasted) version.
blurCtx.drawImage(sharpCanvas, 0, 0, width, height);
}
// 3. Create alphaMaskCanvas
// This canvas defines which parts of the image are sharp (white regions of mask) and blurred (black regions of mask).
const alphaMaskCanvas = document.createElement('canvas');
alphaMaskCanvas.width = width;
alphaMaskCanvas.height = height;
const maskCtx = alphaMaskCanvas.getContext('2d');
// Clamp relative parameters to [0,1] range
focusPosition = Math.max(0, Math.min(1, focusPosition));
focusRange = Math.max(0, Math.min(1, focusRange));
transitionWidth = Math.max(0, Math.min(1, transitionWidth));
if (gradientType === "linear") {
const tempMaskLinearCanvas = document.createElement('canvas');
tempMaskLinearCanvas.width = width;
tempMaskLinearCanvas.height = height;
const tempMaskLinearCtx = tempMaskLinearCanvas.getContext('2d');
tempMaskLinearCtx.translate(width / 2, height / 2);
tempMaskLinearCtx.rotate(angle * Math.PI / 180);
tempMaskLinearCtx.translate(-width / 2, -height / 2);
const grad = tempMaskLinearCtx.createLinearGradient(0, 0, 0, height); // Gradient along Y-axis of rotated context
const pSharpStart = focusPosition - focusRange / 2;
const pSharpEnd = focusPosition + focusRange / 2;
const pTransStartLead = pSharpStart - transitionWidth;
const pTransEndTrail = pSharpEnd + transitionWidth;
grad.addColorStop(0, 'black'); // Ensure start is blurred
grad.addColorStop(Math.max(0, Math.min(1, pTransStartLead)), 'black');
grad.addColorStop(Math.max(0, Math.min(1, pSharpStart)), 'white');
grad.addColorStop(Math.max(0, Math.min(1, pSharpEnd)), 'white');
grad.addColorStop(Math.max(0, Math.min(1, pTransEndTrail)), 'black');
grad.addColorStop(1, 'black'); // Ensure end is blurred
tempMaskLinearCtx.fillStyle = grad;
tempMaskLinearCtx.fillRect(0, 0, width, height);
maskCtx.drawImage(tempMaskLinearCanvas, 0, 0);
} else if (gradientType === "radial") {
const centerX = width / 2;
const centerY = height / 2;
const baseDim = Math.min(width, height);
const sharpRadiusPx = baseDim * focusRange / 2;
const transitionSizePx = baseDim * transitionWidth;
const blurEndRadiusPx = sharpRadiusPx + transitionSizePx;
if (focusRange === 0 && transitionWidth === 0) { // No focus effect defined, all sharp
maskCtx.fillStyle = 'white';
maskCtx.fillRect(0, 0, width, height);
} else if (blurEndRadiusPx <= 0 && sharpRadiusPx <= 0) { // Effectively no focus or transition specified towards positive radius
maskCtx.fillStyle = 'black'; // Make all blurred if radii are non-positive and not the specific "all_sharp" case
maskCtx.fillRect(0, 0, width, height);
}
else {
const grad = maskCtx.createRadialGradient(centerX, centerY, 0, centerX, centerY, Math.max(0.001, blurEndRadiusPx)); // blurEndRadiusPx must be > 0
let stopSharpNormalized = 0;
if (blurEndRadiusPx > 0) { // Avoid division by zero if blurEndRadiusPx is 0
stopSharpNormalized = Math.max(0, Math.min(1, sharpRadiusPx / blurEndRadiusPx));
} else if (sharpRadiusPx > 0) { // all sharp circle, no transition
stopSharpNormalized = 1; // effectively make it all white up to sharpRadiusPx
}
grad.addColorStop(0, 'white');
grad.addColorStop(stopSharpNormalized, 'white');
grad.addColorStop(1, 'black');
maskCtx.fillStyle = grad;
maskCtx.fillRect(0, 0, width, height);
}
} else {
// Default: unknown gradientType, make mask all white (fully sharp)
maskCtx.fillStyle = 'white';
maskCtx.fillRect(0, 0, width, height);
}
// 4. Create final outputCanvas and combine layers
const outputCanvas = document.createElement('canvas');
outputCanvas.width = width;
outputCanvas.height = height;
const outputCtx = outputCanvas.getContext('2d');
outputCtx.drawImage(blurCanvas, 0, 0, width, height); // Draw blurred (or just sat/con) as base
const tempSharpMaskedCanvas = document.createElement('canvas');
tempSharpMaskedCanvas.width = width;
tempSharpMaskedCanvas.height = height;
const tempSharpMaskedCtx = tempSharpMaskedCanvas.getContext('2d');
tempSharpMaskedCtx.drawImage(sharpCanvas, 0, 0, width, height); // sharp (sat/con) image
tempSharpMaskedCtx.globalCompositeOperation = 'destination-in'; // Apply mask
tempSharpMaskedCtx.drawImage(alphaMaskCanvas, 0, 0, width, height); // Mask (white=keep, black=discard)
outputCtx.drawImage(tempSharpMaskedCanvas, 0, 0, width, height); // Draw masked sharp parts over base
return outputCanvas;
}
Apply Changes