You can edit the below JavaScript code to customize the image tool.
/**
* Simulates an old CRT TV's line synchronization issue, creating a glitchy,
* horizontally-shifting effect on the image. It also adds optional scanlines,
* noise, and a vignette for a more authentic retro feel.
*
* @param {Image} originalImg The original HTML Image object to process.
* @param {number} [shiftAmount=25] The maximum horizontal shift in pixels for the distortion effect. Higher values create a more intense "tear".
* @param {number} [distortionFrequency=0.05] Controls the vertical frequency of the rolling distortion wave. Smaller values create wider, slower waves.
* @param {number} [glitchChance=0.02] The probability (0 to 1) of a sharp, random glitch occurring on any given line.
* @param {string} [addScanlines="true"] Whether to add semi-transparent horizontal scanlines. Accepts "true" or "false".
* @param {number} [vignetteAmount=0.4] The intensity of the dark vignette effect around the edges (0 to 1). 0 means no vignette.
* @returns {HTMLCanvasElement} A new canvas element with the TV simulator effect applied.
*/
function processImage(originalImg, shiftAmount = 25, distortionFrequency = 0.05, glitchChance = 0.02, addScanlines = "true", vignetteAmount = 0.4) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', {
willReadFrequently: true
});
const width = originalImg.naturalWidth;
const height = originalImg.naturalHeight;
canvas.width = width;
canvas.height = height;
// Use current time as a seed to make the distortion animate on subsequent calls
const time = Date.now() / 1000;
// --- 1. Apply Line Synchronization Distortion ---
for (let y = 0; y < height; y++) {
// Calculate a sine wave-based shift for a rolling bar effect.
// Combining multiple waves creates a more chaotic, less uniform pattern.
const wave1 = Math.sin((y * distortionFrequency) + time);
const wave2 = Math.cos((y * distortionFrequency * 0.3) + time * 0.7);
let horizontalShift = Math.floor(((wave1 + wave2) / 2) * shiftAmount);
// Add some random, sharp glitches for extra effect
if (Math.random() < glitchChance) {
horizontalShift += Math.floor((Math.random() - 0.5) * shiftAmount * 3);
}
// Calculate the source and destination rectangles for drawing the shifted line
const sx = Math.max(0, -horizontalShift);
const dx = Math.max(0, horizontalShift);
const sWidth = width - Math.abs(horizontalShift);
if (sWidth > 0) {
// Draw a 1-pixel high slice of the original image at the shifted position
ctx.drawImage(
originalImg,
sx, y, sWidth, 1, // source rect (from original image)
dx, y, sWidth, 1 // destination rect (on the canvas)
);
}
}
// --- 2. Add Static Noise ---
const imageData = ctx.getImageData(0, 0, width, height);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
// Only apply noise to filled pixels to avoid making blank areas gray
if (data[i + 3] > 0) {
const noise = (Math.random() - 0.5) * 30; // Noise intensity
data[i] = Math.max(0, Math.min(255, data[i] + noise));
data[i + 1] = Math.max(0, Math.min(255, data[i + 1] + noise));
data[i + 2] = Math.max(0, Math.min(255, data[i + 2] + noise));
}
}
ctx.putImageData(imageData, 0, 0);
// --- 3. Optional Scanlines ---
const useScanlines = String(addScanlines).toLowerCase() === "true";
if (useScanlines) {
ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
for (let y = 0; y < height; y += 3) {
ctx.fillRect(0, y, width, 1);
}
}
// --- 4. Optional Vignette ---
const clampedVignette = Math.max(0, Math.min(1, vignetteAmount));
if (clampedVignette > 0) {
const outerRadius = Math.sqrt(width ** 2 + height ** 2) / 2;
const innerRadius = outerRadius * (1 - clampedVignette);
const gradient = ctx.createRadialGradient(
width / 2, height / 2, innerRadius,
width / 2, height / 2, outerRadius
);
gradient.addColorStop(0, 'rgba(0,0,0,0)');
gradient.addColorStop(1, `rgba(0,0,0,${clampedVignette * 0.9})`);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
}
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 TV Simulator Line Synchronization Tool allows users to apply retro CRT TV distortion effects to images. It creates a glitchy appearance with horizontal shifting, simulating line synchronization issues often seen in old television displays. Users can modify parameters such as the intensity of the shifting effect, the frequency of the distortion, the chance of random glitches, and whether to include scanlines and a vignette effect. This tool is ideal for artists, designers, and content creators looking to add a nostalgic touch to their images, or to create unique visual styles reminiscent of vintage television broadcasts.