Please bookmark this page to avoid losing your image tool!

Image Photocopy Filter

(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, threshold = 128, noiseLevel = 10) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

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

    if (canvas.width === 0 || canvas.height === 0) {
        // Ensure non-zero dimensions for the error canvas itself
        canvas.width = canvas.width || 200; 
        canvas.height = canvas.height || 100;
        
        ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear canvas
        ctx.font = "16px Arial";
        ctx.fillStyle = "black";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillText("Error: Invalid image dimensions.", canvas.width / 2, canvas.height / 2);
        return canvas;
    }

    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    
    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    } catch (e) {
        console.error("Could not get image data, possibly due to CORS policy:", e);
        ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear image potentially drawn
        
        ctx.font = "bold 14px Arial";
        ctx.fillStyle = "red";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        
        const message = "Error: Cannot process image pixels.";
        const subMessage = "(This can happen with images from other websites due to security rules.)";
        
        const textMetricsMessage = ctx.measureText(message);
        const textMetricsSubMessage = ctx.measureText(subMessage);
        
        const totalTextHeight = 30; // Approximate height for two lines with spacing

        ctx.fillText(message, canvas.width / 2, canvas.height / 2 - totalTextHeight / 2 + 7); // Adjusted y

        ctx.font = "12px Arial";
        ctx.fillStyle = "black";
        ctx.fillText(subMessage, canvas.width / 2, canvas.height / 2 + totalTextHeight / 2 - 7); // Adjusted y
        return canvas;
    }
    
    const data = imageData.data;
    
    // Validate and parse parameters
    let numThreshold = Number(threshold);
    if (isNaN(numThreshold)) {
        console.warn(`Threshold parameter "${threshold}" is not a valid number. Using default 128.`);
        numThreshold = 128;
    } else if (numThreshold < 0 || numThreshold > 255) {
        console.warn(`Threshold ${numThreshold} out of range [0, 255]. Clamping to range.`);
        numThreshold = Math.max(0, Math.min(255, numThreshold));
    }

    let numNoiseLevel = Number(noiseLevel);
    if (isNaN(numNoiseLevel)) {
        console.warn(`NoiseLevel parameter "${noiseLevel}" is not a valid number. Using default 10.`);
        numNoiseLevel = 10;
    } else if (numNoiseLevel < 0) {
        console.warn(`NoiseLevel ${numNoiseLevel} is negative. Using 0 (no noise).`);
        numNoiseLevel = 0; 
    }

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

        // Convert to grayscale using luminosity method
        let gray = 0.299 * r + 0.587 * g + 0.114 * b;

        // Add noise
        if (numNoiseLevel > 0) {
            // Generate noise in the range [-numNoiseLevel, +numNoiseLevel]
            const noise = (Math.random() - 0.5) * 2 * numNoiseLevel;
            gray += noise;
            // Clamp gray value to 0-255 range
            gray = Math.max(0, Math.min(255, gray));
        }
        
        // Apply threshold: if gray > threshold, pixel becomes white (255), else black (0).
        const outputValue = (gray > numThreshold) ? 255 : 0;

        data[i] = outputValue;     // Red
        data[i + 1] = outputValue; // Green
        data[i + 2] = outputValue; // Blue
        data[i + 3] = 255;         // Alpha (set to fully opaque for photocopy effect)
    }

    ctx.putImageData(imageData, 0, 0);
    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 Photocopy Filter tool allows users to apply a photocopy effect to images by converting them into high-contrast black and white representations. This effect can emulate the look of a photocopy by thresholding the grayscale values of the image, resulting in a stark black and white image. Users can adjust the threshold level to control the intensity of the effect and add a noise level to simulate imperfections found in real photocopies. This tool is useful for artists, designers, or anyone looking to create stylized images, enhance graphic designs, or generate prints that mimic the aesthetics of photocopies.

Leave a Reply

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