r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / wave / wave.C
blob705380e7e1348ab5c30ca7a16a6fc970c3df12ad
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "defaults.h"
4 #include "filexml.h"
5 #include "guicast.h"
6 #include "keyframe.h"
7 #include "loadbalance.h"
8 #include "picon_png.h"
9 #include "pluginvclient.h"
10 #include "vframe.h"
12 #include <math.h>
13 #include <stdint.h>
14 #include <string.h>
16 #include <libintl.h>
17 #define _(String) gettext(String)
18 #define gettext_noop(String) String
19 #define N_(String) gettext_noop (String)
23 #define SMEAR 0
24 #define BLACKEN 1
28 class WaveEffect;
29 class WaveWindow;
32 class WaveConfig
34 public:
35         WaveConfig();
36         void copy_from(WaveConfig &src);
37         int equivalent(WaveConfig &src);
38         void interpolate(WaveConfig &prev, 
39                 WaveConfig &next, 
40                 long prev_frame, 
41                 long next_frame, 
42                 long current_frame);
43         int mode;
44         int reflective;
45         float amplitude;
46         float phase;
47         float wavelength;
50 class WaveSmear : public BC_Radial
52 public:
53         WaveSmear(WaveEffect *plugin, WaveWindow *window, int x, int y);
54         int handle_event();
55         WaveEffect *plugin;
56         WaveWindow *window;
59 class WaveBlacken : public BC_Radial
61 public:
62         WaveBlacken(WaveEffect *plugin, WaveWindow *window, int x, int y);
63         int handle_event();
64         WaveEffect *plugin;
65         WaveWindow *window;
69 class WaveReflective : public BC_CheckBox
71 public:
72         WaveReflective(WaveEffect *plugin, int x, int y);
73         int handle_event();
74         WaveEffect *plugin;
77 class WaveAmplitude : public BC_FSlider
79 public:
80         WaveAmplitude(WaveEffect *plugin, int x, int y);
81         int handle_event();
82         WaveEffect *plugin;
85 class WavePhase : public BC_FSlider
87 public:
88         WavePhase(WaveEffect *plugin, int x, int y);
89         int handle_event();
90         WaveEffect *plugin;
93 class WaveLength : public BC_FSlider
95 public:
96         WaveLength(WaveEffect *plugin, int x, int y);
97         int handle_event();
98         WaveEffect *plugin;
109 class WaveWindow : public BC_Window
111 public:
112         WaveWindow(WaveEffect *plugin, int x, int y);
113         ~WaveWindow();
114         void create_objects();
115         int close_event();
116         void update_mode();
117         WaveEffect *plugin;
118 //      WaveSmear *smear;
119 //      WaveBlacken *blacken;
120 //      WaveReflective *reflective;
121         WaveAmplitude *amplitude;
122         WavePhase *phase;
123         WaveLength *wavelength;
127 PLUGIN_THREAD_HEADER(WaveEffect, WaveThread, WaveWindow)
133 class WaveServer : public LoadServer
135 public:
136         WaveServer(WaveEffect *plugin, int cpus);
137         void init_packages();
138         LoadClient* new_client();
139         LoadPackage* new_package();
140         WaveEffect *plugin;
143 class WavePackage : public LoadPackage
145 public:
146         WavePackage();
147         int row1, row2;
150 class WaveUnit : public LoadClient
152 public:
153         WaveUnit(WaveEffect *plugin, WaveServer *server);
154         void process_package(LoadPackage *package);
155         WaveEffect *plugin;
166 class WaveEffect : public PluginVClient
168 public:
169         WaveEffect(PluginServer *server);
170         ~WaveEffect();
172         int process_realtime(VFrame *input, VFrame *output);
173         int is_realtime();
174         char* plugin_title();
175         VFrame* new_picon();
176         int load_configuration();
177         int load_defaults();
178         int save_defaults();
179         void save_data(KeyFrame *keyframe);
180         void read_data(KeyFrame *keyframe);
181         int show_gui();
182         int set_string();
183         void raise_window();
184         void update_gui();
186         WaveConfig config;
187         VFrame *temp_frame;
188         VFrame *input, *output;
189         Defaults *defaults;
190         WaveThread *thread;
191         WaveServer *engine;
206 WaveConfig::WaveConfig()
208         mode = SMEAR;
209         reflective = 0;
210         amplitude = 10;
211         phase = 0;
212         wavelength = 10;
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)
226         return 
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, 
235                 WaveConfig &next, 
236                 long prev_frame, 
237                 long next_frame, 
238                 long current_frame)
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();
268         return 1;
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();
285         return 1;
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();
302         return 1;
306 WaveAmplitude::WaveAmplitude(WaveEffect *plugin, int x, int y)
307  : BC_FSlider(x, 
308                         y,
309                         0,
310                         200, 
311                         200, 
312                         (float)0, 
313                         (float)100, 
314                         plugin->config.amplitude)
316         this->plugin = plugin;
318 int WaveAmplitude::handle_event()
320         plugin->config.amplitude = get_value();
321         plugin->send_configure_change();
322         return 1;
327 WavePhase::WavePhase(WaveEffect *plugin, int x, int y)
328  : BC_FSlider(x, 
329                         y,
330                         0,
331                         200, 
332                         200, 
333                         (float)0, 
334                         (float)360, 
335                         plugin->config.phase)
337         this->plugin = plugin;
339 int WavePhase::handle_event()
341         plugin->config.phase = get_value();
342         plugin->send_configure_change();
343         return 1;
346 WaveLength::WaveLength(WaveEffect *plugin, int x, int y)
347  : BC_FSlider(x, 
348                         y,
349                         0,
350                         200, 
351                         200, 
352                         (float)0, 
353                         (float)50, 
354                         plugin->config.wavelength)
356         this->plugin = plugin;
358 int WaveLength::handle_event()
360         plugin->config.wavelength = get_value();
361         plugin->send_configure_change();
362         return 1;
373 WaveWindow::WaveWindow(WaveEffect *plugin, int x, int y)
374  : BC_Window(plugin->gui_string, 
375         x, 
376         y, 
377         320, 
378         150, 
379         320, 
380         150, 
381         0, 
382         0,
383         1)
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));
398 //      y += 20;
399 //      add_subwindow(blacken = new WaveBlacken(plugin, this, x1, y));
400 //      y += 30;
401 //      add_subwindow(reflective = new WaveReflective(plugin, x1, y));
402 //      y += 30;
403         add_subwindow(new BC_Title(x, y, _("Amplitude:")));
404         add_subwindow(amplitude = new WaveAmplitude(plugin, x1, y));
405         y += 30;
406         add_subwindow(new BC_Title(x, y, _("Phase:")));
407         add_subwindow(phase = new WavePhase(plugin, x1, y));
408         y += 30;
409         add_subwindow(new BC_Title(x, y, _("Wavelength:")));
410         add_subwindow(wavelength = new WaveLength(plugin, x1, y));
412         show_window();
413         flush();
416 int WaveWindow::close_event()
418         set_done(1);
419         return 1;
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)
442         temp_frame = 0;
443         engine = 0;
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()
458         return 1;
461 char* WaveEffect::plugin_title()
463         return _("Wave");
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()
476         if(thread)
477         {
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();
486         }
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);
498 // load the defaults
499         defaults = new Defaults(directory);
500         defaults->load();
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);
507         return 0;
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);
517         defaults->save();
518         return 0;
521 void WaveEffect::save_data(KeyFrame *keyframe)
523         FileXML output;
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);
533         output.append_tag();
534         output.terminate_string();
537 void WaveEffect::read_data(KeyFrame *keyframe)
539         FileXML input;
541         input.set_shared_string(keyframe->data, strlen(keyframe->data));
543         while(!input.read_tag())
544         {
545                 if(input.tag.title_is("WAVE"))
546                 {
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);
552                 }
553         }
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);
564         this->input = input;
565         this->output = output;
567         if(EQUIV(config.amplitude, 0) || EQUIV(config.wavelength, 0))
568         {
569                 if(input->get_rows()[0] != output->get_rows()[0])
570                         output->copy_from(input);
571         }
572         else
573         {
574                 if(input->get_rows()[0] == output->get_rows()[0])
575                 {
576                         if(!temp_frame) temp_frame = new VFrame(0,
577                                 input->get_w(),
578                                 input->get_h(),
579                                 input->get_color_model());
580                         temp_frame->copy_from(input);
581                         this->input = temp_frame;
582                 }
583                 
584                 
585                 if(!engine)
586                 {
587                         engine = new WaveServer(this, (PluginClient::smp + 1));
588                 }
589                 
590                 engine->process_packages();
591         }
592         
593         
594         
595         return 0;
603 WavePackage::WavePackage()
604  : LoadPackage()
613 WaveUnit::WaveUnit(WaveEffect *plugin, WaveServer *server)
614  : LoadClient(server)
616         this->plugin = plugin;
621 #define WITHIN(a, b, c) ((((a) <= (b)) && ((b) <= (c))) ? 1 : 0)
623 static float bilinear(double  x,
624           double  y,
625           float  *v)
627         double m0, m1;
628         x = fmod(x, 1.0);
629         y = fmod(y, 1.0);
631         if(x < 0)
632         x += 1.0;
633         if(y < 0)
634         y += 1.0;
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 */
650         double amnt, d;
651         double needx, needy;
652         double dx, dy;
653         double xscale, yscale;
654         double wavelength;
655         int xi, yi;
656         float values[4];
657         float val;
658         int x1, y1, x2, y2;
659         int x1_in, y1_in, x2_in, y2_in;
660         double phase = plugin->config.phase * M_PI / 180;
661         
662         
663         x1 = y1 = 0;
664         x2 = w;
665         y2 = h;
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;
671         if (xhsiz < yhsiz)
672     {
673         xscale = yhsiz / xhsiz;
674         yscale = 1.0;
675     }
676         else if (xhsiz > yhsiz)
677     {
678         xscale = 1.0;
679         yscale = xhsiz / yhsiz;
680     }
681         else
682     {
683         xscale = 1.0;
684         yscale = 1.0;
685     }
687         radius  = MAX(xhsiz, yhsiz);
688         radius2 = radius * radius;
691         wavelength = plugin->config.wavelength / 100 * radius;
696 #define WAVE(type, components, chroma_offset) \
697 { \
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++) \
701         { \
702                 type *dest = (type*)plugin->output->get_rows()[y]; \
704                 for(int x = x1; x < x2; x++) \
705                 { \
706                         dx = (x - cen_x) * xscale; \
707                         dy = (y - cen_y) * yscale; \
708                     d = sqrt(dx * dx + dy * dy); \
710                         if(plugin->config.reflective) \
711                         { \
712                         amnt = plugin->config.amplitude *  \
713                                         fabs(sin(((d / wavelength) *  \
714                                                 (2.0 * M_PI) + \
715                                                 phase))); \
717                         needx = (amnt * dx) / xscale + cen_x; \
718                         needy = (amnt * dy) / yscale + cen_y; \
719                         } \
720                         else \
721                         { \
722                         amnt = plugin->config.amplitude *  \
723                                         sin(((d / wavelength) *  \
724                                                 (2.0 * M_PI) + \
725                                         phase)); \
727                         needx = (amnt + dx) / xscale + cen_x; \
728                         needy = (amnt + dy) / yscale + cen_y; \
729                         } \
731                         xi = (int)needx; \
732                         yi = (int)needy; \
734                         if(plugin->config.mode == SMEAR) \
735                 { \
736                         if(xi > w - 2) \
737                                 { \
738                                         xi = w - 2; \
739                                 } \
740                         else  \
741                                 if(xi < 0) \
742                                 { \
743                                         xi = 0; \
744                                 } \
746                         if(yi > h - 2) \
747                                 { \
748                                         yi = h - 2; \
749                                 } \
750                         else  \
751                                 if(yi < 0) \
752                                 { \
753                                         yi = 0; \
754                                 } \
755                 } \
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++) \
766                 { \
767                         if (x1_in && y1_in) \
768                                         values[0] = *(p + k); \
769                         else \
770                                         values[0] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
772                         if (x2_in && y1_in) \
773                                         values[1] = *(p + components + k); \
774                         else \
775                                         values[1] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
777                         if (x1_in && y2_in) \
778                                         values[2] = *(p + row_size + k); \
779                         else \
780                                         values[2] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
782                         if (x2_in) \
783                                 { \
784                                         if (y2_in) \
785                                         values[3] = *(p + row_size + components + k); \
786                                         else \
787                                         values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
788                                 } \
789                         else \
790                                         values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
792                         val = bilinear(needx, needy, values); \
794                         *dest++ = (type)val; \
795                 } \
796                 } \
797         } \
803         switch(plugin->input->get_color_model())
804         {
805                 case BC_RGB888:
806                         WAVE(unsigned char, 3, 0x0);
807                         break;
808                 case BC_YUV888:
809                         WAVE(unsigned char, 3, 0x80);
810                         break;
811                 case BC_RGB161616:
812                         WAVE(uint16_t, 3, 0x0);
813                         break;
814                 case BC_YUV161616:
815                         WAVE(uint16_t, 3, 0x8000);
816                         break;
817                 case BC_RGBA8888:
818                         WAVE(unsigned char, 4, 0x0);
819                         break;
820                 case BC_YUVA8888:
821                         WAVE(unsigned char, 4, 0x8000);
822                         break;
823                 case BC_RGBA16161616:
824                         WAVE(uint16_t, 4, 0x0);
825                         break;
826                 case BC_YUVA16161616:
827                         WAVE(uint16_t, 4, 0x8000);
828                         break;
829         }
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;
850         int y = 0;
851         for(int i = 0; i < LoadServer::total_packages; i++)
852         {
853                 WavePackage *pkg = (WavePackage*)packages[i];
854                 pkg->row1 = y;
855                 pkg->row2 = y + increment;
856                 y += increment;
857                 if(pkg->row2 > plugin->input->get_h())
858                 {
859                         y = pkg->row2 = plugin->input->get_h();
860                 }
861                 if(pkg->row1 > plugin->input->get_h())
862                 {
863                         y = pkg->row2 = plugin->input->get_h();
864                 }
865         }
869 LoadClient* WaveServer::new_client()
871         return new WaveUnit(plugin, this);
874 LoadPackage* WaveServer::new_package()
876         return new WavePackage;