Please bookmark this page to avoid losing your image tool!

Image Blueprint 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, blueprintColorStr = "0,80,150", lineColorStr = "255,255,255", edgeThreshold = 50) {
    const canvas = document.createElement('canvas');
    // Using { willReadFrequently: true } can optimize getContext for frequent getImageData/putImageData calls
    const ctx = canvas.getContext('2d', { willReadFrequently: true });

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

    canvas.width = imgWidth;
    canvas.height = imgHeight;

    // If image dimensions are invalid (e.g., image not loaded properly), return an empty canvas.
    if (imgWidth === 0 || imgHeight === 0) {
        console.warn("Image has zero width or height.");
        return canvas;
    }

    ctx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);

    let imageData;
    try {
        imageData = ctx.getImageData(0, 0, imgWidth, imgHeight);
    } catch (e) {
        // This can happen due to cross-origin issues if the image is from another domain
        // and the canvas becomes tainted.
        console.error("Error getting ImageData (e.g., cross-origin issue):", e);
        // Return the canvas with the original image drawn, as filtering is not possible.
        return canvas;
    }

    const data = imageData.data; // This is a Uint8ClampedArray: [R, G, B, A, R, G, B, A, ...]
    
    // Create a grayscale version of the image.
    // We'll store grayscale values in a separate array to perform convolution.
    const grayData = new Uint8ClampedArray(imgWidth * imgHeight);
    for (let i = 0; i < data.length; i += 4) {
        const r = data[i];
        const g = data[i+1];
        const b = data[i+2];
        // Standard luminance calculation for grayscale: Y = 0.299R + 0.587G + 0.114B
        const gray = 0.299 * r + 0.587 * g + 0.114 * b;
        grayData[i / 4] = gray; // Store one grayscale value per pixel
    }

    // This array will store the result of the Laplacian convolution (edge detection).
    // Int16Array is used because convolution results can be negative or exceed 255.
    const edgeData = new Int16Array(imgWidth * imgHeight); 

    // Laplacian kernel for edge detection. This kernel highlights regions of rapid intensity change.
    // K = [[-1, -1, -1],
    //      [-1,  8, -1],
    //      [-1, -1, -1]]
    const kernel = [
        -1, -1, -1,
        -1,  8, -1,
        -1, -1, -1
    ];
    const kernelSize = 3; // Dimension of the square kernel (3x3)

    // Apply convolution. We iterate over each pixel (excluding borders) to apply the kernel.
    // Pixels on the border (y=0, y=imgHeight-1, x=0, x=imgWidth-1) will have edgeData[index] = 0
    // (default for Int16Array), and thus will be treated as background.
    for (let y = 1; y < imgHeight - 1; y++) { // Start from 1 and end at imgHeight-2 to avoid borders
        for (let x = 1; x < imgWidth - 1; x++) { // Start from 1 and end at imgWidth-2
            let sum = 0;
            for (let ky = -1; ky <= 1; ky++) { // Kernel y-offset (-1, 0, 1)
                for (let kx = -1; kx <= 1; kx++) { // Kernel x-offset (-1, 0, 1)
                    // Calculate index for grayData (1D array for 2D image)
                    const pixelIndex = (y + ky) * imgWidth + (x + kx);
                    // Calculate index for kernel (1D array for 2D kernel)
                    const kernelIndex = (ky + 1) * kernelSize + (kx + 1);
                    
                    sum += grayData[pixelIndex] * kernel[kernelIndex];
                }
            }
            edgeData[y * imgWidth + x] = sum;
        }
    }
    
    // Parse blueprint background color and line color from string parameters.
    // Default to 0 if parsing fails for a component.
    const [bgR, bgG, bgB] = blueprintColorStr.split(',').map(s => parseInt(s, 10) || 0);
    const [lnR, lnG, lnB] = lineColorStr.split(',').map(s => parseInt(s, 10) || 0);

    // Threshold the edge data and colorize the output image.
    // Iterate through all pixels (including borders).
    for (let i = 0; i < imgWidth * imgHeight; i++) {
        const dataOffset = i * 4; // Each pixel has 4 components (R,G,B,A) in imageData.data
        
        // edgeData[i] contains the convolved value. For border pixels, this will be 0.
        const edgeStrength = edgeData[i];

        if (Math.abs(edgeStrength) > edgeThreshold) {
            // If edge strength is above threshold, color it as a line
            data[dataOffset]     = lnR;
            data[dataOffset + 1] = lnG;
            data[dataOffset + 2] = lnB;
        } else {
            // Otherwise, color it as background
            data[dataOffset]     = bgR;
            data[dataOffset + 1] = bgG;
            data[dataOffset + 2] = bgB;
        }
        data[dataOffset + 3] = 255; // Set alpha to fully opaque
    }

    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 Blueprint Filter tool applies a distinctive blueprint-style effect to images. It processes the uploaded image by converting it to grayscale and then detects and enhances edges using a convolution technique. Users can customize the background and line colors to create a variety of artistic effects. This tool is ideal for creating visually striking representations of images, useful for architects, designers, and artists looking to transform photos into blueprint-like illustrations.

Leave a Reply

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