@@ -74,133 +74,111 @@ std::shared_ptr<Frame> Blur::GetFrame(std::shared_ptr<Frame> frame, int64_t fram
7474 float sigma_value = sigma.GetValue (frame_number);
7575 int iteration_value = iterations.GetInt (frame_number);
7676
77-
78- // Declare arrays for each color channel
79- unsigned char *red = new unsigned char [frame_image->width () * frame_image->height ()]();
80- unsigned char *green = new unsigned char [frame_image->width () * frame_image->height ()]();
81- unsigned char *blue = new unsigned char [frame_image->width () * frame_image->height ()]();
82- unsigned char *alpha = new unsigned char [frame_image->width () * frame_image->height ()]();
83- // Create empty target RGBA arrays (for the results of our blur)
84- unsigned char *blur_red = new unsigned char [frame_image->width () * frame_image->height ()]();
85- unsigned char *blur_green = new unsigned char [frame_image->width () * frame_image->height ()]();
86- unsigned char *blur_blue = new unsigned char [frame_image->width () * frame_image->height ()]();
87- unsigned char *blur_alpha = new unsigned char [frame_image->width () * frame_image->height ()]();
77+ int w = frame_image->width ();
78+ int h = frame_image->height ();
79+
80+ // Declare 2-column arrays for each color channel
81+ typedef struct {
82+ unsigned char *red;
83+ unsigned char *green;
84+ unsigned char *blue;
85+ unsigned char *alpha;
86+ } channels;
87+
88+ channels arrays_in {
89+ new unsigned char [w * h](),
90+ new unsigned char [w * h](),
91+ new unsigned char [w * h](),
92+ new unsigned char [w * h]()
93+ };
94+ channels arrays_out {
95+ new unsigned char [w * h](),
96+ new unsigned char [w * h](),
97+ new unsigned char [w * h](),
98+ new unsigned char [w * h]()
99+ };
88100
89101 // Loop through pixels and split RGBA channels into separate arrays
90102 unsigned char *pixels = (unsigned char *) frame_image->bits ();
91- for (int pixel = 0 , byte_index=0 ; pixel < frame_image->width () * frame_image->height (); pixel++, byte_index+=4 )
103+
104+ #pragma omp parallel for
105+ for (int pixel = 0 ; pixel < w * h; ++pixel)
92106 {
93107 // Get the RGBA values from each pixel
94- unsigned char R = pixels[byte_index];
95- unsigned char G = pixels[byte_index + 1 ];
96- unsigned char B = pixels[byte_index + 2 ];
97- unsigned char A = pixels[byte_index + 3 ];
98-
99- // Split channels into their own arrays
100- red[pixel] = R;
101- green[pixel] = G;
102- blue[pixel] = B;
103- alpha[pixel] = A;
108+ arrays_in.red [pixel] = arrays_out.red [pixel] = pixels[pixel * 4 ];
109+ arrays_in.green [pixel] = arrays_out.green [pixel] = pixels[pixel * 4 + 1 ];
110+ arrays_in.blue [pixel] = arrays_out.blue [pixel] = pixels[pixel * 4 + 2 ];
111+ arrays_in.alpha [pixel] = arrays_out.alpha [pixel] = pixels[pixel * 4 + 3 ];
104112 }
105113
106- // Init target RGBA arrays
107- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) blur_red[i] = red[i];
108- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) blur_green[i] = green[i];
109- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) blur_blue[i] = blue[i];
110- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) blur_alpha[i] = alpha[i];
114+ // Initialize target struct pointers for boxBlur operations
115+ channels *array_a = &arrays_in;
116+ channels *array_b = &arrays_out;
111117
112118 // Loop through each iteration
113- for (int iteration = 0 ; iteration < iteration_value; iteration++ )
119+ for (int iteration = 0 ; iteration < iteration_value; ++iteration )
114120 {
115121 // HORIZONTAL BLUR (if any)
116122 if (horizontal_radius_value > 0.0 ) {
117- // Init boxes for computing blur
118- int *bxs = initBoxes (sigma_value, horizontal_radius_value);
119-
120123 // Apply horizontal blur to target RGBA channels
121- boxBlurH (red, blur_red, frame_image->width (), frame_image->height (), horizontal_radius_value);
122- boxBlurH (green, blur_green, frame_image->width (), frame_image->height (), horizontal_radius_value);
123- boxBlurH (blue, blur_blue, frame_image->width (), frame_image->height (), horizontal_radius_value);
124- boxBlurH (alpha, blur_alpha, frame_image->width (), frame_image->height (), horizontal_radius_value);
125-
126- // Remove boxes
127- delete[] bxs;
128-
129- // Copy blur_<chan> back to <chan> for vertical blur or next iteration
130- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) red[i] = blur_red[i];
131- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) green[i] = blur_green[i];
132- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) blue[i] = blur_blue[i];
133- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) alpha[i] = blur_alpha[i];
124+ #pragma omp parallel
125+ {
126+ boxBlurH (array_a->red , array_b->red , w, h, horizontal_radius_value);
127+ boxBlurH (array_a->green , array_b->green , w, h, horizontal_radius_value);
128+ boxBlurH (array_a->blue , array_b->blue , w, h, horizontal_radius_value);
129+ boxBlurH (array_a->alpha , array_b->alpha , w, h, horizontal_radius_value);
130+ }
131+
132+ // Swap input and output arrays
133+ channels *temp = array_a;
134+ array_a = array_b;
135+ array_b = temp;
134136 }
135137
136138 // VERTICAL BLUR (if any)
137139 if (vertical_radius_value > 0.0 ) {
138- // Init boxes for computing blur
139- int *bxs = initBoxes (sigma_value, vertical_radius_value);
140-
141140 // Apply vertical blur to target RGBA channels
142- boxBlurT (red, blur_red, frame_image->width (), frame_image->height (), vertical_radius_value);
143- boxBlurT (green, blur_green, frame_image->width (), frame_image->height (), vertical_radius_value);
144- boxBlurT (blue, blur_blue, frame_image->width (), frame_image->height (), vertical_radius_value);
145- boxBlurT (alpha, blur_alpha, frame_image->width (), frame_image->height (), vertical_radius_value);
146-
147- // Remove boxes
148- delete[] bxs;
149-
150- // Copy blur_<chan> back to <chan> for vertical blur or next iteration
151- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) red[i] = blur_red[i];
152- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) green[i] = blur_green[i];
153- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) blue[i] = blur_blue[i];
154- for (int i = 0 ; i < (frame_image->width () * frame_image->height ()); i++) alpha[i] = blur_alpha[i];
141+ #pragma omp parallel
142+ {
143+ boxBlurT (array_a->red , array_b->red , w, h, vertical_radius_value);
144+ boxBlurT (array_a->green , array_b->green , w, h, vertical_radius_value);
145+ boxBlurT (array_a->blue , array_b->blue , w, h, vertical_radius_value);
146+ boxBlurT (array_a->alpha , array_b->alpha , w, h, vertical_radius_value);
147+ }
148+
149+ // Swap input and output arrays
150+ channels *temp = array_a;
151+ array_a = array_b;
152+ array_b = temp;
155153 }
156154 }
157155
158156 // Copy RGBA channels back to original image
159- for (int pixel = 0 , byte_index=0 ; pixel < frame_image->width () * frame_image->height (); pixel++, byte_index+=4 )
157+ #pragma omp parallel for
158+ for (int pixel = 0 ; pixel < w * h; ++pixel)
160159 {
161- // Get the RGB values from the pixel
162- unsigned char R = blur_red[pixel];
163- unsigned char G = blur_green[pixel];
164- unsigned char B = blur_blue[pixel];
165- unsigned char A = blur_alpha[pixel];
166-
167- // Split channels into their own arrays
168- pixels[byte_index] = R;
169- pixels[byte_index + 1 ] = G;
170- pixels[byte_index + 2 ] = B;
171- pixels[byte_index + 3 ] = A;
160+ // Combine channels
161+ pixels[pixel * 4 ] = array_b->red [pixel];
162+ pixels[pixel * 4 + 1 ] = array_b->green [pixel];
163+ pixels[pixel * 4 + 2 ] = array_b->blue [pixel];
164+ pixels[pixel * 4 + 3 ] = array_b->alpha [pixel];
172165 }
173166
174167 // Delete channel arrays
175- delete[] red;
176- delete[] green;
177- delete[] blue;
178- delete[] alpha;
179- delete[] blur_red;
180- delete[] blur_green;
181- delete[] blur_blue;
182- delete[] blur_alpha;
168+ delete[] arrays_in.red ;
169+ delete[] arrays_in.green ;
170+ delete[] arrays_in.blue ;
171+ delete[] arrays_in.alpha ;
172+
173+ delete[] arrays_out.red ;
174+ delete[] arrays_out.green ;
175+ delete[] arrays_out.blue ;
176+ delete[] arrays_out.alpha ;
183177
184178 // return the modified frame
185179 return frame;
186180}
187181
188- // Credit: http://blog.ivank.net/fastest-gaussian-blur.html (MIT License)
189- int * Blur::initBoxes (float sigma, int n) // standard deviation, number of boxes
190- {
191- float wIdeal = sqrt ((12.0 * sigma * sigma / n) + 1.0 ); // Ideal averaging filter width
192- int wl = floor (wIdeal);
193- if (wl % 2 == 0 ) wl--;
194- int wu = wl + 2 ;
195-
196- float mIdeal = (12.0 * sigma * sigma - n * wl * wl - 4 * n * wl - 3 * n) / (-4.0 * wl - 4 );
197- int m = round (mIdeal );
198-
199- int *sizes = new int [n]();
200- for (int i = 0 ; i < n; i++) sizes[i] = i < m ? wl : wu;
201- return sizes;
202- }
203-
204182// Credit: http://blog.ivank.net/fastest-gaussian-blur.html (MIT License)
205183void Blur::boxBlurH (unsigned char *scl, unsigned char *tcl, int w, int h, int r) {
206184 float iarr = 1.0 / (r + r + 1 );
0 commit comments