You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, intensity = 20, slices = 10, channelShiftMaxOffset = 5) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const w = originalImg.naturalWidth;
const h = originalImg.naturalHeight;
canvas.width = w;
canvas.height = h;
// If the image has no dimensions (e.g., not loaded or 0x0), return an empty canvas.
if (w === 0 || h === 0) {
return canvas;
}
// Helper function for random integers (inclusive)
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Draw original image onto the canvas
ctx.drawImage(originalImg, 0, 0, w, h);
// Normalize intensity to a factor between 0 and 1
const glitchFactor = Math.max(0, Math.min(1, intensity / 100));
// If intensity is 0, no glitch effects are applied.
// The canvas already has the original image drawn.
if (glitchFactor === 0) {
return canvas;
}
// --- 1. Slicing and Shifting Effect ---
// Number of slices increases with intensity and the 'slices' parameter.
const numSlices = Math.floor(slices * glitchFactor * 1.5);
for (let i = 0; i < numSlices; i++) {
const startY = Math.random() * h; // Random Y position to start the slice
// Slice height: 1px to 10% of image height, scaled by (0.5 + glitchFactor)
// This means higher intensity can lead to larger slice heights.
let sliceHeight = Math.max(1, Math.random() * (h * 0.1) * (0.5 + glitchFactor));
// Adjust sliceHeight if it goes beyond canvas boundary from startY
if (startY + sliceHeight > h) {
sliceHeight = h - startY;
}
// If sliceHeight becomes zero or negative (e.g., startY is at the very bottom), skip this iteration.
if (sliceHeight <= 0) {
continue;
}
// Horizontal offset: up to +/-30% of width, scaled by intensity.
const offsetX = (Math.random() - 0.5) * (w * 0.6) * glitchFactor;
try {
// Get the pixel data for the slice from the current canvas state
const sliceData = ctx.getImageData(0, startY, w, sliceHeight);
// Draw the slice back onto the canvas at the new (horizontally shifted) position
ctx.putImageData(sliceData, offsetX, startY);
} catch (e) {
// Log error if getImageData or putImageData fails, though protections above should minimize this.
// console.warn("Error in slicing effect:", e);
}
}
// --- 2. Channel Shift Effect ---
// The maximum pixel offset for channel shifting is scaled by intensity and channelShiftMaxOffset.
const actualChannelShiftOffset = Math.floor(channelShiftMaxOffset * (0.5 + glitchFactor));
if (glitchFactor > 0 && actualChannelShiftOffset > 0) {
const imageData = ctx.getImageData(0, 0, w, h);
const data = imageData.data;
// Create a copy of the current pixel data to source from (avoids self-interference during shifting)
const sourceDataCopy = new Uint8ClampedArray(data);
// Probability for a scanline to be RGB-shifted: ranges from 5% to 30% based on intensity.
const shiftLineProbability = 0.05 + glitchFactor * 0.25;
for (let y = 0; y < h; y++) {
// Randomly decide if this line should be shifted
if (Math.random() < shiftLineProbability) {
// Determine random offsets for R, G, B channels for this line
const rOffset = getRandomInt(-actualChannelShiftOffset, actualChannelShiftOffset);
const gOffset = getRandomInt(-actualChannelShiftOffset, actualChannelShiftOffset);
const bOffset = getRandomInt(-actualChannelShiftOffset, actualChannelShiftOffset);
for (let x = 0; x < w; x++) {
const idx = (y * w + x) * 4; // Current pixel's R index
// Calculate source X coordinates for R, G, B channels, clamped to image bounds
const rOrigX = Math.max(0, Math.min(w - 1, x + rOffset));
const gOrigX = Math.max(0, Math.min(w - 1, x + gOffset));
const bOrigX = Math.max(0, Math.min(w - 1, x + bOffset));
// Calculate source indices in the copied data array
const rSrcIdx = (y * w + rOrigX) * 4;
const gSrcIdx = (y * w + gOrigX) * 4;
const bSrcIdx = (y * w + bOrigX) * 4;
// Set new pixel data from shifted channels using the source copy
data[idx] = sourceDataCopy[rSrcIdx]; // Red channel
data[idx + 1] = sourceDataCopy[gSrcIdx + 1]; // Green channel
data[idx + 2] = sourceDataCopy[bSrcIdx + 2]; // Blue channel
// Alpha channel is taken from the original pixel's location (no shift)
data[idx + 3] = sourceDataCopy[idx + 3];
}
}
}
// Write the modified pixel data back to the canvas
ctx.putImageData(imageData, 0, 0);
}
// --- 3. Scanlines Effect (subtle) ---
// Add scanlines if intensity is moderately high (e.g., > 15%).
if (glitchFactor > 0.15) {
// Scanline "density" (gap between lines): Denser for higher intensity.
// Ranges roughly from 2 to 7px.
const scanlineDensity = getRandomInt(2, 4) + Math.floor((1 - glitchFactor) * 3);
// Scanline opacity: from 3% to 10% based on intensity.
const scanlineOpacity = 0.03 + glitchFactor * 0.07;
ctx.fillStyle = `rgba(0, 0, 0, ${scanlineOpacity})`; // Dark scanlines
for (let y = 0; y < h; y += scanlineDensity) {
ctx.fillRect(0, y, w, 1); // Draw a 1px high dark line
}
}
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 Glitch Filter Application allows users to apply glitch effects to their images, transforming them into unique and artistic visuals. By adjusting parameters such as intensity, the number of slices, and channel shifting, users can create a variety of distorted looks reminiscent of digital errors or retro aesthetics. This tool can be useful for graphic designers, digital artists, or anyone looking to add a creative twist to their images for use in personal projects, social media, or multimedia presentations.