void blurt(dst_t *dst, int dst_step, src_t *src, int src_step,
int len, int radius, float s)
{
+ if( radius > len ) radius = len;
const int length = radius*2 + 1;
const int inv = s * ((1<<16) + length/2)/length;
int x, n, sum = src[radius*src_step];
int src_vstep = box_blur->src_vstep;
int dst_vstep = box_blur->dst_vstep;
BoxBlurPackage *pkg = (BoxBlurPackage*)package;
- int u1 = pkg->u1, u2 = pkg->u2;
+ int u1 = pkg->u1, u2 = pkg->u2, v = box_blur->v1;
float s = 1.;
if( sizeof(src_t) != sizeof(dst_t) ) {
switch( sizeof(dst_t) ) {
}
}
for( int u=u1; u<u2; ++u ) {
- src_t *sp = src_data + u*src_ustep;
- dst_t *dp = dst_data + u*dst_ustep;
+ src_t *sp = src_data + u*src_ustep + v*src_vstep;
+ dst_t *dp = dst_data + u*dst_ustep + v*dst_vstep;
for( int c=c0; c<=c1; ++c ) {
blur_power(dp+c, dst_vstep, sp+c, src_vstep,
vlen, radius, power, s);
void BoxBlurUnit::process_package(LoadPackage *package)
{
BoxBlur *box_blur = (BoxBlur *)server;
- int src_bpp = box_blur->src_bpp, dst_bpp = box_blur->dst_bpp;
- switch( src_bpp ) {
- case 1: switch( dst_bpp ) {
+ int src_bpc = box_blur->src_bpc, dst_bpc = box_blur->dst_bpc;
+ switch( src_bpc ) {
+ case 1: switch( dst_bpc ) {
case 1: blurt_package<uint8_t, const uint8_t>(package); break;
case 2: blurt_package<uint16_t, const uint8_t>(package); break;
case 4: blurt_package<float, const uint8_t>(package); break;
}
break;
- case 2: switch( dst_bpp ) {
+ case 2: switch( dst_bpc ) {
case 1: blurt_package<uint8_t, const uint16_t>(package); break;
case 2: blurt_package<uint16_t, const uint16_t>(package); break;
case 4: blurt_package<float, const uint16_t>(package); break;
}
break;
- case 4: switch( dst_bpp ) {
+ case 4: switch( dst_bpc ) {
case 1: blurt_package<uint8_t, const float>(package); break;
case 2: blurt_package<uint16_t, const float>(package); break;
case 4: blurt_package<float, const float>(package); break;
void BoxBlur::init_packages()
{
- int u = 0;
+ int u = u1;
for( int i=0,n=LoadServer::get_total_packages(); i<n; ) {
BoxBlurPackage *pkg = (BoxBlurPackage*)get_package(i);
pkg->u1 = u;
- pkg->u2 = u = (++i * ulen) / n;
+ u = u1 + (++i * ulen) / n;
+ pkg->u2 = u;
}
}
this->radius = radius;
this->power = power;
this->uv = uv;
- int src_w = src->get_w(), src_h = src->get_h();
- ulen = !uv ? src_h : src_w;
- vlen = !uv ? src_w : src_h;
+ this->u1 = !uv ? y1 : x1;
+ this->u2 = !uv ? y2 : x2;
+ this->v1 = !uv ? x1 : y1;
+ this->v2 = !uv ? x2 : y2;
+ if( (ulen = u2 - u1) <= 0 ) return;
+ if( (vlen = v2 - v1) <= 0 ) return;
c0 = comp<0 ? 0 : comp;
c1 = comp<0 ? 2 : comp;
src_data = src->get_data();
dst_data = dst->get_data();
int src_pixsz = BC_CModels::calculate_pixelsize(src->get_color_model());
int src_comps = BC_CModels::components(src->get_color_model());
- src_bpp = src_pixsz / src_comps;
+ src_bpc = src_pixsz / src_comps;
int dst_pixsz = BC_CModels::calculate_pixelsize(dst->get_color_model());
int dst_comps = BC_CModels::components(dst->get_color_model());
- dst_bpp = dst_pixsz / dst_comps;
- int dst_linsz = dst->get_bytes_per_line() / dst_bpp;
- int src_linsz = src->get_bytes_per_line() / src_bpp;
+ dst_bpc = dst_pixsz / dst_comps;
+ int dst_linsz = dst->get_bytes_per_line() / dst_bpc;
+ int src_linsz = src->get_bytes_per_line() / src_bpc;
src_ustep = !uv ? src_linsz : src_comps;
- dst_ustep = !uv ? dst_linsz: dst_comps;
+ dst_ustep = !uv ? dst_linsz : dst_comps;
src_vstep = !uv ? src_comps : src_linsz;
dst_vstep = !uv ? dst_comps : dst_linsz;
process_packages();
}
-void BoxBlur::hblur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+int BoxBlur::init_box(VFrame *dst, int x, int y, int w, int h)
{
+ x1 = x; x2 = x+w;
+ y1 = y; y2 = y+h;
+ if( x1 < 0 ) x1 = 0;
+ if( y1 < 0 ) y1 = 0;
+ int dw = dst->get_w(), dh = dst->get_h();
+ if( x2 > dw ) x2 = dw;
+ if( y2 > dh ) y2 = dh;
+ return x2 > x1 && y2 > y1 ? 1 : 0;
+}
+
+void BoxBlur::hblur(VFrame *dst, VFrame *src, int radius, int power, int comp,
+ int x, int y, int w, int h)
+{
+ if( !init_box(dst, x, y, w, h) ) return;
process(dst, src, 0, radius, power, comp);
}
-void BoxBlur::vblur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+void BoxBlur::hblur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+{
+ return hblur(dst, src, radius, power, comp,
+ 0, 0, dst->get_w(), dst->get_h());
+}
+
+void BoxBlur::vblur(VFrame *dst, VFrame *src, int radius, int power, int comp,
+ int x, int y, int w, int h)
{
+ if( !init_box(dst, x, y, w, h) ) return;
process(dst, src, 1, radius, power, comp);
}
-void BoxBlur::blur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+void BoxBlur::vblur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+{
+ return vblur(dst, src, radius, power, comp,
+ 0, 0, dst->get_w(), dst->get_h());
+}
+
+void BoxBlur::blur(VFrame *dst, VFrame *src, int radius, int power, int comp,
+ int x, int y, int w, int h)
{
+ if( !init_box(dst, x, y, w, h) ) return;
process(dst, src, 0, radius, power, comp);
process(dst, dst, 1, radius, power, comp);
}
+void BoxBlur::blur(VFrame *dst, VFrame *src, int radius, int power, int comp)
+{
+ return blur(dst, src, radius, power, comp,
+ 0, 0, dst->get_w(), dst->get_h());
+}
#include "guicast.h"
#include "boxblur.h"
+#include "dragcheckbox.h"
+#include "edl.h"
#include "filexml.h"
#include "language.h"
+#include "plugin.h"
+#include "pluginserver.h"
#include "pluginvclient.h"
+#include "track.h"
+#include "tracks.h"
#include "theme.h"
#include <stdint.h>
class BoxBlurConfig;
class BoxBlurRadius;
class BoxBlurPower;
+class BoxBlurDrag;
+class BoxBlurReset;
+class BoxBlurX;
+class BoxBlurY;
+class BoxBlurW;
+class BoxBlurH;
class BoxBlurWindow;
class BoxBlurEffect;
int equivalent(BoxBlurConfig &that);
void interpolate(BoxBlurConfig &prev, BoxBlurConfig &next,
int64_t prev_frame, int64_t next_frame, int64_t current_frame);
+ void reset();
int horz_radius, vert_radius, power;
+ float box_x, box_y;
+ int box_w, box_h;
+ int drag;
};
int *power;
};
+class BoxBlurX : public BC_TumbleTextBox
+{
+public:
+ BoxBlurX(BoxBlurWindow *gui, int x, int y);
+ int handle_event();
+ BoxBlurWindow *gui;
+};
+class BoxBlurY : public BC_TumbleTextBox
+{
+public:
+ BoxBlurY(BoxBlurWindow *gui, int x, int y);
+ int handle_event();
+ BoxBlurWindow *gui;
+};
+class BoxBlurW : public BC_TumbleTextBox
+{
+public:
+ BoxBlurW(BoxBlurWindow *gui, int x, int y);
+ int handle_event();
+ BoxBlurWindow *gui;
+};
+class BoxBlurH : public BC_TumbleTextBox
+{
+public:
+ BoxBlurH(BoxBlurWindow *gui, int x, int y);
+ int handle_event();
+ BoxBlurWindow *gui;
+};
+
+class BoxBlurDrag : public DragCheckBox
+{
+public:
+ BoxBlurDrag(BoxBlurWindow *gui, BoxBlurEffect *plugin, int x, int y);
+ int handle_event();
+ void update_gui();
+ Track *get_drag_track();
+ int64_t get_drag_position();
+
+ BoxBlurWindow *gui;
+ BoxBlurEffect *plugin;
+};
+
+class BoxBlurReset : public BC_Button
+{
+public:
+ BoxBlurReset(BoxBlurWindow *gui, int x, int y);
+ int handle_event();
+ static int calculate_w(BoxBlurWindow *gui);
+
+ BoxBlurWindow *gui;
+};
+
class BoxBlurWindow : public PluginClientWindow
{
public:
BoxBlurWindow(BoxBlurEffect *plugin);
~BoxBlurWindow();
void create_objects();
+ void update_gui();
+ void update_drag();
BoxBlurEffect *plugin;
+ BoxBlurReset *reset;
BoxBlurRadius *blur_horz;
BoxBlurRadius *blur_vert;
BoxBlurPower *blur_power;
+ BoxBlurDrag *drag;
+ BoxBlurX *box_x;
+ BoxBlurY *box_y;
+ BoxBlurW *box_w;
+ BoxBlurH *box_h;
};
-
class BoxBlurEffect : public PluginVClient
{
public:
int is_realtime();
void save_data(KeyFrame *keyframe);
void read_data(KeyFrame *keyframe);
+ void draw_boundry();
+ VFrame *input, *output;
BoxBlur *box_blur;
};
-BoxBlurConfig::BoxBlurConfig()
+void BoxBlurConfig::reset()
{
horz_radius = 2;
vert_radius = 2;
power = 2;
+ drag = 0;
+ box_x = box_y = 0.0;
+ box_w = box_h = 0;
+}
+
+BoxBlurConfig::BoxBlurConfig()
+{
+ reset();
}
void BoxBlurConfig::copy_from(BoxBlurConfig &that)
horz_radius = that.horz_radius;
vert_radius = that.vert_radius;
power = that.power;
+ drag = that.drag;
+ box_x = that.box_x; box_y = that.box_y;
+ box_w = that.box_w; box_h = that.box_h;
}
int BoxBlurConfig::equivalent(BoxBlurConfig &that)
{
return horz_radius == that.horz_radius &&
vert_radius == that.vert_radius &&
- power == that.power;
+ power == that.power && // drag == that.drag &&
+ EQUIV(box_x, that.box_x) && EQUIV(box_y, that.box_y) &&
+ box_w == that.box_w && box_h == that.box_h;
}
void BoxBlurConfig::interpolate(BoxBlurConfig &prev, BoxBlurConfig &next,
this->horz_radius = u*prev.horz_radius + v*next.horz_radius;
this->vert_radius = u*prev.vert_radius + v*next.vert_radius;
this->power = u*prev.power + v*next.power;
+ this->drag = prev.drag;
+ this->box_x = u*prev.box_x + v*next.box_x;
+ this->box_y = u*prev.box_y + v*next.box_y;
+ this->box_w = u*prev.box_w + v*next.box_w;
+ this->box_h = u*prev.box_h + v*next.box_h;
}
}
BoxBlurWindow::BoxBlurWindow(BoxBlurEffect *plugin)
- : PluginClientWindow(plugin, xS(200), yS(120), xS(200), yS(120), 0)
+ : PluginClientWindow(plugin, xS(250), yS(185), xS(250), yS(185), 0)
{
this->plugin = plugin;
+ box_x = 0; box_y = 0;
+ box_w = 0; box_h = 0;
}
BoxBlurWindow::~BoxBlurWindow()
{
+ delete box_x;
+ delete box_y;
+ delete box_w;
+ delete box_h;
}
void BoxBlurWindow::create_objects()
{
int x = xS(10), y = yS(10);
- int x1 = xS(70), margin = plugin->get_theme()->widget_border;
+ int t1 = x, t2 = t1+xS(24), t3 = get_w()/2, t4 = t3 + xS(24);
+ int margin = plugin->get_theme()->widget_border;
BC_Title *title;
- add_subwindow(title = new BC_Title(x, y, _("Box Blur"), MEDIUMFONT, YELLOW));
- y += title->get_h() + 2*margin;
+ add_subwindow(title = new BC_Title(x, y, _("Box Blur"), MEDIUMFONT_3D));
+ add_subwindow(drag = new BoxBlurDrag(this, plugin, t3, y));
+ drag->create_objects();
+ int x1 = get_w() - BoxBlurReset::calculate_w(this) - 2*margin;
+ add_subwindow(reset = new BoxBlurReset(this, x1, y));
+ y += bmax(title->get_h(), drag->get_h()) + 2*margin;
+
+ add_subwindow(title = new BC_Title(t1, y, _("X:")));
+ box_x = new BoxBlurX(this, t2, y);
+ box_x->create_objects();
+ add_subwindow(title = new BC_Title(t3, y, _("W:")));
+ box_w = new BoxBlurW(this, t4, y);
+ box_w->create_objects();
+ y += bmax(title->get_h(), box_w->get_h()) + margin;
+ add_subwindow(title = new BC_Title(t1, y, _("Y:")));
+ box_y = new BoxBlurY(this, t2, y);
+ box_y->create_objects();
+ add_subwindow(title = new BC_Title(t3, y, _("H:")));
+ box_h = new BoxBlurH(this, t4, y);
+ box_h->create_objects();
+ y += bmax(title->get_h(), box_h->get_h()) + margin;
+
+ y += 2*margin;
+ x1 = xS(70);
add_subwindow(title = new BC_Title(x, y, _("Horz:")));
- add_subwindow(blur_horz = new BoxBlurRadius(this, x1, y, xS(120),
+ add_subwindow(blur_horz = new BoxBlurRadius(this, x1, y, xS(160),
&plugin->config.horz_radius));
y += blur_horz->get_h() + margin;
add_subwindow(title = new BC_Title(x, y, _("Vert:")));
- add_subwindow(blur_vert = new BoxBlurRadius(this, x1, y, xS(120),
+ add_subwindow(blur_vert = new BoxBlurRadius(this, x1, y, xS(160),
&plugin->config.vert_radius));
y += blur_vert->get_h() + margin;
add_subwindow(title = new BC_Title(x, y, _("Power:")));
- add_subwindow(blur_power = new BoxBlurPower(this, x1, y, xS(120),
+ add_subwindow(blur_power = new BoxBlurPower(this, x1, y, xS(160),
&plugin->config.power));
+ y += blur_power->get_h() + margin;
+
show_window(1);
}
+void BoxBlurWindow::update_gui()
+{
+ BoxBlurConfig &config = plugin->config;
+ blur_horz->update(config.horz_radius);
+ blur_vert->update(config.vert_radius);
+ blur_power->update(config.power);
+ box_x->update(config.box_x);
+ box_y->update(config.box_y);
+ box_w->update((int64_t)config.box_w);
+ box_h->update((int64_t)config.box_h);
+ drag->drag_x = config.box_x;
+ drag->drag_y = config.box_y;
+ drag->drag_w = config.box_w;
+ drag->drag_h = config.box_h;
+}
+
REGISTER_PLUGIN(BoxBlurEffect)
NEW_WINDOW_MACRO(BoxBlurEffect, BoxBlurWindow)
output.tag.set_property("HORZ_RADIUS", config.horz_radius);
output.tag.set_property("VERT_RADIUS", config.vert_radius);
output.tag.set_property("POWER", config.power);
+ output.tag.set_property("DRAG", config.drag);
+ output.tag.set_property("BOX_X", config.box_x);
+ output.tag.set_property("BOX_Y", config.box_y);
+ output.tag.set_property("BOX_W", config.box_w);
+ output.tag.set_property("BOX_H", config.box_h);
output.append_tag();
output.tag.set_title("/BOXBLUR");
output.append_tag();
config.horz_radius = input.tag.get_property("HORZ_RADIUS", config.horz_radius);
config.vert_radius = input.tag.get_property("VERT_RADIUS", config.vert_radius);
config.power = input.tag.get_property("POWER", config.power);
+ config.drag = input.tag.get_property("DRAG", config.drag);
+ config.box_x = input.tag.get_property("BOX_X", config.box_x);
+ config.box_y = input.tag.get_property("BOX_Y", config.box_y);
+ config.box_w = input.tag.get_property("BOX_W", config.box_w);
+ config.box_h = input.tag.get_property("BOX_H", config.box_h);
}
}
}
+void BoxBlurEffect::draw_boundry()
+{
+ if( !gui_open() ) return;
+ int box_x = config.box_x, box_y = config.box_y;
+ int box_w = config.box_w ? config.box_w : input->get_w();
+ int box_h = config.box_h ? config.box_h : input->get_h();
+ DragCheckBox::draw_boundary(output, box_x, box_y, box_w, box_h);
+}
+
int BoxBlurEffect::process_realtime(VFrame *input, VFrame *output)
{
+ this->input = input;
+ this->output = output;
load_configuration();
+ int out_w = output->get_w(), out_h = output->get_h();
+
if( !box_blur ) {
- int cpus = input->get_w()*input->get_h()/0x80000 + 1;
+ int cpus = (out_w * out_h)/0x80000 + 1;
box_blur = new BoxBlur(cpus);
}
+ int x = config.box_x, y = config.box_y;
+ int ow = config.box_w ? config.box_w : out_w;
+ int oh = config.box_h ? config.box_h : out_h;
if( config.horz_radius ) {
- box_blur->hblur(output, input, config.horz_radius, config.power);
+ box_blur->hblur(output, input, config.horz_radius, config.power,
+ -1, x,y, ow, oh);
input = output;
}
- if( config.vert_radius )
- box_blur->vblur(output, input, config.vert_radius, config.power);
+ if( config.vert_radius ) {
+ box_blur->vblur(output, input, config.vert_radius, config.power,
+ -1, x,y, ow, oh);
+ }
+
+ if( config.drag )
+ draw_boundry();
+
return 1;
}
load_configuration();
thread->window->lock_window("BoxBlurEffect::update_gui");
BoxBlurWindow *gui = (BoxBlurWindow *)thread->window;
- gui->blur_horz->update(config.horz_radius);
- gui->blur_vert->update(config.vert_radius);
- gui->blur_power->update(config.power);
+ gui->update_gui();
thread->window->unlock_window();
}
+
+BoxBlurX::BoxBlurX(BoxBlurWindow *gui, int x, int y)
+ : BC_TumbleTextBox(gui, gui->plugin->config.box_x,
+ -32767.f, 32767.f, x, y, xS(64))
+{
+ this->gui = gui;
+ set_precision(1);
+}
+int BoxBlurX::handle_event()
+{
+ gui->plugin->config.box_x = atof(get_text());
+ gui->update_drag();
+ return 1;
+}
+
+BoxBlurY::BoxBlurY(BoxBlurWindow *gui, int x, int y)
+ : BC_TumbleTextBox(gui, gui->plugin->config.box_y,
+ -32767.f, 32767.f, x, y, xS(64))
+{
+ this->gui = gui;
+ set_precision(1);
+}
+int BoxBlurY::handle_event()
+{
+ gui->plugin->config.box_y = atof(get_text());
+ gui->update_drag();
+ return 1;
+}
+
+BoxBlurW::BoxBlurW(BoxBlurWindow *gui, int x, int y)
+ : BC_TumbleTextBox(gui, gui->plugin->config.box_w,
+ 0, 32767, x, y, xS(64))
+{
+ this->gui = gui;
+}
+int BoxBlurW::handle_event()
+{
+ gui->plugin->config.box_w = atol(get_text());
+ gui->update_drag();
+ return 1;
+}
+
+BoxBlurH::BoxBlurH(BoxBlurWindow *gui, int x, int y)
+ : BC_TumbleTextBox(gui, gui->plugin->config.box_h,
+ 0, 32767, x, y, xS(64))
+{
+ this->gui = gui;
+}
+int BoxBlurH::handle_event()
+{
+ gui->plugin->config.box_h = atol(get_text());
+ gui->update_drag();
+ return 1;
+}
+
+BoxBlurDrag::BoxBlurDrag(BoxBlurWindow *gui, BoxBlurEffect *plugin, int x, int y)
+ : DragCheckBox(plugin->server->mwindow, x, y, _("Drag"), &plugin->config.drag,
+ plugin->config.box_x, plugin->config.box_y,
+ plugin->config.box_w, plugin->config.box_h)
+{
+ this->plugin = plugin;
+ this->gui = gui;
+}
+
+Track *BoxBlurDrag::get_drag_track()
+{
+ PluginServer *server = plugin->server;
+ int plugin_id = server->plugin_id;
+ Plugin *plugin = server->edl->tracks->plugin_exists(plugin_id);
+ return !plugin ? 0 : plugin->track;
+}
+int64_t BoxBlurDrag::get_drag_position()
+{
+ return plugin->get_source_position();
+}
+
+void BoxBlurDrag::update_gui()
+{
+ plugin->config.drag = get_value();
+ plugin->config.box_x = drag_x;
+ plugin->config.box_y = drag_y;
+ plugin->config.box_w = drag_w+0.5;
+ plugin->config.box_h = drag_h+0.5;
+ gui->box_x->update((float)plugin->config.box_x);
+ gui->box_y->update((float)plugin->config.box_y);
+ gui->box_w->update((int64_t)plugin->config.box_w);
+ gui->box_h->update((int64_t)plugin->config.box_h);
+ plugin->send_configure_change();
+}
+
+int BoxBlurDrag::handle_event()
+{
+ int ret = DragCheckBox::handle_event();
+ plugin->send_configure_change();
+ return ret;
+}
+
+void BoxBlurWindow::update_drag()
+{
+ drag->drag_x = plugin->config.box_x;
+ drag->drag_y = plugin->config.box_y;
+ drag->drag_w = plugin->config.box_w;
+ drag->drag_h = plugin->config.box_h;
+ plugin->send_configure_change();
+}
+
+BoxBlurReset::BoxBlurReset(BoxBlurWindow *gui, int x, int y)
+ : BC_Button(x, y, gui->plugin->get_theme()->get_image_set("reset_button"))
+{
+ this->gui = gui;
+}
+
+int BoxBlurReset::calculate_w(BoxBlurWindow *gui)
+{
+ VFrame **imgs = gui->plugin->get_theme()->get_image_set("reset_button");
+ return imgs[0]->get_w();
+}
+
+int BoxBlurReset::handle_event()
+{
+ BoxBlurEffect *plugin = gui->plugin;
+ plugin->config.reset();
+ gui->update_gui();
+ gui->update_drag();
+ return 1;
+}
+