The pixel loop is in 6 places with slight variations. Each has the same getImageData → loop → clamp → putImageData pattern. A bug fixed in one spot was missed in the other 5.
function createFilterPipeline(filters) {
return function(r, g, b) {
let result = [r, g, b];
for (const filter of filters) {
result = filter(...result);
}
return result;
};
}
function applyPipeline(imageData, filterFns) {
const pixels = imageData.data;
const pipeline = (r, g, b) =>
filterFns.reduce(
([r, g, b], fn) => fn(r, g, b),
[r, g, b]
);
for (let i = 0; i < pixels.length; i += 4) {
const [newR, newG, newB] = pipeline(
pixels[i], pixels[i+1], pixels[i+2]
);
pixels[i] = clamp(newR);
pixels[i + 1] = clamp(newG);
pixels[i + 2] = clamp(newB);
}
}
function getActiveFilters(state) {
const filters = [];
if (state.brightness !== 0)
filters.push((r,g,b) =>
brightness(r,g,b, state.brightness));
if (state.contrast !== 1)
filters.push((r,g,b) =>
contrast(r,g,b, state.contrast));
if (state.grayscale)
filters.push(grayscale);
if (state.invert)
filters.push(invert);
return filters;
}
Only active filters are included. The pipeline is built fresh on every render — no wasted computation on disabled filters.
Replace the Session 27 applyAllFilters() with the pipeline approach. The old function had hardcoded if-checks for each filter. The new one uses getActiveFilters() + applyPipeline().
Demonstrate Array.map() and Array.filter() on filter settings and gallery items — these methods aren't just for pixels:
// Get names of all active filters
const activeNames = Object.entries(filterState)
.filter(([key, val]) => val !== 0 && val !== 1 && val !== false)
.map(([key, val]) => `${key}: ${val}`);
// ["brightness: 50", "contrast: 1.5"]
git switch -c refactor/PIXELCRAFT-016-higher-order-functions
git add src/scripts/
git commit -m "Refactor filters to composable pipeline with HOFs (PIXELCRAFT-016)"
git push origin refactor/PIXELCRAFT-016-higher-order-functions
# PR → Review → Merge → Close ticket ✅
Functional programming and composition.
Small, pure functions composed into powerful pipelines. This is the Unix philosophy in code.