5 #include "bcdisplayinfo.h"
11 #include "loadbalance.h"
12 #include "picon_png.h"
13 #include "pluginvclient.h"
18 class RadialBlurEngine;
24 class RadialBlurConfig
29 int equivalent(RadialBlurConfig &that);
30 void copy_from(RadialBlurConfig &that);
31 void interpolate(RadialBlurConfig &prev,
32 RadialBlurConfig &next,
49 class RadialBlurSize : public BC_ISlider
52 RadialBlurSize(RadialBlurMain *plugin,
59 RadialBlurMain *plugin;
63 class RadialBlurToggle : public BC_CheckBox
66 RadialBlurToggle(RadialBlurMain *plugin,
72 RadialBlurMain *plugin;
76 class RadialBlurWindow : public BC_Window
79 RadialBlurWindow(RadialBlurMain *plugin, int x, int y);
85 RadialBlurSize *x, *y, *steps, *angle;
86 RadialBlurToggle *r, *g, *b, *a;
87 RadialBlurMain *plugin;
92 PLUGIN_THREAD_HEADER(RadialBlurMain, RadialBlurThread, RadialBlurWindow)
95 class RadialBlurMain : public PluginVClient
98 RadialBlurMain(PluginServer *server);
101 int process_buffer(VFrame *frame,
102 int64_t start_position,
107 void save_data(KeyFrame *keyframe);
108 void read_data(KeyFrame *keyframe);
111 PLUGIN_CLASS_MEMBERS(RadialBlurConfig, RadialBlurThread)
113 VFrame *input, *output, *temp;
114 RadialBlurEngine *engine;
117 class RadialBlurPackage : public LoadPackage
124 class RadialBlurUnit : public LoadClient
127 RadialBlurUnit(RadialBlurEngine *server, RadialBlurMain *plugin);
128 void process_package(LoadPackage *package);
129 RadialBlurEngine *server;
130 RadialBlurMain *plugin;
133 class RadialBlurEngine : public LoadServer
136 RadialBlurEngine(RadialBlurMain *plugin,
139 void init_packages();
140 LoadClient* new_client();
141 LoadPackage* new_package();
142 RadialBlurMain *plugin;
163 REGISTER_PLUGIN(RadialBlurMain)
167 RadialBlurConfig::RadialBlurConfig()
179 int RadialBlurConfig::equivalent(RadialBlurConfig &that)
182 angle == that.angle &&
185 steps == that.steps &&
192 void RadialBlurConfig::copy_from(RadialBlurConfig &that)
204 void RadialBlurConfig::interpolate(RadialBlurConfig &prev,
205 RadialBlurConfig &next,
210 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
211 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
212 this->x = (int)(prev.x * prev_scale + next.x * next_scale + 0.5);
213 this->y = (int)(prev.y * prev_scale + next.y * next_scale + 0.5);
214 this->steps = (int)(prev.steps * prev_scale + next.steps * next_scale + 0.5);
215 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale + 0.5);
230 PLUGIN_THREAD_OBJECT(RadialBlurMain, RadialBlurThread, RadialBlurWindow)
234 RadialBlurWindow::RadialBlurWindow(RadialBlurMain *plugin, int x, int y)
235 : BC_Window(plugin->gui_string,
245 this->plugin = plugin;
248 RadialBlurWindow::~RadialBlurWindow()
252 int RadialBlurWindow::create_objects()
256 add_subwindow(new BC_Title(x, y, _("X:")));
258 add_subwindow(this->x = new RadialBlurSize(plugin, x, y, &plugin->config.x, 0, 100));
260 add_subwindow(new BC_Title(x, y, _("Y:")));
262 add_subwindow(this->y = new RadialBlurSize(plugin, x, y, &plugin->config.y, 0, 100));
264 add_subwindow(new BC_Title(x, y, _("Angle:")));
266 add_subwindow(angle = new RadialBlurSize(plugin, x, y, &plugin->config.angle, 0, 360));
268 add_subwindow(new BC_Title(x, y, _("Steps:")));
270 add_subwindow(steps = new RadialBlurSize(plugin, x, y, &plugin->config.steps, 1, 100));
272 add_subwindow(r = new RadialBlurToggle(plugin, x, y, &plugin->config.r, _("Red")));
274 add_subwindow(g = new RadialBlurToggle(plugin, x, y, &plugin->config.g, _("Green")));
276 add_subwindow(b = new RadialBlurToggle(plugin, x, y, &plugin->config.b, _("Blue")));
278 add_subwindow(a = new RadialBlurToggle(plugin, x, y, &plugin->config.a, _("Alpha")));
286 WINDOW_CLOSE_EVENT(RadialBlurWindow)
296 RadialBlurToggle::RadialBlurToggle(RadialBlurMain *plugin,
301 : BC_CheckBox(x, y, *output, string)
303 this->plugin = plugin;
304 this->output = output;
307 int RadialBlurToggle::handle_event()
309 *output = get_value();
310 plugin->send_configure_change();
320 RadialBlurSize::RadialBlurSize(RadialBlurMain *plugin,
326 : BC_ISlider(x, y, 0, 200, 200, min, max, *output)
328 this->plugin = plugin;
329 this->output = output;
331 int RadialBlurSize::handle_event()
333 *output = get_value();
334 plugin->send_configure_change();
347 RadialBlurMain::RadialBlurMain(PluginServer *server)
348 : PluginVClient(server)
350 PLUGIN_CONSTRUCTOR_MACRO
355 RadialBlurMain::~RadialBlurMain()
357 PLUGIN_DESTRUCTOR_MACRO
358 if(engine) delete engine;
359 if(temp) delete temp;
362 char* RadialBlurMain::plugin_title() { return N_("Radial Blur"); }
363 int RadialBlurMain::is_realtime() { return 1; }
366 NEW_PICON_MACRO(RadialBlurMain)
368 SHOW_GUI_MACRO(RadialBlurMain, RadialBlurThread)
370 SET_STRING_MACRO(RadialBlurMain)
372 RAISE_WINDOW_MACRO(RadialBlurMain)
374 LOAD_CONFIGURATION_MACRO(RadialBlurMain, RadialBlurConfig)
376 int RadialBlurMain::process_buffer(VFrame *frame,
377 int64_t start_position,
380 load_configuration();
385 get_source_position(),
388 if(!engine) engine = new RadialBlurEngine(this,
389 get_project_smp() + 1,
390 get_project_smp() + 1);
393 this->output = frame;
396 if(!temp) temp = new VFrame(0,
399 frame->get_color_model());
400 temp->copy_from(frame);
403 engine->process_packages();
408 void RadialBlurMain::update_gui()
412 load_configuration();
413 thread->window->lock_window();
414 thread->window->x->update(config.x);
415 thread->window->y->update(config.y);
416 thread->window->angle->update(config.angle);
417 thread->window->steps->update(config.steps);
418 thread->window->r->update(config.r);
419 thread->window->g->update(config.g);
420 thread->window->b->update(config.b);
421 thread->window->a->update(config.a);
422 thread->window->unlock_window();
427 int RadialBlurMain::load_defaults()
429 char directory[1024], string[1024];
430 // set the default directory
431 sprintf(directory, "%sradialblur.rc", BCASTDIR);
434 defaults = new BC_Hash(directory);
437 config.x = defaults->get("X", config.x);
438 config.y = defaults->get("Y", config.y);
439 config.angle = defaults->get("ANGLE", config.angle);
440 config.steps = defaults->get("STEPS", config.steps);
441 config.r = defaults->get("R", config.r);
442 config.g = defaults->get("G", config.g);
443 config.b = defaults->get("B", config.b);
444 config.a = defaults->get("A", config.a);
449 int RadialBlurMain::save_defaults()
451 defaults->update("X", config.x);
452 defaults->update("Y", config.y);
453 defaults->update("ANGLE", config.angle);
454 defaults->update("STEPS", config.steps);
455 defaults->update("R", config.r);
456 defaults->update("G", config.g);
457 defaults->update("B", config.b);
458 defaults->update("A", config.a);
465 void RadialBlurMain::save_data(KeyFrame *keyframe)
469 // cause data to be stored directly in text
470 output.set_shared_string(keyframe->data, MESSAGESIZE);
471 output.tag.set_title("RADIALBLUR");
473 output.tag.set_property("X", config.x);
474 output.tag.set_property("Y", config.y);
475 output.tag.set_property("ANGLE", config.angle);
476 output.tag.set_property("STEPS", config.steps);
477 output.tag.set_property("R", config.r);
478 output.tag.set_property("G", config.g);
479 output.tag.set_property("B", config.b);
480 output.tag.set_property("A", config.a);
482 output.terminate_string();
485 void RadialBlurMain::read_data(KeyFrame *keyframe)
489 input.set_shared_string(keyframe->data, strlen(keyframe->data));
495 result = input.read_tag();
499 if(input.tag.title_is("RADIALBLUR"))
501 config.x = input.tag.get_property("X", config.x);
502 config.y = input.tag.get_property("Y", config.y);
503 config.angle = input.tag.get_property("ANGLE", config.angle);
504 config.steps = input.tag.get_property("STEPS", config.steps);
505 config.r = input.tag.get_property("R", config.r);
506 config.g = input.tag.get_property("G", config.g);
507 config.b = input.tag.get_property("B", config.b);
508 config.a = input.tag.get_property("A", config.a);
519 RadialBlurPackage::RadialBlurPackage()
525 RadialBlurUnit::RadialBlurUnit(RadialBlurEngine *server,
526 RadialBlurMain *plugin)
529 this->plugin = plugin;
530 this->server = server;
534 #define BLEND_LAYER(COMPONENTS, TYPE, TEMP_TYPE, MAX, DO_YUV) \
536 int chroma_offset = (DO_YUV ? ((MAX + 1) / 2) : 0); \
537 TYPE **in_rows = (TYPE**)plugin->input->get_rows(); \
538 TYPE **out_rows = (TYPE**)plugin->output->get_rows(); \
539 int steps = plugin->config.steps; \
540 double step = (double)plugin->config.angle / 360 * 2 * M_PI / steps; \
542 for(int i = pkg->y1, out_y = pkg->y1 - center_y; \
546 TYPE *out_row = out_rows[i]; \
547 TYPE *in_row = in_rows[i]; \
548 int y_square = out_y * out_y; \
550 for(int j = 0, out_x = -center_x; j < w; j++, out_x++) \
553 TEMP_TYPE accum_r = 0; \
554 TEMP_TYPE accum_g = 0; \
555 TEMP_TYPE accum_b = 0; \
556 TEMP_TYPE accum_a = 0; \
558 /* Output coordinate to polar */ \
559 double magnitude = sqrt(y_square + out_x * out_x); \
562 angle = atan((double)out_x / out_y) + M_PI; \
565 angle = atan((double)out_x / out_y); \
570 angle = M_PI * 1.5; \
572 /* Overlay all steps on this pixel*/ \
573 angle -= (double)plugin->config.angle / 360 * M_PI; \
574 for(int k = 0; k < steps; k++, angle += step) \
576 /* Polar to input coordinate */ \
577 int in_x = (int)(magnitude * sin(angle)) + center_x; \
578 int in_y = (int)(magnitude * cos(angle)) + center_y; \
580 /* Accumulate input coordinate */ \
581 if(in_x >= 0 && in_x < w && in_y >= 0 && in_y < h) \
583 accum_r += in_rows[in_y][in_x * COMPONENTS]; \
586 accum_g += (int)in_rows[in_y][in_x * COMPONENTS + 1]; \
587 accum_b += (int)in_rows[in_y][in_x * COMPONENTS + 2]; \
591 accum_g += in_rows[in_y][in_x * COMPONENTS + 1]; \
592 accum_b += in_rows[in_y][in_x * COMPONENTS + 2]; \
594 if(COMPONENTS == 4) \
595 accum_a += in_rows[in_y][in_x * COMPONENTS + 3]; \
599 accum_g += chroma_offset; \
600 accum_b += chroma_offset; \
604 /* Accumulation to output */ \
607 *out_row++ = (accum_r * fraction) / 0x10000; \
612 *out_row++ = *in_row++; \
618 *out_row++ = ((accum_g * fraction) / 0x10000); \
620 *out_row++ = (accum_g * fraction) / 0x10000; \
625 *out_row++ = *in_row++; \
631 *out_row++ = (accum_b * fraction) / 0x10000; \
633 *out_row++ = (accum_b * fraction) / 0x10000; \
638 *out_row++ = *in_row++; \
641 if(COMPONENTS == 4) \
645 *out_row++ = (accum_a * fraction) / 0x10000; \
650 *out_row++ = *in_row++; \
657 void RadialBlurUnit::process_package(LoadPackage *package)
659 RadialBlurPackage *pkg = (RadialBlurPackage*)package;
660 int h = plugin->output->get_h();
661 int w = plugin->output->get_w();
662 int do_r = plugin->config.r;
663 int do_g = plugin->config.g;
664 int do_b = plugin->config.b;
665 int do_a = plugin->config.a;
666 int fraction = 0x10000 / plugin->config.steps;
667 int center_x = plugin->config.x * w / 100;
668 int center_y = plugin->config.y * h / 100;
670 switch(plugin->input->get_color_model())
673 BLEND_LAYER(3, uint8_t, int, 0xff, 0)
676 BLEND_LAYER(4, uint8_t, int, 0xff, 0)
679 BLEND_LAYER(3, float, float, 1, 0)
682 BLEND_LAYER(4, float, float, 1, 0)
685 BLEND_LAYER(3, uint16_t, int, 0xffff, 0)
687 case BC_RGBA16161616:
688 BLEND_LAYER(4, uint16_t, int, 0xffff, 0)
691 BLEND_LAYER(3, uint8_t, int, 0xff, 1)
694 BLEND_LAYER(4, uint8_t, int, 0xff, 1)
697 BLEND_LAYER(3, uint16_t, int, 0xffff, 1)
699 case BC_YUVA16161616:
700 BLEND_LAYER(4, uint16_t, int, 0xffff, 1)
710 RadialBlurEngine::RadialBlurEngine(RadialBlurMain *plugin,
713 : LoadServer(total_clients, total_packages)
714 // : LoadServer(1, 1)
716 this->plugin = plugin;
719 void RadialBlurEngine::init_packages()
721 for(int i = 0; i < get_total_packages(); i++)
723 RadialBlurPackage *package = (RadialBlurPackage*)get_package(i);
724 package->y1 = plugin->output->get_h() * i / get_total_packages();
725 package->y2 = plugin->output->get_h() * (i + 1) / get_total_packages();
729 LoadClient* RadialBlurEngine::new_client()
731 return new RadialBlurUnit(this, plugin);
734 LoadPackage* RadialBlurEngine::new_package()
736 return new RadialBlurPackage;