update internationalization data
[goodguy/history.git] / cinelerra-5.0 / plugins / wave / wave.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "bcdisplayinfo.h"
23 #include "clip.h"
24 #include "bchash.h"
25 #include "filexml.h"
26 #include "guicast.h"
27 #include "keyframe.h"
28 #include "language.h"
29 #include "loadbalance.h"
30 #include "pluginvclient.h"
31 #include "vframe.h"
32
33 #include <math.h>
34 #include <stdint.h>
35 #include <string.h>
36
37
38
39
40 #define SMEAR 0
41 #define BLACKEN 1
42
43
44
45 class WaveEffect;
46 class WaveWindow;
47
48
49 class WaveConfig
50 {
51 public:
52         WaveConfig();
53         void copy_from(WaveConfig &src);
54         int equivalent(WaveConfig &src);
55         void interpolate(WaveConfig &prev, 
56                 WaveConfig &next, 
57                 long prev_frame, 
58                 long next_frame, 
59                 long current_frame);
60         int mode;
61         int reflective;
62         float amplitude;
63         float phase;
64         float wavelength;
65 };
66
67 class WaveSmear : public BC_Radial
68 {
69 public:
70         WaveSmear(WaveEffect *plugin, WaveWindow *window, int x, int y);
71         int handle_event();
72         WaveEffect *plugin;
73         WaveWindow *window;
74 };
75
76 class WaveBlacken : public BC_Radial
77 {
78 public:
79         WaveBlacken(WaveEffect *plugin, WaveWindow *window, int x, int y);
80         int handle_event();
81         WaveEffect *plugin;
82         WaveWindow *window;
83 };
84
85
86 class WaveReflective : public BC_CheckBox
87 {
88 public:
89         WaveReflective(WaveEffect *plugin, int x, int y);
90         int handle_event();
91         WaveEffect *plugin;
92 };
93
94 class WaveAmplitude : public BC_FSlider
95 {
96 public:
97         WaveAmplitude(WaveEffect *plugin, int x, int y);
98         int handle_event();
99         WaveEffect *plugin;
100 };
101
102 class WavePhase : public BC_FSlider
103 {
104 public:
105         WavePhase(WaveEffect *plugin, int x, int y);
106         int handle_event();
107         WaveEffect *plugin;
108 };
109
110 class WaveLength : public BC_FSlider
111 {
112 public:
113         WaveLength(WaveEffect *plugin, int x, int y);
114         int handle_event();
115         WaveEffect *plugin;
116 };
117
118
119
120
121
122
123
124
125
126 class WaveWindow : public PluginClientWindow
127 {
128 public:
129         WaveWindow(WaveEffect *plugin);
130         ~WaveWindow();
131         void create_objects();
132         void update_mode();
133         WaveEffect *plugin;
134 //      WaveSmear *smear;
135 //      WaveBlacken *blacken;
136 //      WaveReflective *reflective;
137         WaveAmplitude *amplitude;
138         WavePhase *phase;
139         WaveLength *wavelength;
140 };
141
142
143
144
145
146
147
148 class WaveServer : public LoadServer
149 {
150 public:
151         WaveServer(WaveEffect *plugin, int cpus);
152         void init_packages();
153         LoadClient* new_client();
154         LoadPackage* new_package();
155         WaveEffect *plugin;
156 };
157
158 class WavePackage : public LoadPackage
159 {
160 public:
161         WavePackage();
162         int row1, row2;
163 };
164
165 class WaveUnit : public LoadClient
166 {
167 public:
168         WaveUnit(WaveEffect *plugin, WaveServer *server);
169         void process_package(LoadPackage *package);
170         WaveEffect *plugin;
171 };
172
173
174
175
176
177
178
179
180
181 class WaveEffect : public PluginVClient
182 {
183 public:
184         WaveEffect(PluginServer *server);
185         ~WaveEffect();
186
187         PLUGIN_CLASS_MEMBERS(WaveConfig)
188         int process_realtime(VFrame *input, VFrame *output);
189         int is_realtime();
190         void save_data(KeyFrame *keyframe);
191         void read_data(KeyFrame *keyframe);
192         void update_gui();
193
194         VFrame *temp_frame;
195         VFrame *input, *output;
196         WaveServer *engine;
197 };
198
199
200
201
202
203
204
205
206
207
208
209
210
211 WaveConfig::WaveConfig()
212 {
213         mode = SMEAR;
214         reflective = 0;
215         amplitude = 10;
216         phase = 0;
217         wavelength = 10;
218 }
219
220 void WaveConfig::copy_from(WaveConfig &src)
221 {
222         this->mode = src.mode;
223         this->reflective = src.reflective;
224         this->amplitude = src.amplitude;
225         this->phase = src.phase;
226         this->wavelength = src.wavelength;
227 }
228
229 int WaveConfig::equivalent(WaveConfig &src)
230 {
231         return 
232                 (this->mode == src.mode) &&
233                 EQUIV(this->reflective, src.reflective) &&
234                 EQUIV(this->amplitude, src.amplitude) &&
235                 EQUIV(this->phase, src.phase) &&
236                 EQUIV(this->wavelength, src.wavelength);
237 }
238
239 void WaveConfig::interpolate(WaveConfig &prev, 
240                 WaveConfig &next, 
241                 long prev_frame, 
242                 long next_frame, 
243                 long current_frame)
244 {
245         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
246         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
247
248         this->amplitude = prev.amplitude * prev_scale + next.amplitude * next_scale;
249         this->phase = prev.phase * prev_scale + next.phase * next_scale;
250         this->wavelength = prev.wavelength * prev_scale + next.wavelength * next_scale;
251         this->mode = prev.mode;
252         this->reflective = prev.reflective;
253 }
254
255
256
257
258
259
260
261
262 WaveSmear::WaveSmear(WaveEffect *plugin, WaveWindow *window, int x, int y)
263  : BC_Radial(x, y, plugin->config.mode == SMEAR, _("Smear"))
264 {
265         this->plugin = plugin;
266         this->window = window;
267 }
268 int WaveSmear::handle_event()
269 {
270         plugin->config.mode = SMEAR;
271         window->update_mode();
272         plugin->send_configure_change();
273         return 1;
274 }
275
276
277
278
279 WaveBlacken::WaveBlacken(WaveEffect *plugin, WaveWindow *window, int x, int y)
280  : BC_Radial(x, y, plugin->config.mode == BLACKEN, _("Blacken"))
281 {
282         this->plugin = plugin;
283         this->window = window;
284 }
285 int WaveBlacken::handle_event()
286 {
287         plugin->config.mode = BLACKEN;
288         window->update_mode();
289         plugin->send_configure_change();
290         return 1;
291 }
292
293
294
295
296
297
298 WaveReflective::WaveReflective(WaveEffect *plugin, int x, int y)
299  : BC_CheckBox(x, y, plugin->config.reflective, _("Reflective"))
300 {
301         this->plugin = plugin;
302 }
303 int WaveReflective::handle_event()
304 {
305         plugin->config.reflective = get_value();
306         plugin->send_configure_change();
307         return 1;
308 }
309
310
311 WaveAmplitude::WaveAmplitude(WaveEffect *plugin, int x, int y)
312  : BC_FSlider(x, 
313                         y,
314                         0,
315                         200, 
316                         200, 
317                         (float)0, 
318                         (float)100, 
319                         plugin->config.amplitude)
320 {
321         this->plugin = plugin;
322 }
323 int WaveAmplitude::handle_event()
324 {
325         plugin->config.amplitude = get_value();
326         plugin->send_configure_change();
327         return 1;
328 }
329
330
331
332 WavePhase::WavePhase(WaveEffect *plugin, int x, int y)
333  : BC_FSlider(x, 
334                         y,
335                         0,
336                         200, 
337                         200, 
338                         (float)0, 
339                         (float)360, 
340                         plugin->config.phase)
341 {
342         this->plugin = plugin;
343 }
344 int WavePhase::handle_event()
345 {
346         plugin->config.phase = get_value();
347         plugin->send_configure_change();
348         return 1;
349 }
350
351 WaveLength::WaveLength(WaveEffect *plugin, int x, int y)
352  : BC_FSlider(x, 
353                         y,
354                         0,
355                         200, 
356                         200, 
357                         (float)0, 
358                         (float)50, 
359                         plugin->config.wavelength)
360 {
361         this->plugin = plugin;
362 }
363 int WaveLength::handle_event()
364 {
365         plugin->config.wavelength = get_value();
366         plugin->send_configure_change();
367         return 1;
368 }
369
370
371
372
373
374
375
376
377
378 WaveWindow::WaveWindow(WaveEffect *plugin)
379  : PluginClientWindow(plugin, 
380         320, 
381         150, 
382         320, 
383         150, 
384         0)
385 {
386         this->plugin = plugin;
387 }
388
389 WaveWindow::~WaveWindow()
390 {
391 }
392
393 void WaveWindow::create_objects()
394 {
395         int x = 10, y = 10, x1 = 100;
396
397 //      add_subwindow(new BC_Title(x, y, _("Mode:")));
398 //      add_subwindow(smear = new WaveSmear(plugin, this, x1, y));
399 //      y += 20;
400 //      add_subwindow(blacken = new WaveBlacken(plugin, this, x1, y));
401 //      y += 30;
402 //      add_subwindow(reflective = new WaveReflective(plugin, x1, y));
403 //      y += 30;
404         add_subwindow(new BC_Title(x, y, _("Amplitude:")));
405         add_subwindow(amplitude = new WaveAmplitude(plugin, x1, y));
406         y += 30;
407         add_subwindow(new BC_Title(x, y, _("Phase:")));
408         add_subwindow(phase = new WavePhase(plugin, x1, y));
409         y += 30;
410         add_subwindow(new BC_Title(x, y, _("Wavelength:")));
411         add_subwindow(wavelength = new WaveLength(plugin, x1, y));
412
413         show_window();
414         flush();
415 }
416
417 void WaveWindow::update_mode()
418 {
419 //      smear->update(plugin->config.mode == SMEAR);
420 //      blacken->update(plugin->config.mode == BLACKEN);
421 }
422
423
424
425
426
427
428
429 REGISTER_PLUGIN(WaveEffect)
430
431
432
433
434 WaveEffect::WaveEffect(PluginServer *server)
435  : PluginVClient(server)
436 {
437         temp_frame = 0;
438         engine = 0;
439         
440 }
441
442 WaveEffect::~WaveEffect()
443 {
444         
445
446         if(temp_frame) delete temp_frame;
447         if(engine) delete engine;
448 }
449
450
451 const char* WaveEffect::plugin_title() { return _("Wave"); }
452 int WaveEffect::is_realtime() { return 1; }
453
454
455 NEW_WINDOW_MACRO(WaveEffect, WaveWindow)
456
457 void WaveEffect::update_gui()
458 {
459         if(thread)
460         {
461                 thread->window->lock_window();
462                 load_configuration();
463                 ((WaveWindow*)thread->window)->update_mode();
464 //              thread->window->reflective->update(config.reflective);
465                 ((WaveWindow*)thread->window)->amplitude->update(config.amplitude);
466                 ((WaveWindow*)thread->window)->phase->update(config.phase);
467                 ((WaveWindow*)thread->window)->wavelength->update(config.wavelength);
468                 thread->window->unlock_window();
469         }
470 }
471
472
473 LOAD_CONFIGURATION_MACRO(WaveEffect, WaveConfig)
474
475
476 void WaveEffect::save_data(KeyFrame *keyframe)
477 {
478         FileXML output;
479
480 // cause data to be stored directly in text
481         output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
482         output.tag.set_title("WAVE");
483         output.tag.set_property("MODE", config.mode);
484         output.tag.set_property("REFLECTIVE", config.reflective);
485         output.tag.set_property("AMPLITUDE", config.amplitude);
486         output.tag.set_property("PHASE", config.phase);
487         output.tag.set_property("WAVELENGTH", config.wavelength);
488         output.append_tag();
489         output.terminate_string();
490 }
491
492 void WaveEffect::read_data(KeyFrame *keyframe)
493 {
494         FileXML input;
495
496         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
497
498         while(!input.read_tag())
499         {
500                 if(input.tag.title_is("WAVE"))
501                 {
502                         config.mode = input.tag.get_property("MODE", config.mode);
503                         config.reflective = input.tag.get_property("REFLECTIVE", config.reflective);
504                         config.amplitude = input.tag.get_property("AMPLITUDE", config.amplitude);
505                         config.phase = input.tag.get_property("PHASE", config.phase);
506                         config.wavelength = input.tag.get_property("WAVELENGTH", config.wavelength);
507                 }
508         }
509 }
510
511
512 int WaveEffect::process_realtime(VFrame *input, VFrame *output)
513 {
514         load_configuration();
515
516
517
518 //printf("WaveEffect::process_realtime %f %d\n", config.radius, config.use_intensity);
519         this->input = input;
520         this->output = output;
521
522         if(EQUIV(config.amplitude, 0) || EQUIV(config.wavelength, 0))
523         {
524                 if(input->get_rows()[0] != output->get_rows()[0])
525                         output->copy_from(input);
526         }
527         else
528         {
529                 if(input->get_rows()[0] == output->get_rows()[0])
530                 {
531                         if(!temp_frame) temp_frame = new VFrame(0,
532                                 -1,
533                                 input->get_w(),
534                                 input->get_h(),
535                                 input->get_color_model(),
536                                 -1);
537                         temp_frame->copy_from(input);
538                         this->input = temp_frame;
539                 }
540                 
541                 
542                 if(!engine)
543                 {
544                         engine = new WaveServer(this, (PluginClient::smp + 1));
545                 }
546                 
547                 engine->process_packages();
548         }
549         
550         
551         
552         return 0;
553 }
554
555
556
557
558
559
560 WavePackage::WavePackage()
561  : LoadPackage()
562 {
563 }
564
565
566
567
568
569
570 WaveUnit::WaveUnit(WaveEffect *plugin, WaveServer *server)
571  : LoadClient(server)
572 {
573         this->plugin = plugin;
574 }
575
576
577
578 #define WITHIN(a, b, c) ((((a) <= (b)) && ((b) <= (c))) ? 1 : 0)
579
580 static float bilinear(double  x,
581           double  y,
582           float  *v)
583 {
584         double m0, m1;
585         x = fmod(x, 1.0);
586         y = fmod(y, 1.0);
587
588         if(x < 0)
589         x += 1.0;
590         if(y < 0)
591         y += 1.0;
592
593         m0 = (1.0 - x) * v[0] + x * v[1];
594         m1 = (1.0 - x) * v[2] + x * v[3];
595
596         return((1.0 - y) * m0 + y * m1);
597 }
598
599 void WaveUnit::process_package(LoadPackage *package)
600 {
601         WavePackage *pkg = (WavePackage*)package;
602         int w = plugin->input->get_w();
603         int h = plugin->input->get_h();
604         double cen_x, cen_y;       /* Center of wave */
605         double xhsiz, yhsiz;       /* Half size of selection */
606         double radius;             /* Radius */
607         double amnt, d;
608         double needx, needy;
609         double dx, dy;
610         double xscale, yscale;
611         double wavelength;
612         int xi, yi;
613         float values[4];
614         float val;
615         int x1, y1, x2, y2;
616         int x1_in, y1_in, x2_in, y2_in;
617         double phase = plugin->config.phase * M_PI / 180;
618         
619         
620         x1 = y1 = 0;
621         x2 = w;
622         y2 = h;
623         cen_x = (double) (x2 - 1 + x1) / 2.0;
624         cen_y = (double) (y2 - 1 + y1) / 2.0;
625         xhsiz = (double) (x2 - x1) / 2.0;
626         yhsiz = (double) (y2 - y1) / 2.0;
627
628         if (xhsiz < yhsiz)
629     {
630         xscale = yhsiz / xhsiz;
631         yscale = 1.0;
632     }
633         else if (xhsiz > yhsiz)
634     {
635         xscale = 1.0;
636         yscale = xhsiz / yhsiz;
637     }
638         else
639     {
640         xscale = 1.0;
641         yscale = 1.0;
642     }
643
644         radius  = MAX(xhsiz, yhsiz);
645
646
647         wavelength = plugin->config.wavelength / 100 * radius;
648
649
650
651
652 #define WAVE(type, components, chroma_offset) \
653 { \
654         int row_size = w * components; \
655         type **in_rows = (type**)plugin->input->get_rows(); \
656         for(int y = pkg->row1; y < pkg->row2; y++) \
657         { \
658                 type *dest = (type*)plugin->output->get_rows()[y]; \
659  \
660                 for(int x = x1; x < x2; x++) \
661                 { \
662                         dx = (x - cen_x) * xscale; \
663                         dy = (y - cen_y) * yscale; \
664                     d = sqrt(dx * dx + dy * dy); \
665  \
666                         if(plugin->config.reflective) \
667                         { \
668                         amnt = plugin->config.amplitude *  \
669                                         fabs(sin(((d / wavelength) *  \
670                                                 (2.0 * M_PI) + \
671                                                 phase))); \
672  \
673                         needx = (amnt * dx) / xscale + cen_x; \
674                         needy = (amnt * dy) / yscale + cen_y; \
675                         } \
676                         else \
677                         { \
678                         amnt = plugin->config.amplitude *  \
679                                         sin(((d / wavelength) *  \
680                                                 (2.0 * M_PI) + \
681                                         phase)); \
682  \
683                         needx = (amnt + dx) / xscale + cen_x; \
684                         needy = (amnt + dy) / yscale + cen_y; \
685                         } \
686  \
687                         xi = (int)needx; \
688                         yi = (int)needy; \
689  \
690                         if(plugin->config.mode == SMEAR) \
691                 { \
692                         if(xi > w - 2) \
693                                 { \
694                                         xi = w - 2; \
695                                 } \
696                         else  \
697                                 if(xi < 0) \
698                                 { \
699                                         xi = 0; \
700                                 } \
701  \
702                         if(yi > h - 2) \
703                                 { \
704                                         yi = h - 2; \
705                                 } \
706                         else  \
707                                 if(yi < 0) \
708                                 { \
709                                         yi = 0; \
710                                 } \
711                 } \
712  \
713                         type *p = in_rows[CLIP(yi, 0, h - 1)] + \
714                                 CLIP(xi, 0, w - 1) * components; \
715                         x1_in = WITHIN(0, xi, w - 1); \
716                         y1_in = WITHIN(0, yi, h - 1); \
717                         x2_in = WITHIN(0, xi + 1, w - 1); \
718                         y2_in = WITHIN(0, yi + 1, h - 1); \
719  \
720  \
721                         for(int k = 0; k < components; k++) \
722                 { \
723                         if (x1_in && y1_in) \
724                                         values[0] = *(p + k); \
725                         else \
726                                         values[0] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
727  \
728                         if (x2_in && y1_in) \
729                                         values[1] = *(p + components + k); \
730                         else \
731                                         values[1] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
732  \
733                         if (x1_in && y2_in) \
734                                         values[2] = *(p + row_size + k); \
735                         else \
736                                         values[2] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
737  \
738                         if (x2_in) \
739                                 { \
740                                         if (y2_in) \
741                                         values[3] = *(p + row_size + components + k); \
742                                         else \
743                                         values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
744                                 } \
745                         else \
746                                         values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
747  \
748                         val = bilinear(needx, needy, values); \
749  \
750                         *dest++ = (type)val; \
751                 } \
752                 } \
753         } \
754 }
755
756
757
758
759         switch(plugin->input->get_color_model())
760         {
761                 case BC_RGB888:
762                         WAVE(unsigned char, 3, 0x0);
763                         break;
764                 case BC_RGB_FLOAT:
765                         WAVE(float, 3, 0x0);
766                         break;
767                 case BC_YUV888:
768                         WAVE(unsigned char, 3, 0x80);
769                         break;
770                 case BC_RGB161616:
771                         WAVE(uint16_t, 3, 0x0);
772                         break;
773                 case BC_YUV161616:
774                         WAVE(uint16_t, 3, 0x8000);
775                         break;
776                 case BC_RGBA_FLOAT:
777                         WAVE(unsigned char, 4, 0x0);
778                         break;
779                 case BC_RGBA8888:
780                         WAVE(unsigned char, 4, 0x0);
781                         break;
782                 case BC_YUVA8888:
783                         WAVE(unsigned char, 4, 0x8000);
784                         break;
785                 case BC_RGBA16161616:
786                         WAVE(uint16_t, 4, 0x0);
787                         break;
788                 case BC_YUVA16161616:
789                         WAVE(uint16_t, 4, 0x8000);
790                         break;
791         }
792
793
794
795
796 }
797
798
799
800
801
802
803 WaveServer::WaveServer(WaveEffect *plugin, int cpus)
804  : LoadServer(cpus, cpus)
805 {
806         this->plugin = plugin;
807 }
808
809 void WaveServer::init_packages()
810 {
811         for(int i = 0; i < LoadServer::get_total_packages(); i++)
812         {
813                 WavePackage *pkg = (WavePackage*)get_package(i);
814                 pkg->row1 = plugin->input->get_h() * i / LoadServer::get_total_packages();
815                 pkg->row2 = plugin->input->get_h() * (i + 1) / LoadServer::get_total_packages();
816         }
817 }
818
819
820 LoadClient* WaveServer::new_client()
821 {
822         return new WaveUnit(plugin, this);
823 }
824
825 LoadPackage* WaveServer::new_package()
826 {
827         return new WavePackage;
828 }
829