4 * Copyright (C) 1997-2020 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
26 #include "pluginvclient.h"
43 void copy_from(BoxBlurConfig &that);
44 int equivalent(BoxBlurConfig &that);
45 void interpolate(BoxBlurConfig &prev, BoxBlurConfig &next,
46 int64_t prev_frame, int64_t next_frame, int64_t current_frame);
48 int horz_radius, vert_radius, power;
52 class BoxBlurRadius : public BC_ISlider
55 BoxBlurRadius(BoxBlurWindow *gui, int x, int y, int w, int *radius);
62 class BoxBlurPower : public BC_ISlider
65 BoxBlurPower(BoxBlurWindow *gui, int x, int y, int w, int *power);
72 class BoxBlurWindow : public PluginClientWindow
75 BoxBlurWindow(BoxBlurEffect *plugin);
77 void create_objects();
79 BoxBlurEffect *plugin;
80 BoxBlurRadius *blur_horz;
81 BoxBlurRadius *blur_vert;
82 BoxBlurPower *blur_power;
87 class BoxBlurEffect : public PluginVClient
90 BoxBlurEffect(PluginServer *server);
93 PLUGIN_CLASS_MEMBERS(BoxBlurConfig)
94 int process_realtime(VFrame *input, VFrame *output);
97 void save_data(KeyFrame *keyframe);
98 void read_data(KeyFrame *keyframe);
104 BoxBlurConfig::BoxBlurConfig()
111 void BoxBlurConfig::copy_from(BoxBlurConfig &that)
113 horz_radius = that.horz_radius;
114 vert_radius = that.vert_radius;
118 int BoxBlurConfig::equivalent(BoxBlurConfig &that)
120 return horz_radius == that.horz_radius &&
121 vert_radius == that.vert_radius &&
125 void BoxBlurConfig::interpolate(BoxBlurConfig &prev, BoxBlurConfig &next,
126 int64_t prev_frame, int64_t next_frame, int64_t current_frame)
128 double u = (double)(next_frame - current_frame) / (next_frame - prev_frame);
130 this->horz_radius = u*prev.horz_radius + v*next.horz_radius;
131 this->vert_radius = u*prev.vert_radius + v*next.vert_radius;
132 this->power = u*prev.power + v*next.power;
136 BoxBlurRadius::BoxBlurRadius(BoxBlurWindow *gui, int x, int y, int w, int *radius)
137 : BC_ISlider(x, y, 0, w, w, 0, 100, *radius)
140 this->radius = radius;
142 int BoxBlurRadius::handle_event()
144 *radius = get_value();
145 gui->plugin->send_configure_change();
149 BoxBlurPower::BoxBlurPower(BoxBlurWindow *gui, int x, int y, int w, int *power)
150 : BC_ISlider(x, y, 0, w, w, 1, 10, *power)
155 int BoxBlurPower::handle_event()
157 *power = get_value();
158 gui->plugin->send_configure_change();
162 BoxBlurWindow::BoxBlurWindow(BoxBlurEffect *plugin)
163 : PluginClientWindow(plugin, xS(200), yS(120), xS(200), yS(120), 0)
165 this->plugin = plugin;
168 BoxBlurWindow::~BoxBlurWindow()
172 void BoxBlurWindow::create_objects()
174 int x = xS(10), y = yS(10);
175 int x1 = xS(70), margin = plugin->get_theme()->widget_border;
177 add_subwindow(title = new BC_Title(x, y, _("Box Blur"), MEDIUMFONT, YELLOW));
178 y += title->get_h() + 2*margin;
179 add_subwindow(title = new BC_Title(x, y, _("Horz:")));
180 add_subwindow(blur_horz = new BoxBlurRadius(this, x1, y, xS(120),
181 &plugin->config.horz_radius));
182 y += blur_horz->get_h() + margin;
183 add_subwindow(title = new BC_Title(x, y, _("Vert:")));
184 add_subwindow(blur_vert = new BoxBlurRadius(this, x1, y, xS(120),
185 &plugin->config.vert_radius));
186 y += blur_vert->get_h() + margin;
187 add_subwindow(title = new BC_Title(x, y, _("Power:")));
188 add_subwindow(blur_power = new BoxBlurPower(this, x1, y, xS(120),
189 &plugin->config.power));
194 REGISTER_PLUGIN(BoxBlurEffect)
195 NEW_WINDOW_MACRO(BoxBlurEffect, BoxBlurWindow)
196 LOAD_CONFIGURATION_MACRO(BoxBlurEffect, BoxBlurConfig)
199 BoxBlurEffect::BoxBlurEffect(PluginServer *server)
200 : PluginVClient(server)
205 BoxBlurEffect::~BoxBlurEffect()
210 const char* BoxBlurEffect::plugin_title() { return N_("BoxBlur"); }
211 int BoxBlurEffect::is_realtime() { return 1; }
214 void BoxBlurEffect::save_data(KeyFrame *keyframe)
217 output.set_shared_output(keyframe->xbuf);
218 output.tag.set_title("BOXBLUR");
219 output.tag.set_property("HORZ_RADIUS", config.horz_radius);
220 output.tag.set_property("VERT_RADIUS", config.vert_radius);
221 output.tag.set_property("POWER", config.power);
223 output.tag.set_title("/BOXBLUR");
225 output.append_newline();
226 output.terminate_string();
229 void BoxBlurEffect::read_data(KeyFrame *keyframe)
232 input.set_shared_input(keyframe->xbuf);
235 while( !(result = input.read_tag()) ) {
236 if( input.tag.title_is("BOXBLUR") ) {
237 config.horz_radius = input.tag.get_property("HORZ_RADIUS", config.horz_radius);
238 config.vert_radius = input.tag.get_property("VERT_RADIUS", config.vert_radius);
239 config.power = input.tag.get_property("POWER", config.power);
244 int BoxBlurEffect::process_realtime(VFrame *input, VFrame *output)
246 load_configuration();
248 int cpus = input->get_w()*input->get_h()/0x80000 + 1;
249 box_blur = new BoxBlur(cpus);
251 if( config.horz_radius ) {
252 box_blur->hblur(output, input, config.horz_radius, config.power);
255 if( config.vert_radius )
256 box_blur->vblur(output, input, config.vert_radius, config.power);
260 void BoxBlurEffect::update_gui()
262 if( !thread ) return;
263 load_configuration();
264 thread->window->lock_window("BoxBlurEffect::update_gui");
265 BoxBlurWindow *gui = (BoxBlurWindow *)thread->window;
266 gui->blur_horz->update(config.horz_radius);
267 gui->blur_vert->update(config.vert_radius);
268 gui->blur_power->update(config.power);
269 thread->window->unlock_window();