Please bookmark this page to avoid losing your image tool!

Image LCD Pixel 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, pixelSize = 10) {

    let numPixelSize = parseFloat(pixelSize);
    if (isNaN(numPixelSize) || numPixelSize <= 0) {
        // If pixelSize is not a valid positive number (e.g., "abc", 0, -5), use default.
        numPixelSize = 10; 
    }
    // Ensure pixelSize is an integer and at least 3 for R, G, B stripes to be visible.
    numPixelSize = Math.max(3, Math.floor(numPixelSize));

    // Validate the originalImg object and its dimensions
    if (!originalImg || 
        typeof originalImg.width !== 'number' || 
        typeof originalImg.height !== 'number' || 
        originalImg.width <= 0 || 
        originalImg.height <= 0) {
        
        console.error("Invalid image input: Image is null, not loaded, or has zero/invalid dimensions.");
        const errorCanvas = document.createElement('canvas');
        // Attempt to use original image's dimensions if they are somewhat valid, otherwise default
        const w = (originalImg && typeof originalImg.width === 'number' && originalImg.width > 0) ? originalImg.width : 300;
        const h = (originalImg && typeof originalImg.height === 'number' && originalImg.height > 0) ? originalImg.height : 150;
        errorCanvas.width = w;
        errorCanvas.height = h;
        const errorCtx = errorCanvas.getContext('2d');
        errorCtx.fillStyle = '#f0f0f0'; // Light gray background
        errorCtx.fillRect(0, 0, w, h);
        errorCtx.fillStyle = 'red';
        errorCtx.textAlign = 'center';
        errorCtx.textBaseline = 'middle';
        errorCtx.font = '16px Arial';
        errorCtx.fillText('Invalid or unloaded image.', w / 2, h / 2);
        return errorCanvas;
    }

    const originalWidth = originalImg.width;
    const originalHeight = originalImg.height;

    // Create a temporary canvas to get pixel data from the original image
    const tempCanvas = document.createElement('canvas');
    tempCanvas.width = originalWidth;
    tempCanvas.height = originalHeight;
    const tempCtx = tempCanvas.getContext('2d');
    
    let originalImageData;
    try {
        // Draw the image onto the temporary canvas
        tempCtx.drawImage(originalImg, 0, 0, originalWidth, originalHeight);
        // Get the pixel data from the temporary canvas
        originalImageData = tempCtx.getImageData(0, 0, originalWidth, originalHeight);
    } catch (e) {
        // This can happen due to cross-origin restrictions if the image is from another domain
        // and the canvas becomes tainted.
        console.error("Error getting image data (likely cross-origin issue):", e);
        const errorCanvas = document.createElement('canvas');
        errorCanvas.width = originalWidth; // originalWidth/Height are validated by this point
        errorCanvas.height = originalHeight;
        const errorCtx = errorCanvas.getContext('2d');
        errorCtx.fillStyle = '#f0f0f0';
        errorCtx.fillRect(0, 0, originalWidth, originalHeight);
        errorCtx.fillStyle = 'red';
        errorCtx.textAlign = 'center';
        errorCtx.textBaseline = 'middle';
        errorCtx.font = '16px Arial';
        errorCtx.fillText('Error processing image.', originalWidth / 2, originalHeight / 2 - 10);
        errorCtx.fillText('(Possibly a cross-origin issue)', originalWidth / 2, originalHeight / 2 + 10);
        return errorCanvas;
    }
    const data = originalImageData.data; // Array of [R,G,B,A, R,G,B,A, ...] values

    // Create the output canvas
    const outputCanvas = document.createElement('canvas');
    outputCanvas.width = originalWidth;
    outputCanvas.height = originalHeight;
    const outputCtx = outputCanvas.getContext('2d');

    // Calculate the width of each sub-pixel stripe (R, G, B)
    // Integer division ensures whole pixels for stripes
    const stripeWidthR = Math.floor(numPixelSize / 3);
    const stripeWidthG = Math.floor(numPixelSize / 3);
    // The blue stripe gets the remaining width to ensure total width is numPixelSize
    const stripeWidthB = numPixelSize - stripeWidthR - stripeWidthG; 

    // Iterate over the image in blocks of numPixelSize
    for (let y = 0; y < originalHeight; y += numPixelSize) {
        for (let x = 0; x < originalWidth; x += numPixelSize) {
            let sumR = 0, sumG = 0, sumB = 0, sumA = 0;
            let count = 0;

            // Define the boundaries of the current block in the source image
            // Ensure we don't go outside the image dimensions
            const blockEndY = Math.min(y + numPixelSize, originalHeight);
            const blockEndX = Math.min(x + numPixelSize, originalWidth);

            // Calculate the average color and alpha of the current block
            for (let currentY = y; currentY < blockEndY; currentY++) {
                for (let currentX = x; currentX < blockEndX; currentX++) {
                    const offset = (currentY * originalWidth + currentX) * 4; // 4 components (R,G,B,A)
                    sumR += data[offset];
                    sumG += data[offset + 1];
                    sumB += data[offset + 2];
                    sumA += data[offset + 3];
                    count++;
                }
            }

            if (count === 0) {
                // This should not happen if loops are correct and image has area,
                // but as a safe guard.
                continue; 
            }

            // Average R, G, B, A values for the block
            const avgR = Math.floor(sumR / count);
            const avgG = Math.floor(sumG / count);
            const avgB = Math.floor(sumB / count);
            const avgA = Math.floor(sumA / count) / 255; // Normalize alpha to 0.0 - 1.0

            // Draw the "LCD pixel" (RGB stripes) on the output canvas
            // The height of each stripe is numPixelSize
            // The fillRects will be clipped at canvas edges automatically.

            // Red stripe
            if (stripeWidthR > 0) {
                outputCtx.fillStyle = `rgba(${avgR}, 0, 0, ${avgA})`;
                outputCtx.fillRect(x, y, stripeWidthR, numPixelSize);
            }

            // Green stripe
            if (stripeWidthG > 0) {
                outputCtx.fillStyle = `rgba(0, ${avgG}, 0, ${avgA})`;
                outputCtx.fillRect(x + stripeWidthR, y, stripeWidthG, numPixelSize);
            }

            // Blue stripe
            if (stripeWidthB > 0) {
                outputCtx.fillStyle = `rgba(0, 0, ${avgB}, ${avgA})`;
                outputCtx.fillRect(x + stripeWidthR + stripeWidthG, y, stripeWidthB, numPixelSize);
            }
        }
    }

    return outputCanvas;
}

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 LCD Pixel Filter Effect Tool allows users to apply a unique LCD pixel effect to images by converting them into blocks of RGB stripes. Users can specify the size of these blocks, which will determine the thickness of each stripe, resulting in an artistic pixelation that mimics the look of an LCD display. This tool is useful for creating stylized images for digital art, graphic design, or social media posts, providing a fun way to manipulate photos for creative purposes.

Leave a Reply

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