You can edit the below JavaScript code to customize the image tool.
async function processImage(originalImg, strength = 0.7, innerRadiusPercent = 0.1, outerRadiusPercent = 0.6) {
// Clamp and validate parameters
strength = Math.max(0, Math.min(1, strength));
innerRadiusPercent = Math.max(0, Math.min(1, innerRadiusPercent));
outerRadiusPercent = Math.max(0, Math.min(1, outerRadiusPercent));
// The filter is centered on the image
const centerXPercent = 0.5;
const centerYPercent = 0.5;
// Ensure outerRadiusPercent is not smaller than innerRadiusPercent. If so, swap them.
// This makes the order of inner/outer radius input flexible.
if (outerRadiusPercent < innerRadiusPercent) {
[innerRadiusPercent, outerRadiusPercent] = [outerRadiusPercent, innerRadiusPercent];
}
// Now, innerRadiusPercent <= outerRadiusPercent is guaranteed.
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const width = originalImg.naturalWidth;
const height = originalImg.naturalHeight;
canvas.width = width;
canvas.height = height;
// 1. Draw the original image
// This needs to be done early, as it's the base.
if (width > 0 && height > 0) {
ctx.drawImage(originalImg, 0, 0, width, height);
}
// If image dimensions are zero or strength is zero, no filter effect is applied.
// The canvas (empty or with original image) is returned.
if (width === 0 || height === 0 || strength === 0) {
return canvas;
}
// 2. Calculate gradient parameters in pixels
const actualCenterX = centerXPercent * width;
const actualCenterY = centerYPercent * height;
// Calculate the distance from the center to the furthest corner.
// This distance defines the maximum extent for radial percentages.
const corners = [
{ x: 0, y: 0 }, { x: width, y: 0 },
{ x: 0, y: height }, { x: width, y: height }
];
let maxDistanceToCorner = 0;
const center = { x: actualCenterX, y: actualCenterY };
for (const corner of corners) {
const dist = Math.sqrt(Math.pow(center.x - corner.x, 2) + Math.pow(center.y - corner.y, 2));
if (dist > maxDistanceToCorner) {
maxDistanceToCorner = dist;
}
}
// If maxDistanceToCorner is 0 (e.g. for a 0x0 image, though handled earlier, or a 1x1 image with center exactly at that pixel,
// making all corner distances 0 if calculation was integer-based, but with float it's okay for 1x1),
// radii will be 0. This is fine, but createRadialGradient needs r1 > r0.
// For a 1x1 image, naturalWidth=1, naturalHeight=1. actualCenterX=0.5, actualCenterY=0.5.
// maxDistanceToCorner = sqrt(0.5^2 + 0.5^2) = sqrt(0.5) ~= 0.707. It's non-zero.
let actualInnerRadius = innerRadiusPercent * maxDistanceToCorner;
let actualOuterRadius = outerRadiusPercent * maxDistanceToCorner;
// For createRadialGradient, r0 and r1 must be non-negative, and r1 must be strictly greater than r0.
// Our percentages (0-1) and maxDistanceToCorner (>=0) ensure radii are non-negative.
if (actualOuterRadius <= actualInnerRadius) {
// This handles cases where innerRadiusPercent === outerRadiusPercent,
// or if maxDistanceToCorner is so small that floating point precision makes them equal.
// Add a small epsilon (e.g., 0.1 pixels) to ensure outerRadius is strictly larger.
// This results in a very sharp transition if percentages were equal.
actualOuterRadius = actualInnerRadius + 0.1;
}
// If both radii are 0 (maxDistanceToCorner was 0), actualInnerRadius will be 0, actualOuterRadius 0.1.
// This is valid for createRadialGradient.
// 3. Create and apply the radial gradient overlay
const gradient = ctx.createRadialGradient(
actualCenterX, actualCenterY, actualInnerRadius,
actualCenterX, actualCenterY, actualOuterRadius
);
// The gradient transitions from fully transparent black at the inner radius (center of effect)
// to semi-transparent black (opacity defined by 'strength') at the outer radius.
gradient.addColorStop(0, 'rgba(0,0,0,0)');
gradient.addColorStop(1, `rgba(0,0,0,${strength})`);
ctx.fillStyle = gradient;
// Fill the entire canvas with this gradient. It will be drawn on top of the original image.
ctx.fillRect(0, 0, width, height);
return canvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Center Graduated ND Filter Effect Tool allows users to apply a graduated neutral density filter effect to their images. This tool is particularly useful for photographers and graphic designers looking to enhance their images by reducing the brightness of specific areas, especially for landscapes and skies. Users can customize the strength of the filter effect and define the radii of the gradient, allowing for flexible adjustments to achieve the desired look. This can help in creating more balanced exposures in images where there are significant differences in brightness between the foreground and background.