You can edit the below JavaScript code to customize the image tool.
async function processImage(
originalImg,
tintColorStr = "50,150,255", // RGB string for tint, e.g., "R,G,B"
scanlineDarkness = 0.3, // How dark scanlines are (0-1, 0 for none, 1 for black)
scanlineSpacing = 4, // Vertical spacing of scanlines in pixels (e.g., 4 means a line every 4 rows)
glowRadius = 0, // Blur radius for glow effect in pixels (0 to disable glow)
glowIntensity = 0.4 // Opacity of the glow effect (0-1), applied if glowRadius > 0
) {
const canvas = document.createElement('canvas');
// Add { willReadFrequently: true } for potential performance optimization if available/needed.
const ctx = canvas.getContext('2d', { willReadFrequently: true });
const imgWidth = originalImg.naturalWidth || originalImg.width;
const imgHeight = originalImg.naturalHeight || originalImg.height;
// Handle cases where the image might not be loaded or has no dimensions
if (imgWidth === 0 || imgHeight === 0) {
console.warn("Original image has zero width or height. Returning a 1x1 canvas.");
canvas.width = 1;
canvas.height = 1;
// Optionally, you could throw an error or return null
// throw new Error("Image has no dimensions or is not loaded.");
return canvas;
}
canvas.width = imgWidth;
canvas.height = imgHeight;
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
// Get the image data for pixel manipulation
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// Parse and validate tintColorStr
let [parsedR, parsedG, parsedB] = tintColorStr.split(',').map(c => parseInt(c.trim(), 10));
if (isNaN(parsedR) || isNaN(parsedG) || isNaN(parsedB)) {
console.warn(`Invalid tintColorStr: "${tintColorStr}". Using default "50,150,255".`);
[parsedR, parsedG, parsedB] = [50, 150, 255];
}
const tintR = Math.max(0, Math.min(255, parsedR));
const tintG = Math.max(0, Math.min(255, parsedG));
const tintB = Math.max(0, Math.min(255, parsedB));
// Validate and clamp other parameters
const currentScanlineDarkness = Math.max(0, Math.min(1, scanlineDarkness));
const currentScanlineSpacing = Math.max(1, Math.round(scanlineSpacing));
const currentGlowRadius = Math.max(0, glowRadius);
const currentGlowIntensity = Math.max(0, Math.min(1, glowIntensity));
// Iterate over each pixel
for (let y = 0; y < canvas.height; y++) {
for (let x = 0; x < canvas.width; x++) {
const i = (y * canvas.width + x) * 4; // Index for the pixel's R channel
const rOrig = data[i];
const gOrig = data[i + 1];
const bOrig = data[i + 2];
// Alpha data[i + 3] is preserved
// 1. Convert to grayscale
// Using luminosity method: 0.299R + 0.587G + 0.114B
const gray = 0.299 * rOrig + 0.587 * gOrig + 0.114 * bOrig;
// 2. Apply tint
// Modulate the tint color by the grayscale intensity
let tintedR = (gray / 255) * tintR;
let tintedG = (gray / 255) * tintG;
let tintedB = (gray / 255) * tintB;
// 3. Apply scanlines
// Check if the current row 'y' should be a scanline
if (currentScanlineSpacing > 0 && y % currentScanlineSpacing === 0) {
// Darken the pixel for the scanline effect
tintedR *= (1 - currentScanlineDarkness);
tintedG *= (1 - currentScanlineDarkness);
tintedB *= (1 - currentScanlineDarkness);
}
// Assign modified RGB values back to image data
// Uint8ClampedArray automatically clamps values between 0 and 255
data[i] = tintedR;
data[i + 1] = tintedG;
data[i + 2] = tintedB;
}
}
// Put the modified image data back onto the canvas
ctx.putImageData(imageData, 0, 0);
// 4. Apply glow effect (optional)
if (currentGlowRadius > 0 && currentGlowIntensity > 0 && typeof ctx.filter !== 'undefined') {
const glowCanvas = document.createElement('canvas');
glowCanvas.width = canvas.width;
glowCanvas.height = canvas.height;
const glowCtx = glowCanvas.getContext('2d');
// Set the blur filter on the glow context
glowCtx.filter = `blur(${currentGlowRadius}px)`;
// Draw the already processed canvas (with tint and scanlines) onto the glowCanvas.
// The blur filter will be applied during this drawing operation.
glowCtx.drawImage(canvas, 0, 0);
// Reset filter on glowCtx as it's good practice, though not strictly needed here
// as glowCtx is temporary.
glowCtx.filter = 'none';
// Composite the blurred image (glow) back onto the main canvas
ctx.globalCompositeOperation = 'lighter'; // 'screen' or 'lighter' are good for glow
ctx.globalAlpha = currentGlowIntensity; // Control the intensity of the glow
ctx.drawImage(glowCanvas, 0, 0);
// Reset composite operation and alpha on the main context
ctx.globalCompositeOperation = 'source-over';
ctx.globalAlpha = 1.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 Hologram Filter Effect Tool allows users to apply a unique visual effect to their images that simulates a holographic appearance. This tool modifies images by converting them to grayscale, applying a customizable tint, adding scanlines for a retro effect, and can optionally include a glowing effect. Ideal for enhancing digital artwork, creating visually striking social media posts, or adding a creative touch to presentations, this tool caters to artists and non-artists alike looking to create eye-catching visuals.