Skip to content

Instantly share code, notes, and snippets.

@rikschennink
Created October 11, 2021 09:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rikschennink/b65a45ede5ceecc423a6bbbfbff3b327 to your computer and use it in GitHub Desktop.
Save rikschennink/b65a45ede5ceecc423a6bbbfbff3b327 to your computer and use it in GitHub Desktop.
Convolution filter for use in worker
export default (
options: { imageData: ImageData; matrix: number[] },
done: (err: string, imageData: ImageData) => void
): void => {
const { imageData, matrix } = options;
if (!matrix) return done(null, imageData);
// calculate kernel weight
let kernelWeight = matrix.reduce((prev, curr) => prev + curr);
kernelWeight = kernelWeight <= 0 ? 1 : kernelWeight;
// input info
const inputWidth = imageData.width;
const inputHeight = imageData.height;
const inputData = imageData.data;
let i = 0;
let x = 0;
let y = 0;
const side = Math.round(Math.sqrt(matrix.length));
const sideHalf = Math.floor(side / 2);
let r = 0,
g = 0,
b = 0,
a = 0,
cx = 0,
cy = 0,
scy = 0,
scx = 0,
srcOff = 0,
weight = 0;
const outputData = new Uint8ClampedArray(inputWidth * inputHeight * 4);
for (y = 0; y < inputHeight; y++) {
for (x = 0; x < inputWidth; x++) {
// calculate the weighed sum of the source image pixels that
// fall under the convolution matrix
r = 0;
g = 0;
b = 0;
a = 0;
for (cy = 0; cy < side; cy++) {
for (cx = 0; cx < side; cx++) {
scy = y + cy - sideHalf;
scx = x + cx - sideHalf;
if (scy < 0) {
scy = inputHeight - 1;
}
if (scy >= inputHeight) {
scy = 0;
}
if (scx < 0) {
scx = inputWidth - 1;
}
if (scx >= inputWidth) {
scx = 0;
}
srcOff = (scy * inputWidth + scx) * 4;
weight = matrix[cy * side + cx];
r += inputData[srcOff] * weight;
g += inputData[srcOff + 1] * weight;
b += inputData[srcOff + 2] * weight;
a += inputData[srcOff + 3] * weight;
}
}
outputData[i] = r / kernelWeight;
outputData[i + 1] = g / kernelWeight;
outputData[i + 2] = b / kernelWeight;
outputData[i + 3] = a / kernelWeight;
i += 4;
}
}
done(null, {
data: outputData,
width: inputWidth,
height: inputHeight,
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment