You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, shadowLength = 100, angleDeg = 45, shadowColorStr = '#000000', shadowOpacity = 0.7) {
// Helper function to parse CSS color string and apply an overall opacity multiplier.
// Returns an RGBA color string e.g. "rgba(255,0,0,0.5)".
function getRgbaColorWithOpacity(colorStr, opacityMultiplier) {
let r = 0, g = 0, b = 0, a = 0;
// Create a temporary DOM element to resolve the input colorStr string to an RGBA value.
const resolverDiv = document.createElement("div");
resolverDiv.style.color = colorStr;
// Element must be in the DOM for getComputedStyle to work reliably.
document.body.appendChild(resolverDiv);
const computedColor = window.getComputedStyle(resolverDiv).color;
document.body.removeChild(resolverDiv);
// Parse the computed color string (which is usually in "rgb(r, g, b)" or "rgba(r, g, b, a)" format).
const match = computedColor.match(/rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\)/);
if (match) {
r = parseInt(match[1]);
g = parseInt(match[2]);
b = parseInt(match[3]);
const alphaFromColor = match[4] !== undefined ? parseFloat(match[4]) : 1;
a = alphaFromColor * opacityMultiplier;
a = Math.max(0, Math.min(1, a)); // Clamp final alpha to [0, 1]
} else {
// Fallback if color parsing fails.
console.warn(`Could not parse shadowColorStr '${colorStr}'. Defaulting to black.`);
r = 0; g = 0; b = 0;
a = opacityMultiplier; // Relies on shadowOpacity being pre-clamped.
}
return `rgba(${r}, ${g}, ${b}, ${a})`;
}
// 0. Parameter Sanitization and Validation
shadowLength = Math.max(0, Number(shadowLength));
angleDeg = Number(angleDeg);
shadowOpacity = Math.max(0, Math.min(1, Number(shadowOpacity)));
if (!originalImg || typeof originalImg.width === 'undefined' || originalImg.width === 0 || originalImg.height === 0) {
console.warn("processImage: Original image is invalid or has zero dimensions.");
const emptyCanvas = document.createElement('canvas');
emptyCanvas.width = 1;
emptyCanvas.height = 1;
return emptyCanvas;
}
// 1. Calculate Shadow and Canvas Geometry
const angleRad = angleDeg * Math.PI / 180;
const dxUnit = Math.cos(angleRad); // Unit vector x for shadow direction
const dyUnit = Math.sin(angleRad); // Unit vector y for shadow direction
const totalShadowOffsetX = dxUnit * shadowLength;
const totalShadowOffsetY = dyUnit * shadowLength;
const canvasWidth = Math.ceil(originalImg.width + Math.abs(totalShadowOffsetX));
const canvasHeight = Math.ceil(originalImg.height + Math.abs(totalShadowOffsetY));
const imageDrawX = (totalShadowOffsetX < 0) ? Math.ceil(Math.abs(totalShadowOffsetX)) : 0;
const imageDrawY = (totalShadowOffsetY < 0) ? Math.ceil(Math.abs(totalShadowOffsetY)) : 0;
const mainCanvas = document.createElement('canvas');
mainCanvas.width = canvasWidth;
mainCanvas.height = canvasHeight;
const ctx = mainCanvas.getContext('2d');
// 2. Determine the final shadow color
const finalShadowRgbaFillStyle = getRgbaColorWithOpacity(shadowColorStr, shadowOpacity);
// 3. Create a Silhouette Canvas
const silhouetteCanvas = document.createElement('canvas');
silhouetteCanvas.width = originalImg.width;
silhouetteCanvas.height = originalImg.height;
const silhouetteCtx = silhouetteCanvas.getContext('2d');
silhouetteCtx.drawImage(originalImg, 0, 0, originalImg.width, originalImg.height);
silhouetteCtx.globalCompositeOperation = 'source-in';
silhouetteCtx.fillStyle = finalShadowRgbaFillStyle;
silhouetteCtx.fillRect(0, 0, originalImg.width, originalImg.height);
// 4. Draw the Shadow Layers on the Main Canvas
// If shadowLength is 0 or the silhouette is fully transparent (due to shadowOpacity or shadowColorStr alpha),
// this loop won't run or drawing the transparent silhouette will have no effect.
if (shadowLength > 0) { // Only attempt to draw shadow if length is positive
// Check if silhouette has any visible pixels. Minor optimization.
// A more robust check would be to check final 'a' in finalShadowRgbaFillStyle
// However, drawing a fully transparent silhouette is a no-op, so it's implicitly handled.
for (let i = 1; i <= shadowLength; i++) {
const currentShadowLayerX = imageDrawX + i * dxUnit;
const currentShadowLayerY = imageDrawY + i * dyUnit;
ctx.drawImage(silhouetteCanvas, currentShadowLayerX, currentShadowLayerY);
}
}
// 5. Draw the Original Image on Top
ctx.globalCompositeOperation = 'source-over';
ctx.drawImage(originalImg, imageDrawX, imageDrawY);
// 6. Return the Main Canvas
return mainCanvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Long Shadow Filter Effect Tool allows users to create a long, stylized shadow effect for images. By specifying parameters such as shadow length, angle, color, and opacity, users can enhance their images with a visually appealing shadow that adds depth and dimension. This tool is ideal for graphic designers, social media marketers, and anyone looking to improve their images for presentations, online posts, or creative projects.