4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
31 WaveConfig::WaveConfig()
37 void WaveConfig::reset(int clear)
47 case RESET_AMPLITUDE : amplitude = 0;
49 case RESET_PHASE : phase = 0;
51 case RESET_WAVELENGTH : wavelength = 0;
53 case RESET_DEFAULT_SETTINGS :
64 void WaveConfig::copy_from(WaveConfig &src)
66 this->mode = src.mode;
67 this->reflective = src.reflective;
68 this->amplitude = src.amplitude;
69 this->phase = src.phase;
70 this->wavelength = src.wavelength;
73 int WaveConfig::equivalent(WaveConfig &src)
76 (this->mode == src.mode) &&
77 EQUIV(this->reflective, src.reflective) &&
78 EQUIV(this->amplitude, src.amplitude) &&
79 EQUIV(this->phase, src.phase) &&
80 EQUIV(this->wavelength, src.wavelength);
83 void WaveConfig::interpolate(WaveConfig &prev,
89 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
90 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
92 this->amplitude = prev.amplitude * prev_scale + next.amplitude * next_scale;
93 this->phase = prev.phase * prev_scale + next.phase * next_scale;
94 this->wavelength = prev.wavelength * prev_scale + next.wavelength * next_scale;
95 this->mode = prev.mode;
96 this->reflective = prev.reflective;
106 WaveSmear::WaveSmear(WaveEffect *plugin, WaveWindow *window, int x, int y)
107 : BC_Radial(x, y, plugin->config.mode == SMEAR, _("Smear"))
109 this->plugin = plugin;
110 this->window = window;
112 int WaveSmear::handle_event()
114 plugin->config.mode = SMEAR;
115 window->update_mode();
116 plugin->send_configure_change();
123 WaveBlacken::WaveBlacken(WaveEffect *plugin, WaveWindow *window, int x, int y)
124 : BC_Radial(x, y, plugin->config.mode == BLACKEN, _("Blacken"))
126 this->plugin = plugin;
127 this->window = window;
129 int WaveBlacken::handle_event()
131 plugin->config.mode = BLACKEN;
132 window->update_mode();
133 plugin->send_configure_change();
142 WaveReflective::WaveReflective(WaveEffect *plugin, int x, int y)
143 : BC_CheckBox(x, y, plugin->config.reflective, _("Reflective"))
145 this->plugin = plugin;
147 int WaveReflective::handle_event()
149 plugin->config.reflective = get_value();
150 plugin->send_configure_change();
155 WaveFText::WaveFText(WaveWindow *gui, WaveEffect *plugin,
156 WaveFSlider *slider, float *output, int x, int y, float min, float max)
157 : BC_TumbleTextBox(gui, *output,
158 min, max, x, y, xS(60), 2)
161 this->plugin = plugin;
162 this->output = output;
163 this->slider = slider;
169 WaveFText::~WaveFText()
173 int WaveFText::handle_event()
175 *output = atof(get_text());
176 if(*output > max) *output = max;
177 if(*output < min) *output = min;
178 slider->update(*output);
179 plugin->send_configure_change();
184 WaveFSlider::WaveFSlider(WaveEffect *plugin,
185 WaveFText *text, float *output, int x, int y, float min, float max)
186 : BC_FSlider(x, y, 0, xS(180), xS(180), min, max, *output)
188 this->plugin = plugin;
189 this->output = output;
191 enable_show_value(0); // Hide caption
194 WaveFSlider::~WaveFSlider()
198 int WaveFSlider::handle_event()
200 *output = get_value();
201 text->update(*output);
202 plugin->send_configure_change();
207 WaveReset::WaveReset(WaveEffect *plugin, WaveWindow *gui, int x, int y)
208 : BC_GenericButton(x, y, _("Reset"))
210 this->plugin = plugin;
213 WaveReset::~WaveReset()
216 int WaveReset::handle_event()
218 plugin->config.reset(RESET_ALL);
219 gui->update_gui(RESET_ALL);
220 plugin->send_configure_change();
224 WaveDefaultSettings::WaveDefaultSettings(WaveEffect *plugin, WaveWindow *gui, int x, int y, int w)
225 : BC_GenericButton(x, y, w, _("Default"))
227 this->plugin = plugin;
230 WaveDefaultSettings::~WaveDefaultSettings()
233 int WaveDefaultSettings::handle_event()
235 plugin->config.reset(RESET_DEFAULT_SETTINGS);
236 gui->update_gui(RESET_DEFAULT_SETTINGS);
237 plugin->send_configure_change();
241 WaveClr::WaveClr(WaveEffect *plugin, WaveWindow *gui, int x, int y, int clear)
242 : BC_Button(x, y, plugin->get_theme()->get_image_set("reset_button"))
244 this->plugin = plugin;
251 int WaveClr::handle_event()
253 // clear==1 ==> Amplitude slider
254 // clear==2 ==> Phase slider
255 // clear==3 ==> Steps slider
256 plugin->config.reset(clear);
257 gui->update_gui(clear);
258 plugin->send_configure_change();
265 WaveWindow::WaveWindow(WaveEffect *plugin)
266 : PluginClientWindow(plugin, xS(420), yS(160), xS(420), yS(160), 0)
268 this->plugin = plugin;
271 WaveWindow::~WaveWindow()
275 void WaveWindow::create_objects()
277 int xs10 = xS(10), xs100 = xS(100);
278 int ys10 = yS(10), ys30 = yS(30), ys40 = yS(40);
279 int x = xs10, y = ys10;
280 int x2 = xS(100), x3 = xS(200);
281 int clr_x = get_w()-x - xS(22); // note: clrBtn_w = 22
282 int defaultBtn_w = xs100;
286 // add_subwindow(new BC_Title(x, y, _("Mode:")));
287 // add_subwindow(smear = new WaveSmear(plugin, this, x1, y));
289 // add_subwindow(blacken = new WaveBlacken(plugin, this, x1, y));
291 // add_subwindow(reflective = new WaveReflective(plugin, x1, y));
295 add_subwindow(new BC_Title(x, y, _("Amplitude:")));
296 amplitude_text = new WaveFText(this, plugin,
297 0, &plugin->config.amplitude, (x + x2), y, AMPLITUDE_MIN, AMPLITUDE_MAX);
298 amplitude_text->create_objects();
299 amplitude_slider = new WaveFSlider(plugin,
300 amplitude_text, &plugin->config.amplitude, x3, y, AMPLITUDE_MIN, AMPLITUDE_MAX);
301 add_subwindow(amplitude_slider);
302 amplitude_text->slider = amplitude_slider;
303 clr_x = x3 + amplitude_slider->get_w() + x;
304 add_subwindow(amplitude_Clr = new WaveClr(plugin, this, clr_x, y, RESET_AMPLITUDE));
307 add_subwindow(new BC_Title(x, y, _("Phase:")));
308 phase_text = new WaveFText(this, plugin,
309 0, &plugin->config.phase, (x + x2), y, PHASE_MIN, PHASE_MAX);
310 phase_text->create_objects();
311 phase_slider = new WaveFSlider(plugin,
312 phase_text, &plugin->config.phase, x3, y, PHASE_MIN, PHASE_MAX);
313 add_subwindow(phase_slider);
314 phase_text->slider = phase_slider;
315 add_subwindow(phase_Clr = new WaveClr(plugin, this, clr_x, y, RESET_PHASE));
318 add_subwindow(new BC_Title(x, y, _("Wavelength:")));
319 wavelength_text = new WaveFText(this, plugin,
320 0, &plugin->config.wavelength, (x + x2), y, WAVELENGTH_MIN, WAVELENGTH_MAX);
321 wavelength_text->create_objects();
322 wavelength_slider = new WaveFSlider(plugin,
323 wavelength_text, &plugin->config.wavelength, x3, y, WAVELENGTH_MIN, WAVELENGTH_MAX);
324 add_subwindow(wavelength_slider);
325 wavelength_text->slider = wavelength_slider;
326 add_subwindow(wavelength_Clr = new WaveClr(plugin, this, clr_x, y, RESET_WAVELENGTH));
330 add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
332 add_subwindow(reset = new WaveReset(plugin, this, x, y));
333 add_subwindow(default_settings = new WaveDefaultSettings(plugin, this,
334 (get_w() - xs10 - defaultBtn_w), y, defaultBtn_w));
340 void WaveWindow::update_mode()
342 // smear->update(plugin->config.mode == SMEAR);
343 // blacken->update(plugin->config.mode == BLACKEN);
347 void WaveWindow::update_gui(int clear)
350 case RESET_AMPLITUDE :
351 amplitude_text->update(plugin->config.amplitude);
352 amplitude_slider->update(plugin->config.amplitude);
355 phase_text->update(plugin->config.phase);
356 phase_slider->update(plugin->config.phase);
358 case RESET_WAVELENGTH :
359 wavelength_text->update(plugin->config.wavelength);
360 wavelength_slider->update(plugin->config.wavelength);
363 case RESET_DEFAULT_SETTINGS :
365 amplitude_text->update(plugin->config.amplitude);
366 amplitude_slider->update(plugin->config.amplitude);
367 phase_text->update(plugin->config.phase);
368 phase_slider->update(plugin->config.phase);
369 wavelength_text->update(plugin->config.wavelength);
370 wavelength_slider->update(plugin->config.wavelength);
383 REGISTER_PLUGIN(WaveEffect)
388 WaveEffect::WaveEffect(PluginServer *server)
389 : PluginVClient(server)
396 WaveEffect::~WaveEffect()
400 if(temp_frame) delete temp_frame;
401 if(engine) delete engine;
405 const char* WaveEffect::plugin_title() { return N_("Wave"); }
406 int WaveEffect::is_realtime() { return 1; }
409 NEW_WINDOW_MACRO(WaveEffect, WaveWindow)
411 void WaveEffect::update_gui()
415 thread->window->lock_window();
416 load_configuration();
417 ((WaveWindow*)thread->window)->update_mode();
418 // thread->window->reflective->update(config.reflective);
419 ((WaveWindow*)thread->window)->amplitude_text->update(config.amplitude);
420 ((WaveWindow*)thread->window)->amplitude_slider->update(config.amplitude);
421 ((WaveWindow*)thread->window)->phase_text->update(config.phase);
422 ((WaveWindow*)thread->window)->phase_slider->update(config.phase);
423 ((WaveWindow*)thread->window)->wavelength_text->update(config.wavelength);
424 ((WaveWindow*)thread->window)->wavelength_slider->update(config.wavelength);
425 thread->window->unlock_window();
430 LOAD_CONFIGURATION_MACRO(WaveEffect, WaveConfig)
433 void WaveEffect::save_data(KeyFrame *keyframe)
437 // cause data to be stored directly in text
438 output.set_shared_output(keyframe->xbuf);
439 output.tag.set_title("WAVE");
440 output.tag.set_property("MODE", config.mode);
441 output.tag.set_property("REFLECTIVE", config.reflective);
442 output.tag.set_property("AMPLITUDE", config.amplitude);
443 output.tag.set_property("PHASE", config.phase);
444 output.tag.set_property("WAVELENGTH", config.wavelength);
446 output.tag.set_title("/WAVE");
448 output.append_newline();
449 output.terminate_string();
452 void WaveEffect::read_data(KeyFrame *keyframe)
456 input.set_shared_input(keyframe->xbuf);
458 while(!input.read_tag())
460 if(input.tag.title_is("WAVE"))
462 config.mode = input.tag.get_property("MODE", config.mode);
463 config.reflective = input.tag.get_property("REFLECTIVE", config.reflective);
464 config.amplitude = input.tag.get_property("AMPLITUDE", config.amplitude);
465 config.phase = input.tag.get_property("PHASE", config.phase);
466 config.wavelength = input.tag.get_property("WAVELENGTH", config.wavelength);
472 int WaveEffect::process_realtime(VFrame *input, VFrame *output)
474 load_configuration();
478 //printf("WaveEffect::process_realtime %f %d\n", config.radius, config.use_intensity);
480 this->output = output;
482 if(EQUIV(config.amplitude, 0) || EQUIV(config.wavelength, 0))
484 if(input->get_rows()[0] != output->get_rows()[0])
485 output->copy_from(input);
489 if(input->get_rows()[0] == output->get_rows()[0])
491 if(!temp_frame) temp_frame = new VFrame(input->get_w(), input->get_h(),
492 input->get_color_model(), 0);
493 temp_frame->copy_from(input);
494 this->input = temp_frame;
500 engine = new WaveServer(this, (PluginClient::smp + 1));
503 engine->process_packages();
516 WavePackage::WavePackage()
526 WaveUnit::WaveUnit(WaveEffect *plugin, WaveServer *server)
529 this->plugin = plugin;
534 #define WITHIN(a, b, c) ((((a) <= (b)) && ((b) <= (c))) ? 1 : 0)
536 static float bilinear(double x,
549 m0 = (1.0 - x) * v[0] + x * v[1];
550 m1 = (1.0 - x) * v[2] + x * v[3];
552 return((1.0 - y) * m0 + y * m1);
555 void WaveUnit::process_package(LoadPackage *package)
557 WavePackage *pkg = (WavePackage*)package;
558 int w = plugin->input->get_w();
559 int h = plugin->input->get_h();
560 double cen_x, cen_y; /* Center of wave */
561 double xhsiz, yhsiz; /* Half size of selection */
562 double radius; /* Radius */
566 double xscale, yscale;
572 int x1_in, y1_in, x2_in, y2_in;
573 double phase = plugin->config.phase * M_PI / 180;
579 cen_x = (double) (x2 - 1 + x1) / 2.0;
580 cen_y = (double) (y2 - 1 + y1) / 2.0;
581 xhsiz = (double) (x2 - x1) / 2.0;
582 yhsiz = (double) (y2 - y1) / 2.0;
586 xscale = yhsiz / xhsiz;
589 else if (xhsiz > yhsiz)
592 yscale = xhsiz / yhsiz;
600 radius = MAX(xhsiz, yhsiz);
603 wavelength = plugin->config.wavelength / 100 * radius;
608 #define WAVE(type, components, chroma_offset) \
610 int row_size = w * components; \
611 type **in_rows = (type**)plugin->input->get_rows(); \
612 for(int y = pkg->row1; y < pkg->row2; y++) \
614 type *dest = (type*)plugin->output->get_rows()[y]; \
616 for(int x = x1; x < x2; x++) \
618 dx = (x - cen_x) * xscale; \
619 dy = (y - cen_y) * yscale; \
620 d = sqrt(dx * dx + dy * dy); \
622 if(plugin->config.reflective) \
624 amnt = plugin->config.amplitude * \
625 fabs(sin(((d / wavelength) * \
629 needx = (amnt * dx) / xscale + cen_x; \
630 needy = (amnt * dy) / yscale + cen_y; \
634 amnt = plugin->config.amplitude * \
635 sin(((d / wavelength) * \
639 needx = (amnt + dx) / xscale + cen_x; \
640 needy = (amnt + dy) / yscale + cen_y; \
646 if(plugin->config.mode == SMEAR) \
669 type *p = in_rows[CLIP(yi, 0, h - 1)] + \
670 CLIP(xi, 0, w - 1) * components; \
671 x1_in = WITHIN(0, xi, w - 1); \
672 y1_in = WITHIN(0, yi, h - 1); \
673 x2_in = WITHIN(0, xi + 1, w - 1); \
674 y2_in = WITHIN(0, yi + 1, h - 1); \
677 for(int k = 0; k < components; k++) \
679 if (x1_in && y1_in) \
680 values[0] = *(p + k); \
682 values[0] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
684 if (x2_in && y1_in) \
685 values[1] = *(p + components + k); \
687 values[1] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
689 if (x1_in && y2_in) \
690 values[2] = *(p + row_size + k); \
692 values[2] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
697 values[3] = *(p + row_size + components + k); \
699 values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
702 values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
704 val = bilinear(needx, needy, values); \
706 *dest++ = (type)val; \
715 switch(plugin->input->get_color_model())
718 WAVE(unsigned char, 3, 0x0);
724 WAVE(unsigned char, 3, 0x80);
727 WAVE(uint16_t, 3, 0x0);
730 WAVE(uint16_t, 3, 0x8000);
733 WAVE(unsigned char, 4, 0x0);
736 WAVE(unsigned char, 4, 0x0);
739 WAVE(unsigned char, 4, 0x8000);
741 case BC_RGBA16161616:
742 WAVE(uint16_t, 4, 0x0);
744 case BC_YUVA16161616:
745 WAVE(uint16_t, 4, 0x8000);
759 WaveServer::WaveServer(WaveEffect *plugin, int cpus)
760 : LoadServer(cpus, cpus)
762 this->plugin = plugin;
765 void WaveServer::init_packages()
767 for(int i = 0; i < LoadServer::get_total_packages(); i++)
769 WavePackage *pkg = (WavePackage*)get_package(i);
770 pkg->row1 = plugin->input->get_h() * i / LoadServer::get_total_packages();
771 pkg->row2 = plugin->input->get_h() * (i + 1) / LoadServer::get_total_packages();
776 LoadClient* WaveServer::new_client()
778 return new WaveUnit(plugin, this);
781 LoadPackage* WaveServer::new_package()
783 return new WavePackage;