Skip to content

Commit 7868157

Browse files
committed
Streamline blur effect code
1 parent 49972b2 commit 7868157

File tree

2 files changed

+74
-97
lines changed

2 files changed

+74
-97
lines changed

include/effects/Blur.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ namespace openshot
6767
void init_effect_details();
6868

6969
/// Internal blur methods (inspired and credited to http://blog.ivank.net/fastest-gaussian-blur.html)
70-
int* initBoxes(float sigma, int n);
7170
void boxBlurH(unsigned char *scl, unsigned char *tcl, int w, int h, int r);
7271
void boxBlurT(unsigned char *scl, unsigned char *tcl, int w, int h, int r);
7372

src/effects/Blur.cpp

Lines changed: 74 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
205183
void 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

Comments
 (0)