1 #include "bcdisplayinfo.h"
7 #include "loadbalance.h"
9 #include "pluginvclient.h"
17 #define _(String) gettext(String)
18 #define gettext_noop(String) String
19 #define N_(String) gettext_noop (String)
36 void copy_from(WaveConfig &src);
37 int equivalent(WaveConfig &src);
38 void interpolate(WaveConfig &prev,
50 class WaveSmear : public BC_Radial
53 WaveSmear(WaveEffect *plugin, WaveWindow *window, int x, int y);
59 class WaveBlacken : public BC_Radial
62 WaveBlacken(WaveEffect *plugin, WaveWindow *window, int x, int y);
69 class WaveReflective : public BC_CheckBox
72 WaveReflective(WaveEffect *plugin, int x, int y);
77 class WaveAmplitude : public BC_FSlider
80 WaveAmplitude(WaveEffect *plugin, int x, int y);
85 class WavePhase : public BC_FSlider
88 WavePhase(WaveEffect *plugin, int x, int y);
93 class WaveLength : public BC_FSlider
96 WaveLength(WaveEffect *plugin, int x, int y);
109 class WaveWindow : public BC_Window
112 WaveWindow(WaveEffect *plugin, int x, int y);
114 void create_objects();
119 // WaveBlacken *blacken;
120 // WaveReflective *reflective;
121 WaveAmplitude *amplitude;
123 WaveLength *wavelength;
127 PLUGIN_THREAD_HEADER(WaveEffect, WaveThread, WaveWindow)
133 class WaveServer : public LoadServer
136 WaveServer(WaveEffect *plugin, int cpus);
137 void init_packages();
138 LoadClient* new_client();
139 LoadPackage* new_package();
143 class WavePackage : public LoadPackage
150 class WaveUnit : public LoadClient
153 WaveUnit(WaveEffect *plugin, WaveServer *server);
154 void process_package(LoadPackage *package);
166 class WaveEffect : public PluginVClient
169 WaveEffect(PluginServer *server);
172 int process_realtime(VFrame *input, VFrame *output);
174 char* plugin_title();
176 int load_configuration();
179 void save_data(KeyFrame *keyframe);
180 void read_data(KeyFrame *keyframe);
188 VFrame *input, *output;
206 WaveConfig::WaveConfig()
215 void WaveConfig::copy_from(WaveConfig &src)
217 this->mode = src.mode;
218 this->reflective = src.reflective;
219 this->amplitude = src.amplitude;
220 this->phase = src.phase;
221 this->wavelength = src.wavelength;
224 int WaveConfig::equivalent(WaveConfig &src)
227 (this->mode == src.mode) &&
228 EQUIV(this->reflective, src.reflective) &&
229 EQUIV(this->amplitude, src.amplitude) &&
230 EQUIV(this->phase, src.phase) &&
231 EQUIV(this->wavelength, src.wavelength);
234 void WaveConfig::interpolate(WaveConfig &prev,
240 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
241 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
243 this->amplitude = prev.amplitude * prev_scale + next.amplitude * next_scale;
244 this->phase = prev.phase * prev_scale + next.phase * next_scale;
245 this->wavelength = prev.wavelength * prev_scale + next.wavelength * next_scale;
246 this->mode = prev.mode;
247 this->reflective = prev.reflective;
257 WaveSmear::WaveSmear(WaveEffect *plugin, WaveWindow *window, int x, int y)
258 : BC_Radial(x, y, plugin->config.mode == SMEAR, _("Smear"))
260 this->plugin = plugin;
261 this->window = window;
263 int WaveSmear::handle_event()
265 plugin->config.mode = SMEAR;
266 window->update_mode();
267 plugin->send_configure_change();
274 WaveBlacken::WaveBlacken(WaveEffect *plugin, WaveWindow *window, int x, int y)
275 : BC_Radial(x, y, plugin->config.mode == BLACKEN, _("Blacken"))
277 this->plugin = plugin;
278 this->window = window;
280 int WaveBlacken::handle_event()
282 plugin->config.mode = BLACKEN;
283 window->update_mode();
284 plugin->send_configure_change();
293 WaveReflective::WaveReflective(WaveEffect *plugin, int x, int y)
294 : BC_CheckBox(x, y, plugin->config.reflective, _("Reflective"))
296 this->plugin = plugin;
298 int WaveReflective::handle_event()
300 plugin->config.reflective = get_value();
301 plugin->send_configure_change();
306 WaveAmplitude::WaveAmplitude(WaveEffect *plugin, int x, int y)
314 plugin->config.amplitude)
316 this->plugin = plugin;
318 int WaveAmplitude::handle_event()
320 plugin->config.amplitude = get_value();
321 plugin->send_configure_change();
327 WavePhase::WavePhase(WaveEffect *plugin, int x, int y)
335 plugin->config.phase)
337 this->plugin = plugin;
339 int WavePhase::handle_event()
341 plugin->config.phase = get_value();
342 plugin->send_configure_change();
346 WaveLength::WaveLength(WaveEffect *plugin, int x, int y)
354 plugin->config.wavelength)
356 this->plugin = plugin;
358 int WaveLength::handle_event()
360 plugin->config.wavelength = get_value();
361 plugin->send_configure_change();
373 WaveWindow::WaveWindow(WaveEffect *plugin, int x, int y)
374 : BC_Window(plugin->gui_string,
385 this->plugin = plugin;
388 WaveWindow::~WaveWindow()
392 void WaveWindow::create_objects()
394 int x = 10, y = 10, x1 = 100;
396 // add_subwindow(new BC_Title(x, y, _("Mode:")));
397 // add_subwindow(smear = new WaveSmear(plugin, this, x1, y));
399 // add_subwindow(blacken = new WaveBlacken(plugin, this, x1, y));
401 // add_subwindow(reflective = new WaveReflective(plugin, x1, y));
403 add_subwindow(new BC_Title(x, y, _("Amplitude:")));
404 add_subwindow(amplitude = new WaveAmplitude(plugin, x1, y));
406 add_subwindow(new BC_Title(x, y, _("Phase:")));
407 add_subwindow(phase = new WavePhase(plugin, x1, y));
409 add_subwindow(new BC_Title(x, y, _("Wavelength:")));
410 add_subwindow(wavelength = new WaveLength(plugin, x1, y));
416 int WaveWindow::close_event()
422 void WaveWindow::update_mode()
424 // smear->update(plugin->config.mode == SMEAR);
425 // blacken->update(plugin->config.mode == BLACKEN);
429 PLUGIN_THREAD_OBJECT(WaveEffect, WaveThread, WaveWindow)
434 REGISTER_PLUGIN(WaveEffect)
439 WaveEffect::WaveEffect(PluginServer *server)
440 : PluginVClient(server)
444 PLUGIN_CONSTRUCTOR_MACRO
447 WaveEffect::~WaveEffect()
449 PLUGIN_DESTRUCTOR_MACRO
451 if(temp_frame) delete temp_frame;
452 if(engine) delete engine;
456 int WaveEffect::is_realtime()
461 char* WaveEffect::plugin_title()
466 NEW_PICON_MACRO(WaveEffect)
468 SHOW_GUI_MACRO(WaveEffect, WaveThread)
470 RAISE_WINDOW_MACRO(WaveEffect)
472 SET_STRING_MACRO(WaveEffect)
474 void WaveEffect::update_gui()
478 thread->window->lock_window();
479 load_configuration();
480 thread->window->update_mode();
481 // thread->window->reflective->update(config.reflective);
482 thread->window->amplitude->update(config.amplitude);
483 thread->window->phase->update(config.phase);
484 thread->window->wavelength->update(config.wavelength);
485 thread->window->unlock_window();
490 LOAD_CONFIGURATION_MACRO(WaveEffect, WaveConfig)
492 int WaveEffect::load_defaults()
494 char directory[BCTEXTLEN];
495 // set the default directory
496 sprintf(directory, "%swave.rc", BCASTDIR);
499 defaults = new Defaults(directory);
502 config.mode = defaults->get("MODE", config.mode);
503 config.reflective = defaults->get("REFLECTIVE", config.reflective);
504 config.amplitude = defaults->get("AMPLITUDE", config.amplitude);
505 config.phase = defaults->get("PHASE", config.phase);
506 config.wavelength = defaults->get("WAVELENGTH", config.wavelength);
510 int WaveEffect::save_defaults()
512 defaults->update("MODE", config.mode);
513 defaults->update("REFLECTIVE", config.reflective);
514 defaults->update("AMPLITUDE", config.amplitude);
515 defaults->update("PHASE", config.phase);
516 defaults->update("WAVELENGTH", config.wavelength);
521 void WaveEffect::save_data(KeyFrame *keyframe)
525 // cause data to be stored directly in text
526 output.set_shared_string(keyframe->data, MESSAGESIZE);
527 output.tag.set_title("WAVE");
528 output.tag.set_property("MODE", config.mode);
529 output.tag.set_property("REFLECTIVE", config.reflective);
530 output.tag.set_property("AMPLITUDE", config.amplitude);
531 output.tag.set_property("PHASE", config.phase);
532 output.tag.set_property("WAVELENGTH", config.wavelength);
534 output.terminate_string();
537 void WaveEffect::read_data(KeyFrame *keyframe)
541 input.set_shared_string(keyframe->data, strlen(keyframe->data));
543 while(!input.read_tag())
545 if(input.tag.title_is("WAVE"))
547 config.mode = input.tag.get_property("MODE", config.mode);
548 config.reflective = input.tag.get_property("REFLECTIVE", config.reflective);
549 config.amplitude = input.tag.get_property("AMPLITUDE", config.amplitude);
550 config.phase = input.tag.get_property("PHASE", config.phase);
551 config.wavelength = input.tag.get_property("WAVELENGTH", config.wavelength);
557 int WaveEffect::process_realtime(VFrame *input, VFrame *output)
559 load_configuration();
563 //printf("WaveEffect::process_realtime %f %d\n", config.radius, config.use_intensity);
565 this->output = output;
567 if(EQUIV(config.amplitude, 0) || EQUIV(config.wavelength, 0))
569 if(input->get_rows()[0] != output->get_rows()[0])
570 output->copy_from(input);
574 if(input->get_rows()[0] == output->get_rows()[0])
576 if(!temp_frame) temp_frame = new VFrame(0,
579 input->get_color_model());
580 temp_frame->copy_from(input);
581 this->input = temp_frame;
587 engine = new WaveServer(this, (PluginClient::smp + 1));
590 engine->process_packages();
603 WavePackage::WavePackage()
613 WaveUnit::WaveUnit(WaveEffect *plugin, WaveServer *server)
616 this->plugin = plugin;
621 #define WITHIN(a, b, c) ((((a) <= (b)) && ((b) <= (c))) ? 1 : 0)
623 static float bilinear(double x,
636 m0 = (1.0 - x) * v[0] + x * v[1];
637 m1 = (1.0 - x) * v[2] + x * v[3];
639 return((1.0 - y) * m0 + y * m1);
642 void WaveUnit::process_package(LoadPackage *package)
644 WavePackage *pkg = (WavePackage*)package;
645 int w = plugin->input->get_w();
646 int h = plugin->input->get_h();
647 double cen_x, cen_y; /* Center of wave */
648 double xhsiz, yhsiz; /* Half size of selection */
649 double radius, radius2; /* Radius and radius^2 */
653 double xscale, yscale;
659 int x1_in, y1_in, x2_in, y2_in;
660 double phase = plugin->config.phase * M_PI / 180;
666 cen_x = (double) (x2 - 1 + x1) / 2.0;
667 cen_y = (double) (y2 - 1 + y1) / 2.0;
668 xhsiz = (double) (x2 - x1) / 2.0;
669 yhsiz = (double) (y2 - y1) / 2.0;
673 xscale = yhsiz / xhsiz;
676 else if (xhsiz > yhsiz)
679 yscale = xhsiz / yhsiz;
687 radius = MAX(xhsiz, yhsiz);
688 radius2 = radius * radius;
691 wavelength = plugin->config.wavelength / 100 * radius;
696 #define WAVE(type, components, chroma_offset) \
698 int row_size = w * components; \
699 type **in_rows = (type**)plugin->input->get_rows(); \
700 for(int y = pkg->row1; y < pkg->row2; y++) \
702 type *dest = (type*)plugin->output->get_rows()[y]; \
704 for(int x = x1; x < x2; x++) \
706 dx = (x - cen_x) * xscale; \
707 dy = (y - cen_y) * yscale; \
708 d = sqrt(dx * dx + dy * dy); \
710 if(plugin->config.reflective) \
712 amnt = plugin->config.amplitude * \
713 fabs(sin(((d / wavelength) * \
717 needx = (amnt * dx) / xscale + cen_x; \
718 needy = (amnt * dy) / yscale + cen_y; \
722 amnt = plugin->config.amplitude * \
723 sin(((d / wavelength) * \
727 needx = (amnt + dx) / xscale + cen_x; \
728 needy = (amnt + dy) / yscale + cen_y; \
734 if(plugin->config.mode == SMEAR) \
757 type *p = in_rows[CLIP(yi, 0, h - 1)] + \
758 CLIP(xi, 0, w - 1) * components; \
759 x1_in = WITHIN(0, xi, w - 1); \
760 y1_in = WITHIN(0, yi, h - 1); \
761 x2_in = WITHIN(0, xi + 1, w - 1); \
762 y2_in = WITHIN(0, yi + 1, h - 1); \
765 for(int k = 0; k < components; k++) \
767 if (x1_in && y1_in) \
768 values[0] = *(p + k); \
770 values[0] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
772 if (x2_in && y1_in) \
773 values[1] = *(p + components + k); \
775 values[1] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
777 if (x1_in && y2_in) \
778 values[2] = *(p + row_size + k); \
780 values[2] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
785 values[3] = *(p + row_size + components + k); \
787 values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
790 values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
792 val = bilinear(needx, needy, values); \
794 *dest++ = (type)val; \
803 switch(plugin->input->get_color_model())
806 WAVE(unsigned char, 3, 0x0);
809 WAVE(unsigned char, 3, 0x80);
812 WAVE(uint16_t, 3, 0x0);
815 WAVE(uint16_t, 3, 0x8000);
818 WAVE(unsigned char, 4, 0x0);
821 WAVE(unsigned char, 4, 0x8000);
823 case BC_RGBA16161616:
824 WAVE(uint16_t, 4, 0x0);
826 case BC_YUVA16161616:
827 WAVE(uint16_t, 4, 0x8000);
841 WaveServer::WaveServer(WaveEffect *plugin, int cpus)
842 : LoadServer(cpus, cpus)
844 this->plugin = plugin;
847 void WaveServer::init_packages()
849 int increment = plugin->input->get_h() / LoadServer::total_packages + 1;
851 for(int i = 0; i < LoadServer::total_packages; i++)
853 WavePackage *pkg = (WavePackage*)packages[i];
855 pkg->row2 = y + increment;
857 if(pkg->row2 > plugin->input->get_h())
859 y = pkg->row2 = plugin->input->get_h();
861 if(pkg->row1 > plugin->input->get_h())
863 y = pkg->row2 = plugin->input->get_h();
869 LoadClient* WaveServer::new_client()
871 return new WaveUnit(plugin, this);
874 LoadPackage* WaveServer::new_package()
876 return new WavePackage;