You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, scanlineThickness = 2, scanlineOpacity = 0.25, rgbShift = 3, noiseLevel = 15) {
// Parse parameters to ensure they are handled properly (whether strings or numbers are passed)
scanlineThickness = isNaN(Number(scanlineThickness)) ? 2 : Math.max(1, Math.floor(Number(scanlineThickness)));
scanlineOpacity = isNaN(Number(scanlineOpacity)) ? 0.25 : Math.max(0, Math.min(1, Number(scanlineOpacity)));
rgbShift = isNaN(Number(rgbShift)) ? 3 : Math.floor(Number(rgbShift));
noiseLevel = isNaN(Number(noiseLevel)) ? 15 : Number(noiseLevel);
// Setup the canvas
const canvas = document.createElement('canvas');
const width = originalImg.width;
const height = originalImg.height;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// Draw the original image onto the canvas
ctx.drawImage(originalImg, 0, 0);
// Extract image data for pixel manipulation (RGB shift & Noise)
const imgData = ctx.getImageData(0, 0, width, height);
const data = imgData.data;
const outData = new Uint8ClampedArray(data.length);
// Apply chromatic aberration (RGB channel shift) and static noise
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const i = (y * width + x) * 4;
// Offset X coordinates for Red and Blue channels
const iRed = (y * width + Math.max(0, x - rgbShift)) * 4;
const iBlue = (y * width + Math.min(width - 1, x + rgbShift)) * 4;
let r = data[iRed];
let g = data[i + 1]; // Green stays in the center
let b = data[iBlue + 2];
let a = data[i + 3];
// Apply static noise
if (noiseLevel > 0) {
const noise = (Math.random() - 0.5) * 2 * noiseLevel;
r += noise;
g += noise;
b += noise;
}
outData[i] = r;
outData[i + 1] = g;
outData[i + 2] = b;
outData[i + 3] = a;
}
}
// Put modified data back onto the canvas
const newImgData = new ImageData(outData, width, height);
ctx.putImageData(newImgData, 0, 0);
// Render horizontal TV Scanlines
ctx.fillStyle = `rgba(0, 0, 0, ${scanlineOpacity})`;
for (let y = 0; y < height; y += scanlineThickness * 2) {
ctx.fillRect(0, y, width, scanlineThickness);
}
// Apply a vignette effect to simulate curved CRT edges
const diagonal = Math.sqrt(width * width + height * height);
const gradient = ctx.createRadialGradient(
width / 2, height / 2, diagonal * 0.3, // Inner transparent circle
width / 2, height / 2, diagonal * 0.6 // Outer dark edge
);
gradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
gradient.addColorStop(1, 'rgba(0, 0, 0, 0.6)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
return canvas;
}
Apply Changes