Please bookmark this page to avoid losing your image tool!

Image Newspaper Collage 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.
async function processImage(originalImg, numLevels = 3, ditherStrength = 1.0, addTextStr = "true", numSnippets = 5, snippetFontSize = 14, snippetFontColor = "30,30,30", snippetOpacity = 0.4, snippetFontFamily = "sans-serif") {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d', { willReadFrequently: true }); // Opt-in for frequent readbacks

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

    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);

    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const data = imageData.data;

    const bayerMatrix4x4 = [
        [0, 8, 2, 10],
        [12, 4, 14, 6],
        [3, 11, 1, 9],
        [15, 7, 13, 5]
    ];
    const bayerSize = 4;
    
    // Ensure numLevels is at least 2 for meaningful quantization.
    // 1 level would just be a single color, not really a newspaper effect.
    const effectiveNumLevels = Math.max(2, Math.floor(numLevels));

    for (let y = 0; y < canvas.height; y++) {
        for (let x = 0; x < canvas.width; x++) {
            const i = (y * canvas.width + x) * 4;
            const r = data[i];
            const g = data[i + 1];
            const b = data[i + 2];

            // Convert to grayscale using luminosity method
            const gray = 0.299 * r + 0.587 * g + 0.114 * b;
            
            const normalizedGray = gray / 255.0; // Normalize to 0-1 range

            // Get Bayer matrix value, normalized (0 to almost 1)
            const bayerValue = bayerMatrix4x4[y % bayerSize][x % bayerSize];
            const normalizedBayer = bayerValue / (bayerSize * bayerSize); // e.g., for 4x4, divide by 16

            // Dithering logic (inspired by ordered dithering for multiple levels)
            // The dither component shifts the gray value before quantization.
            // (normalizedBayer - 0.5) creates a value roughly in [-0.5, 0.5]
            const ditherComponent = ditherStrength * (normalizedBayer - 0.5);
            
            // Scale normalizedGray to the range of level indices [0, effectiveNumLevels-1]
            // Then add dither component.
            // Example: M levels. Input I (0-1). Output is round((M-1)*I + dither_comp) / (M-1)
            let valueToQuantize = (effectiveNumLevels - 1) * normalizedGray + ditherComponent;
            
            let levelIndex = Math.round(valueToQuantize);
            
            // Clamp levelIndex to be within [0, effectiveNumLevels-1]
            levelIndex = Math.max(0, Math.min(effectiveNumLevels - 1, levelIndex));

            let finalGrayNorm;
            if (effectiveNumLevels <= 1) { // Should be prevented by Math.max(2,...)
                finalGrayNorm = (normalizedGray > 0.5) ? 1.0 : 0.0; 
            } else {
                finalGrayNorm = levelIndex / (effectiveNumLevels - 1.0);
            }
            
            // Ensure final value is clamped (should be redundant if logic is correct)
            finalGrayNorm = Math.max(0.0, Math.min(1.0, finalGrayNorm)); 
            const finalValue = Math.round(finalGrayNorm * 255);

            data[i] = finalValue;
            data[i + 1] = finalValue;
            data[i + 2] = finalValue;
            // Alpha (data[i+3]) remains unchanged
        }
    }
    ctx.putImageData(imageData, 0, 0);

    // Add text snippets if requested
    const shouldAddText = String(addTextStr).toLowerCase() === 'true';
    if (shouldAddText && numSnippets > 0) {
        const snippetTexts = [
            "NEWS TODAY", "HEADLINES", "EXTRA EXTRA", "READ ALL ABOUT IT", 
            "LOREM IPSUM", "DOLOR SIT AMET", "CONSECTETUR", "ADIPISCING ELIT",
            "BREAKING NEWS", "TOP STORY", "EXCLUSIVE", "REPORT", "UPDATE",
            "ANALYSIS", "OPINION", "LOCAL NEWS", "WORLD EVENTS"
        ];

        const parsedColors = String(snippetFontColor).split(',').map(s => parseInt(s.trim(), 10));
        const textR = Number.isFinite(parsedColors[0]) ? parsedColors[0] : 30;
        const textG = Number.isFinite(parsedColors[1]) ? parsedColors[1] : 30;
        const textB = Number.isFinite(parsedColors[2]) ? parsedColors[2] : 30;
        
        ctx.fillStyle = `rgba(${textR}, ${textG}, ${textB}, ${Math.max(0, Math.min(1, snippetOpacity))})`;
        ctx.font = `${Math.max(1, snippetFontSize)}px ${snippetFontFamily}`; // Ensure font size is positive
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";

        for (let i = 0; i < numSnippets; i++) {
            const text = snippetTexts[Math.floor(Math.random() * snippetTexts.length)];
            const x = Math.random() * canvas.width;
            const y = Math.random() * canvas.height;
            // Random angle, e.g., up to +/- 30 degrees (PI/6 radians)
            const angle = (Math.random() - 0.5) * (Math.PI / 6); 

            ctx.save();
            ctx.translate(x, y);
            ctx.rotate(angle);
            ctx.fillText(text.toUpperCase(), 0, 0); // Using toUpperCase for a blocky, headline feel
            ctx.restore();
        }
    }

    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 Newspaper Collage Filter Effect Tool allows users to transform their images into a newspaper-style collage. This transformation includes converting the image to grayscale with a controlled quantization level for a vintage look, while dithering effects add texture reminiscent of newsprint. Additionally, users can overlay random news-style text snippets onto the image, further enhancing the collage effect. This tool is ideal for creating artistic visuals for social media, blog posts, or personal projects that require a creative, retro aesthetic.

Leave a Reply

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