Code

Canvas

Pixel Manipulation

Intermediate Direct per-pixel access via ImageData — grayscale, invert, sepia, brightness, and pixelate filters in pure TypeScript. MDN Reference

// Get raw pixel data
const imgData = ctx.getImageData(0, 0, W, H);
const d = imgData.data; // Uint8ClampedArray
// d = [R,G,B,A, R,G,B,A, ...]

// Grayscale (luminance formula)
for (let i = 0; i < d.length; i += 4) {
  const lum = 0.2126 * d[i]
             + 0.7152 * d[i+1]
             + 0.0722 * d[i+2];
  d[i] = d[i+1] = d[i+2] = lum;
}
ctx.putImageData(imgData, 0, 0);

// Invert
for (let i = 0; i < d.length; i += 4) {
  d[i]   = 255 - d[i];
  d[i+1] = 255 - d[i+1];
  d[i+2] = 255 - d[i+2];
}

// Sepia
const r = d[i], g = d[i+1], b = d[i+2];
d[i]   = Math.min(255, r*.393 + g*.769 + b*.189);
d[i+1] = Math.min(255, r*.349 + g*.686 + b*.168);
d[i+2] = Math.min(255, r*.272 + g*.534 + b*.131);

// Brightness ×1.5
d[i]   = Math.min(255, d[i]   * 1.5);
d[i+1] = Math.min(255, d[i+1] * 1.5);
d[i+2] = Math.min(255, d[i+2] * 1.5);

// Pixelate — sample top-left of block
const px = 10;
for (let y = 0; y < H; y += px) {
  for (let x = 0; x < W; x += px) {
    const base = (y * W + x) * 4;
    // fill entire px×px block with same colour
  }
}
Key APIs
  • ctx.getImageData(x, y, w, h) — reads pixels into a Uint8ClampedArray
  • ctx.putImageData(imageData, x, y) — writes pixels back to the canvas
  • ctx.createImageData(w, h) — allocates a blank pixel buffer
  • Pixel index: (row × width + col) × 4[R, G, B, A]
  • Values are clamped to 0–255 automatically by Uint8ClampedArray
  • For large images, use an OffscreenCanvas with a Web Worker to avoid blocking the main thread