Please bookmark this page to avoid losing your image tool!

Low Resolution CCTV Style Image Effect Generator

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
async function processImage(
    originalImg,
    pixelRes = 96,
    blurSigma = 5,
    noiseStd = 30,
    darkenAlpha = 0.8,
    darkenBeta = -30,
    motionBlurSize = 15,
    jpegQuality = 0.1,
    scanLineSpacing = 4
) {
    const w = originalImg.width;
    const h = originalImg.height;

    // Main canvas
    const mainCanvas = document.createElement('canvas');
    mainCanvas.width = w;
    mainCanvas.height = h;
    const ctx = mainCanvas.getContext('2d');

    // 1. Pixelation: VERY low resolution & Upscale back (creates nearest-neighbor pixelation)
    const smallCanvas = document.createElement('canvas');
    smallCanvas.width = pixelRes;
    smallCanvas.height = pixelRes;
    const smallCtx = smallCanvas.getContext('2d');
    smallCtx.drawImage(originalImg, 0, 0, pixelRes, pixelRes);

    const upscaledCanvas = document.createElement('canvas');
    upscaledCanvas.width = w;
    upscaledCanvas.height = h;
    const upCtx = upscaledCanvas.getContext('2d');
    upCtx.imageSmoothingEnabled = false; // INTER_NEAREST equivalent
    upCtx.drawImage(smallCanvas, 0, 0, w, h);

    // 2. Strong Gaussian blur
    ctx.filter = `blur(${blurSigma}px)`;
    ctx.drawImage(upscaledCanvas, 0, 0);
    ctx.filter = 'none';

    // 3. Add heavy noise & Darken image (Simulate low light CCTV)
    const imgData = ctx.getImageData(0, 0, w, h);
    const data = imgData.data;

    // Helper: Generate normally distributed noise (Box-Muller approximation)
    function randomNormal() {
        let u = 0, v = 0;
        while (u === 0) u = Math.random(); 
        while (v === 0) v = Math.random();
        return Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
    }

    for (let i = 0; i < data.length; i += 4) {
        for (let c = 0; c < 3; c++) {
            // Add normal distribution noise per color channel independent of each other
            const noise = randomNormal() * noiseStd;
            let val = data[i + c] + noise;
            
            // Clamp intermediate noisy image to 0-255 before darken step
            val = Math.max(0, Math.min(255, val));
            
            // Simulate cv2.convertScaleAbs(img, alpha=0.8, beta=-30)
            val = Math.abs(val * darkenAlpha + darkenBeta);
            
            data[i + c] = val; // Uint8ClampedArray naturally clamps final value to 0-255
        }
    }
    ctx.putImageData(imgData, 0, 0);

    // 4. Motion blur (horizontal filter2D)
    // Draw current context into a temporary buffer to use for sliding
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = w;
    tempCanvas.height = h;
    const tCtx = tempCanvas.getContext('2d');
    tCtx.drawImage(mainCanvas, 0, 0);

    ctx.clearRect(0, 0, w, h);
    
    // We average images exactly by dynamically varying the alpha based on frame order (1/n)
    let framesDrawn = 0;
    let startOffset = -Math.floor((motionBlurSize - 1) / 2);
    let endOffset = Math.floor(motionBlurSize / 2);
    
    for (let offset = startOffset; offset <= endOffset; offset++) {
        framesDrawn++;
        ctx.globalAlpha = 1 / framesDrawn;
        ctx.drawImage(tempCanvas, offset, 0);
    }
    ctx.globalAlpha = 1.0;

    // 5. JPEG compression artifacts
    // We encode the canvas to a low-quality JS Data URL JPEG and draw it back
    const jpegUrl = mainCanvas.toDataURL('image/jpeg', jpegQuality);
    const artifactImg = new Image();
    artifactImg.src = jpegUrl;
    await new Promise((resolve, reject) => {
        artifactImg.onload = resolve;
        artifactImg.onerror = reject;
    });
    ctx.drawImage(artifactImg, 0, 0);

    // 6. Horizontal scan lines
    ctx.fillStyle = 'rgba(0, 0, 0, 0.25)'; // Semi-transparent black lines
    for (let y = 0; y < h; y += scanLineSpacing) {
        ctx.fillRect(0, y, w, 1);
    }

    return mainCanvas;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

This tool allows users to apply a low-resolution CCTV aesthetic to their images. It simulates the visual characteristics of security camera footage by incorporating several effects, including pixelation, Gaussian blur, heavy digital noise, and low-light darkening. Additionally, it applies motion blur, JPEG compression artifacts, and horizontal scan lines to enhance the surveillance-style appearance. This tool is ideal for filmmakers, graphic designers, or content creators looking to add gritty, realistic surveillance effects to visual projects or digital art.

Leave a Reply

Your email address will not be published. Required fields are marked *