5 #include "bcdisplayinfo.h"
10 #include "loadbalance.h"
11 #include "picon_png.h"
12 #include "pluginvclient.h"
17 #define _(String) gettext(String)
18 #define gettext_noop(String) String
19 #define N_(String) gettext_noop (String)
22 class RadialBlurEngine;
28 class RadialBlurConfig
33 int equivalent(RadialBlurConfig &that);
34 void copy_from(RadialBlurConfig &that);
35 void interpolate(RadialBlurConfig &prev,
36 RadialBlurConfig &next,
53 class RadialBlurSize : public BC_ISlider
56 RadialBlurSize(RadialBlurMain *plugin,
63 RadialBlurMain *plugin;
67 class RadialBlurToggle : public BC_CheckBox
70 RadialBlurToggle(RadialBlurMain *plugin,
76 RadialBlurMain *plugin;
80 class RadialBlurWindow : public BC_Window
83 RadialBlurWindow(RadialBlurMain *plugin, int x, int y);
89 RadialBlurSize *x, *y, *steps, *angle;
90 RadialBlurToggle *r, *g, *b, *a;
91 RadialBlurMain *plugin;
96 PLUGIN_THREAD_HEADER(RadialBlurMain, RadialBlurThread, RadialBlurWindow)
99 class RadialBlurMain : public PluginVClient
102 RadialBlurMain(PluginServer *server);
105 int process_realtime(VFrame *input_ptr, VFrame *output_ptr);
109 void save_data(KeyFrame *keyframe);
110 void read_data(KeyFrame *keyframe);
113 PLUGIN_CLASS_MEMBERS(RadialBlurConfig, RadialBlurThread)
115 VFrame *input, *output, *temp;
116 RadialBlurEngine *engine;
119 class RadialBlurPackage : public LoadPackage
126 class RadialBlurUnit : public LoadClient
129 RadialBlurUnit(RadialBlurEngine *server, RadialBlurMain *plugin);
130 void process_package(LoadPackage *package);
131 RadialBlurEngine *server;
132 RadialBlurMain *plugin;
135 class RadialBlurEngine : public LoadServer
138 RadialBlurEngine(RadialBlurMain *plugin,
141 void init_packages();
142 LoadClient* new_client();
143 LoadPackage* new_package();
144 RadialBlurMain *plugin;
165 REGISTER_PLUGIN(RadialBlurMain)
169 RadialBlurConfig::RadialBlurConfig()
181 int RadialBlurConfig::equivalent(RadialBlurConfig &that)
184 angle == that.angle &&
187 steps == that.steps &&
194 void RadialBlurConfig::copy_from(RadialBlurConfig &that)
206 void RadialBlurConfig::interpolate(RadialBlurConfig &prev,
207 RadialBlurConfig &next,
212 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
213 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
214 this->x = (int)(prev.x * prev_scale + next.x * next_scale + 0.5);
215 this->y = (int)(prev.y * prev_scale + next.y * next_scale + 0.5);
216 this->steps = (int)(prev.steps * prev_scale + next.steps * next_scale + 0.5);
217 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale + 0.5);
232 PLUGIN_THREAD_OBJECT(RadialBlurMain, RadialBlurThread, RadialBlurWindow)
236 RadialBlurWindow::RadialBlurWindow(RadialBlurMain *plugin, int x, int y)
237 : BC_Window(plugin->gui_string,
247 this->plugin = plugin;
250 RadialBlurWindow::~RadialBlurWindow()
254 int RadialBlurWindow::create_objects()
258 add_subwindow(new BC_Title(x, y, _("X:")));
260 add_subwindow(this->x = new RadialBlurSize(plugin, x, y, &plugin->config.x, 0, 100));
262 add_subwindow(new BC_Title(x, y, _("Y:")));
264 add_subwindow(this->y = new RadialBlurSize(plugin, x, y, &plugin->config.y, 0, 100));
266 add_subwindow(new BC_Title(x, y, _("Angle:")));
268 add_subwindow(angle = new RadialBlurSize(plugin, x, y, &plugin->config.angle, 0, 360));
270 add_subwindow(new BC_Title(x, y, _("Steps:")));
272 add_subwindow(steps = new RadialBlurSize(plugin, x, y, &plugin->config.steps, 1, 100));
274 add_subwindow(r = new RadialBlurToggle(plugin, x, y, &plugin->config.r, _("Red")));
276 add_subwindow(g = new RadialBlurToggle(plugin, x, y, &plugin->config.g, _("Green")));
278 add_subwindow(b = new RadialBlurToggle(plugin, x, y, &plugin->config.b, _("Blue")));
280 add_subwindow(a = new RadialBlurToggle(plugin, x, y, &plugin->config.a, _("Alpha")));
288 int RadialBlurWindow::close_event()
290 // Set result to 1 to indicate a plugin side close
304 RadialBlurToggle::RadialBlurToggle(RadialBlurMain *plugin,
309 : BC_CheckBox(x, y, *output, string)
311 this->plugin = plugin;
312 this->output = output;
315 int RadialBlurToggle::handle_event()
317 *output = get_value();
318 plugin->send_configure_change();
328 RadialBlurSize::RadialBlurSize(RadialBlurMain *plugin,
334 : BC_ISlider(x, y, 0, 200, 200, min, max, *output)
336 this->plugin = plugin;
337 this->output = output;
339 int RadialBlurSize::handle_event()
341 *output = get_value();
342 plugin->send_configure_change();
355 RadialBlurMain::RadialBlurMain(PluginServer *server)
356 : PluginVClient(server)
358 PLUGIN_CONSTRUCTOR_MACRO
363 RadialBlurMain::~RadialBlurMain()
365 PLUGIN_DESTRUCTOR_MACRO
366 if(engine) delete engine;
367 if(temp) delete temp;
370 char* RadialBlurMain::plugin_title() { return _("Radial Blur"); }
371 int RadialBlurMain::is_realtime() { return 1; }
374 NEW_PICON_MACRO(RadialBlurMain)
376 SHOW_GUI_MACRO(RadialBlurMain, RadialBlurThread)
378 SET_STRING_MACRO(RadialBlurMain)
380 RAISE_WINDOW_MACRO(RadialBlurMain)
382 LOAD_CONFIGURATION_MACRO(RadialBlurMain, RadialBlurConfig)
384 int RadialBlurMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
386 load_configuration();
388 if(!engine) engine = new RadialBlurEngine(this,
389 get_project_smp() + 1,
390 get_project_smp() + 1);
392 this->input = input_ptr;
393 this->output = output_ptr;
396 if(input_ptr->get_rows()[0] == output_ptr->get_rows()[0])
398 if(!temp) temp = new VFrame(0,
401 input_ptr->get_color_model());
402 temp->copy_from(input_ptr);
406 engine->process_packages();
411 void RadialBlurMain::update_gui()
415 load_configuration();
416 thread->window->lock_window();
417 thread->window->x->update(config.x);
418 thread->window->y->update(config.y);
419 thread->window->angle->update(config.angle);
420 thread->window->steps->update(config.steps);
421 thread->window->r->update(config.r);
422 thread->window->g->update(config.g);
423 thread->window->b->update(config.b);
424 thread->window->a->update(config.a);
425 thread->window->unlock_window();
430 int RadialBlurMain::load_defaults()
432 char directory[1024], string[1024];
433 // set the default directory
434 sprintf(directory, "%sradialblur.rc", BCASTDIR);
437 defaults = new Defaults(directory);
440 config.x = defaults->get("X", config.x);
441 config.y = defaults->get("Y", config.y);
442 config.angle = defaults->get("ANGLE", config.angle);
443 config.steps = defaults->get("STEPS", config.steps);
444 config.r = defaults->get("R", config.r);
445 config.g = defaults->get("G", config.g);
446 config.b = defaults->get("B", config.b);
447 config.a = defaults->get("A", config.a);
452 int RadialBlurMain::save_defaults()
454 defaults->update("X", config.x);
455 defaults->update("Y", config.y);
456 defaults->update("ANGLE", config.angle);
457 defaults->update("STEPS", config.steps);
458 defaults->update("R", config.r);
459 defaults->update("G", config.g);
460 defaults->update("B", config.b);
461 defaults->update("A", config.a);
468 void RadialBlurMain::save_data(KeyFrame *keyframe)
472 // cause data to be stored directly in text
473 output.set_shared_string(keyframe->data, MESSAGESIZE);
474 output.tag.set_title("RADIALBLUR");
476 output.tag.set_property("X", config.x);
477 output.tag.set_property("Y", config.y);
478 output.tag.set_property("ANGLE", config.angle);
479 output.tag.set_property("STEPS", config.steps);
480 output.tag.set_property("R", config.r);
481 output.tag.set_property("G", config.g);
482 output.tag.set_property("B", config.b);
483 output.tag.set_property("A", config.a);
485 output.terminate_string();
488 void RadialBlurMain::read_data(KeyFrame *keyframe)
492 input.set_shared_string(keyframe->data, strlen(keyframe->data));
498 result = input.read_tag();
502 if(input.tag.title_is("RADIALBLUR"))
504 config.x = input.tag.get_property("X", config.x);
505 config.y = input.tag.get_property("Y", config.y);
506 config.angle = input.tag.get_property("ANGLE", config.angle);
507 config.steps = input.tag.get_property("STEPS", config.steps);
508 config.r = input.tag.get_property("R", config.r);
509 config.g = input.tag.get_property("G", config.g);
510 config.b = input.tag.get_property("B", config.b);
511 config.a = input.tag.get_property("A", config.a);
522 RadialBlurPackage::RadialBlurPackage()
528 RadialBlurUnit::RadialBlurUnit(RadialBlurEngine *server,
529 RadialBlurMain *plugin)
532 this->plugin = plugin;
533 this->server = server;
537 #define BLEND_LAYER(COMPONENTS, TYPE, MAX, DO_YUV) \
539 int chroma_offset = (DO_YUV ? ((MAX + 1) / 2) : 0); \
540 TYPE **in_rows = (TYPE**)plugin->input->get_rows(); \
541 TYPE **out_rows = (TYPE**)plugin->output->get_rows(); \
542 int steps = plugin->config.steps; \
543 double step = (double)plugin->config.angle / 360 * 2 * M_PI / steps; \
545 for(int i = pkg->y1, out_y = pkg->y1 - center_y; \
549 TYPE *out_row = out_rows[i]; \
550 TYPE *in_row = in_rows[i]; \
551 int y_square = out_y * out_y; \
553 for(int j = 0, out_x = -center_x; j < w; j++, out_x++) \
561 /* Output coordinate to polar */ \
562 double magnitude = sqrt(y_square + out_x * out_x); \
565 angle = atan((double)out_x / out_y) + M_PI; \
568 angle = atan((double)out_x / out_y); \
573 angle = M_PI * 1.5; \
575 /* Overlay all steps on this pixel*/ \
576 angle -= (double)plugin->config.angle / 360 * M_PI; \
577 for(int k = 0; k < steps; k++, angle += step) \
579 /* Polar to input coordinate */ \
580 int in_x = (int)(magnitude * sin(angle)) + center_x; \
581 int in_y = (int)(magnitude * cos(angle)) + center_y; \
583 /* Accumulate input coordinate */ \
584 if(in_x >= 0 && in_x < w && in_y >= 0 && in_y < h) \
586 accum_r += in_rows[in_y][in_x * COMPONENTS]; \
589 accum_g += (int)in_rows[in_y][in_x * COMPONENTS + 1]; \
590 accum_b += (int)in_rows[in_y][in_x * COMPONENTS + 2]; \
594 accum_g += in_rows[in_y][in_x * COMPONENTS + 1]; \
595 accum_b += in_rows[in_y][in_x * COMPONENTS + 2]; \
597 if(COMPONENTS == 4) \
598 accum_a += in_rows[in_y][in_x * COMPONENTS + 3]; \
602 accum_g += chroma_offset; \
603 accum_b += chroma_offset; \
607 /* Accumulation to output */ \
610 *out_row++ = (accum_r * fraction) >> 16; \
615 *out_row++ = *in_row++; \
621 *out_row++ = ((accum_g * fraction) >> 16); \
623 *out_row++ = (accum_g * fraction) >> 16; \
628 *out_row++ = *in_row++; \
634 *out_row++ = ((accum_b * fraction) >> 16); \
636 *out_row++ = (accum_b * fraction) >> 16; \
641 *out_row++ = *in_row++; \
644 if(COMPONENTS == 4) \
648 *out_row++ = (accum_a * fraction) >> 16; \
653 *out_row++ = *in_row++; \
660 void RadialBlurUnit::process_package(LoadPackage *package)
662 RadialBlurPackage *pkg = (RadialBlurPackage*)package;
663 int h = plugin->output->get_h();
664 int w = plugin->output->get_w();
665 int do_r = plugin->config.r;
666 int do_g = plugin->config.g;
667 int do_b = plugin->config.b;
668 int do_a = plugin->config.a;
669 int fraction = 0x10000 / plugin->config.steps;
670 int center_x = plugin->config.x * w / 100;
671 int center_y = plugin->config.y * h / 100;
673 switch(plugin->input->get_color_model())
676 BLEND_LAYER(3, uint8_t, 0xff, 0)
679 BLEND_LAYER(4, uint8_t, 0xff, 0)
682 BLEND_LAYER(3, uint16_t, 0xffff, 0)
684 case BC_RGBA16161616:
685 BLEND_LAYER(4, uint16_t, 0xffff, 0)
688 BLEND_LAYER(3, uint8_t, 0xff, 1)
691 BLEND_LAYER(4, uint8_t, 0xff, 1)
694 BLEND_LAYER(3, uint16_t, 0xffff, 1)
696 case BC_YUVA16161616:
697 BLEND_LAYER(4, uint16_t, 0xffff, 1)
707 RadialBlurEngine::RadialBlurEngine(RadialBlurMain *plugin,
710 : LoadServer(total_clients, total_packages)
711 // : LoadServer(1, 1)
713 this->plugin = plugin;
716 void RadialBlurEngine::init_packages()
718 int package_h = (int)((float)plugin->output->get_h() /
721 for(int i = 0; i < total_packages; i++)
723 RadialBlurPackage *package = (RadialBlurPackage*)packages[i];
725 package->y2 = y1 + package_h;
726 package->y1 = MIN(plugin->output->get_h(), package->y1);
727 package->y2 = MIN(plugin->output->get_h(), package->y2);
732 LoadClient* RadialBlurEngine::new_client()
734 return new RadialBlurUnit(this, plugin);
737 LoadPackage* RadialBlurEngine::new_package()
739 return new RadialBlurPackage;