1 #include "../motion/affine.h"
2 #include "bcdisplayinfo.h"
9 #include "pluginvclient.h"
10 #include "rotateframe.h"
18 #define SQR(x) ((x) * (x))
31 int equivalent(RotateConfig &that);
32 void copy_from(RotateConfig &that);
33 void interpolate(RotateConfig &prev,
46 class RotateToggle : public BC_Radial
49 RotateToggle(RotateWindow *window,
63 class RotateDrawPivot : public BC_CheckBox
66 RotateDrawPivot(RotateWindow *window,
76 class RotateInterpolate : public BC_CheckBox
79 RotateInterpolate(RotateEffect *plugin, int x, int y);
84 class RotateFine : public BC_FPot
87 RotateFine(RotateWindow *window,
97 class RotateX : public BC_FPot
100 RotateX(RotateWindow *window,
101 RotateEffect *plugin,
105 RotateEffect *plugin;
106 RotateWindow *window;
109 class RotateY : public BC_FPot
112 RotateY(RotateWindow *window,
113 RotateEffect *plugin,
117 RotateEffect *plugin;
118 RotateWindow *window;
122 class RotateText : public BC_TextBox
125 RotateText(RotateWindow *window,
126 RotateEffect *plugin,
131 RotateEffect *plugin;
132 RotateWindow *window;
135 class RotateWindow : public BC_Window
138 RotateWindow(RotateEffect *plugin, int x, int y);
140 int create_objects();
145 int update_toggles();
147 RotateEffect *plugin;
148 RotateToggle *toggle0;
149 RotateToggle *toggle90;
150 RotateToggle *toggle180;
151 RotateToggle *toggle270;
152 RotateDrawPivot *draw_pivot;
157 // RotateInterpolate *bilinear;
161 PLUGIN_THREAD_HEADER(RotateEffect, RotateThread, RotateWindow)
164 class RotateEffect : public PluginVClient
167 RotateEffect(PluginServer *server);
170 int process_buffer(VFrame *frame,
171 int64_t start_position,
174 char* plugin_title();
180 int load_configuration();
183 void save_data(KeyFrame *keyframe);
184 void read_data(KeyFrame *keyframe);
188 AffineEngine *engine;
189 RotateThread *thread;
191 int need_reconfigure;
200 REGISTER_PLUGIN(RotateEffect)
219 RotateConfig::RotateConfig()
227 int RotateConfig::equivalent(RotateConfig &that)
229 return EQUIV(angle, that.angle) &&
230 EQUIV(pivot_x, that.pivot_y) &&
231 EQUIV(pivot_y, that.pivot_y) &&
232 draw_pivot == that.draw_pivot;
235 void RotateConfig::copy_from(RotateConfig &that)
238 pivot_x = that.pivot_x;
239 pivot_y = that.pivot_y;
240 draw_pivot = that.draw_pivot;
241 // bilinear = that.bilinear;
244 void RotateConfig::interpolate(RotateConfig &prev,
250 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
251 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
253 this->angle = prev.angle * prev_scale + next.angle * next_scale;
254 this->pivot_x = prev.pivot_x * prev_scale + next.pivot_x * next_scale;
255 this->pivot_y = prev.pivot_y * prev_scale + next.pivot_y * next_scale;
256 draw_pivot = prev.draw_pivot;
257 // bilinear = prev.bilinear;
270 RotateToggle::RotateToggle(RotateWindow *window,
271 RotateEffect *plugin,
277 : BC_Radial(x, y, init_value, string)
280 this->plugin = plugin;
281 this->window = window;
284 int RotateToggle::handle_event()
286 plugin->config.angle = (float)value;
288 plugin->send_configure_change();
298 RotateDrawPivot::RotateDrawPivot(RotateWindow *window,
299 RotateEffect *plugin,
302 : BC_CheckBox(x, y, plugin->config.draw_pivot, _("Draw pivot"))
304 this->plugin = plugin;
305 this->window = window;
308 int RotateDrawPivot::handle_event()
310 plugin->config.draw_pivot = get_value();
311 plugin->send_configure_change();
319 // RotateInterpolate::RotateInterpolate(RotateEffect *plugin, int x, int y)
320 // : BC_CheckBox(x, y, plugin->config.bilinear, _("Interpolate"))
322 // this->plugin = plugin;
324 // int RotateInterpolate::handle_event()
326 // plugin->config.bilinear = get_value();
327 // plugin->send_configure_change();
334 RotateFine::RotateFine(RotateWindow *window, RotateEffect *plugin, int x, int y)
337 (float)plugin->config.angle,
341 this->window = window;
342 this->plugin = plugin;
347 int RotateFine::handle_event()
349 plugin->config.angle = get_value();
350 window->update_toggles();
351 window->update_text();
352 plugin->send_configure_change();
358 RotateText::RotateText(RotateWindow *window,
359 RotateEffect *plugin,
366 (float)plugin->config.angle)
368 this->window = window;
369 this->plugin = plugin;
373 int RotateText::handle_event()
375 plugin->config.angle = atof(get_text());
376 window->update_toggles();
377 window->update_fine();
378 plugin->send_configure_change();
384 RotateX::RotateX(RotateWindow *window, RotateEffect *plugin, int x, int y)
387 (float)plugin->config.pivot_x,
391 this->window = window;
392 this->plugin = plugin;
397 int RotateX::handle_event()
399 plugin->config.pivot_x = get_value();
400 plugin->send_configure_change();
404 RotateY::RotateY(RotateWindow *window, RotateEffect *plugin, int x, int y)
407 (float)plugin->config.pivot_y,
411 this->window = window;
412 this->plugin = plugin;
417 int RotateY::handle_event()
419 plugin->config.pivot_y = get_value();
420 plugin->send_configure_change();
431 RotateWindow::RotateWindow(RotateEffect *plugin, int x, int y)
432 : BC_Window(plugin->gui_string,
443 this->plugin = plugin;
448 int RotateWindow::create_objects()
455 add_tool(new BC_Title(x, y, _("Rotate")));
458 add_tool(toggle0 = new RotateToggle(this,
460 plugin->config.angle == 0,
467 add_tool(toggle90 = new RotateToggle(this,
469 plugin->config.angle == 90,
476 add_tool(toggle180 = new RotateToggle(this,
478 plugin->config.angle == 180,
485 add_tool(toggle270 = new RotateToggle(this,
487 plugin->config.angle == 270,
492 // add_subwindow(bilinear = new RotateInterpolate(plugin, 10, y + 60));
495 add_tool(fine = new RotateFine(this, plugin, x, y));
496 y += fine->get_h() + 10;
497 add_tool(text = new RotateText(this, plugin, x, y));
499 add_tool(new BC_Title(x, y, _("Degrees")));
505 y += text->get_h() + 10;
506 add_subwindow(title = new BC_Title(x, y, _("Pivot (x,y):")));
507 y += title->get_h() + 10;
508 add_subwindow(this->x = new RotateX(this, plugin, x, y));
509 x += this->x->get_w() + 10;
510 add_subwindow(this->y = new RotateY(this, plugin, x, y));
513 y += this->y->get_h() + 10;
514 add_subwindow(draw_pivot = new RotateDrawPivot(this, plugin, x, y));
524 WINDOW_CLOSE_EVENT(RotateWindow)
526 int RotateWindow::update()
531 // bilinear->update(plugin->config.bilinear);
535 int RotateWindow::update_fine()
537 fine->update(plugin->config.angle);
538 x->update(plugin->config.pivot_x);
539 y->update(plugin->config.pivot_y);
543 int RotateWindow::update_text()
545 text->update(plugin->config.angle);
549 int RotateWindow::update_toggles()
551 toggle0->update(EQUIV(plugin->config.angle, 0));
552 toggle90->update(EQUIV(plugin->config.angle, 90));
553 toggle180->update(EQUIV(plugin->config.angle, 180));
554 toggle270->update(EQUIV(plugin->config.angle, 270));
555 draw_pivot->update(plugin->config.draw_pivot);
573 PLUGIN_THREAD_OBJECT(RotateEffect, RotateThread, RotateWindow)
592 RotateEffect::RotateEffect(PluginServer *server)
593 : PluginVClient(server)
596 need_reconfigure = 1;
597 PLUGIN_CONSTRUCTOR_MACRO
600 RotateEffect::~RotateEffect()
602 PLUGIN_DESTRUCTOR_MACRO
603 if(engine) delete engine;
608 char* RotateEffect::plugin_title() { return N_("Rotate"); }
609 int RotateEffect::is_realtime() { return 1; }
611 NEW_PICON_MACRO(RotateEffect)
613 SET_STRING_MACRO(RotateEffect)
615 SHOW_GUI_MACRO(RotateEffect, RotateThread)
617 RAISE_WINDOW_MACRO(RotateEffect)
620 void RotateEffect::update_gui()
624 load_configuration();
625 thread->window->lock_window();
626 thread->window->update();
627 thread->window->unlock_window();
631 LOAD_CONFIGURATION_MACRO(RotateEffect, RotateConfig)
635 int RotateEffect::load_defaults()
637 char directory[1024], string[1024];
638 // set the default directory
639 sprintf(directory, "%srotate.rc", BCASTDIR);
642 defaults = new BC_Hash(directory);
645 config.angle = defaults->get("ANGLE", (float)config.angle);
646 config.pivot_x = defaults->get("PIVOT_X", (float)config.pivot_x);
647 config.pivot_y = defaults->get("PIVOT_Y", (float)config.pivot_y);
648 config.draw_pivot = defaults->get("DRAW_PIVOT", (int)config.draw_pivot);
649 // config.bilinear = defaults->get("INTERPOLATE", (int)config.bilinear);
653 int RotateEffect::save_defaults()
655 defaults->update("ANGLE", (float)config.angle);
656 defaults->update("PIVOT_X", (float)config.pivot_x);
657 defaults->update("PIVOT_Y", (float)config.pivot_y);
658 defaults->update("DRAW_PIVOT", (int)config.draw_pivot);
659 // defaults->update("INTERPOLATE", (int)config.bilinear);
664 void RotateEffect::save_data(KeyFrame *keyframe)
668 // cause data to be stored directly in text
669 output.set_shared_string(keyframe->data, MESSAGESIZE);
670 output.tag.set_title("ROTATE");
671 output.tag.set_property("ANGLE", (float)config.angle);
672 output.tag.set_property("PIVOT_X", (float)config.pivot_x);
673 output.tag.set_property("PIVOT_Y", (float)config.pivot_y);
674 output.tag.set_property("DRAW_PIVOT", (int)config.draw_pivot);
675 // output.tag.set_property("INTERPOLATE", (int)config.bilinear);
677 output.terminate_string();
678 // data is now in *text
681 void RotateEffect::read_data(KeyFrame *keyframe)
685 input.set_shared_string(keyframe->data, strlen(keyframe->data));
691 result = input.read_tag();
695 if(input.tag.title_is("ROTATE"))
697 config.angle = input.tag.get_property("ANGLE", (float)config.angle);
698 config.pivot_x = input.tag.get_property("PIVOT_X", (float)config.pivot_x);
699 config.pivot_y = input.tag.get_property("PIVOT_Y", (float)config.pivot_y);
700 config.draw_pivot = input.tag.get_property("DRAW_PIVOT", (int)config.draw_pivot);
701 // config.bilinear = input.tag.get_property("INTERPOLATE", (int)config.bilinear);
707 int RotateEffect::process_buffer(VFrame *frame,
708 int64_t start_position,
711 load_configuration();
712 int w = frame->get_w();
713 int h = frame->get_h();
714 //printf("RotateEffect::process_realtime 1 %d %f\n", config.bilinear, config.angle);
717 if(config.angle == 0)
727 if(!engine) engine = new AffineEngine(PluginClient::smp + 1,
728 PluginClient::smp + 1);
729 engine->set_pivot((int)(config.pivot_x * get_input()->get_w() / 100),
730 (int)(config.pivot_y * get_input()->get_h() / 100));
743 // engine->set_viewport(50,
747 // engine->set_pivot(100, 100);
750 VFrame *temp_frame = PluginVClient::new_temp(get_input()->get_w(),
751 get_input()->get_h(),
752 get_input()->get_color_model());
753 read_frame(temp_frame,
758 frame->clear_frame();
759 engine->rotate(frame,
767 #define DRAW_CENTER(components, type, max) \
769 type **rows = (type**)get_output()->get_rows(); \
770 if(center_x >= 0 && center_x < w || \
771 center_y >= 0 && center_y < h) \
773 type *hrow = rows[center_y] + components * (center_x - CENTER_W / 2); \
774 for(int i = center_x - CENTER_W / 2; i <= center_x + CENTER_W / 2; i++) \
776 if(i >= 0 && i < w) \
778 hrow[0] = max - hrow[0]; \
779 hrow[1] = max - hrow[1]; \
780 hrow[2] = max - hrow[2]; \
781 hrow += components; \
785 for(int i = center_y - CENTER_W / 2; i <= center_y + CENTER_W / 2; i++) \
787 if(i >= 0 && i < h) \
789 type *vrow = rows[i] + center_x * components; \
790 vrow[0] = max - vrow[0]; \
791 vrow[1] = max - vrow[1]; \
792 vrow[2] = max - vrow[2]; \
798 if(config.draw_pivot)
800 int center_x = (int)(config.pivot_x * w / 100); \
801 int center_y = (int)(config.pivot_y * h / 100); \
802 switch(get_output()->get_color_model())
805 DRAW_CENTER(3, float, 1.0)
808 DRAW_CENTER(4, float, 1.0)
811 DRAW_CENTER(3, unsigned char, 0xff)
814 DRAW_CENTER(4, unsigned char, 0xff)
817 DRAW_CENTER(3, unsigned char, 0xff)
820 DRAW_CENTER(4, unsigned char, 0xff)
825 // Conserve memory by deleting large frames
826 if(get_input()->get_w() > PLUGIN_MAX_W &&
827 get_input()->get_h() > PLUGIN_MAX_H)
837 int RotateEffect::handle_opengl()
840 engine->set_opengl(1);
841 engine->rotate(get_output(),
844 engine->set_opengl(0);
846 if(config.draw_pivot)
848 int w = get_output()->get_w();
849 int h = get_output()->get_h();
850 int center_x = (int)(config.pivot_x * w / 100); \
851 int center_y = (int)(config.pivot_y * h / 100); \
853 glDisable(GL_TEXTURE_2D);
854 glColor4f(1.0, 1.0, 1.0, 1.0);
856 glEnable(GL_COLOR_LOGIC_OP);
858 glVertex3f(center_x, -h + center_y - CENTER_H / 2, 0.0);
859 glVertex3f(center_x, -h + center_y + CENTER_H / 2, 0.0);
862 glVertex3f(center_x - CENTER_W / 2, -h + center_y, 0.0);
863 glVertex3f(center_x + CENTER_W / 2, -h + center_y, 0.0);
865 glDisable(GL_COLOR_LOGIC_OP);