021
LVL 01 — WAVE DEFENDER SESSION 021 DAY 21

GRAYSCALE FILTER

🎫 PIXELCRAFT-009
Feature | 🔵 Easy | Priority: 🟠 High

The Grayscale button logs a message but doesn't actually process the image. Implement the grayscale filter: for each pixel, average R, G, B values and set all three channels to that average.
CONCEPTS.UNLOCKED
🔁
Loops: for
The tool for repetitive tasks. for (let i = 0; i < length; i++) — runs the body once per iteration. You'll process millions of pixels with one loop.
[ ]
Arrays
Ordered lists of values: [1, 2, 3]. Access by index: arr[0] (first), arr[arr.length - 1] (last). Pixel data is one giant flat array.
🎨
The Canvas API
The <canvas> element + getContext('2d') gives you a drawing surface. You can draw shapes, images, and — crucially — read and write individual pixels.
📥
Getting Pixel Data
ctx.getImageData() returns a Uint8ClampedArray: [R, G, B, A, R, G, B, A, ...]. Every 4 values = one pixel. Values range 0–255.
📤
Writing Pixel Data Back
ctx.putImageData(imageData, 0, 0) — writes your modified pixel array back to the canvas. The complete filter pipeline: get → modify → put.
Performance Measurement
console.time('label') and console.timeEnd('label') — measure how long your code takes. Essential for knowing if your filter is fast enough.
HANDS-ON.TASKS
01
Understand Image Pixel Data
const ctx = canvas.getContext('2d'); const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const pixels = imageData.data; // Uint8ClampedArray: [R, G, B, A, R, G, B, A, ...] console.log("Total values:", pixels.length); // width * height * 4 console.log("First pixel RGB:", pixels[0], pixels[1], pixels[2]);
A 1920×1080 image has 2,073,600 pixels × 4 channels (RGBA) = 8,294,400 values in the array. Every image you see on screen is just a grid of numbers.
02
Write the Grayscale Loop
for (let i = 0; i < pixels.length; i += 4) { const r = pixels[i]; const g = pixels[i + 1]; const b = pixels[i + 2]; // Alpha (pixels[i + 3]) stays unchanged const gray = Math.round((r + g + b) / 3); pixels[i] = gray; // R pixels[i + 1] = gray; // G pixels[i + 2] = gray; // B } ctx.putImageData(imageData, 0, 0); // Write back to canvas
i += 4 because each pixel is 4 values (RGBA). We skip Alpha — it controls transparency and shouldn't change when converting to grayscale.
03
Wire to Button

Clicking Grayscale → runs the filter → image turns grayscale!

Connect the loop to the button's click handler from Session 20.

04
Measure Performance
console.time('grayscale'); // ... filter code ... console.timeEnd('grayscale'); // "grayscale: 15ms" on a 1080p image

Try with different image sizes. How does the time scale?

05
Test & Close the Ticket

Upload different images, apply grayscale, verify results look correct.

git switch -c feature/PIXELCRAFT-009-grayscale-filter git add src/scripts/ git commit -m "Implement grayscale filter with pixel loop (PIXELCRAFT-009)" git push origin feature/PIXELCRAFT-009-grayscale-filter # PR → Review → Merge → Close ticket ✅
CS.DEEP-DIVE

Time complexity O(n).

Your loop visits every pixel exactly once. For n pixels, it does n iterations — that's O(n), linear time.

// How time scales with input size:

1080p image → ~2 million iterations
4K image    → ~8 million iterations

// Time grows proportionally with size.
// This is the most fundamental concept
// in algorithm analysis:

O(1)     → constant (array lookup)
O(log n) → logarithmic (binary search)
O(n)     → linear (your filter) ← you are here
O(n²)    → quadratic (nested loops)

// Each has dramatically different
// performance at scale.
"Pixel Art"
[A] Write a "sepia" filter: R = min(255, 0.393r + 0.769g + 0.189b), G = min(255, 0.349r + 0.686g + 0.168b), B = min(255, 0.272r + 0.534g + 0.131b).
[B] Create a "red channel only" filter: keep R, set G and B to 0. Then do the same for green-only and blue-only. View each result.
[C] Benchmark your grayscale filter at 480p, 720p, 1080p, and 4K. Plot the results — is the growth truly linear?
REF.MATERIAL
ARTICLE
Mozilla Developer Network
The official guide to getImageData, putImageData, and the pixel array. Everything you need for image filters.
CANVASPIXELSMDN
VIDEO
Programming with Mosh
Complete walkthrough of for, while, do-while, and for...of loops with practical examples and common patterns.
LOOPSFUNDAMENTALS
VIDEO
Fireship
The fastest possible intro to time complexity: O(1), O(n), O(n²), O(log n). Visual examples of how each scales.
BIG-OALGORITHMSQUICK
ARTICLE
Mozilla Developer Network
Complete reference for the for loop: syntax, variations, break, continue, and labeled loops.
LOOPSREFERENCE
ARTICLE
Mozilla Developer Network
The definitive Array reference: methods, iteration, searching, sorting. Bookmark for Sessions 22+.
ARRAYSREFERENCE
// LEAVE EXCITED BECAUSE
You turned a color photo grayscale with code you wrote. Every Instagram filter works the same way — a loop over pixels applying math. You built the core of what PixelCraft does.