Reading Pixel Data from Images Using Canvas — Histograms and Color Analysis

The Canvas API gives you direct access to every pixel in an image. Here's how to use that for real analysis: histograms, channel separation, and precise color picking.

Getting Raw Pixel Data

function getImageData(imageFile) { return new Promise((resolve) => { const img = new Image(); img.onload = () => { const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); resolve(ctx.getImageData(0, 0, img.width, img.height)); }; img.src = URL.createObjectURL(imageFile); }); } 

getImageData() returns a flat Uint8ClampedArray with 4 values per pixel: [R, G, B, A, R, G, B, A, ...].

Building a Histogram

A histogram counts how many pixels have each brightness value (0–255):

function buildHistogram(imageData) { const r = new Array(256).fill(0); const g = new Array(256).fill(0); const b = new Array(256).fill(0); const luma = new Array(256).fill(0); const data = imageData.data; for (let i = 0; i < data.length; i += 4) { r[data[i]]++; g[data[i + 1]]++; b[data[i + 2]]++; // Perceptual luminance (BT.601) const l = Math.round(0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2]); luma[l]++; } return { r, g, b, luma }; } 

The luma formula uses BT.601 weights, which match human perception — green contributes most to perceived brightness.

Channel Separation

To show each color channel as a grayscale image:

function extractChannel(imageData, channel) { const result = new ImageData(imageData.width, imageData.height); const src = imageData.data; const dst = result.data; const offset = { r: 0, g: 1, b: 2, a: 3 }[channel]; for (let i = 0; i < src.length; i += 4) { const value = src[i + offset]; dst[i] = dst[i + 1] = dst[i + 2] = value; dst[i + 3] = 255; } return result; } 

Pixel Color Picker

Get the exact color at a mouse position:

function getPixelColor(canvas, x, y) { const ctx = canvas.getContext('2d'); const pixel = ctx.getImageData(x, y, 1, 1).data; const [r, g, b, a] = pixel; const hex = '#' + [r, g, b].map(v => v.toString(16).padStart(2, '0')).join(''); return { r, g, b, a, hex }; } 

Gotcha: The coordinates must be relative to the canvas element, not the page. Use getBoundingClientRect() to convert mouse coordinates.

Analyze your images at toolzip.app/tools/image-inspector.