00001 #include "bcdisplayinfo.h"
00002 #include "clip.h"
00003 #include "bchash.h"
00004 #include "filexml.h"
00005 #include "guicast.h"
00006 #include "keyframe.h"
00007 #include "language.h"
00008 #include "loadbalance.h"
00009 #include "picon_png.h"
00010 #include "pluginvclient.h"
00011 #include "vframe.h"
00012
00013 #include <math.h>
00014 #include <stdint.h>
00015 #include <string.h>
00016
00017
00018
00019
00020 #define SMEAR 0
00021 #define BLACKEN 1
00022
00023
00024
00025 class WaveEffect;
00026 class WaveWindow;
00027
00028
00029 class WaveConfig
00030 {
00031 public:
00032 WaveConfig();
00033 void copy_from(WaveConfig &src);
00034 int equivalent(WaveConfig &src);
00035 void interpolate(WaveConfig &prev,
00036 WaveConfig &next,
00037 long prev_frame,
00038 long next_frame,
00039 long current_frame);
00040 int mode;
00041 int reflective;
00042 float amplitude;
00043 float phase;
00044 float wavelength;
00045 };
00046
00047 class WaveSmear : public BC_Radial
00048 {
00049 public:
00050 WaveSmear(WaveEffect *plugin, WaveWindow *window, int x, int y);
00051 int handle_event();
00052 WaveEffect *plugin;
00053 WaveWindow *window;
00054 };
00055
00056 class WaveBlacken : public BC_Radial
00057 {
00058 public:
00059 WaveBlacken(WaveEffect *plugin, WaveWindow *window, int x, int y);
00060 int handle_event();
00061 WaveEffect *plugin;
00062 WaveWindow *window;
00063 };
00064
00065
00066 class WaveReflective : public BC_CheckBox
00067 {
00068 public:
00069 WaveReflective(WaveEffect *plugin, int x, int y);
00070 int handle_event();
00071 WaveEffect *plugin;
00072 };
00073
00074 class WaveAmplitude : public BC_FSlider
00075 {
00076 public:
00077 WaveAmplitude(WaveEffect *plugin, int x, int y);
00078 int handle_event();
00079 WaveEffect *plugin;
00080 };
00081
00082 class WavePhase : public BC_FSlider
00083 {
00084 public:
00085 WavePhase(WaveEffect *plugin, int x, int y);
00086 int handle_event();
00087 WaveEffect *plugin;
00088 };
00089
00090 class WaveLength : public BC_FSlider
00091 {
00092 public:
00093 WaveLength(WaveEffect *plugin, int x, int y);
00094 int handle_event();
00095 WaveEffect *plugin;
00096 };
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 class WaveWindow : public BC_Window
00107 {
00108 public:
00109 WaveWindow(WaveEffect *plugin, int x, int y);
00110 ~WaveWindow();
00111 void create_objects();
00112 int close_event();
00113 void update_mode();
00114 WaveEffect *plugin;
00115
00116
00117
00118 WaveAmplitude *amplitude;
00119 WavePhase *phase;
00120 WaveLength *wavelength;
00121 };
00122
00123
00124 PLUGIN_THREAD_HEADER(WaveEffect, WaveThread, WaveWindow)
00125
00126
00127
00128
00129
00130 class WaveServer : public LoadServer
00131 {
00132 public:
00133 WaveServer(WaveEffect *plugin, int cpus);
00134 void init_packages();
00135 LoadClient* new_client();
00136 LoadPackage* new_package();
00137 WaveEffect *plugin;
00138 };
00139
00140 class WavePackage : public LoadPackage
00141 {
00142 public:
00143 WavePackage();
00144 int row1, row2;
00145 };
00146
00147 class WaveUnit : public LoadClient
00148 {
00149 public:
00150 WaveUnit(WaveEffect *plugin, WaveServer *server);
00151 void process_package(LoadPackage *package);
00152 WaveEffect *plugin;
00153 };
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 class WaveEffect : public PluginVClient
00164 {
00165 public:
00166 WaveEffect(PluginServer *server);
00167 ~WaveEffect();
00168
00169 int process_realtime(VFrame *input, VFrame *output);
00170 int is_realtime();
00171 char* plugin_title();
00172 VFrame* new_picon();
00173 int load_configuration();
00174 int load_defaults();
00175 int save_defaults();
00176 void save_data(KeyFrame *keyframe);
00177 void read_data(KeyFrame *keyframe);
00178 int show_gui();
00179 int set_string();
00180 void raise_window();
00181 void update_gui();
00182
00183 WaveConfig config;
00184 VFrame *temp_frame;
00185 VFrame *input, *output;
00186 BC_Hash *defaults;
00187 WaveThread *thread;
00188 WaveServer *engine;
00189 };
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 WaveConfig::WaveConfig()
00204 {
00205 mode = SMEAR;
00206 reflective = 0;
00207 amplitude = 10;
00208 phase = 0;
00209 wavelength = 10;
00210 }
00211
00212 void WaveConfig::copy_from(WaveConfig &src)
00213 {
00214 this->mode = src.mode;
00215 this->reflective = src.reflective;
00216 this->amplitude = src.amplitude;
00217 this->phase = src.phase;
00218 this->wavelength = src.wavelength;
00219 }
00220
00221 int WaveConfig::equivalent(WaveConfig &src)
00222 {
00223 return
00224 (this->mode == src.mode) &&
00225 EQUIV(this->reflective, src.reflective) &&
00226 EQUIV(this->amplitude, src.amplitude) &&
00227 EQUIV(this->phase, src.phase) &&
00228 EQUIV(this->wavelength, src.wavelength);
00229 }
00230
00231 void WaveConfig::interpolate(WaveConfig &prev,
00232 WaveConfig &next,
00233 long prev_frame,
00234 long next_frame,
00235 long current_frame)
00236 {
00237 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
00238 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
00239
00240 this->amplitude = prev.amplitude * prev_scale + next.amplitude * next_scale;
00241 this->phase = prev.phase * prev_scale + next.phase * next_scale;
00242 this->wavelength = prev.wavelength * prev_scale + next.wavelength * next_scale;
00243 this->mode = prev.mode;
00244 this->reflective = prev.reflective;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254 WaveSmear::WaveSmear(WaveEffect *plugin, WaveWindow *window, int x, int y)
00255 : BC_Radial(x, y, plugin->config.mode == SMEAR, _("Smear"))
00256 {
00257 this->plugin = plugin;
00258 this->window = window;
00259 }
00260 int WaveSmear::handle_event()
00261 {
00262 plugin->config.mode = SMEAR;
00263 window->update_mode();
00264 plugin->send_configure_change();
00265 return 1;
00266 }
00267
00268
00269
00270
00271 WaveBlacken::WaveBlacken(WaveEffect *plugin, WaveWindow *window, int x, int y)
00272 : BC_Radial(x, y, plugin->config.mode == BLACKEN, _("Blacken"))
00273 {
00274 this->plugin = plugin;
00275 this->window = window;
00276 }
00277 int WaveBlacken::handle_event()
00278 {
00279 plugin->config.mode = BLACKEN;
00280 window->update_mode();
00281 plugin->send_configure_change();
00282 return 1;
00283 }
00284
00285
00286
00287
00288
00289
00290 WaveReflective::WaveReflective(WaveEffect *plugin, int x, int y)
00291 : BC_CheckBox(x, y, plugin->config.reflective, _("Reflective"))
00292 {
00293 this->plugin = plugin;
00294 }
00295 int WaveReflective::handle_event()
00296 {
00297 plugin->config.reflective = get_value();
00298 plugin->send_configure_change();
00299 return 1;
00300 }
00301
00302
00303 WaveAmplitude::WaveAmplitude(WaveEffect *plugin, int x, int y)
00304 : BC_FSlider(x,
00305 y,
00306 0,
00307 200,
00308 200,
00309 (float)0,
00310 (float)100,
00311 plugin->config.amplitude)
00312 {
00313 this->plugin = plugin;
00314 }
00315 int WaveAmplitude::handle_event()
00316 {
00317 plugin->config.amplitude = get_value();
00318 plugin->send_configure_change();
00319 return 1;
00320 }
00321
00322
00323
00324 WavePhase::WavePhase(WaveEffect *plugin, int x, int y)
00325 : BC_FSlider(x,
00326 y,
00327 0,
00328 200,
00329 200,
00330 (float)0,
00331 (float)360,
00332 plugin->config.phase)
00333 {
00334 this->plugin = plugin;
00335 }
00336 int WavePhase::handle_event()
00337 {
00338 plugin->config.phase = get_value();
00339 plugin->send_configure_change();
00340 return 1;
00341 }
00342
00343 WaveLength::WaveLength(WaveEffect *plugin, int x, int y)
00344 : BC_FSlider(x,
00345 y,
00346 0,
00347 200,
00348 200,
00349 (float)0,
00350 (float)50,
00351 plugin->config.wavelength)
00352 {
00353 this->plugin = plugin;
00354 }
00355 int WaveLength::handle_event()
00356 {
00357 plugin->config.wavelength = get_value();
00358 plugin->send_configure_change();
00359 return 1;
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 WaveWindow::WaveWindow(WaveEffect *plugin, int x, int y)
00371 : BC_Window(plugin->gui_string,
00372 x,
00373 y,
00374 320,
00375 150,
00376 320,
00377 150,
00378 0,
00379 0,
00380 1)
00381 {
00382 this->plugin = plugin;
00383 }
00384
00385 WaveWindow::~WaveWindow()
00386 {
00387 }
00388
00389 void WaveWindow::create_objects()
00390 {
00391 int x = 10, y = 10, x1 = 100;
00392
00393
00394
00395
00396
00397
00398
00399
00400 add_subwindow(new BC_Title(x, y, _("Amplitude:")));
00401 add_subwindow(amplitude = new WaveAmplitude(plugin, x1, y));
00402 y += 30;
00403 add_subwindow(new BC_Title(x, y, _("Phase:")));
00404 add_subwindow(phase = new WavePhase(plugin, x1, y));
00405 y += 30;
00406 add_subwindow(new BC_Title(x, y, _("Wavelength:")));
00407 add_subwindow(wavelength = new WaveLength(plugin, x1, y));
00408
00409 show_window();
00410 flush();
00411 }
00412
00413 int WaveWindow::close_event()
00414 {
00415 set_done(1);
00416 return 1;
00417 }
00418
00419 void WaveWindow::update_mode()
00420 {
00421
00422
00423 }
00424
00425
00426 PLUGIN_THREAD_OBJECT(WaveEffect, WaveThread, WaveWindow)
00427
00428
00429
00430
00431 REGISTER_PLUGIN(WaveEffect)
00432
00433
00434
00435
00436 WaveEffect::WaveEffect(PluginServer *server)
00437 : PluginVClient(server)
00438 {
00439 temp_frame = 0;
00440 engine = 0;
00441 PLUGIN_CONSTRUCTOR_MACRO
00442 }
00443
00444 WaveEffect::~WaveEffect()
00445 {
00446 PLUGIN_DESTRUCTOR_MACRO
00447
00448 if(temp_frame) delete temp_frame;
00449 if(engine) delete engine;
00450 }
00451
00452
00453 char* WaveEffect::plugin_title() { return N_("Wave"); }
00454 int WaveEffect::is_realtime() { return 1; }
00455
00456 NEW_PICON_MACRO(WaveEffect)
00457
00458 SHOW_GUI_MACRO(WaveEffect, WaveThread)
00459
00460 RAISE_WINDOW_MACRO(WaveEffect)
00461
00462 SET_STRING_MACRO(WaveEffect)
00463
00464 void WaveEffect::update_gui()
00465 {
00466 if(thread)
00467 {
00468 thread->window->lock_window();
00469 load_configuration();
00470 thread->window->update_mode();
00471
00472 thread->window->amplitude->update(config.amplitude);
00473 thread->window->phase->update(config.phase);
00474 thread->window->wavelength->update(config.wavelength);
00475 thread->window->unlock_window();
00476 }
00477 }
00478
00479
00480 LOAD_CONFIGURATION_MACRO(WaveEffect, WaveConfig)
00481
00482 int WaveEffect::load_defaults()
00483 {
00484 char directory[BCTEXTLEN];
00485
00486 sprintf(directory, "%swave.rc", BCASTDIR);
00487
00488
00489 defaults = new BC_Hash(directory);
00490 defaults->load();
00491
00492 config.mode = defaults->get("MODE", config.mode);
00493 config.reflective = defaults->get("REFLECTIVE", config.reflective);
00494 config.amplitude = defaults->get("AMPLITUDE", config.amplitude);
00495 config.phase = defaults->get("PHASE", config.phase);
00496 config.wavelength = defaults->get("WAVELENGTH", config.wavelength);
00497 return 0;
00498 }
00499
00500 int WaveEffect::save_defaults()
00501 {
00502 defaults->update("MODE", config.mode);
00503 defaults->update("REFLECTIVE", config.reflective);
00504 defaults->update("AMPLITUDE", config.amplitude);
00505 defaults->update("PHASE", config.phase);
00506 defaults->update("WAVELENGTH", config.wavelength);
00507 defaults->save();
00508 return 0;
00509 }
00510
00511 void WaveEffect::save_data(KeyFrame *keyframe)
00512 {
00513 FileXML output;
00514
00515
00516 output.set_shared_string(keyframe->data, MESSAGESIZE);
00517 output.tag.set_title("WAVE");
00518 output.tag.set_property("MODE", config.mode);
00519 output.tag.set_property("REFLECTIVE", config.reflective);
00520 output.tag.set_property("AMPLITUDE", config.amplitude);
00521 output.tag.set_property("PHASE", config.phase);
00522 output.tag.set_property("WAVELENGTH", config.wavelength);
00523 output.append_tag();
00524 output.tag.set_title("/WAVE");
00525 output.append_tag();
00526 output.terminate_string();
00527 }
00528
00529 void WaveEffect::read_data(KeyFrame *keyframe)
00530 {
00531 FileXML input;
00532
00533 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00534
00535 while(!input.read_tag())
00536 {
00537 if(input.tag.title_is("WAVE"))
00538 {
00539 config.mode = input.tag.get_property("MODE", config.mode);
00540 config.reflective = input.tag.get_property("REFLECTIVE", config.reflective);
00541 config.amplitude = input.tag.get_property("AMPLITUDE", config.amplitude);
00542 config.phase = input.tag.get_property("PHASE", config.phase);
00543 config.wavelength = input.tag.get_property("WAVELENGTH", config.wavelength);
00544 }
00545 }
00546 }
00547
00548
00549 int WaveEffect::process_realtime(VFrame *input, VFrame *output)
00550 {
00551 load_configuration();
00552
00553
00554
00555
00556 this->input = input;
00557 this->output = output;
00558
00559 if(EQUIV(config.amplitude, 0) || EQUIV(config.wavelength, 0))
00560 {
00561 if(input->get_rows()[0] != output->get_rows()[0])
00562 output->copy_from(input);
00563 }
00564 else
00565 {
00566 if(input->get_rows()[0] == output->get_rows()[0])
00567 {
00568 if(!temp_frame) temp_frame = new VFrame(0,
00569 input->get_w(),
00570 input->get_h(),
00571 input->get_color_model());
00572 temp_frame->copy_from(input);
00573 this->input = temp_frame;
00574 }
00575
00576
00577 if(!engine)
00578 {
00579 engine = new WaveServer(this, (PluginClient::smp + 1));
00580 }
00581
00582 engine->process_packages();
00583 }
00584
00585
00586
00587 return 0;
00588 }
00589
00590
00591
00592
00593
00594
00595 WavePackage::WavePackage()
00596 : LoadPackage()
00597 {
00598 }
00599
00600
00601
00602
00603
00604
00605 WaveUnit::WaveUnit(WaveEffect *plugin, WaveServer *server)
00606 : LoadClient(server)
00607 {
00608 this->plugin = plugin;
00609 }
00610
00611
00612
00613 #define WITHIN(a, b, c) ((((a) <= (b)) && ((b) <= (c))) ? 1 : 0)
00614
00615 static float bilinear(double x,
00616 double y,
00617 float *v)
00618 {
00619 double m0, m1;
00620 x = fmod(x, 1.0);
00621 y = fmod(y, 1.0);
00622
00623 if(x < 0)
00624 x += 1.0;
00625 if(y < 0)
00626 y += 1.0;
00627
00628 m0 = (1.0 - x) * v[0] + x * v[1];
00629 m1 = (1.0 - x) * v[2] + x * v[3];
00630
00631 return((1.0 - y) * m0 + y * m1);
00632 }
00633
00634 void WaveUnit::process_package(LoadPackage *package)
00635 {
00636 WavePackage *pkg = (WavePackage*)package;
00637 int w = plugin->input->get_w();
00638 int h = plugin->input->get_h();
00639 double cen_x, cen_y;
00640 double xhsiz, yhsiz;
00641 double radius, radius2;
00642 double amnt, d;
00643 double needx, needy;
00644 double dx, dy;
00645 double xscale, yscale;
00646 double wavelength;
00647 int xi, yi;
00648 float values[4];
00649 float val;
00650 int x1, y1, x2, y2;
00651 int x1_in, y1_in, x2_in, y2_in;
00652 double phase = plugin->config.phase * M_PI / 180;
00653
00654
00655 x1 = y1 = 0;
00656 x2 = w;
00657 y2 = h;
00658 cen_x = (double) (x2 - 1 + x1) / 2.0;
00659 cen_y = (double) (y2 - 1 + y1) / 2.0;
00660 xhsiz = (double) (x2 - x1) / 2.0;
00661 yhsiz = (double) (y2 - y1) / 2.0;
00662
00663 if (xhsiz < yhsiz)
00664 {
00665 xscale = yhsiz / xhsiz;
00666 yscale = 1.0;
00667 }
00668 else if (xhsiz > yhsiz)
00669 {
00670 xscale = 1.0;
00671 yscale = xhsiz / yhsiz;
00672 }
00673 else
00674 {
00675 xscale = 1.0;
00676 yscale = 1.0;
00677 }
00678
00679 radius = MAX(xhsiz, yhsiz);
00680 radius2 = radius * radius;
00681
00682
00683 wavelength = plugin->config.wavelength / 100 * radius;
00684
00685
00686
00687
00688 #define WAVE(type, components, chroma_offset) \
00689 { \
00690 int row_size = w * components; \
00691 type **in_rows = (type**)plugin->input->get_rows(); \
00692 for(int y = pkg->row1; y < pkg->row2; y++) \
00693 { \
00694 type *dest = (type*)plugin->output->get_rows()[y]; \
00695 \
00696 for(int x = x1; x < x2; x++) \
00697 { \
00698 dx = (x - cen_x) * xscale; \
00699 dy = (y - cen_y) * yscale; \
00700 d = sqrt(dx * dx + dy * dy); \
00701 \
00702 if(plugin->config.reflective) \
00703 { \
00704 amnt = plugin->config.amplitude * \
00705 fabs(sin(((d / wavelength) * \
00706 (2.0 * M_PI) + \
00707 phase))); \
00708 \
00709 needx = (amnt * dx) / xscale + cen_x; \
00710 needy = (amnt * dy) / yscale + cen_y; \
00711 } \
00712 else \
00713 { \
00714 amnt = plugin->config.amplitude * \
00715 sin(((d / wavelength) * \
00716 (2.0 * M_PI) + \
00717 phase)); \
00718 \
00719 needx = (amnt + dx) / xscale + cen_x; \
00720 needy = (amnt + dy) / yscale + cen_y; \
00721 } \
00722 \
00723 xi = (int)needx; \
00724 yi = (int)needy; \
00725 \
00726 if(plugin->config.mode == SMEAR) \
00727 { \
00728 if(xi > w - 2) \
00729 { \
00730 xi = w - 2; \
00731 } \
00732 else \
00733 if(xi < 0) \
00734 { \
00735 xi = 0; \
00736 } \
00737 \
00738 if(yi > h - 2) \
00739 { \
00740 yi = h - 2; \
00741 } \
00742 else \
00743 if(yi < 0) \
00744 { \
00745 yi = 0; \
00746 } \
00747 } \
00748 \
00749 type *p = in_rows[CLIP(yi, 0, h - 1)] + \
00750 CLIP(xi, 0, w - 1) * components; \
00751 x1_in = WITHIN(0, xi, w - 1); \
00752 y1_in = WITHIN(0, yi, h - 1); \
00753 x2_in = WITHIN(0, xi + 1, w - 1); \
00754 y2_in = WITHIN(0, yi + 1, h - 1); \
00755 \
00756 \
00757 for(int k = 0; k < components; k++) \
00758 { \
00759 if (x1_in && y1_in) \
00760 values[0] = *(p + k); \
00761 else \
00762 values[0] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
00763 \
00764 if (x2_in && y1_in) \
00765 values[1] = *(p + components + k); \
00766 else \
00767 values[1] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
00768 \
00769 if (x1_in && y2_in) \
00770 values[2] = *(p + row_size + k); \
00771 else \
00772 values[2] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
00773 \
00774 if (x2_in) \
00775 { \
00776 if (y2_in) \
00777 values[3] = *(p + row_size + components + k); \
00778 else \
00779 values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
00780 } \
00781 else \
00782 values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
00783 \
00784 val = bilinear(needx, needy, values); \
00785 \
00786 *dest++ = (type)val; \
00787 } \
00788 } \
00789 } \
00790 }
00791
00792
00793
00794
00795 switch(plugin->input->get_color_model())
00796 {
00797 case BC_RGB888:
00798 WAVE(unsigned char, 3, 0x0);
00799 break;
00800 case BC_RGB_FLOAT:
00801 WAVE(float, 3, 0x0);
00802 break;
00803 case BC_YUV888:
00804 WAVE(unsigned char, 3, 0x80);
00805 break;
00806 case BC_RGB161616:
00807 WAVE(uint16_t, 3, 0x0);
00808 break;
00809 case BC_YUV161616:
00810 WAVE(uint16_t, 3, 0x8000);
00811 break;
00812 case BC_RGBA_FLOAT:
00813 WAVE(unsigned char, 4, 0x0);
00814 break;
00815 case BC_RGBA8888:
00816 WAVE(unsigned char, 4, 0x0);
00817 break;
00818 case BC_YUVA8888:
00819 WAVE(unsigned char, 4, 0x8000);
00820 break;
00821 case BC_RGBA16161616:
00822 WAVE(uint16_t, 4, 0x0);
00823 break;
00824 case BC_YUVA16161616:
00825 WAVE(uint16_t, 4, 0x8000);
00826 break;
00827 }
00828
00829
00830
00831
00832 }
00833
00834
00835
00836
00837
00838
00839 WaveServer::WaveServer(WaveEffect *plugin, int cpus)
00840 : LoadServer(cpus, cpus)
00841 {
00842 this->plugin = plugin;
00843 }
00844
00845 void WaveServer::init_packages()
00846 {
00847 for(int i = 0; i < LoadServer::get_total_packages(); i++)
00848 {
00849 WavePackage *pkg = (WavePackage*)get_package(i);
00850 pkg->row1 = plugin->input->get_h() * i / LoadServer::get_total_packages();
00851 pkg->row2 = plugin->input->get_h() * (i + 1) / LoadServer::get_total_packages();
00852 }
00853 }
00854
00855
00856 LoadClient* WaveServer::new_client()
00857 {
00858 return new WaveUnit(plugin, this);
00859 }
00860
00861 LoadPackage* WaveServer::new_package()
00862 {
00863 return new WavePackage;
00864 }
00865