Skip to content

Commit 7ed50f0

Browse files
Replace each loop with a chunk of Promises.
This is an attempt to parallelise the function.
1 parent e02128b commit 7ed50f0

File tree

1 file changed

+59
-33
lines changed

1 file changed

+59
-33
lines changed

src/utils/image.js

+59-33
Original file line numberDiff line numberDiff line change
@@ -687,11 +687,13 @@ export class RawImage {
687687
* Performs a Gaussian blur on the image.
688688
* @param {number} kernelSize - Kernel size (must be odd).
689689
* @param {number} sigma - Standard deviation of the Gaussian.
690+
* @param {number} numChunks - Number of chunks to divide the image into for parallel processing.
690691
* @returns {Promise<RawImage>} - The blurred image.
691692
*/
692-
async gaussianBlur(kernelSize = 3, sigma = 1) {
693+
async gaussianBlur(kernelSize = 3, sigma = 1, numChunks = 4) {
693694
const kernel = this.generateGaussianKernel(kernelSize, sigma);
694695
const halfSize = Math.floor(kernelSize / 2);
696+
695697
const width = this.width;
696698
const height = this.height;
697699
const channels = this.channels;
@@ -703,43 +705,67 @@ export class RawImage {
703705
const horizontalPass = new Float32Array(this.data.length);
704706
const verticalPass = new Uint8ClampedArray(this.data.length);
705707

706-
// Horizontal pass.
707-
for (let y = 0; y < height; y++) {
708-
for (let x = 0; x < width; x++) {
709-
for (let c = 0; c < channels; c++) {
710-
let sum = 0;
711-
712-
for (let kx = -halfSize; kx <= halfSize; kx++) {
713-
const pixelX = Math.min(Math.max(x + kx, 0), width - 1);
714-
const dataIndex = ((y * width) + pixelX) * channels + c;
715-
const kernelValue = kernel[kx + halfSize];
716-
sum += this.data[dataIndex] * kernelValue;
708+
const chunkHeight = Math.ceil(height / numChunks);
709+
710+
// Process horizontal pass in chunks.
711+
const horizontalPassPromises = Array.from({ length: numChunks }, (_, chunkIndex) => {
712+
return new Promise(resolve => {
713+
const startY = chunkIndex * chunkHeight;
714+
const endY = Math.min(startY + chunkHeight, height);
715+
716+
for (let y = startY; y < endY; y++) {
717+
for (let x = 0; x < width; x++) {
718+
for (let c = 0; c < channels; c++) {
719+
let sum = 0;
720+
721+
for (let kx = -halfSize; kx <= halfSize; kx++) {
722+
const pixelX = Math.min(Math.max(x + kx, 0), width - 1);
723+
const dataIndex = (((y * width) + pixelX) * channels) + c;
724+
const kernelValue = kernel[kx + halfSize];
725+
sum += this.data[dataIndex] * kernelValue;
726+
}
727+
728+
const outputIndex = (((y * width) + x) * channels) + c;
729+
horizontalPass[outputIndex] = sum;
730+
}
717731
}
718-
719-
const outputIndex = ((y * width) + x) * channels + c;
720-
horizontalPass[outputIndex] = sum;
721732
}
722-
}
723-
}
724-
725-
// Vertical pass.
726-
for (let y = 0; y < height; y++) {
727-
for (let x = 0; x < width; x++) {
728-
for (let c = 0; c < channels; c++) {
729-
let sum = 0;
733+
resolve();
734+
});
735+
});
730736

731-
for (let ky = -halfSize; ky <= halfSize; ky++) {
732-
const pixelY = Math.min(Math.max(y + ky, 0), height - 1);
733-
const dataIndex = ((pixelY * width) + x) * channels + c;
734-
const kernelValue = kernel[ky + halfSize];
735-
sum += horizontalPass[dataIndex] * kernelValue;
737+
// Wait for all horizontal chunks to complete.
738+
await Promise.all(horizontalPassPromises);
739+
740+
// Process vertical pass in chunks.
741+
const verticalPassPromises = Array.from({ length: numChunks }, (_, chunkIndex) => {
742+
return new Promise(resolve => {
743+
const startY = chunkIndex * chunkHeight;
744+
const endY = Math.min(startY + chunkHeight, height);
745+
746+
for (let y = startY; y < endY; y++) {
747+
for (let x = 0; x < width; x++) {
748+
for (let c = 0; c < channels; c++) {
749+
let sum = 0;
750+
751+
for (let ky = -halfSize; ky <= halfSize; ky++) {
752+
const pixelY = Math.min(Math.max(y + ky, 0), height - 1);
753+
const dataIndex = (((pixelY * width) + x) * channels) + c;
754+
const kernelValue = kernel[ky + halfSize];
755+
sum += horizontalPass[dataIndex] * kernelValue;
756+
}
757+
758+
const outputIndex = (((y * width) + x) * channels) + c;
759+
verticalPass[outputIndex] = sum;
760+
}
736761
}
737-
738-
const outputIndex = ((y * width) + x) * channels + c;
739-
verticalPass[outputIndex] = sum;
740762
}
741-
}
742-
}
763+
resolve();
764+
});
765+
});
766+
767+
// Wait for all vertical chunks to complete.
768+
await Promise.all(verticalPassPromises);
743769

744770
this.data = verticalPass;
745771
return this;

0 commit comments

Comments
 (0)