You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, outerFillColor = 'black', rimColor = 'darkgray', rimThickness = 5, showCrosshairsStr = 'true', crosshairColor = 'rgba(0, 255, 0, 0.7)', crosshairThickness = 2) {
const canvas = document.createElement('canvas');
// Use naturalWidth/Height for intrinsic image dimensions, fallback to width/height.
canvas.width = originalImg.naturalWidth || originalImg.width;
canvas.height = originalImg.naturalHeight || originalImg.height;
// If image dimensions are zero (e.g., image not loaded or invalid),
// return the canvas (it will be 0x0 or have one dimension as 0).
if (canvas.width === 0 || canvas.height === 0) {
// console.warn("Image Periscope View Filter: Input image has zero dimensions.");
return canvas;
}
const ctx = canvas.getContext('2d');
// Convert string parameter for showing crosshairs to boolean
const showCrosshairs = showCrosshairsStr.toString().toLowerCase() === 'true';
const cx = canvas.width / 2;
const cy = canvas.height / 2;
// viewRadius is the radius of the circular visible area of the image.
// It's constrained by the smaller dimension of the canvas.
const viewRadius = Math.min(cx, cy);
// If viewRadius is zero or negative (e.g., for a 1xN or Nx1 image, or issues with dimensions),
// it's not possible to draw a meaningful circular view.
if (viewRadius <= 0) {
// Fill with outer color and return. The canvas might show just this color.
ctx.fillStyle = outerFillColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
return canvas;
}
// Step 1: Fill the entire canvas with outerFillColor.
// This color forms the background visible outside the periscope's circular view.
ctx.fillStyle = outerFillColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Step 2: Draw the image within a circular clip.
ctx.save(); // Save context state before applying clipping
ctx.beginPath();
ctx.arc(cx, cy, viewRadius, 0, Math.PI * 2); // Define the circular path for the view
ctx.closePath();
ctx.clip(); // Apply the circular path as the clipping region
// Draw the original image. It will only be visible inside the circular clipped area.
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
ctx.restore(); // Restore context state to remove clipping, so rim/crosshairs draw normally.
// Step 3: Draw the periscope rim (the border of the circular view).
// The rim is drawn such that its outer edge aligns with viewRadius.
if (rimThickness > 0) {
// The centerline of the rim's stroke is calculated to position the rim correctly.
// It's (viewRadius - rimThickness / 2), so the stroke (of rimThickness)
// extends from (viewRadius - rimThickness) [inner edge] to viewRadius [outer edge].
const rimArcRadius = viewRadius - (rimThickness / 2);
if (rimArcRadius > 0) { // Ensure the radius for the arc stroke is positive
ctx.strokeStyle = rimColor;
ctx.lineWidth = rimThickness;
ctx.beginPath();
ctx.arc(cx, cy, rimArcRadius, 0, Math.PI * 2);
ctx.stroke();
}
// If rimArcRadius is not positive (i.e., rim is too thick for the viewRadius),
// the rim is not drawn to prevent errors or an undesirable full fill.
}
// Step 4: Draw crosshairs if enabled.
if (showCrosshairs && crosshairThickness > 0) {
// crosshairExtentRadius is the length of each arm of the crosshair from the center.
// It should not go beyond the inner edge of the rim.
const actualRimThickness = Math.max(0, rimThickness); // Sanitize rimThickness (ensure non-negative)
const crosshairExtentRadius = Math.max(0, viewRadius - actualRimThickness);
if (crosshairExtentRadius > 0) { // Only draw if there's space for crosshairs
ctx.strokeStyle = crosshairColor;
ctx.lineWidth = crosshairThickness;
ctx.beginPath();
// Vertical line
ctx.moveTo(cx, cy - crosshairExtentRadius);
ctx.lineTo(cx, cy + crosshairExtentRadius);
// Horizontal line
ctx.moveTo(cx - crosshairExtentRadius, cy);
ctx.lineTo(cx + crosshairExtentRadius, cy);
ctx.stroke();
// Small central dot for the crosshairs
// Dot size is scaled with crosshairThickness and crosshairExtentRadius,
// with a minimum size of 1px radius and a maximum cap (e.g., 5px radius).
const dotRadius = Math.max(1, Math.min(crosshairThickness * 1.5, crosshairExtentRadius * 0.05, 5));
// Ensure the dot is meaningfully smaller than the crosshair lines and actually fits.
if (dotRadius > 0 && dotRadius < crosshairExtentRadius / 2) {
const originalFillStyle = ctx.fillStyle; // Save current fill style
ctx.fillStyle = crosshairColor; // Use crosshair color for the dot
ctx.beginPath();
ctx.arc(cx, cy, dotRadius, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = originalFillStyle; // Restore original fill style
}
}
}
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 Periscope View Filter Effect Tool allows users to apply a unique circular view effect to their images, resembling the view through a periscope. This tool enables customization by letting users set colors for the outer background and the rim of the circular view, as well as adjust the thickness of the rim. Additionally, users can opt to include crosshairs inside the circular view, which can enhance visibility and focus on specific areas of the image. This tool is ideal for creating visually interesting effects for images in graphic design, presentations, or social media posts.