3 #include "blurwindow.h"
20 BlurConfig::BlurConfig()
28 int BlurConfig::equivalent(BlurConfig &that)
30 return (vertical == that.vertical &&
31 horizontal == that.horizontal &&
32 radius == that.radius &&
39 void BlurConfig::copy_from(BlurConfig &that)
41 vertical = that.vertical;
42 horizontal = that.horizontal;
50 void BlurConfig::interpolate(BlurConfig &prev,
54 int64_t current_frame)
56 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
57 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
60 //printf("BlurConfig::interpolate %d %d %d\n", prev_frame, next_frame, current_frame);
61 this->vertical = (int)(prev.vertical * prev_scale + next.vertical * next_scale);
62 this->horizontal = (int)(prev.horizontal * prev_scale + next.horizontal * next_scale);
63 this->radius = (int)(prev.radius * prev_scale + next.radius * next_scale);
75 REGISTER_PLUGIN(BlurMain)
84 BlurMain::BlurMain(PluginServer *server)
85 : PluginVClient(server)
91 PLUGIN_CONSTRUCTOR_MACRO
96 //printf("BlurMain::~BlurMain 1\n");
97 PLUGIN_DESTRUCTOR_MACRO
102 for(int i = 0; i < (PluginClient::smp + 1); i++)
108 char* BlurMain::plugin_title() { return N_("Blur"); }
109 int BlurMain::is_realtime() { return 1; }
112 NEW_PICON_MACRO(BlurMain)
114 SHOW_GUI_MACRO(BlurMain, BlurThread)
116 SET_STRING_MACRO(BlurMain)
118 RAISE_WINDOW_MACRO(BlurMain)
120 LOAD_CONFIGURATION_MACRO(BlurMain, BlurConfig)
125 int BlurMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
128 unsigned char **input_rows, **output_rows;
130 this->input = input_ptr;
131 this->output = output_ptr;
132 need_reconfigure |= load_configuration();
135 //printf("BlurMain::process_realtime 1 %d %d\n", need_reconfigure, config.radius);
138 int y1, y2, y_increment;
142 y_increment = input->get_h() / (smp + 1);
145 engine = new BlurEngine*[(PluginClient::smp + 1)];
146 for(int i = 0; i < (PluginClient::smp + 1); i++)
148 y2 = y1 + y_increment;
149 if(i == (PluginClient::smp + 1) - 1 &&
150 y2 < input->get_h() - 1)
151 y2 = input->get_h() - 1;
153 engine[i] = new BlurEngine(this, y1, y2);
159 for(i = 0; i < (PluginClient::smp + 1); i++)
160 engine[i]->reconfigure();
161 need_reconfigure = 0;
166 (temp->get_w() != input_ptr->get_w() ||
167 temp->get_h() != input_ptr->get_h()))
177 input_ptr->get_color_model());
179 input_rows = input_ptr->get_rows();
180 output_rows = output_ptr->get_rows();
182 if(config.radius < 2 ||
183 (!config.vertical && !config.horizontal))
185 // Data never processed so copy if necessary
186 //printf("BlurMain::process_realtime 2 %d\n", radius);
187 if(input_rows[0] != output_rows[0])
189 output_ptr->copy_from(input_ptr);
196 // Can't blur recursively. Need to blur to a temp and
197 // horizontally to the output in 2 discrete passes.
198 //printf("BlurMain::process_realtime 3 %d\n", (smp + 1));
199 for(i = 0; i < (smp + 1); i++)
201 engine[i]->start_process_frame(output_ptr, input_ptr);
204 for(i = 0; i < (smp + 1); i++)
206 engine[i]->wait_process_frame();
214 void BlurMain::update_gui()
218 load_configuration();
219 thread->window->lock_window();
220 thread->window->horizontal->update(config.horizontal);
221 thread->window->vertical->update(config.vertical);
222 thread->window->radius->update(config.radius);
223 thread->window->a->update(config.a);
224 thread->window->r->update(config.r);
225 thread->window->g->update(config.g);
226 thread->window->b->update(config.b);
227 thread->window->unlock_window();
232 int BlurMain::load_defaults()
234 char directory[1024], string[1024];
235 // set the default directory
236 sprintf(directory, "%sblur.rc", BCASTDIR);
239 defaults = new Defaults(directory);
242 config.vertical = defaults->get("VERTICAL", config.vertical);
243 config.horizontal = defaults->get("HORIZONTAL", config.horizontal);
244 config.radius = defaults->get("RADIUS", config.radius);
245 config.r = defaults->get("R", config.r);
246 config.g = defaults->get("G", config.g);
247 config.b = defaults->get("B", config.b);
248 config.a = defaults->get("A", config.a);
253 int BlurMain::save_defaults()
255 defaults->update("VERTICAL", config.vertical);
256 defaults->update("HORIZONTAL", config.horizontal);
257 defaults->update("RADIUS", config.radius);
258 defaults->update("R", config.r);
259 defaults->update("G", config.g);
260 defaults->update("B", config.b);
261 defaults->update("A", config.a);
268 void BlurMain::save_data(KeyFrame *keyframe)
272 // cause data to be stored directly in text
273 output.set_shared_string(keyframe->data, MESSAGESIZE);
274 output.tag.set_title("BLUR");
275 output.tag.set_property("VERTICAL", config.vertical);
276 output.tag.set_property("HORIZONTAL", config.horizontal);
277 output.tag.set_property("RADIUS", config.radius);
278 output.tag.set_property("R", config.r);
279 output.tag.set_property("G", config.g);
280 output.tag.set_property("B", config.b);
281 output.tag.set_property("A", config.a);
283 output.terminate_string();
286 void BlurMain::read_data(KeyFrame *keyframe)
290 input.set_shared_string(keyframe->data, strlen(keyframe->data));
296 result = input.read_tag();
300 if(input.tag.title_is("BLUR"))
302 config.vertical = input.tag.get_property("VERTICAL", config.vertical);
303 config.horizontal = input.tag.get_property("HORIZONTAL", config.horizontal);
304 config.radius = input.tag.get_property("RADIUS", config.radius);
305 //printf("BlurMain::read_data 1 %d %d %s\n", get_source_position(), keyframe->position, keyframe->data);
306 config.r = input.tag.get_property("R", config.r);
307 config.g = input.tag.get_property("G", config.g);
308 config.b = input.tag.get_property("B", config.b);
309 config.a = input.tag.get_property("A", config.a);
323 BlurEngine::BlurEngine(BlurMain *plugin, int start_out, int end_out)
326 int size = plugin->input->get_w() > plugin->input->get_h() ?
327 plugin->input->get_w() : plugin->input->get_h();
328 this->plugin = plugin;
329 this->start_out = start_out;
330 this->end_out = end_out;
332 val_p = new pixel_f[size];
333 val_m = new pixel_f[size];
334 src = new pixel_f[size];
335 dst = new pixel_f[size];
341 BlurEngine::~BlurEngine()
348 int BlurEngine::start_process_frame(VFrame *output, VFrame *input)
350 this->output = output;
356 int BlurEngine::wait_process_frame()
362 void BlurEngine::run()
372 output_lock.unlock();
376 start_in = start_out - plugin->config.radius;
377 end_in = end_out + plugin->config.radius;
378 if(start_in < 0) start_in = 0;
379 if(end_in > plugin->input->get_h()) end_in = plugin->input->get_h();
380 strip_size = end_in - start_in;
381 color_model = input->get_color_model();
382 int w = input->get_w();
383 int h = input->get_h();
389 #define BLUR(type, max, components) \
391 type **input_rows = (type **)input->get_rows(); \
392 type **output_rows = (type **)output->get_rows(); \
393 type **current_input = input_rows; \
394 type **current_output = output_rows; \
397 if(plugin->config.vertical) \
399 /* Vertical pass */ \
400 if(plugin->config.horizontal) \
402 current_output = (type **)plugin->temp->get_rows(); \
405 for(j = 0; j < w; j++) \
407 bzero(val_p, sizeof(pixel_f) * (end_in - start_in)); \
408 bzero(val_m, sizeof(pixel_f) * (end_in - start_in)); \
410 for(l = 0, k = start_in; k < end_in; l++, k++) \
412 if(plugin->config.r) src[l].r = (float)current_input[k][j * components]; \
413 if(plugin->config.g) src[l].g = (float)current_input[k][j * components + 1]; \
414 if(plugin->config.b) src[l].b = (float)current_input[k][j * components + 2]; \
415 if(components == 4) \
416 if(plugin->config.a) src[l].a = (float)current_input[k][j * components + 3]; \
419 if(components == 4) \
420 blur_strip4(strip_size); \
422 blur_strip3(strip_size); \
424 for(l = start_out - start_in, k = start_out; k < end_out; l++, k++) \
426 if(plugin->config.r) current_output[k][j * components] = (type)dst[l].r; \
427 if(plugin->config.g) current_output[k][j * components + 1] = (type)dst[l].g; \
428 if(plugin->config.b) current_output[k][j * components + 2] = (type)dst[l].b; \
429 if(components == 4) \
430 if(plugin->config.a) current_output[k][j * components + 3] = (type)dst[l].a; \
434 current_input = current_output; \
435 current_output = output_rows; \
439 if(plugin->config.horizontal) \
441 /* Horizontal pass */ \
442 for(j = start_out; j < end_out; j++) \
444 bzero(val_p, sizeof(pixel_f) * w); \
445 bzero(val_m, sizeof(pixel_f) * w); \
447 for(k = 0; k < w; k++) \
449 if(plugin->config.r) src[k].r = (float)current_input[j][k * components]; \
450 if(plugin->config.g) src[k].g = (float)current_input[j][k * components + 1]; \
451 if(plugin->config.b) src[k].b = (float)current_input[j][k * components + 2]; \
452 if(components == 4) \
453 if(plugin->config.a) src[k].a = (float)current_input[j][k * components + 3]; \
456 if(components == 4) \
461 for(k = 0; k < w; k++) \
463 if(plugin->config.r) current_output[j][k * components] = (type)dst[k].r; \
464 if(plugin->config.g) current_output[j][k * components + 1] = (type)dst[k].g; \
465 if(plugin->config.b) current_output[j][k * components + 2] = (type)dst[k].b; \
466 if(components == 4) \
467 if(plugin->config.a) current_output[j][k * components + 3] = (type)dst[k].a; \
479 BLUR(unsigned char, 0xff, 3);
486 BLUR(unsigned char, 0xff, 4);
493 BLUR(uint16_t, 0xffff, 3);
495 case BC_RGBA16161616:
496 case BC_YUVA16161616:
497 BLUR(uint16_t, 0xffff, 4);
501 output_lock.unlock();
505 int BlurEngine::reconfigure()
507 std_dev = sqrt(-(double)(plugin->config.radius * plugin->config.radius) /
508 (2 * log (1.0 / 255.0)));
512 int BlurEngine::get_constants()
518 div = sqrt(2 * M_PI) * std_dev;
519 constants[0] = -1.783 / std_dev;
520 constants[1] = -1.723 / std_dev;
521 constants[2] = 0.6318 / std_dev;
522 constants[3] = 1.997 / std_dev;
523 constants[4] = 1.6803 / div;
524 constants[5] = 3.735 / div;
525 constants[6] = -0.6803 / div;
526 constants[7] = -0.2598 / div;
528 n_p[0] = constants[4] + constants[6];
529 n_p[1] = exp(constants[1]) *
530 (constants[7] * sin(constants[3]) -
531 (constants[6] + 2 * constants[4]) * cos(constants[3])) +
533 (constants[5] * sin(constants[2]) -
534 (2 * constants[6] + constants[4]) * cos(constants[2]));
536 n_p[2] = 2 * exp(constants[0] + constants[1]) *
537 ((constants[4] + constants[6]) * cos(constants[3]) *
538 cos(constants[2]) - constants[5] *
539 cos(constants[3]) * sin(constants[2]) -
540 constants[7] * cos(constants[2]) * sin(constants[3])) +
541 constants[6] * exp(2 * constants[0]) +
542 constants[4] * exp(2 * constants[1]);
544 n_p[3] = exp(constants[1] + 2 * constants[0]) *
545 (constants[7] * sin(constants[3]) -
546 constants[6] * cos(constants[3])) +
547 exp(constants[0] + 2 * constants[1]) *
548 (constants[5] * sin(constants[2]) - constants[4] *
553 d_p[1] = -2 * exp(constants[1]) * cos(constants[3]) -
554 2 * exp(constants[0]) * cos(constants[2]);
556 d_p[2] = 4 * cos(constants[3]) * cos(constants[2]) *
557 exp(constants[0] + constants[1]) +
558 exp(2 * constants[1]) + exp (2 * constants[0]);
560 d_p[3] = -2 * cos(constants[2]) * exp(constants[0] + 2 * constants[1]) -
561 2 * cos(constants[3]) * exp(constants[1] + 2 * constants[0]);
563 d_p[4] = exp(2 * constants[0] + 2 * constants[1]);
565 for(i = 0; i < 5; i++) d_m[i] = d_p[i];
568 for(i = 1; i <= 4; i++)
569 n_m[i] = n_p[i] - d_p[i] * n_p[0];
571 double sum_n_p, sum_n_m, sum_d;
577 for(i = 0; i < 5; i++)
584 a = sum_n_p / (1 + sum_d);
585 b = sum_n_m / (1 + sum_d);
587 for (i = 0; i < 5; i++)
589 bd_p[i] = d_p[i] * a;
590 bd_m[i] = d_m[i] * b;
595 #define BOUNDARY(x) if((x) > vmax) (x) = vmax; else if((x) < 0) (x) = 0;
597 int BlurEngine::transfer_pixels(pixel_f *src1, pixel_f *src2, pixel_f *dest, int size)
602 // printf("BlurEngine::transfer_pixels %d %d %d %d\n",
606 // plugin->config.a);
608 for(i = 0; i < size; i++)
610 sum = src1[i].r + src2[i].r;
613 sum = src1[i].g + src2[i].g;
616 sum = src1[i].b + src2[i].b;
619 sum = src1[i].a + src2[i].a;
627 int BlurEngine::multiply_alpha(pixel_f *row, int size)
630 register float alpha;
632 // for(i = 0; i < size; i++)
634 // alpha = (float)row[i].a / vmax;
635 // row[i].r *= alpha;
636 // row[i].g *= alpha;
637 // row[i].b *= alpha;
642 int BlurEngine::separate_alpha(pixel_f *row, int size)
645 register float alpha;
646 register float result;
648 // for(i = 0; i < size; i++)
650 // if(row[i].a > 0 && row[i].a < vmax)
652 // alpha = (float)row[i].a / vmax;
653 // result = (float)row[i].r / alpha;
654 // row[i].r = (result > vmax ? vmax : result);
655 // result = (float)row[i].g / alpha;
656 // row[i].g = (result > vmax ? vmax : result);
657 // result = (float)row[i].b / alpha;
658 // row[i].b = (result > vmax ? vmax : result);
664 int BlurEngine::blur_strip3(int &size)
666 multiply_alpha(src, size);
669 sp_m = src + size - 1;
671 vm = val_m + size - 1;
677 for(int k = 0; k < size; k++)
679 terms = (k < 4) ? k : 4;
680 for(l = 0; l <= terms; l++)
684 vp->r += n_p[l] * sp_p[-l].r - d_p[l] * vp[-l].r;
685 vm->r += n_m[l] * sp_m[l].r - d_m[l] * vm[l].r;
689 vp->g += n_p[l] * sp_p[-l].g - d_p[l] * vp[-l].g;
690 vm->g += n_m[l] * sp_m[l].g - d_m[l] * vm[l].g;
694 vp->b += n_p[l] * sp_p[-l].b - d_p[l] * vp[-l].b;
695 vm->b += n_m[l] * sp_m[l].b - d_m[l] * vm[l].b;
702 vp->r += (n_p[l] - bd_p[l]) * initial_p.r;
703 vm->r += (n_m[l] - bd_m[l]) * initial_m.r;
707 vp->g += (n_p[l] - bd_p[l]) * initial_p.g;
708 vm->g += (n_m[l] - bd_m[l]) * initial_m.g;
712 vp->b += (n_p[l] - bd_p[l]) * initial_p.b;
713 vm->b += (n_m[l] - bd_m[l]) * initial_m.b;
721 transfer_pixels(val_p, val_m, dst, size);
722 separate_alpha(dst, size);
727 int BlurEngine::blur_strip4(int &size)
729 multiply_alpha(src, size);
732 sp_m = src + size - 1;
734 vm = val_m + size - 1;
740 for(int k = 0; k < size; k++)
742 terms = (k < 4) ? k : 4;
744 for(l = 0; l <= terms; l++)
748 vp->r += n_p[l] * sp_p[-l].r - d_p[l] * vp[-l].r;
749 vm->r += n_m[l] * sp_m[l].r - d_m[l] * vm[l].r;
753 vp->g += n_p[l] * sp_p[-l].g - d_p[l] * vp[-l].g;
754 vm->g += n_m[l] * sp_m[l].g - d_m[l] * vm[l].g;
758 vp->b += n_p[l] * sp_p[-l].b - d_p[l] * vp[-l].b;
759 vm->b += n_m[l] * sp_m[l].b - d_m[l] * vm[l].b;
763 vp->a += n_p[l] * sp_p[-l].a - d_p[l] * vp[-l].a;
764 vm->a += n_m[l] * sp_m[l].a - d_m[l] * vm[l].a;
772 vp->r += (n_p[l] - bd_p[l]) * initial_p.r;
773 vm->r += (n_m[l] - bd_m[l]) * initial_m.r;
777 vp->g += (n_p[l] - bd_p[l]) * initial_p.g;
778 vm->g += (n_m[l] - bd_m[l]) * initial_m.g;
782 vp->b += (n_p[l] - bd_p[l]) * initial_p.b;
783 vm->b += (n_m[l] - bd_m[l]) * initial_m.b;
787 vp->a += (n_p[l] - bd_p[l]) * initial_p.a;
788 vm->a += (n_m[l] - bd_m[l]) * initial_m.a;
797 transfer_pixels(val_p, val_m, dst, size);
798 separate_alpha(dst, size);