@@ -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