19 Blur::Blur() : horizontal_radius(6.0), vertical_radius(6.0), sigma(3.0), iterations(3.0),
22 init_effect_details();
27 horizontal_radius(new_horizontal_radius), vertical_radius(new_vertical_radius),
31 init_effect_details();
35 void Blur::init_effect_details()
50 std::shared_ptr<openshot::Frame>
Blur::GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number)
53 std::shared_ptr<QImage> frame_image = frame->GetImage();
62 int w = frame_image->width();
63 int h = frame_image->height();
66 QImage image_copy = frame_image->copy();
67 std::shared_ptr<QImage> frame_image_2 = std::make_shared<QImage>(image_copy);
70 for (
int iteration = 0; iteration < iteration_value; ++iteration)
73 if (horizontal_radius_value > 0.0) {
75 boxBlurH(frame_image->bits(), frame_image_2->bits(), w, h, horizontal_radius_value);
78 frame_image.swap(frame_image_2);
82 if (vertical_radius_value > 0.0) {
84 boxBlurT(frame_image->bits(), frame_image_2->bits(), w, h, vertical_radius_value);
87 frame_image.swap(frame_image_2);
101 std::shared_ptr<QImage> mask_image, int64_t frame_number)
const {
103 if (!original_image || !effected_image || !mask_image)
105 if (original_image->size() != effected_image->size() || effected_image->size() != mask_image->size())
108 unsigned char* original_pixels =
reinterpret_cast<unsigned char*
>(original_image->bits());
109 unsigned char* effected_pixels =
reinterpret_cast<unsigned char*
>(effected_image->bits());
110 unsigned char* mask_pixels =
reinterpret_cast<unsigned char*
>(mask_image->bits());
111 const int pixel_count = effected_image->width() * effected_image->height();
113 #pragma omp parallel for schedule(static)
114 for (
int i = 0; i < pixel_count; ++i) {
115 const int idx = i * 4;
116 float factor =
static_cast<float>(qGray(mask_pixels[idx], mask_pixels[idx + 1], mask_pixels[idx + 2])) / 255.0f;
118 factor = 1.0f - factor;
120 factor = factor * factor;
121 const float inverse = 1.0f - factor;
124 effected_pixels[idx] =
static_cast<unsigned char>(
125 (original_pixels[idx] * inverse) + (effected_pixels[idx] * factor));
126 effected_pixels[idx + 1] =
static_cast<unsigned char>(
127 (original_pixels[idx + 1] * inverse) + (effected_pixels[idx + 1] * factor));
128 effected_pixels[idx + 2] =
static_cast<unsigned char>(
129 (original_pixels[idx + 2] * inverse) + (effected_pixels[idx + 2] * factor));
130 effected_pixels[idx + 3] = original_pixels[idx + 3];
136 void Blur::boxBlurH(
unsigned char *scl,
unsigned char *tcl,
int w,
int h,
int r) {
137 const float iarr = 1.0f / (r + r + 1);
139 #pragma omp parallel for shared(scl, tcl)
140 for (
int i = 0; i < h; ++i) {
141 const unsigned char* src = scl + i * w * 4;
142 unsigned char* dst = tcl + i * w * 4;
144 const unsigned char* first = src;
145 const unsigned char* last = src + (w - 1) * 4;
148 for (
int c = 0; c < 4; ++c)
149 val[c] = (r + 1) * first[c];
150 for (
int j = 0; j < r; ++j) {
151 const unsigned char* p = src + j * 4;
152 for (
int c = 0; c < 4; ++c)
157 for (
int j = 0; j <= r; ++j, ++ri) {
158 const unsigned char* add = src + ri * 4;
159 unsigned char* out = dst + j * 4;
160 for (
int c = 0; c < 4; ++c) {
161 val[c] += add[c] - first[c];
162 out[c] = (
unsigned char)(val[c] * iarr + 0.5f);
165 for (
int j = r + 1; j < w - r; ++j, ++li, ++ri) {
166 const unsigned char* add = src + ri * 4;
167 const unsigned char* sub = src + li * 4;
168 unsigned char* out = dst + j * 4;
169 for (
int c = 0; c < 4; ++c) {
170 val[c] += add[c] - sub[c];
171 out[c] = (
unsigned char)(val[c] * iarr + 0.5f);
174 for (
int j = w - r; j < w; ++j, ++li) {
175 const unsigned char* sub = src + li * 4;
176 unsigned char* out = dst + j * 4;
177 for (
int c = 0; c < 4; ++c) {
178 val[c] += last[c] - sub[c];
179 out[c] = (
unsigned char)(val[c] * iarr + 0.5f);
185 void Blur::boxBlurT(
unsigned char *scl,
unsigned char *tcl,
int w,
int h,
int r) {
186 const float iarr = 1.0f / (r + r + 1);
187 const int stride = w * 4;
189 #pragma omp parallel for shared(scl, tcl)
190 for (
int i = 0; i < w; ++i) {
191 const unsigned char* col_src = scl + i * 4;
192 unsigned char* col_dst = tcl + i * 4;
194 const unsigned char* first = col_src;
195 const unsigned char* last = col_src + (h - 1) * stride;
198 for (
int c = 0; c < 4; ++c)
199 val[c] = (r + 1) * first[c];
200 for (
int j = 0; j < r; ++j) {
201 const unsigned char* p = col_src + j * stride;
202 for (
int c = 0; c < 4; ++c)
207 for (
int j = 0; j <= r; ++j, ++ri) {
208 const unsigned char* add = col_src + ri * stride;
209 unsigned char* out = col_dst + j * stride;
210 for (
int c = 0; c < 4; ++c) {
211 val[c] += add[c] - first[c];
212 out[c] = (
unsigned char)(val[c] * iarr + 0.5f);
215 for (
int j = r + 1; j < h - r; ++j, ++li, ++ri) {
216 const unsigned char* add = col_src + ri * stride;
217 const unsigned char* sub = col_src + li * stride;
218 unsigned char* out = col_dst + j * stride;
219 for (
int c = 0; c < 4; ++c) {
220 val[c] += add[c] - sub[c];
221 out[c] = (
unsigned char)(val[c] * iarr + 0.5f);
224 for (
int j = h - r; j < h; ++j, ++li) {
225 const unsigned char* sub = col_src + li * stride;
226 unsigned char* out = col_dst + j * stride;
227 for (
int c = 0; c < 4; ++c) {
228 val[c] += last[c] - sub[c];
229 out[c] = (
unsigned char)(val[c] * iarr + 0.5f);
268 catch (
const std::exception& e)
271 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
282 if (!root[
"horizontal_radius"].isNull())
284 if (!root[
"vertical_radius"].isNull())
286 if (!root[
"sigma"].isNull())
288 if (!root[
"iterations"].isNull())
290 if (!root[
"mask_mode"].isNull())
310 return root.toStyledString();