You can edit the below JavaScript code to customize the image tool.
async function processImage(originalImg,
circleSizeFactorStr = "0.8",
vignetteSoftnessStr = "0.5",
vignetteOpacityStr = "0.9",
crosshairColorStr = "rgba(80,200,80,0.6)", // A slightly brighter, translucent green
drawCrosshairsStr = "false",
crosshairThicknessStr = "2") {
// 1. Parameter parsing and validation
let circleSizeFactor = parseFloat(circleSizeFactorStr);
if (isNaN(circleSizeFactor) || circleSizeFactor < 0 || circleSizeFactor > 1) {
circleSizeFactor = 0.8;
}
let vignetteSoftness = parseFloat(vignetteSoftnessStr);
if (isNaN(vignetteSoftness) || vignetteSoftness < 0 || vignetteSoftness > 1) {
vignetteSoftness = 0.5;
}
let vignetteOpacity = parseFloat(vignetteOpacityStr);
if (isNaN(vignetteOpacity) || vignetteOpacity < 0 || vignetteOpacity > 1) {
vignetteOpacity = 0.9;
}
const crosshairColor = crosshairColorStr; // Already a string, validation usually not needed for CSS colors
const drawCrosshairs = drawCrosshairsStr.toLowerCase() === 'true';
let crosshairThickness = parseInt(crosshairThicknessStr, 10);
if (isNaN(crosshairThickness) || crosshairThickness <= 0) {
crosshairThickness = 2;
}
// 2. Canvas Setup
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const imgWidth = originalImg.naturalWidth;
const imgHeight = originalImg.naturalHeight;
// Handle unloaded or zero-size image gracefully
if (imgWidth === 0 || imgHeight === 0) {
canvas.width = 1; // Avoid 0-size canvas issues
canvas.height = 1;
// Optionally, fill with a default color or leave transparent
// ctx.fillStyle = 'grey'; ctx.fillRect(0,0,1,1);
return canvas;
}
canvas.width = imgWidth;
canvas.height = imgHeight;
// 3. Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
// 4. Calculate vignette parameters
const centerX = imgWidth / 2;
const centerY = imgHeight / 2;
// maxRadius is the radius of the largest circle that fits within the image bounds
const maxRadius = Math.min(centerX, centerY);
// Apply vignette if opacity is greater than 0 and there's a drawable area
if (vignetteOpacity > 0 && maxRadius > 0) {
// r0: Radius where the perfectly clear area (defined by circleSizeFactor) ends
// and the vignette effect begins to appear.
const r0 = maxRadius * circleSizeFactor;
// r1: Radius where the vignette reaches its full target opacity.
// This is determined by vignetteSoftness:
// - vignetteSoftness = 0: r1 is very close to r0 (results in a sharp transition).
// - vignetteSoftness = 1: r1 is maxRadius (results in the softest transition, fading to image edge).
// The term (maxRadius - r0) represents the available distance over which the gradient can transition.
let r1 = r0 + (maxRadius - r0) * vignetteSoftness;
// Ensure r1 is strictly greater than r0 for the radial gradient to work as documented.
// A minimal difference (e.g., 0.1 pixels) is sufficient if r0 and r1 would otherwise be equal.
// This case occurs if:
// - circleSizeFactor is 1 (r0 = maxRadius), making (maxRadius - r0) = 0, so r1_calculated = r0.
// - vignetteSoftness is 0, making (maxRadius - r0) * vignetteSoftness = 0, so r1_calculated = r0.
if (r1 <= r0) {
// If r0 itself is maxRadius (e.g., circleSizeFactor=1), r1 will become maxRadius + 0.1.
// This means the 'clear' color stop is at maxRadius, and full vignette opacity is reached
// just outside maxRadius. Effectively, the view within maxRadius remains clear.
r1 = r0 + 0.1;
}
const gradient = ctx.createRadialGradient(centerX, centerY, r0, centerX, centerY, r1);
// Color stop 0: At radius r0 (end of clear area), the overlay is fully transparent.
gradient.addColorStop(0, 'rgba(0,0,0,0)');
// Color stop 1: At radius r1, the overlay reaches its full target vignetteOpacity.
gradient.addColorStop(1, `rgba(0,0,0,${vignetteOpacity})`);
// How gradient colors are applied by fillRect:
// - For radii < r0: color of stop 0 (transparent).
// - For radii > r1: color of stop 1 (full vignette opacity).
// - For radii between r0 and r1: color is interpolated.
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, imgWidth, imgHeight); // Apply vignette overlay
}
// 5. Draw crosshairs if enabled
if (drawCrosshairs && maxRadius > 0) {
ctx.strokeStyle = crosshairColor;
ctx.lineWidth = crosshairThickness;
ctx.beginPath();
// Crosshairs extent can be based on the clear circle size (r0) or the full view (maxRadius).
// Using r0 ties the crosshair size to the primary clear viewing area.
const crosshairExtent = maxRadius * circleSizeFactor;
// Only draw crosshairs if they have a non-zero extent.
if (crosshairExtent > 0) {
// Horizontal line
ctx.moveTo(centerX - crosshairExtent, centerY);
ctx.lineTo(centerX + crosshairExtent, centerY);
// Vertical line
ctx.moveTo(centerX, centerY - crosshairExtent);
ctx.lineTo(centerX, centerY + crosshairExtent);
ctx.stroke();
}
}
// 6. Return the processed canvas
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 Microscope View Filter Application allows users to enhance their images by applying a microscope-style filter. Users can adjust parameters such as the size of the central clear area, the softness and opacity of a vignette effect, and the appearance of crosshairs for precise viewing. This tool is useful for educational purposes, presentations, scientific analysis, and anywhere detailed examination of images is required, enabling users to focus on specific areas of interest while subtly dimming the surrounding fields.