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()
46 void WaveConfig::copy_from(WaveConfig &src)
48 this->mode = src.mode;
49 this->reflective = src.reflective;
50 this->amplitude = src.amplitude;
51 this->phase = src.phase;
52 this->wavelength = src.wavelength;
55 int WaveConfig::equivalent(WaveConfig &src)
58 (this->mode == src.mode) &&
59 EQUIV(this->reflective, src.reflective) &&
60 EQUIV(this->amplitude, src.amplitude) &&
61 EQUIV(this->phase, src.phase) &&
62 EQUIV(this->wavelength, src.wavelength);
65 void WaveConfig::interpolate(WaveConfig &prev,
71 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
72 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
74 this->amplitude = prev.amplitude * prev_scale + next.amplitude * next_scale;
75 this->phase = prev.phase * prev_scale + next.phase * next_scale;
76 this->wavelength = prev.wavelength * prev_scale + next.wavelength * next_scale;
77 this->mode = prev.mode;
78 this->reflective = prev.reflective;
88 WaveSmear::WaveSmear(WaveEffect *plugin, WaveWindow *window, int x, int y)
89 : BC_Radial(x, y, plugin->config.mode == SMEAR, _("Smear"))
91 this->plugin = plugin;
92 this->window = window;
94 int WaveSmear::handle_event()
96 plugin->config.mode = SMEAR;
97 window->update_mode();
98 plugin->send_configure_change();
105 WaveBlacken::WaveBlacken(WaveEffect *plugin, WaveWindow *window, int x, int y)
106 : BC_Radial(x, y, plugin->config.mode == BLACKEN, _("Blacken"))
108 this->plugin = plugin;
109 this->window = window;
111 int WaveBlacken::handle_event()
113 plugin->config.mode = BLACKEN;
114 window->update_mode();
115 plugin->send_configure_change();
124 WaveReflective::WaveReflective(WaveEffect *plugin, int x, int y)
125 : BC_CheckBox(x, y, plugin->config.reflective, _("Reflective"))
127 this->plugin = plugin;
129 int WaveReflective::handle_event()
131 plugin->config.reflective = get_value();
132 plugin->send_configure_change();
137 WaveAmplitude::WaveAmplitude(WaveEffect *plugin, int x, int y)
145 plugin->config.amplitude)
147 this->plugin = plugin;
149 int WaveAmplitude::handle_event()
151 plugin->config.amplitude = get_value();
152 plugin->send_configure_change();
158 WavePhase::WavePhase(WaveEffect *plugin, int x, int y)
166 plugin->config.phase)
168 this->plugin = plugin;
170 int WavePhase::handle_event()
172 plugin->config.phase = get_value();
173 plugin->send_configure_change();
177 WaveLength::WaveLength(WaveEffect *plugin, int x, int y)
185 plugin->config.wavelength)
187 this->plugin = plugin;
189 int WaveLength::handle_event()
191 plugin->config.wavelength = get_value();
192 plugin->send_configure_change();
196 WaveReset::WaveReset(WaveEffect *plugin, WaveWindow *gui, int x, int y)
197 : BC_GenericButton(x, y, _("Reset"))
199 this->plugin = plugin;
202 WaveReset::~WaveReset()
205 int WaveReset::handle_event()
207 plugin->config.reset();
209 plugin->send_configure_change();
219 WaveWindow::WaveWindow(WaveEffect *plugin)
220 : PluginClientWindow(plugin, 335, 140, 335, 140, 0)
222 this->plugin = plugin;
225 WaveWindow::~WaveWindow()
229 void WaveWindow::create_objects()
231 int x = 10, y = 10, x1 = 115;
233 // add_subwindow(new BC_Title(x, y, _("Mode:")));
234 // add_subwindow(smear = new WaveSmear(plugin, this, x1, y));
236 // add_subwindow(blacken = new WaveBlacken(plugin, this, x1, y));
238 // add_subwindow(reflective = new WaveReflective(plugin, x1, y));
240 add_subwindow(new BC_Title(x, y, _("Amplitude:")));
241 add_subwindow(amplitude = new WaveAmplitude(plugin, x1, y));
243 add_subwindow(new BC_Title(x, y, _("Phase:")));
244 add_subwindow(phase = new WavePhase(plugin, x1, y));
246 add_subwindow(new BC_Title(x, y, _("Wavelength:")));
247 add_subwindow(wavelength = new WaveLength(plugin, x1, y));
249 add_subwindow(reset = new WaveReset(plugin, this, x, y));
255 void WaveWindow::update_mode()
257 // smear->update(plugin->config.mode == SMEAR);
258 // blacken->update(plugin->config.mode == BLACKEN);
262 void WaveWindow::update()
264 amplitude->update(plugin->config.amplitude);
265 phase->update(plugin->config.phase);
266 wavelength->update(plugin->config.wavelength);
277 REGISTER_PLUGIN(WaveEffect)
282 WaveEffect::WaveEffect(PluginServer *server)
283 : PluginVClient(server)
290 WaveEffect::~WaveEffect()
294 if(temp_frame) delete temp_frame;
295 if(engine) delete engine;
299 const char* WaveEffect::plugin_title() { return N_("Wave"); }
300 int WaveEffect::is_realtime() { return 1; }
303 NEW_WINDOW_MACRO(WaveEffect, WaveWindow)
305 void WaveEffect::update_gui()
309 thread->window->lock_window();
310 load_configuration();
311 ((WaveWindow*)thread->window)->update_mode();
312 // thread->window->reflective->update(config.reflective);
313 ((WaveWindow*)thread->window)->amplitude->update(config.amplitude);
314 ((WaveWindow*)thread->window)->phase->update(config.phase);
315 ((WaveWindow*)thread->window)->wavelength->update(config.wavelength);
316 thread->window->unlock_window();
321 LOAD_CONFIGURATION_MACRO(WaveEffect, WaveConfig)
324 void WaveEffect::save_data(KeyFrame *keyframe)
328 // cause data to be stored directly in text
329 output.set_shared_output(keyframe->xbuf);
330 output.tag.set_title("WAVE");
331 output.tag.set_property("MODE", config.mode);
332 output.tag.set_property("REFLECTIVE", config.reflective);
333 output.tag.set_property("AMPLITUDE", config.amplitude);
334 output.tag.set_property("PHASE", config.phase);
335 output.tag.set_property("WAVELENGTH", config.wavelength);
337 output.tag.set_title("/WAVE");
339 output.append_newline();
340 output.terminate_string();
343 void WaveEffect::read_data(KeyFrame *keyframe)
347 input.set_shared_input(keyframe->xbuf);
349 while(!input.read_tag())
351 if(input.tag.title_is("WAVE"))
353 config.mode = input.tag.get_property("MODE", config.mode);
354 config.reflective = input.tag.get_property("REFLECTIVE", config.reflective);
355 config.amplitude = input.tag.get_property("AMPLITUDE", config.amplitude);
356 config.phase = input.tag.get_property("PHASE", config.phase);
357 config.wavelength = input.tag.get_property("WAVELENGTH", config.wavelength);
363 int WaveEffect::process_realtime(VFrame *input, VFrame *output)
365 load_configuration();
369 //printf("WaveEffect::process_realtime %f %d\n", config.radius, config.use_intensity);
371 this->output = output;
373 if(EQUIV(config.amplitude, 0) || EQUIV(config.wavelength, 0))
375 if(input->get_rows()[0] != output->get_rows()[0])
376 output->copy_from(input);
380 if(input->get_rows()[0] == output->get_rows()[0])
382 if(!temp_frame) temp_frame = new VFrame(input->get_w(), input->get_h(),
383 input->get_color_model(), 0);
384 temp_frame->copy_from(input);
385 this->input = temp_frame;
391 engine = new WaveServer(this, (PluginClient::smp + 1));
394 engine->process_packages();
407 WavePackage::WavePackage()
417 WaveUnit::WaveUnit(WaveEffect *plugin, WaveServer *server)
420 this->plugin = plugin;
425 #define WITHIN(a, b, c) ((((a) <= (b)) && ((b) <= (c))) ? 1 : 0)
427 static float bilinear(double x,
440 m0 = (1.0 - x) * v[0] + x * v[1];
441 m1 = (1.0 - x) * v[2] + x * v[3];
443 return((1.0 - y) * m0 + y * m1);
446 void WaveUnit::process_package(LoadPackage *package)
448 WavePackage *pkg = (WavePackage*)package;
449 int w = plugin->input->get_w();
450 int h = plugin->input->get_h();
451 double cen_x, cen_y; /* Center of wave */
452 double xhsiz, yhsiz; /* Half size of selection */
453 double radius; /* Radius */
457 double xscale, yscale;
463 int x1_in, y1_in, x2_in, y2_in;
464 double phase = plugin->config.phase * M_PI / 180;
470 cen_x = (double) (x2 - 1 + x1) / 2.0;
471 cen_y = (double) (y2 - 1 + y1) / 2.0;
472 xhsiz = (double) (x2 - x1) / 2.0;
473 yhsiz = (double) (y2 - y1) / 2.0;
477 xscale = yhsiz / xhsiz;
480 else if (xhsiz > yhsiz)
483 yscale = xhsiz / yhsiz;
491 radius = MAX(xhsiz, yhsiz);
494 wavelength = plugin->config.wavelength / 100 * radius;
499 #define WAVE(type, components, chroma_offset) \
501 int row_size = w * components; \
502 type **in_rows = (type**)plugin->input->get_rows(); \
503 for(int y = pkg->row1; y < pkg->row2; y++) \
505 type *dest = (type*)plugin->output->get_rows()[y]; \
507 for(int x = x1; x < x2; x++) \
509 dx = (x - cen_x) * xscale; \
510 dy = (y - cen_y) * yscale; \
511 d = sqrt(dx * dx + dy * dy); \
513 if(plugin->config.reflective) \
515 amnt = plugin->config.amplitude * \
516 fabs(sin(((d / wavelength) * \
520 needx = (amnt * dx) / xscale + cen_x; \
521 needy = (amnt * dy) / yscale + cen_y; \
525 amnt = plugin->config.amplitude * \
526 sin(((d / wavelength) * \
530 needx = (amnt + dx) / xscale + cen_x; \
531 needy = (amnt + dy) / yscale + cen_y; \
537 if(plugin->config.mode == SMEAR) \
560 type *p = in_rows[CLIP(yi, 0, h - 1)] + \
561 CLIP(xi, 0, w - 1) * components; \
562 x1_in = WITHIN(0, xi, w - 1); \
563 y1_in = WITHIN(0, yi, h - 1); \
564 x2_in = WITHIN(0, xi + 1, w - 1); \
565 y2_in = WITHIN(0, yi + 1, h - 1); \
568 for(int k = 0; k < components; k++) \
570 if (x1_in && y1_in) \
571 values[0] = *(p + k); \
573 values[0] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
575 if (x2_in && y1_in) \
576 values[1] = *(p + components + k); \
578 values[1] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
580 if (x1_in && y2_in) \
581 values[2] = *(p + row_size + k); \
583 values[2] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
588 values[3] = *(p + row_size + components + k); \
590 values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
593 values[3] = ((k == 1 || k == 2) ? 0 : chroma_offset); \
595 val = bilinear(needx, needy, values); \
597 *dest++ = (type)val; \
606 switch(plugin->input->get_color_model())
609 WAVE(unsigned char, 3, 0x0);
615 WAVE(unsigned char, 3, 0x80);
618 WAVE(uint16_t, 3, 0x0);
621 WAVE(uint16_t, 3, 0x8000);
624 WAVE(unsigned char, 4, 0x0);
627 WAVE(unsigned char, 4, 0x0);
630 WAVE(unsigned char, 4, 0x8000);
632 case BC_RGBA16161616:
633 WAVE(uint16_t, 4, 0x0);
635 case BC_YUVA16161616:
636 WAVE(uint16_t, 4, 0x8000);
650 WaveServer::WaveServer(WaveEffect *plugin, int cpus)
651 : LoadServer(cpus, cpus)
653 this->plugin = plugin;
656 void WaveServer::init_packages()
658 for(int i = 0; i < LoadServer::get_total_packages(); i++)
660 WavePackage *pkg = (WavePackage*)get_package(i);
661 pkg->row1 = plugin->input->get_h() * i / LoadServer::get_total_packages();
662 pkg->row2 = plugin->input->get_h() * (i + 1) / LoadServer::get_total_packages();
667 LoadClient* WaveServer::new_client()
669 return new WaveUnit(plugin, this);
672 LoadPackage* WaveServer::new_package()
674 return new WavePackage;