Please bookmark this page to avoid losing your image tool!

Image Fax Transmission 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, ditheringType = "bayer4x4", noiseAmount = 0.03, scanLineOpacity = 0.08, scanRowInterval = 3, preBlurRadius = 0.3) {
    // Bayer matrices (normalized for direct comparison with intensity 0-1)
    // These are defined inside the function to keep it self-contained.
    const BAYER_MATRIX_2X2_NORMALIZED = [
        [0/4, 2/4],
        [3/4, 1/4]
    ];

    const BAYER_MATRIX_4X4_NORMALIZED = [
        [ 0/16,  8/16,  2/16, 10/16],
        [12/16,  4/16, 14/16,  6/16],
        [ 3/16, 11/16,  1/16,  9/16],
        [15/16,  7/16, 13/16,  5/16]
    ];

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true }); // Optimization hint for frequent getImageData/putImageData

    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

    if (!width || !height) {
        console.error("Image has zero dimensions. Cannot process.");
        // Return an empty or minimal canvas to avoid breaking caller
        canvas.width = 1;
        canvas.height = 1;
        ctx.clearRect(0, 0, 1, 1); // Ensure it's blank
        return canvas;
    }

    canvas.width = width;
    canvas.height = height;

    // 1. Optional Pre-blur to simulate slight focus imperfection or ink bleed
    if (preBlurRadius > 0) {
        // Apply blur to the original image drawing
        ctx.filter = `blur(${preBlurRadius}px)`;
        ctx.drawImage(originalImg, 0, 0, width, height);
        ctx.filter = 'none'; // Reset filter before getImageData
    } else {
        // Draw image without blur
        ctx.drawImage(originalImg, 0, 0, width, height);
    }

    // 2. Get image data for pixel manipulation
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, width, height);
    } catch (e) {
        console.error("Could not get image data. Tainted canvas?", e);
        // If canvas is tainted (e.g., cross-origin image without CORS), return the drawn (possibly blurred) image.
        return canvas;
    }
    const data = imageData.data;

    // 3. Process pixels: Grayscale, Dithering, Noise
    for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
            const i = (y * width + x) * 4; // Index for the red component of the pixel
            const r = data[i];
            const g = data[i + 1];
            const b = data[i + 2];

            // Convert to grayscale (luminosity method for perceptually accurate brightness)
            const gray = 0.299 * r + 0.587 * g + 0.114 * b;
            const normalizedGray = gray / 255.0; // Normalize to 0-1 range

            let finalColorVal = 0; // 0 for black, 255 for white

            // Apply dithering
            if (ditheringType === "none") {
                // Simple thresholding
                finalColorVal = gray < 128 ? 0 : 255;
            } else if (ditheringType === "bayer2x2") {
                const matX = x % 2;
                const matY = y % 2;
                const threshold = BAYER_MATRIX_2X2_NORMALIZED[matY][matX];
                finalColorVal = normalizedGray > threshold ? 255 : 0;
            } else { // Default to "bayer4x4" or any other unrecognized type
                const matX = x % 4;
                const matY = y % 4;
                const threshold = BAYER_MATRIX_4X4_NORMALIZED[matY][matX];
                finalColorVal = normalizedGray > threshold ? 255 : 0;
            }

            // Apply noise (salt-and-pepper style on the binarized image)
            if (noiseAmount > 0 && Math.random() < noiseAmount) {
                finalColorVal = Math.random() < 0.5 ? 0 : 255;
            }

            data[i] = finalColorVal;     // Red
            data[i + 1] = finalColorVal; // Green
            data[i + 2] = finalColorVal; // Blue
            // Alpha (data[i + 3]) remains unchanged
        }
    }

    // 4. Put the modified pixel data back onto the canvas
    ctx.putImageData(imageData, 0, 0);

    // 5. Draw Scan Lines on top of the processed image
    if (scanLineOpacity > 0 && scanRowInterval > 0) {
        ctx.fillStyle = `rgba(0, 0, 0, ${scanLineOpacity})`;
        for (let y = 0; y < height; y += Math.max(1, Math.floor(scanRowInterval))) { // Ensure interval is at least 1
            ctx.fillRect(0, y, width, 1); // Draw a 1px high scan 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!

Description

The Image Fax Transmission Filter Effect Tool allows users to apply a vintage fax-like effect to images. This tool processes images by converting them to grayscale, applying dithering techniques to simulate low-resolution output, and adding noise for authenticity. Additionally, users can introduce scan lines to enhance the visual resemblance to classic faxed documents. This tool is ideal for creating artistic renditions of photos, designing retro-themed graphics, or simulating old technology looks in digital content.

Leave a Reply

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