Please bookmark this page to avoid losing your image tool!

Image Surveillance Camera Filter Effect Tool

(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.
function processImage(originalImg,
    noiseAmount = 0.08,
    scanlineThickness = 1,
    scanlineGap = 1,
    scanlineAlpha = 0.1,
    showTimestamp = 1, // Use 1 for true, 0 for false
    timestampPrefix = "CAM 01 REC ",
    timestampFontSize = 14,
    timestampFontColor = "rgba(255, 255, 180, 0.7)", // Light yellow, semi-transparent
    timestampBgColor = "rgba(0, 0, 0, 0.3)"      // Dark semi-transparent background
) {
    const canvas = document.createElement('canvas');
    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

    if (width === 0 || height === 0) {
        console.error("Image has zero dimensions.");
        // Return a canvas with an error message
        const errCanvas = document.createElement('canvas');
        errCanvas.width = 150; 
        errCanvas.height = 30;
        const errCtx = errCanvas.getContext('2d');
        if (errCtx) {
            errCtx.font = '12px sans-serif';
            errCtx.fillStyle = 'red';
            errCtx.fillText('Invalid image dimensions', 5, 20);
        }
        return errCanvas;
    }

    canvas.width = width;
    canvas.height = height;
    const ctx = canvas.getContext('2d');

    if (!ctx) {
        console.error("Failed to get 2D context from canvas.");
        // Fallback to returning an empty canvas or the original image if it's displayable
        return canvas; // Return the empty canvas
    }

    // 1. Draw original image
    ctx.drawImage(originalImg, 0, 0, width, height);

    // 2. Apply Grayscale + Noise
    try {
        const imageData = ctx.getImageData(0, 0, width, height);
        const data = imageData.data;

        for (let i = 0; i < data.length; i += 4) {
            const r = data[i];
            const g = data[i + 1];
            const b = data[i + 2];

            // Grayscale (luminosity method)
            let gray = 0.299 * r + 0.587 * g + 0.114 * b;

            // Add noise
            if (noiseAmount > 0) {
                // Generate noise in [-1, 1), scale by noiseAmount and 255
                const randomNoise = (Math.random() * 2 - 1) * noiseAmount * 255;
                gray += randomNoise;
            }

            // Clamp value to [0, 255]
            gray = Math.max(0, Math.min(255, gray));

            data[i] = gray;
            data[i + 1] = gray;
            data[i + 2] = gray;
            // Alpha (data[i+3]) remains unchanged
        }
        ctx.putImageData(imageData, 0, 0);
    } catch (e) {
        console.error("Error processing image data (possibly CORS issue if image is cross-origin and canvas is tainted):", e);
        // If we can't process pixels, we might still draw scanlines and timestamp over original.
        // For now, we'll continue, effects might be drawn over colored image.
    }


    // 3. Draw Scanlines
    if (scanlineThickness > 0 && scanlineAlpha > 0) {
        const totalLineAndGapHeight = scanlineThickness + scanlineGap;
        if (totalLineAndGapHeight > 0) {
            ctx.fillStyle = `rgba(0, 0, 0, ${scanlineAlpha})`;
            for (let y = 0; y < height; y += totalLineAndGapHeight) {
                ctx.fillRect(0, y, width, scanlineThickness);
            }
        }
    }

    // 4. Draw Timestamp
    if (showTimestamp === 1) {
        const now = new Date();
        const year = now.getFullYear();
        const month = (now.getMonth() + 1).toString().padStart(2, '0');
        const day = now.getDate().toString().padStart(2, '0');
        const hours = now.getHours().toString().padStart(2, '0');
        const minutes = now.getMinutes().toString().padStart(2, '0');
        const seconds = now.getSeconds().toString().padStart(2, '0');
        
        const dateTimeString = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
        const fullTimestampText = `${timestampPrefix}${dateTimeString}`;

        ctx.font = `${timestampFontSize}px monospace`;
        ctx.textBaseline = 'top';
        
        const textMetrics = ctx.measureText(fullTimestampText);
        const textWidth = textMetrics.width;
        // Approximate text height using font size. For more accuracy, could use
        // textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent,
        // but timestampFontSize is often sufficient for layout.
        const textHeight = timestampFontSize; 

        // Padding for the text from canvas edge and for background around text
        const osdMargin = 5; // Margin of OSD block from canvas edge
        const textInternalPadding = Math.max(2, Math.round(timestampFontSize * 0.15)); // Padding around text within its background

        const textX = osdMargin;
        const textY = osdMargin;

        // Draw background for timestamp for better readability
        if (timestampBgColor && timestampBgColor !== "transparent" && timestampBgColor !== "none") {
            ctx.fillStyle = timestampBgColor;
            ctx.fillRect(
                textX - textInternalPadding,
                textY - textInternalPadding,
                textWidth + 2 * textInternalPadding,
                textHeight + 2 * textInternalPadding 
            );
        }
        
        // Draw timestamp text
        ctx.fillStyle = timestampFontColor;
        ctx.fillText(fullTimestampText, textX, textY);
    }

    return canvas;
}

Free Image Tool Creator

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

Description

The Image Surveillance Camera Filter Effect Tool allows users to transform images to simulate the look of footage captured by surveillance cameras. This includes applying a grayscale and noise effect to mimic low-quality security video, adding scanlines for an authentic vintage effect, and overlaying a timestamp with customizable formatting. This tool is perfect for creating stylized images that convey a sense of security or surveillance, ideal for artistic projects, presentations, or any scenario where a security camera aesthetic is desired.

Leave a Reply

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