You can edit the below JavaScript code to customize the image tool.
function processImage(
originalImg,
scanLineYPercent = 50,
scanLineWidthPx = 40,
scanLineBrightnessFactor = 1.8,
overallTint = "rgba(0, 255, 0, 0.1)",
scanLineCoreColor = "rgba(170, 255, 170, 0.9)", // Light green, high alpha
scanLineCoreHeightPx = 3,
scanLineCoreBlurPx = 10,
glitchIntensity = 4
) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Ensure width and height are from the loaded image
// For HTMLImageElement, naturalWidth/Height are intrinsic, width/height can be styled.
// For Image objects created in JS, width/height are typically the decoded dimensions after load.
const width = originalImg.naturalWidth || originalImg.width;
const height = originalImg.naturalHeight || originalImg.height;
if (width === 0 || height === 0) {
// Handle cases where image might not be fully loaded or is invalid
console.error("Image has zero dimensions. Ensure the image is loaded before processing.");
// Return a minimal canvas or throw an error, based on desired behavior.
canvas.width = 1;
canvas.height = 1;
return canvas;
}
canvas.width = width;
canvas.height = height;
// 1. Draw original image onto the canvas
ctx.drawImage(originalImg, 0, 0, width, height);
// 2. Get image data for pixel manipulation
let sourceImageData;
try {
sourceImageData = ctx.getImageData(0, 0, width, height);
} catch (e) {
// This can happen due to CORS issues if the image is drawn from another domain
// and the canvas becomes tainted, preventing getImageData.
console.error("Could not getImageData (possibly CORS issue with the image source):", e);
// Fallback: return the canvas with just the original image drawn.
// The filter effect requiring pixel access cannot be applied.
return canvas;
}
const outputImageData = ctx.createImageData(width, height);
const sourceData = sourceImageData.data;
const outputData = outputImageData.data;
// Calculate properties for the scan line effect band
const scanLineCenterY = height * (scanLineYPercent / 100);
// Ensure scanEffectHalfWidth is non-negative
const scanEffectHalfWidth = Math.max(0, scanLineWidthPx / 2);
// 3. Pixel manipulation loop: apply brightness changes and glitch effect within the scan band
for (let y = 0; y < height; y++) {
const distanceFromScanCenter = Math.abs(y - scanLineCenterY);
let effectIntensity = 0; // 0 for no effect, 1 for max effect at scan line center
// Calculate effectIntensity only if within the band and the band has a positive width
if (distanceFromScanCenter <= scanEffectHalfWidth && scanEffectHalfWidth > 0) {
// Using a power of 2 for a sharper falloff from the center of the scan line
effectIntensity = Math.pow(1 - (distanceFromScanCenter / scanEffectHalfWidth), 2);
}
let currentPixelBrightnessFactor = 1.0; // Default: no brightness change
let currentGlitchOffsetX = 0; // Default: no horizontal glitch
if (effectIntensity > 0) {
// Apply brightness factor based on proximity to scan line center
currentPixelBrightnessFactor = 1 + (scanLineBrightnessFactor - 1) * effectIntensity;
// Apply glitch if intensity is positive
if (glitchIntensity > 0) {
// Random horizontal offset for glitch, scaled by effectIntensity and glitchIntensity parameter
currentGlitchOffsetX = Math.round((Math.random() - 0.5) * 2 * glitchIntensity * effectIntensity);
}
}
for (let x = 0; x < width; x++) {
const destIdx = (y * width + x) * 4; // Index for the current pixel in the 1D outputData array
// Determine source pixel x-coordinate for glitching, clamping to image bounds
const srcX = Math.max(0, Math.min(width - 1, x - currentGlitchOffsetX));
const srcIdx = (y * width + srcX) * 4; // Index for source pixel in 1D sourceData array
// Get RGBA components from the (possibly glitched) source pixel
const r = sourceData[srcIdx + 0];
const g = sourceData[srcIdx + 1];
const b = sourceData[srcIdx + 2];
const a = sourceData[srcIdx + 3];
// Apply brightness modification and write to outputData
outputData[destIdx + 0] = Math.min(255, r * currentPixelBrightnessFactor); // Red
outputData[destIdx + 1] = Math.min(255, g * currentPixelBrightnessFactor); // Green
outputData[destIdx + 2] = Math.min(255, b * currentPixelBrightnessFactor); // Blue
outputData[destIdx + 3] = a; // Preserve original alpha
}
}
// 4. Put the modified image data (with scan band effects) back onto the canvas
ctx.putImageData(outputImageData, 0, 0);
// 5. Apply overall tint layer if specified (and not fully transparent)
// This tint is applied on top of the pixel-processed image.
if (overallTint && overallTint !== "rgba(0,0,0,0)" && overallTint !== "transparent") {
ctx.fillStyle = overallTint;
ctx.fillRect(0, 0, width, height); // Uses default 'source-over' globalCompositeOperation
}
// 6. Draw the bright core scan line on top of everything
// This line is drawn if its height parameter is positive.
if (scanLineCoreHeightPx > 0) {
// Calculate actual Y position of the line's center
const coreLineActualY = height * (scanLineYPercent / 100);
ctx.lineCap = 'butt'; // Style for line endings ('butt', 'round', 'square')
ctx.strokeStyle = scanLineCoreColor;
ctx.lineWidth = scanLineCoreHeightPx;
// Apply a glow effect using shadow if blur radius is positive
if (scanLineCoreBlurPx > 0) {
ctx.shadowColor = scanLineCoreColor; // Shadow color can be the same as the line or different
ctx.shadowBlur = scanLineCoreBlurPx;
}
// Draw the horizontal line
ctx.beginPath();
ctx.moveTo(0, coreLineActualY);
ctx.lineTo(width, coreLineActualY);
ctx.stroke();
// Reset shadow properties to avoid affecting subsequent drawing operations on this context
ctx.shadowColor = 'transparent'; // Or a specific non-shadow color like 'rgba(0,0,0,0)'
ctx.shadowBlur = 0;
ctx.lineCap = 'butt'; // Reset to default if necessary
}
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 Retina Scan Filter Effect Tool allows users to apply a unique scan line effect to images, simulating a futuristic scanning or glitch effect. Users can customize various parameters such as the position and width of the scan line, brightness adjustments, and overall tint. This tool is useful for enhancing visual materials in digital art, creating stylized effects for graphic design, or adding a distinct aesthetic to images for presentations and social media content.