5 #include "bcdisplayinfo.h"
10 #include "loadbalance.h"
11 #include "picon_png.h"
12 #include "pluginvclient.h"
16 #define _(String) gettext(String)
17 #define gettext_noop(String) String
18 #define N_(String) gettext_noop (String)
22 class LinearBlurEngine;
28 class LinearBlurConfig
33 int equivalent(LinearBlurConfig &that);
34 void copy_from(LinearBlurConfig &that);
35 void interpolate(LinearBlurConfig &prev,
36 LinearBlurConfig &next,
52 class LinearBlurSize : public BC_ISlider
55 LinearBlurSize(LinearBlurMain *plugin,
62 LinearBlurMain *plugin;
66 class LinearBlurToggle : public BC_CheckBox
69 LinearBlurToggle(LinearBlurMain *plugin,
75 LinearBlurMain *plugin;
79 class LinearBlurWindow : public BC_Window
82 LinearBlurWindow(LinearBlurMain *plugin, int x, int y);
88 LinearBlurSize *angle, *steps, *radius;
89 LinearBlurToggle *r, *g, *b, *a;
90 LinearBlurMain *plugin;
95 PLUGIN_THREAD_HEADER(LinearBlurMain, LinearBlurThread, LinearBlurWindow)
98 class LinearBlurMain : public PluginVClient
101 LinearBlurMain(PluginServer *server);
104 int process_realtime(VFrame *input_ptr, VFrame *output_ptr);
108 void save_data(KeyFrame *keyframe);
109 void read_data(KeyFrame *keyframe);
112 PLUGIN_CLASS_MEMBERS(LinearBlurConfig, LinearBlurThread)
114 void delete_tables();
115 VFrame *input, *output, *temp;
116 LinearBlurEngine *engine;
120 int need_reconfigure;
124 class LinearBlurPackage : public LoadPackage
131 class LinearBlurUnit : public LoadClient
134 LinearBlurUnit(LinearBlurEngine *server, LinearBlurMain *plugin);
135 void process_package(LoadPackage *package);
136 LinearBlurEngine *server;
137 LinearBlurMain *plugin;
140 class LinearBlurEngine : public LoadServer
143 LinearBlurEngine(LinearBlurMain *plugin,
146 void init_packages();
147 LoadClient* new_client();
148 LoadPackage* new_package();
149 LinearBlurMain *plugin;
170 REGISTER_PLUGIN(LinearBlurMain)
174 LinearBlurConfig::LinearBlurConfig()
185 int LinearBlurConfig::equivalent(LinearBlurConfig &that)
188 radius == that.radius &&
189 angle == that.angle &&
190 steps == that.steps &&
197 void LinearBlurConfig::copy_from(LinearBlurConfig &that)
199 radius = that.radius;
208 void LinearBlurConfig::interpolate(LinearBlurConfig &prev,
209 LinearBlurConfig &next,
214 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
215 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
216 this->radius = (int)(prev.radius * prev_scale + next.radius * next_scale + 0.5);
217 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale + 0.5);
218 this->steps = (int)(prev.steps * prev_scale + next.steps * next_scale + 0.5);
233 PLUGIN_THREAD_OBJECT(LinearBlurMain, LinearBlurThread, LinearBlurWindow)
237 LinearBlurWindow::LinearBlurWindow(LinearBlurMain *plugin, int x, int y)
238 : BC_Window(plugin->gui_string,
248 this->plugin = plugin;
251 LinearBlurWindow::~LinearBlurWindow()
255 int LinearBlurWindow::create_objects()
259 add_subwindow(new BC_Title(x, y, _("Length:")));
261 add_subwindow(radius = new LinearBlurSize(plugin, x, y, &plugin->config.radius, 0, 100));
263 add_subwindow(new BC_Title(x, y, _("Angle:")));
265 add_subwindow(angle = new LinearBlurSize(plugin, x, y, &plugin->config.angle, -180, 180));
267 add_subwindow(new BC_Title(x, y, _("Steps:")));
269 add_subwindow(steps = new LinearBlurSize(plugin, x, y, &plugin->config.steps, 1, 100));
271 add_subwindow(r = new LinearBlurToggle(plugin, x, y, &plugin->config.r, _("Red")));
273 add_subwindow(g = new LinearBlurToggle(plugin, x, y, &plugin->config.g, _("Green")));
275 add_subwindow(b = new LinearBlurToggle(plugin, x, y, &plugin->config.b, _("Blue")));
277 add_subwindow(a = new LinearBlurToggle(plugin, x, y, &plugin->config.a, _("Alpha")));
285 int LinearBlurWindow::close_event()
287 // Set result to 1 to indicate a plugin side close
301 LinearBlurToggle::LinearBlurToggle(LinearBlurMain *plugin,
306 : BC_CheckBox(x, y, *output, string)
308 this->plugin = plugin;
309 this->output = output;
312 int LinearBlurToggle::handle_event()
314 *output = get_value();
315 plugin->send_configure_change();
325 LinearBlurSize::LinearBlurSize(LinearBlurMain *plugin,
331 : BC_ISlider(x, y, 0, 200, 200, min, max, *output)
333 this->plugin = plugin;
334 this->output = output;
336 int LinearBlurSize::handle_event()
338 *output = get_value();
339 plugin->send_configure_change();
352 LinearBlurMain::LinearBlurMain(PluginServer *server)
353 : PluginVClient(server)
355 PLUGIN_CONSTRUCTOR_MACRO
361 need_reconfigure = 1;
365 LinearBlurMain::~LinearBlurMain()
367 PLUGIN_DESTRUCTOR_MACRO
368 if(engine) delete engine;
370 if(accum) delete [] accum;
371 if(temp) delete temp;
374 char* LinearBlurMain::plugin_title() { return _("Linear Blur"); }
375 int LinearBlurMain::is_realtime() { return 1; }
378 NEW_PICON_MACRO(LinearBlurMain)
380 SHOW_GUI_MACRO(LinearBlurMain, LinearBlurThread)
382 SET_STRING_MACRO(LinearBlurMain)
384 RAISE_WINDOW_MACRO(LinearBlurMain)
386 LOAD_CONFIGURATION_MACRO(LinearBlurMain, LinearBlurConfig)
388 void LinearBlurMain::delete_tables()
392 for(int i = 0; i < table_entries; i++)
393 delete [] scale_x_table[i];
394 delete [] scale_x_table;
399 for(int i = 0; i < table_entries; i++)
400 delete [] scale_y_table[i];
401 delete [] scale_y_table;
408 int LinearBlurMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
410 need_reconfigure |= load_configuration();
412 //printf("LinearBlurMain::process_realtime 1 %d\n", config.radius);
413 if(!engine) engine = new LinearBlurEngine(this,
414 get_project_smp() + 1,
415 get_project_smp() + 1);
416 if(!accum) accum = new int[input_ptr->get_w() *
418 cmodel_components(input_ptr->get_color_model())];
420 this->input = input_ptr;
421 this->output = output_ptr;
424 if(input_ptr->get_rows()[0] == output_ptr->get_rows()[0])
426 if(!temp) temp = new VFrame(0,
429 input_ptr->get_color_model());
430 temp->copy_from(input_ptr);
434 // Generate tables here. The same table is used by many packages to render
435 // each horizontal stripe. Need to cover the entire output range in each
436 // table to avoid green borders
439 int w = input->get_w();
440 int h = input->get_h();
443 int angle = config.angle;
444 int radius = config.radius * MIN(w, h) / 100;
446 while(angle < 0) angle += 360;
467 y_offset = (int)(sin((float)config.angle / 360 * 2 * M_PI) * radius);
468 x_offset = (int)(cos((float)config.angle / 360 * 2 * M_PI) * radius);
474 scale_x_table = new int*[config.steps];
475 scale_y_table = new int*[config.steps];
476 table_entries = config.steps;
478 //printf("LinearBlurMain::process_realtime 1 %d %d %d\n", radius, x_offset, y_offset);
480 for(int i = 0; i < config.steps; i++)
482 float fraction = (float)(i - config.steps / 2) / config.steps;
483 int x = (int)(fraction * x_offset);
484 int y = (int)(fraction * y_offset);
488 scale_y_table[i] = y_table = new int[h];
489 scale_x_table[i] = x_table = new int[w];
491 for(int j = 0; j < h; j++)
495 for(int j = 0; j < w; j++)
500 need_reconfigure = 0;
503 bzero(accum, input_ptr->get_w() *
505 cmodel_components(input_ptr->get_color_model()) *
507 engine->process_packages();
512 void LinearBlurMain::update_gui()
516 load_configuration();
517 thread->window->lock_window();
518 thread->window->radius->update(config.radius);
519 thread->window->angle->update(config.angle);
520 thread->window->steps->update(config.steps);
521 thread->window->r->update(config.r);
522 thread->window->g->update(config.g);
523 thread->window->b->update(config.b);
524 thread->window->a->update(config.a);
525 thread->window->unlock_window();
530 int LinearBlurMain::load_defaults()
532 char directory[1024], string[1024];
533 // set the default directory
534 sprintf(directory, "%slinearblur.rc", BCASTDIR);
537 defaults = new Defaults(directory);
540 config.radius = defaults->get("RADIUS", config.radius);
541 config.angle = defaults->get("ANGLE", config.angle);
542 config.steps = defaults->get("STEPS", config.steps);
543 config.r = defaults->get("R", config.r);
544 config.g = defaults->get("G", config.g);
545 config.b = defaults->get("B", config.b);
546 config.a = defaults->get("A", config.a);
551 int LinearBlurMain::save_defaults()
553 defaults->update("RADIUS", config.radius);
554 defaults->update("ANGLE", config.angle);
555 defaults->update("STEPS", config.steps);
556 defaults->update("R", config.r);
557 defaults->update("G", config.g);
558 defaults->update("B", config.b);
559 defaults->update("A", config.a);
566 void LinearBlurMain::save_data(KeyFrame *keyframe)
570 // cause data to be stored directly in text
571 output.set_shared_string(keyframe->data, MESSAGESIZE);
572 output.tag.set_title("LINEARBLUR");
574 output.tag.set_property("RADIUS", config.radius);
575 output.tag.set_property("ANGLE", config.angle);
576 output.tag.set_property("STEPS", config.steps);
577 output.tag.set_property("R", config.r);
578 output.tag.set_property("G", config.g);
579 output.tag.set_property("B", config.b);
580 output.tag.set_property("A", config.a);
582 output.terminate_string();
585 void LinearBlurMain::read_data(KeyFrame *keyframe)
589 input.set_shared_string(keyframe->data, strlen(keyframe->data));
595 result = input.read_tag();
599 if(input.tag.title_is("LINEARBLUR"))
601 config.radius = input.tag.get_property("RADIUS", config.radius);
602 config.angle = input.tag.get_property("ANGLE", config.angle);
603 config.steps = input.tag.get_property("STEPS", config.steps);
604 config.r = input.tag.get_property("R", config.r);
605 config.g = input.tag.get_property("G", config.g);
606 config.b = input.tag.get_property("B", config.b);
607 config.a = input.tag.get_property("A", config.a);
618 LinearBlurPackage::LinearBlurPackage()
626 LinearBlurUnit::LinearBlurUnit(LinearBlurEngine *server,
627 LinearBlurMain *plugin)
630 this->plugin = plugin;
631 this->server = server;
635 #define BLEND_LAYER(COMPONENTS, TYPE, MAX, DO_YUV) \
637 const int chroma_offset = (DO_YUV ? ((MAX + 1) / 2) : 0); \
638 for(int j = pkg->y1; j < pkg->y2; j++) \
640 int *out_row = plugin->accum + COMPONENTS * w * j; \
641 int in_y = y_table[j]; \
644 if(in_y >= 0 && in_y < h) \
646 TYPE *in_row = (TYPE*)plugin->input->get_rows()[in_y]; \
647 for(int k = 0; k < w; k++) \
649 int in_x = x_table[k]; \
651 if(in_x >= 0 && in_x < w) \
653 int in_offset = in_x * COMPONENTS; \
654 *out_row++ += in_row[in_offset]; \
657 *out_row++ += in_row[in_offset + 1]; \
658 *out_row++ += in_row[in_offset + 2]; \
662 *out_row++ += (int)in_row[in_offset + 1]; \
663 *out_row++ += (int)in_row[in_offset + 2]; \
665 if(COMPONENTS == 4) \
666 *out_row++ += in_row[in_offset + 3]; \
668 /* Blend nothing */ \
674 *out_row++ += chroma_offset; \
675 *out_row++ += chroma_offset; \
681 if(COMPONENTS == 4) out_row++; \
688 for(int k = 0; k < w; k++) \
691 *out_row++ += chroma_offset; \
692 *out_row++ += chroma_offset; \
693 if(COMPONENTS == 4) out_row++; \
698 /* Copy to output */ \
699 if(i == plugin->config.steps - 1) \
701 for(int j = pkg->y1; j < pkg->y2; j++) \
703 int *in_row = plugin->accum + COMPONENTS * w * j; \
704 TYPE *in_backup = (TYPE*)plugin->input->get_rows()[j]; \
705 TYPE *out_row = (TYPE*)plugin->output->get_rows()[j]; \
706 for(int k = 0; k < w; k++) \
710 *out_row++ = (*in_row++ * fraction) >> 16; \
715 *out_row++ = *in_backup++; \
723 *out_row++ = ((*in_row++ * fraction) >> 16); \
728 *out_row++ = *in_backup++; \
734 *out_row++ = ((*in_row++ * fraction) >> 16); \
739 *out_row++ = *in_backup++; \
747 *out_row++ = (*in_row++ * fraction) >> 16; \
752 *out_row++ = *in_backup++; \
758 *out_row++ = (*in_row++ * fraction) >> 16; \
763 *out_row++ = *in_backup++; \
768 if(COMPONENTS == 4) \
772 *out_row++ = (*in_row++ * fraction) >> 16; \
777 *out_row++ = *in_backup++; \
786 void LinearBlurUnit::process_package(LoadPackage *package)
788 LinearBlurPackage *pkg = (LinearBlurPackage*)package;
789 int h = plugin->output->get_h();
790 int w = plugin->output->get_w();
792 int fraction = 0x10000 / plugin->config.steps;
793 int do_r = plugin->config.r;
794 int do_g = plugin->config.g;
795 int do_b = plugin->config.b;
796 int do_a = plugin->config.a;
797 for(int i = 0; i < plugin->config.steps; i++)
799 int *x_table = plugin->scale_x_table[i];
800 int *y_table = plugin->scale_y_table[i];
802 switch(plugin->input->get_color_model())
805 BLEND_LAYER(3, uint8_t, 0xff, 0)
808 BLEND_LAYER(4, uint8_t, 0xff, 0)
811 BLEND_LAYER(3, uint16_t, 0xffff, 0)
813 case BC_RGBA16161616:
814 BLEND_LAYER(4, uint16_t, 0xffff, 0)
817 BLEND_LAYER(3, uint8_t, 0xff, 1)
820 BLEND_LAYER(4, uint8_t, 0xff, 1)
823 BLEND_LAYER(3, uint16_t, 0xffff, 1)
825 case BC_YUVA16161616:
826 BLEND_LAYER(4, uint16_t, 0xffff, 1)
837 LinearBlurEngine::LinearBlurEngine(LinearBlurMain *plugin,
840 : LoadServer(total_clients, total_packages)
842 this->plugin = plugin;
845 void LinearBlurEngine::init_packages()
847 int package_h = (int)((float)plugin->output->get_h() /
850 for(int i = 0; i < total_packages; i++)
852 LinearBlurPackage *package = (LinearBlurPackage*)packages[i];
854 package->y2 = y1 + package_h;
855 package->y1 = MIN(plugin->output->get_h(), package->y1);
856 package->y2 = MIN(plugin->output->get_h(), package->y2);
861 LoadClient* LinearBlurEngine::new_client()
863 return new LinearBlurUnit(this, plugin);
866 LoadPackage* LinearBlurEngine::new_package()
868 return new LinearBlurPackage;