You can edit the below JavaScript code to customize the image tool.
/**
* Visualizes an image as a grid of colored squares, representing a binary (two-state) version of the image.
* It processes the input image pixel by pixel, calculates the brightness (luminance) of each pixel,
* and compares it to a specified threshold. If the brightness is above the threshold, it's considered a '1',
* otherwise it's a '0'. It then draws a corresponding colored block for each pixel on a new canvas.
*
* @param {Image} originalImg The source HTML Image object. It should be fully loaded before calling this function.
* @param {number} [blockSize=4] The size (width and height) in pixels for each square in the output grid.
* @param {number} [threshold=128] The brightness threshold (from 0 to 255) used to determine whether a pixel is 'on' (1) or 'off' (0).
* @param {string} [zeroColor='#000000'] A CSS color string for the blocks representing pixels below the threshold ('0').
* @param {string} [oneColor='#FFFFFF'] A CSS color string for the blocks representing pixels above the threshold ('1').
* @param {number} [spacing=1] The gap in pixels between each block in the grid.
* @returns {HTMLCanvasElement} A new canvas element displaying the binary visualization of the image.
*/
function processImage(originalImg, blockSize = 4, threshold = 128, zeroColor = '#000000', oneColor = '#FFFFFF', spacing = 1) {
// Ensure numeric parameters are valid numbers, falling back to defaults if not.
blockSize = Number(blockSize) || 4;
threshold = Number(threshold) || 128;
spacing = Number(spacing) || 0;
const width = originalImg.naturalWidth;
const height = originalImg.naturalHeight;
// Handle invalid or not-yet-loaded images gracefully.
if (width === 0 || height === 0) {
const emptyCanvas = document.createElement('canvas');
emptyCanvas.width = 1;
emptyCanvas.height = 1;
return emptyCanvas;
}
// Create a temporary, in-memory canvas to get the image's raw pixel data.
const tempCanvas = document.createElement('canvas');
tempCanvas.width = width;
tempCanvas.height = height;
// Using { willReadFrequently: true } can be an optimization hint for the browser.
const tempCtx = tempCanvas.getContext('2d', {
willReadFrequently: true
});
tempCtx.drawImage(originalImg, 0, 0, width, height);
let imageData;
try {
// This can throw a security error if the image is from a different origin (CORS).
imageData = tempCtx.getImageData(0, 0, width, height);
} catch (e) {
console.error("Could not get image data. The image might be from a different origin (CORS policy).", e);
const errorCanvas = document.createElement('canvas');
errorCanvas.width = 450;
errorCanvas.height = 100;
const errorCtx = errorCanvas.getContext('2d');
errorCtx.fillStyle = '#f8f8f8';
errorCtx.fillRect(0, 0, errorCanvas.width, errorCanvas.height);
errorCtx.strokeStyle = 'red';
errorCtx.strokeRect(0, 0, errorCanvas.width, errorCanvas.height);
errorCtx.fillStyle = 'red';
errorCtx.font = '16px monospace';
errorCtx.textAlign = 'center';
errorCtx.textBaseline = 'middle';
errorCtx.fillText('Error: Cannot process cross-origin image.', errorCanvas.width / 2, errorCanvas.height / 2 - 10);
errorCtx.fillText('Please use an image hosted on the same domain.', errorCanvas.width / 2, errorCanvas.height / 2 + 10);
return errorCanvas;
}
const data = imageData.data;
// Create the final output canvas.
const outputCanvas = document.createElement('canvas');
const outputCtx = outputCanvas.getContext('2d');
const totalBlockSize = blockSize + spacing;
// Calculate the dimensions of the final canvas, removing the trailing space.
outputCanvas.width = width * totalBlockSize - (spacing > 0 ? spacing : 0);
outputCanvas.height = height * totalBlockSize - (spacing > 0 ? spacing : 0);
// If there is spacing, fill the background. The spaces will reveal this color.
// We use the zeroColor as the background, assuming '0' is the 'off' or background state.
if (spacing > 0) {
outputCtx.fillStyle = zeroColor;
outputCtx.fillRect(0, 0, outputCanvas.width, outputCanvas.height);
}
// Iterate over each pixel of the source image.
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
// Calculate the index for the pixel's data in the flat array.
const index = (y * width + x) * 4;
const r = data[index];
const g = data[index + 1];
const b = data[index + 2];
// Calculate luminance using a standard formula for perceived brightness.
const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
// If the luminance is above the threshold, it's a '1' (oneColor).
if (luminance >= threshold) {
outputCtx.fillStyle = oneColor;
// Calculate the top-left corner of the block to draw.
const drawX = x * totalBlockSize;
const drawY = y * totalBlockSize;
outputCtx.fillRect(drawX, drawY, blockSize, blockSize);
}
// If the luminance is below the threshold, it's a '0' (zeroColor).
// We don't need to draw these blocks if there is spacing, because
// the background is already filled with zeroColor.
else if (spacing <= 0) {
outputCtx.fillStyle = zeroColor;
const drawX = x * totalBlockSize;
const drawY = y * totalBlockSize;
outputCtx.fillRect(drawX, drawY, blockSize, blockSize);
}
}
}
return outputCanvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Binary Data Visualizer is a tool that transforms an image into a grid of colored squares, representing a binary version of the original image. It processes each pixel to assess its brightness, using a specified threshold to determine whether each pixel is represented as ‘on’ (1) or ‘off’ (0). This allows users to visualize images in a simplified, binary format, making it useful for applications in educational contexts, graphic design, or artistic explorations where a minimalist representation of images is desired. Users can customize various parameters, including the size and color of the output pixels, enhancing flexibility for different visual requirements.