You can edit the below JavaScript code to customize the image tool.
/**
* Applies a shadow puppet filter effect to an image.
*
* @param {HTMLImageElement} originalImg - The original HTMLImageElement. Assumed to be fully loaded.
* @param {number} [brightnessThreshold=128] - Brightness value (0-255) to decide if a pixel becomes shadow or background.
* Pixels with luminance less than this threshold become shadow.
* @param {string} [shadowColorStr="black"] - CSS color string for the shadow/puppet.
* @param {string} [backgroundColorStr="lightyellow"] - CSS color string for the background/screen.
* @param {number} [alphaCutoff=10] - Alpha value (0-255). Pixels in the original image with alpha less than this
* will be unconditionally treated as background. This helps handle images
* with existing transparency.
* @returns {HTMLCanvasElement} A new canvas element with the shadow puppet effect applied.
*/
function processImage(originalImg, brightnessThreshold = 128, shadowColorStr = "black", backgroundColorStr = "lightyellow", alphaCutoff = 10) {
const canvas = document.createElement('canvas');
// Use { willReadFrequently: true } for potential performance optimization if supported/needed.
const ctx = canvas.getContext('2d', { willReadFrequently: true });
// Use naturalWidth/Height for intrinsic dimensions, fallback to width/height
canvas.width = originalImg.naturalWidth || originalImg.width;
canvas.height = originalImg.naturalHeight || originalImg.height;
// Helper function to parse a CSS color string (e.g., "red", "#FF0000", "rgba(255,0,0,0.5)")
// into an RGBA object {r, g, b, a}.
function parseColorToRGBA(colorStr) {
const tempCanvas = document.createElement('canvas');
tempCanvas.width = 1;
tempCanvas.height = 1;
const tempCtx = tempCanvas.getContext('2d');
tempCtx.fillStyle = colorStr; // Assigning the color string
tempCtx.fillRect(0, 0, 1, 1); // Drawing a 1x1 pixel rectangle filled with this color
// Reading the pixel data of this 1x1 rectangle
const imageData = tempCtx.getImageData(0, 0, 1, 1).data;
return { r: imageData[0], g: imageData[1], b: imageData[2], a: imageData[3] };
}
const shadowRGB = parseColorToRGBA(shadowColorStr);
const backgroundRGB = parseColorToRGBA(backgroundColorStr);
// Draw the original image onto the main canvas
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// This can happen if the image is from a different origin and the canvas becomes tainted.
console.error("Error getting ImageData: ", e);
// Fallback: return a canvas indicating an error.
ctx.fillStyle = "rgba(128, 128, 128, 0.5)"; // Grey background
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (canvas.width > 100 && canvas.height > 30) { // Simple check if canvas is large enough for text
ctx.fillStyle = "black";
ctx.font = "16px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText("Error processing image", canvas.width / 2, canvas.height / 2);
}
return canvas;
}
const data = imageData.data; // Pixel data array: [R, G, B, A, R, G, B, A, ...]
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const originalAlpha = data[i + 3];
// If the original pixel's alpha is below the cutoff, treat it as fully transparent
// part of the original image, which should become background screen.
if (originalAlpha < alphaCutoff) {
data[i] = backgroundRGB.r;
data[i + 1] = backgroundRGB.g;
data[i + 2] = backgroundRGB.b;
data[i + 3] = backgroundRGB.a; // Use alpha from parsed background color
} else {
// For other pixels, decide based on their luminance (brightness).
// Standard luminance calculation:
const grayscale = 0.299 * r + 0.587 * g + 0.114 * b;
if (grayscale < brightnessThreshold) {
// Pixel is darker than the threshold: it becomes part of the shadow.
data[i] = shadowRGB.r;
data[i + 1] = shadowRGB.g;
data[i + 2] = shadowRGB.b;
data[i + 3] = shadowRGB.a; // Use alpha from parsed shadow color
} else {
// Pixel is lighter than or equal to the threshold: it becomes part of the background.
data[i] = backgroundRGB.r;
data[i + 1] = backgroundRGB.g;
data[i + 2] = backgroundRGB.b;
data[i + 3] = backgroundRGB.a; // Use alpha from parsed background color
}
}
}
// Put the modified pixel data back onto the canvas
ctx.putImageData(imageData, 0, 0);
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 Shadow Puppet Filter Effect Creator is an online tool that allows users to apply a shadow puppet effect to their images. Using customizable settings for brightness threshold, shadow color, and background color, this tool transforms images into playful shadow-like visuals. It is useful for creative projects, enhancing artistic designs, making unique graphics for presentations, or simply for fun exploration of image effects. Users can easily generate visually striking images that can be used in digital art, social media, and more.