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!
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.