Please bookmark this page to avoid losing your image tool!

Image Blueprint Drawing Filter Effect

(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, blurRadius = 5, lineColorStr = "255,255,255", backgroundColorStr = "0,51,102") {
    // Helper to parse color string "r,g,b" into an object {r, g, b}
    // Clamps values to 0-255. Handles invalid or missing parts.
    function parseColor(colorStr) {
        const parts = (typeof colorStr === 'string' ? colorStr : '').split(',').map(s => parseInt(s.trim(), 10));
        const r = Number.isFinite(parts[0]) ? parts[0] : 0;
        const g = Number.isFinite(parts[1]) ? parts[1] : 0;
        const b = Number.isFinite(parts[2]) ? parts[2] : 0;
        return { 
            r: Math.max(0, Math.min(255, r)), 
            g: Math.max(0, Math.min(255, g)), 
            b: Math.max(0, Math.min(255, b)) 
        };
    }

    const lineColor = parseColor(lineColorStr);
    const backgroundColor = parseColor(backgroundColorStr);

    // Use naturalWidth/Height if available, otherwise width/height.
    // For a JS Image object, width/height are usually the intrinsic dimensions after loading.
    const width = originalImg.naturalWidth || originalImg.width;
    const height = originalImg.naturalHeight || originalImg.height;

    if (width === 0 || height === 0) {
        // Return an empty canvas or handle error for zero-dimension image
        const emptyCanvas = document.createElement('canvas');
        emptyCanvas.width = width;
        emptyCanvas.height = height;
        console.warn("Original image has zero width or height.");
        return emptyCanvas;
    }

    // 1. Create grayscale version of the image
    // We'll store grayscale values (0-255) for each pixel in an array.
    const canvas1 = document.createElement('canvas');
    canvas1.width = width;
    canvas1.height = height;
    const ctx1 = canvas1.getContext('2d', { willReadFrequently: true }); // Optimization hint
    ctx1.drawImage(originalImg, 0, 0, width, height);
    
    const imageData1 = ctx1.getImageData(0, 0, width, height);
    const data1 = imageData1.data;
    
    const grayscaleValues = new Uint8ClampedArray(width * height); 

    for (let i = 0; i < data1.length; i += 4) {
        const r = data1[i];
        const g = data1[i+1];
        const b = data1[i+2];
        // Using standard luminance calculation, rounded to nearest integer
        const gray = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
        grayscaleValues[i / 4] = gray;
    }

    // 2. Create inverted grayscale image (to be stored in canvas2)
    // This image will then be blurred.
    const canvas2 = document.createElement('canvas');
    canvas2.width = width;
    canvas2.height = height;
    const ctx2 = canvas2.getContext('2d', { willReadFrequently: true }); 
    
    const imageData2 = ctx2.createImageData(width, height);
    const data2 = imageData2.data;

    for (let i = 0; i < grayscaleValues.length; i++) {
        const invertedGray = 255 - grayscaleValues[i];
        const pixelIndex = i * 4;
        data2[pixelIndex]     = invertedGray; // R
        data2[pixelIndex + 1] = invertedGray; // G
        data2[pixelIndex + 2] = invertedGray; // B
        data2[pixelIndex + 3] = 255;          // Alpha
    }
    ctx2.putImageData(imageData2, 0, 0);

    // 3. Blur the inverted grayscale image (result in canvas3)
    const canvas3 = document.createElement('canvas');
    canvas3.width = width;
    canvas3.height = height;
    const ctx3 = canvas3.getContext('2d', { willReadFrequently: true });

    // Apply blur using canvas filter. A blurRadius of 0 means no blur.
    // The filter syntax requires a unit, e.g., 'px'.
    if (typeof blurRadius === 'number' && blurRadius > 0) {
        ctx3.filter = `blur(${blurRadius}px)`;
    }
    ctx3.drawImage(canvas2, 0, 0, width, height); // Draw canvas2 to canvas3, applying blur if filter is set

    const imageData3 = ctx3.getImageData(0, 0, width, height);
    const data3 = imageData3.data; // This is the blurred inverted grayscale image (RGBA)
    
    // Store blurred inverted grayscale values (0-255) for each pixel
    const blurredInvertedGrayscaleValues = new Uint8ClampedArray(width * height);
    for (let i = 0; i < blurredInvertedGrayscaleValues.length; i++) {
        // Image is grayscale, so R, G, and B channels are the same. Using R channel.
        blurredInvertedGrayscaleValues[i] = data3[i * 4]; 
    }

    // 4. Color Dodge blend
    // Base: original grayscale (from grayscaleValues)
    // Blend: blurred inverted grayscale (from blurredInvertedGrayscaleValues)
    // Result: sketch-like lines (stored in dodgeResultValues)
    const dodgeResultValues = new Uint8ClampedArray(width * height);
    for (let i = 0; i < grayscaleValues.length; i++) {
        const baseVal = grayscaleValues[i];
        const blendVal = blurredInvertedGrayscaleValues[i];
        
        if (blendVal === 255) { // If blend layer is white, result is white
            dodgeResultValues[i] = 255;
        } else {
            // Standard Color Dodge formula: Result = Base / (1 - Blend/255)
            // which is equivalent to Base * 255 / (255 - Blend)
            // Denominator (255 - blendVal) will be > 0 because blendVal < 255 here.
            const denominator = 255 - blendVal;
            dodgeResultValues[i] = Math.min(255, (baseVal * 255) / denominator);
        }
    }

    // 5. Final colorization to blueprint style
    // Apply line color and background color based on the intensity from dodgeResultValues
    const outputCanvas = document.createElement('canvas');
    outputCanvas.width = width;
    outputCanvas.height = height;
    const outputCtx = outputCanvas.getContext('2d'); 
    
    const outputImageData = outputCtx.createImageData(width, height);
    const outputData = outputImageData.data;

    for (let i = 0; i < dodgeResultValues.length; i++) {
        // intensity is normalized from 0 (maps to background) to 1 (maps to line color)
        const intensity = dodgeResultValues[i] / 255.0; 
        const pixelIndex = i * 4;
        
        // Linear interpolation between background color and line color
        outputData[pixelIndex]     = Math.round(intensity * lineColor.r + (1 - intensity) * backgroundColor.r); // R
        outputData[pixelIndex + 1] = Math.round(intensity * lineColor.g + (1 - intensity) * backgroundColor.g); // G
        outputData[pixelIndex + 2] = Math.round(intensity * lineColor.b + (1 - intensity) * backgroundColor.b); // B
        outputData[pixelIndex + 3] = 255; // Alpha (fully opaque)
    }
    outputCtx.putImageData(outputImageData, 0, 0);

    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 Blueprint Drawing Filter Effect tool transforms images into a blueprint-style drawing by applying a series of image processing techniques. This includes converting the original image to grayscale, inverting the colors, and blurring the result to create a sketch-like effect. Users can customize the line color and background color, allowing for various artistic representations. This tool can be used for creating unique artwork from photographs, designing visually distinct graphics for presentations, or generating creative layouts for architectural designs and engineering plans.

Leave a Reply

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