function applyConvolution(
imageData, kernel
) {
const { data, width, height } = imageData;
const output =
new Uint8ClampedArray(data);
const kSize =
Math.sqrt(kernel.length);
const half = Math.floor(kSize / 2);
for (let y = half;
y < height - half; y++) {
for (let x = half;
x < width - half; x++) {
let r = 0, g = 0, b = 0;
for (let ky = 0; ky < kSize; ky++) {
for (let kx = 0;
kx < kSize; kx++) {
const px = x + kx - half;
const py = y + ky - half;
const i =
(py * width + px) * 4;
const w =
kernel[ky * kSize + kx];
r += data[i] * w;
g += data[i + 1] * w;
b += data[i + 2] * w;
}
}
const i = (y * width + x) * 4;
output[i] = r;
output[i + 1] = g;
output[i + 2] = b;
}
}
return new ImageData(
output, width, height);
}
const KERNELS = {
blur: [
1/9, 1/9, 1/9,
1/9, 1/9, 1/9,
1/9, 1/9, 1/9
],
gaussianBlur: [
1/16, 2/16, 1/16,
2/16, 4/16, 2/16,
1/16, 2/16, 1/16
],
sharpen: [
0, -1, 0,
-1, 5, -1,
0, -1, 0
],
edgeDetect: [
-1, -1, -1,
-1, 8, -1,
-1, -1, -1
],
emboss: [
-2, -1, 0,
-1, 1, 1,
0, 1, 2
],
};
function applyColorMatrix(
imageData, matrix
) {
const d = imageData.data;
for (let i = 0; i < d.length; i += 4) {
const r = d[i], g = d[i+1],
b = d[i+2];
d[i] = r*matrix[0] + g*matrix[1]
+ b*matrix[2];
d[i+1] = r*matrix[3] + g*matrix[4]
+ b*matrix[5];
d[i+2] = r*matrix[6] + g*matrix[7]
+ b*matrix[8];
}
return imageData;
}
const SEPIA_MATRIX = [
0.393, 0.769, 0.189,
0.349, 0.686, 0.168,
0.272, 0.534, 0.131,
];
const GRAYSCALE_MATRIX = [
0.299, 0.587, 0.114,
0.299, 0.587, 0.114,
0.299, 0.587, 0.114,
];
function applyVignette(
imageData, intensity = 0.5
) {
const { data, width, height }
= imageData;
const cx = width / 2;
const cy = height / 2;
const maxDist =
Math.sqrt(cx * cx + cy * cy);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const dx = x - cx;
const dy = y - cy;
const dist =
Math.sqrt(dx * dx + dy * dy);
const factor = 1 -
((dist / maxDist) * intensity);
const i = (y * width + x) * 4;
data[i] *= factor;
data[i + 1] *= factor;
data[i + 2] *= factor;
}
}
return imageData;
}
Build an Instagram-style filter picker: render a 100px thumbnail, apply each filter to a copy, display all as clickable previews. Show filter name below each. Click to apply to the full image.
git switch -c feature/PIXELCRAFT-065-advanced-filters
git add src/
git commit -m "Add convolution filters + color matrix + vignette (PIXELCRAFT-065)"
git push origin feature/PIXELCRAFT-065-advanced-filters
# PR → Review → Merge → Close ticket ✅
Convolution is one of the most important operations in all of computing.
The same operation that blurs your photo is at the heart of Convolutional Neural Networks (CNNs) — the architecture behind modern AI image recognition.