4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5 * Copyright (C) 2003-2016 Cinelerra CV contributors
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "bcdisplayinfo.h"
31 #include "timefront.h"
34 #include "overlayframe.h"
40 REGISTER_PLUGIN(TimeFrontMain)
47 TimeFrontConfig::TimeFrontConfig()
53 track_usage = TimeFrontConfig::OTHERTRACK_INTENSITY;
54 shape = TimeFrontConfig::LINEAR;
55 rate = TimeFrontConfig::LINEAR;
62 int TimeFrontConfig::equivalent(TimeFrontConfig &that)
64 return (EQUIV(angle, that.angle) &&
65 EQUIV(in_radius, that.in_radius) &&
66 EQUIV(out_radius, that.out_radius) &&
67 frame_range == that.frame_range &&
68 track_usage == that.track_usage &&
69 shape == that.shape &&
71 EQUIV(center_x, that.center_x) &&
72 EQUIV(center_y, that.center_y) &&
73 invert == that.invert &&
74 show_grayscale == that.show_grayscale);
77 void TimeFrontConfig::copy_from(TimeFrontConfig &that)
80 in_radius = that.in_radius;
81 out_radius = that.out_radius;
82 frame_range = that.frame_range;
83 track_usage = that.track_usage;
86 center_x = that.center_x;
87 center_y = that.center_y;
89 show_grayscale = that.show_grayscale;
92 void TimeFrontConfig::interpolate(TimeFrontConfig &prev,
93 TimeFrontConfig &next,
98 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
99 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
102 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale);
103 this->in_radius = (int)(prev.in_radius * prev_scale + next.in_radius * next_scale);
104 this->out_radius = (int)(prev.out_radius * prev_scale + next.out_radius * next_scale);
105 frame_range = (int)(prev.frame_range * prev_scale + next.frame_range * next_scale);
106 track_usage = prev.track_usage;
109 center_x = prev.center_x * prev_scale + next.center_x * next_scale;
110 center_y = prev.center_y * prev_scale + next.center_y * next_scale;
111 invert = prev.invert;
112 show_grayscale = prev.show_grayscale;
122 TimeFrontWindow::TimeFrontWindow(TimeFrontMain *plugin)
123 : PluginClientWindow(plugin,
130 this->plugin = plugin;
141 out_radius_title = 0;
143 track_usage_title = 0;
148 TimeFrontWindow::~TimeFrontWindow()
152 void TimeFrontWindow::create_objects()
155 int ys10 = yS(10), ys35 = yS(35), ys40 = yS(40), ys140 = yS(140);
156 int x = xs10, y = ys10;
159 add_subwindow(title = new BC_Title(x, y, _("Type:")));
160 add_subwindow(shape = new TimeFrontShape(plugin,
162 x + title->get_w() + xs10,
164 shape->create_objects();
169 add_subwindow(title = new BC_Title(x, y, _("Time range:")));
170 add_subwindow(frame_range = new TimeFrontFrameRange(plugin, x + title->get_w() + xs10, y));
171 frame_range_x = x + frame_range->get_w() + xs10;
176 add_subwindow(invert = new TimeFrontInvert(plugin, x, y));
177 add_subwindow(show_grayscale = new TimeFrontShowGrayscale(plugin, x+ xS(100), y));
184 void TimeFrontWindow::update_shape()
186 int x = shape_x, y = shape_y;
188 if(plugin->config.shape == TimeFrontConfig::LINEAR)
190 delete center_x_title;
191 delete center_y_title;
194 delete track_usage_title;
200 track_usage_title = 0;
204 add_subwindow(angle_title = new BC_Title(x, y, _("Angle:")));
205 add_subwindow(angle = new TimeFrontAngle(plugin, x + angle_title->get_w() + xS(10), y));
208 y = shape_y + yS(40);
210 add_subwindow(rate_title = new BC_Title(x, y, _("Rate:")));
211 add_subwindow(rate = new TimeFrontRate(plugin,
212 x + rate_title->get_w() + xS(10),
214 rate->create_objects();
216 add_subwindow(in_radius_title = new BC_Title(x, y, _("Inner radius:")));
217 add_subwindow(in_radius = new TimeFrontInRadius(plugin, x + in_radius_title->get_w() + xS(10), y));
219 add_subwindow(out_radius_title = new BC_Title(x, y, _("Outer radius:")));
220 add_subwindow(out_radius = new TimeFrontOutRadius(plugin, x + out_radius_title->get_w() + xS(10), y));
225 if(plugin->config.shape == TimeFrontConfig::RADIAL)
229 delete track_usage_title;
233 track_usage_title = 0;
237 add_subwindow(center_x_title = new BC_Title(x, y, _("Center X:")));
238 add_subwindow(center_x = new TimeFrontCenterX(plugin,
239 x + center_x_title->get_w() + xS(10),
241 x += center_x_title->get_w() + xS(10) + center_x->get_w() + xS(10);
242 add_subwindow(center_y_title = new BC_Title(x, y, _("Center Y:")));
243 add_subwindow(center_y = new TimeFrontCenterY(plugin,
244 x + center_y_title->get_w() + xS(10),
251 y = shape_y + yS(40);
253 add_subwindow(rate_title = new BC_Title(x, y, _("Rate:")));
254 add_subwindow(rate = new TimeFrontRate(plugin,
255 x + rate_title->get_w() + xS(10),
257 rate->create_objects();
259 add_subwindow(in_radius_title = new BC_Title(x, y, _("Inner radius:")));
260 add_subwindow(in_radius = new TimeFrontInRadius(plugin, x + in_radius_title->get_w() + xS(10), y));
262 add_subwindow(out_radius_title = new BC_Title(x, y, _("Outer radius:")));
263 add_subwindow(out_radius = new TimeFrontOutRadius(plugin, x + out_radius_title->get_w() + xS(10), y));
267 if(plugin->config.shape == TimeFrontConfig::OTHERTRACK)
269 delete center_x_title;
270 delete center_y_title;
277 delete in_radius_title;
279 delete out_radius_title;
291 out_radius_title = 0;
295 add_subwindow(track_usage_title = new BC_Title(x, y, _("As timefront use:")));
296 add_subwindow(track_usage = new TimeFrontTrackUsage(plugin,
298 x + track_usage_title->get_w() + xS(10),
300 track_usage->create_objects();
304 if(plugin->config.shape == TimeFrontConfig::ALPHA)
306 delete center_x_title;
307 delete center_y_title;
314 delete in_radius_title;
316 delete out_radius_title;
318 delete track_usage_title;
330 out_radius_title = 0;
332 track_usage_title = 0;
351 TimeFrontShape::TimeFrontShape(TimeFrontMain *plugin,
352 TimeFrontWindow *gui,
355 : BC_PopupMenu(x, y, xS(230), to_text(plugin->config.shape), 1)
357 this->plugin = plugin;
360 void TimeFrontShape::create_objects()
362 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LINEAR)));
363 add_item(new BC_MenuItem(to_text(TimeFrontConfig::RADIAL)));
364 add_item(new BC_MenuItem(to_text(TimeFrontConfig::ALPHA)));
365 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK)));
367 char* TimeFrontShape::to_text(int shape)
371 case TimeFrontConfig::LINEAR:
373 case TimeFrontConfig::OTHERTRACK:
374 return _("Other track as timefront");
375 case TimeFrontConfig::ALPHA:
376 return _("Alpha as timefront");
381 int TimeFrontShape::from_text(char *text)
383 if(!strcmp(text, to_text(TimeFrontConfig::LINEAR)))
384 return TimeFrontConfig::LINEAR;
385 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK)))
386 return TimeFrontConfig::OTHERTRACK;
387 if(!strcmp(text, to_text(TimeFrontConfig::ALPHA)))
388 return TimeFrontConfig::ALPHA;
389 return TimeFrontConfig::RADIAL;
391 int TimeFrontShape::handle_event()
393 plugin->config.shape = from_text(get_text());
396 plugin->send_configure_change();
401 TimeFrontTrackUsage::TimeFrontTrackUsage(TimeFrontMain *plugin,
402 TimeFrontWindow *gui, int x, int y)
403 : BC_PopupMenu(x, y, xS(140), to_text(plugin->config.track_usage), 1)
405 this->plugin = plugin;
408 void TimeFrontTrackUsage::create_objects()
410 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK_INTENSITY)));
411 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK_ALPHA)));
413 char* TimeFrontTrackUsage::to_text(int track_usage)
417 case TimeFrontConfig::OTHERTRACK_INTENSITY:
418 return _("Intensity");
419 case TimeFrontConfig::OTHERTRACK_ALPHA:
420 return _("Alpha mask");
425 int TimeFrontTrackUsage::from_text(char *text)
427 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK_INTENSITY)))
428 return TimeFrontConfig::OTHERTRACK_INTENSITY;
429 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK_ALPHA)))
430 return TimeFrontConfig::OTHERTRACK_ALPHA;
432 return TimeFrontConfig::OTHERTRACK_INTENSITY;
434 int TimeFrontTrackUsage::handle_event()
436 plugin->config.track_usage = from_text(get_text());
439 plugin->send_configure_change();
446 TimeFrontCenterX::TimeFrontCenterX(TimeFrontMain *plugin, int x, int y)
447 : BC_FPot(x, y, plugin->config.center_x, 0, 100)
449 this->plugin = plugin;
451 int TimeFrontCenterX::handle_event()
453 plugin->config.center_x = get_value();
454 plugin->send_configure_change();
460 TimeFrontCenterY::TimeFrontCenterY(TimeFrontMain *plugin, int x, int y)
461 : BC_FPot(x, y, plugin->config.center_y, 0, 100)
463 this->plugin = plugin;
466 int TimeFrontCenterY::handle_event()
468 plugin->config.center_y = get_value();
469 plugin->send_configure_change();
476 TimeFrontAngle::TimeFrontAngle(TimeFrontMain *plugin, int x, int y)
479 plugin->config.angle,
483 this->plugin = plugin;
486 int TimeFrontAngle::handle_event()
488 plugin->config.angle = get_value();
489 plugin->send_configure_change();
494 TimeFrontRate::TimeFrontRate(TimeFrontMain *plugin, int x, int y)
495 : BC_PopupMenu(x, y, xS(155), to_text(plugin->config.rate), 1)
497 this->plugin = plugin;
499 void TimeFrontRate::create_objects()
501 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LINEAR)));
502 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LOG)));
503 add_item(new BC_MenuItem(to_text(TimeFrontConfig::SQUARE)));
505 char* TimeFrontRate::to_text(int shape)
509 case TimeFrontConfig::LINEAR:
511 case TimeFrontConfig::LOG:
517 int TimeFrontRate::from_text(char *text)
519 if(!strcmp(text, to_text(TimeFrontConfig::LINEAR)))
520 return TimeFrontConfig::LINEAR;
521 if(!strcmp(text, to_text(TimeFrontConfig::LOG)))
522 return TimeFrontConfig::LOG;
523 return TimeFrontConfig::SQUARE;
525 int TimeFrontRate::handle_event()
527 plugin->config.rate = from_text(get_text());
528 plugin->send_configure_change();
534 TimeFrontInRadius::TimeFrontInRadius(TimeFrontMain *plugin, int x, int y)
542 (float)plugin->config.in_radius)
544 this->plugin = plugin;
547 int TimeFrontInRadius::handle_event()
549 plugin->config.in_radius = get_value();
550 plugin->send_configure_change();
555 TimeFrontOutRadius::TimeFrontOutRadius(TimeFrontMain *plugin, int x, int y)
563 (float)plugin->config.out_radius)
565 this->plugin = plugin;
568 int TimeFrontOutRadius::handle_event()
570 plugin->config.out_radius = get_value();
571 plugin->send_configure_change();
575 TimeFrontFrameRange::TimeFrontFrameRange(TimeFrontMain *plugin, int x, int y)
583 (int)plugin->config.frame_range)
585 this->plugin = plugin;
588 int TimeFrontFrameRange::handle_event()
590 plugin->config.frame_range = get_value();
591 plugin->send_configure_change();
596 TimeFrontInvert::TimeFrontInvert(TimeFrontMain *client, int x, int y)
599 client->config.invert,
602 this->plugin = client;
605 int TimeFrontInvert::handle_event()
607 plugin->config.invert = get_value();
608 plugin->send_configure_change();
612 TimeFrontShowGrayscale::TimeFrontShowGrayscale(TimeFrontMain *client, int x, int y)
615 client->config.show_grayscale,
616 _("Show grayscale (for tuning"))
618 this->plugin = client;
621 int TimeFrontShowGrayscale::handle_event()
623 plugin->config.show_grayscale = get_value();
624 plugin->send_configure_change();
630 TimeFrontMain::TimeFrontMain(PluginServer *server)
631 : PluginVClient(server)
634 need_reconfigure = 1;
640 TimeFrontMain::~TimeFrontMain()
644 if(gradient) delete gradient;
645 if(engine) delete engine;
646 if(overlayer) delete overlayer;
649 const char* TimeFrontMain::plugin_title() { return N_("TimeFront"); }
650 int TimeFrontMain::is_realtime() { return 1; }
651 int TimeFrontMain::is_multichannel() { return 1; }
655 NEW_WINDOW_MACRO(TimeFrontMain, TimeFrontWindow)
657 LOAD_CONFIGURATION_MACRO(TimeFrontMain, TimeFrontConfig)
659 int TimeFrontMain::is_synthesis()
664 #define GRADIENTFROMAVG(type, inttype, components, maxval) \
665 for(int i = 0; i < tfframe->get_h(); i++) \
667 type *in_row = (type *)tfframe->get_rows()[i]; \
668 unsigned char *grad_row = gradient->get_rows()[i]; \
669 for(int j = 0; j < tfframe->get_w(); j++) \
671 inttype tmp = (inttype) in_row[j * components] + \
672 in_row[j * components + 1] + \
673 in_row[j * components + 2]; \
674 if (components == 3) \
675 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * tmp / maxval / 3, 0.0F, config.frame_range)); \
676 else if(components == 4) \
677 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * tmp * in_row[j * components + 3] / maxval / maxval / 3, 0.0F, config.frame_range)); \
681 #define GRADIENTFROMCHANNEL(type, components, max, channel) \
682 for(int i = 0; i < tfframe->get_h(); i++) \
684 type *in_row = (type *)tfframe->get_rows()[i]; \
685 unsigned char *grad_row = gradient->get_rows()[i]; \
686 for(int j = 0; j < tfframe->get_w(); j++) \
688 if (components == 3) \
689 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * in_row[j * components + channel] / max, 0.0F, config.frame_range)); \
690 else if(components == 4) \
691 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * in_row[j * components + channel] * in_row[j * components + 3]/ max /max, 0.0F, config.frame_range)); \
695 #define SETALPHA(type, max) \
696 for(int i = 0; i < outframes[0]->get_h(); i++) \
698 type *out_row = (type *)outframes[0]->get_rows()[i]; \
699 for(int j = 0; j < outframes[0]->get_w(); j++) \
701 out_row[j * 4 + 3] = max; \
705 #define GRADIENTTOPICTURE(type, inttype, components, max, invertion) \
706 for(int i = 0; i < height; i++) \
708 type *out_row = (type *)outframes[0]->get_rows()[i]; \
709 unsigned char *grad_row = gradient->get_rows()[i]; \
710 for (int j = 0; j < width; j++) \
712 out_row[0] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
713 out_row[1] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
714 out_row[2] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
715 if (components == 4) \
717 out_row += components; \
722 #define GRADIENTTOYUVPICTURE(type, inttype, components, max, invertion) \
723 for(int i = 0; i < height; i++) \
725 type *out_row = (type *)outframes[0]->get_rows()[i]; \
726 unsigned char *grad_row = gradient->get_rows()[i]; \
727 for (int j = 0; j < width; j++) \
729 out_row[0] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
730 out_row[1] = max/2; \
731 out_row[2] = max/2; \
732 if (components == 4) \
734 out_row += components; \
739 #define COMPOSITEIMAGE(type, components, invertion) \
740 for (int i = 0; i < height; i++) \
742 type *out_row = (type *)outframes[0]->get_rows()[i]; \
743 unsigned char *gradient_row = gradient->get_rows()[i]; \
744 for (int j = 0; j < width; j++) \
746 unsigned int choice = invertion gradient_row[j]; \
748 type *in_row = (type *)framelist[choice]->get_rows()[i]; \
749 out_row[0] = in_row[j * components + 0]; \
750 out_row[1] = in_row[j * components + 1]; \
751 out_row[2] = in_row[j * components + 2]; \
752 if (components == 4) \
753 out_row[3] = in_row[j * components + 3]; \
755 out_row += components; \
761 int TimeFrontMain::process_buffer(VFrame **frame,
762 int64_t start_position,
764 //int TimeFrontMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
766 VFrame **outframes = frame;
767 VFrame *(framelist[1024]);
768 framelist[0] = new VFrame (outframes[0]->get_w(), outframes[0]->get_h(),
769 outframes[0]->get_color_model(), 0);
770 read_frame(framelist[0],
775 this->input = framelist[0];
776 this->output = outframes[0];
777 need_reconfigure |= load_configuration();
778 if (config.shape == TimeFrontConfig::OTHERTRACK)
780 // this->output = frame[1];
781 if (get_total_buffers() != 2)
783 // FIXME, maybe this should go to some other notification area?
784 printf(_("ERROR: TimeFront plugin - If you are using another track for timefront, you have to have it under shared effects\n"));
787 if (outframes[0]->get_w() != outframes[1]->get_w() || outframes[0]->get_h() != outframes[1]->get_h())
789 printf(_("Sizes of master track and timefront track do not match\n"));
794 // Generate new gradient
797 need_reconfigure = 0;
800 gradient = new VFrame( outframes[0]->get_w(), outframes[0]->get_h(), BC_A8, 0);
802 if (config.shape != TimeFrontConfig::OTHERTRACK &&
803 config.shape != TimeFrontConfig::ALPHA)
805 if(!engine) engine = new TimeFrontServer(this,
806 get_project_smp() + 1,
807 get_project_smp() + 1);
808 engine->process_packages();
812 if (config.shape == TimeFrontConfig::ALPHA)
815 gradient = new VFrame(outframes[0]->get_w(), outframes[0]->get_h(), BC_A8, 0);
816 VFrame *tfframe = framelist[0];
817 switch (tfframe->get_color_model())
821 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3);
826 GRADIENTFROMCHANNEL(float, 4, 1.0f, 3);
831 printf(_("TimeFront plugin error: ALPHA used, but project color model does not have alpha\n"));
838 if (config.shape == TimeFrontConfig::OTHERTRACK)
841 gradient = new VFrame(outframes[0]->get_w(), outframes[0]->get_h(), BC_A8, 0);
842 VFrame *tfframe = outframes[1];
848 if (config.track_usage == TimeFrontConfig::OTHERTRACK_INTENSITY)
850 switch (tfframe->get_color_model())
853 GRADIENTFROMAVG(unsigned char, unsigned short, 4, 255); // Has to be 2 ranges bigger, sice we need precision for alpha
856 GRADIENTFROMAVG(unsigned char, unsigned short, 3, 255);
859 GRADIENTFROMAVG(float, float, 3, 1.0f);
862 GRADIENTFROMAVG(float, float, 4, 1.0f);
864 case BC_YUV888: // We cheat and take Y component as intensity
865 GRADIENTFROMCHANNEL(unsigned char, 3, 255, 0);
868 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 0);
874 if (config.track_usage == TimeFrontConfig::OTHERTRACK_ALPHA)
876 switch (tfframe->get_color_model())
880 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3);
885 GRADIENTFROMCHANNEL(float, 4, 1.0f, 3);
890 printf(_("TimeFront plugin error: ALPHA track used, but project color model does not have alpha\n"));
897 printf(_("TimeFront plugin error: unsupported track_usage parameter\n"));
902 if (!config.show_grayscale)
904 for (int i = 1; i <= config.frame_range; i++)
906 framelist[i] = new VFrame (outframes[0]->get_w(), outframes[0]->get_h(),
907 outframes[0]->get_color_model(), 0);
909 read_frame(framelist[i],
918 int width = outframes[0]->get_w();
919 int height = outframes[0]->get_h();
920 if (config.show_grayscale)
924 switch (outframes[0]->get_color_model())
927 GRADIENTTOPICTURE(unsigned char, unsigned short, 3, 255, );
930 GRADIENTTOPICTURE(unsigned char, unsigned short, 4, 255, );
933 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 3, 255, );
936 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 4, 255, );
939 GRADIENTTOPICTURE(float, float, 3, 1.0f, );
942 GRADIENTTOPICTURE(float, float, 4, 1.0f, );
949 switch (outframes[0]->get_color_model())
952 GRADIENTTOPICTURE(unsigned char, unsigned short, 3, 255, config.frame_range -);
955 GRADIENTTOPICTURE(unsigned char, unsigned short, 4, 255, config.frame_range -);
958 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 3, 255, config.frame_range -);
961 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 4, 255, config.frame_range -);
964 GRADIENTTOPICTURE(float, float, 3, 1.0f, config.frame_range -);
967 GRADIENTTOPICTURE(float, float, 4, 1.0f, config.frame_range -);
976 switch (outframes[0]->get_color_model())
979 COMPOSITEIMAGE(unsigned char, 3, );
982 COMPOSITEIMAGE(unsigned char, 4, );
985 COMPOSITEIMAGE(unsigned char, 3, );
988 COMPOSITEIMAGE(unsigned char, 4, );
991 COMPOSITEIMAGE(float, 3, );
994 COMPOSITEIMAGE(float, 4, );
1002 switch (outframes[0]->get_color_model())
1005 COMPOSITEIMAGE(unsigned char, 3, config.frame_range -);
1008 COMPOSITEIMAGE(unsigned char, 4, config.frame_range -);
1011 COMPOSITEIMAGE(unsigned char, 3, config.frame_range -);
1014 COMPOSITEIMAGE(unsigned char, 4, config.frame_range -);
1017 COMPOSITEIMAGE(float, 3, config.frame_range -);
1020 COMPOSITEIMAGE(float, 4, config.frame_range -);
1027 if (config.shape == TimeFrontConfig::ALPHA)
1030 switch (outframes[0]->get_color_model())
1034 SETALPHA(unsigned char, 255);
1037 SETALPHA(float, 1.0f);
1045 delete framelist[0];
1046 if (!config.show_grayscale)
1048 for (int i = 1; i <= config.frame_range; i++)
1049 delete framelist[i];
1055 void TimeFrontMain::update_gui()
1059 if(load_configuration())
1061 thread->window->lock_window("TimeFrontMain::update_gui");
1062 ((TimeFrontWindow*)thread->window)->frame_range->update(config.frame_range);
1063 ((TimeFrontWindow*)thread->window)->shape->set_text(TimeFrontShape::to_text(config.shape));
1064 ((TimeFrontWindow*)thread->window)->show_grayscale->update(config.show_grayscale);
1065 ((TimeFrontWindow*)thread->window)->invert->update(config.invert);
1066 ((TimeFrontWindow*)thread->window)->shape->set_text(TimeFrontShape::to_text(config.shape));
1067 if (((TimeFrontWindow*)thread->window)->rate)
1068 ((TimeFrontWindow*)thread->window)->rate->set_text(TimeFrontRate::to_text(config.rate));
1069 if (((TimeFrontWindow*)thread->window)->in_radius)
1070 ((TimeFrontWindow*)thread->window)->in_radius->update(config.in_radius);
1071 if (((TimeFrontWindow*)thread->window)->out_radius)
1072 ((TimeFrontWindow*)thread->window)->out_radius->update(config.out_radius);
1073 if (((TimeFrontWindow*)thread->window)->track_usage)
1074 ((TimeFrontWindow*)thread->window)->track_usage->set_text(TimeFrontTrackUsage::to_text(config.track_usage));
1075 if(((TimeFrontWindow*)thread->window)->angle)
1076 ((TimeFrontWindow*)thread->window)->angle->update(config.angle);
1077 if(((TimeFrontWindow*)thread->window)->center_x)
1078 ((TimeFrontWindow*)thread->window)->center_x->update(config.center_x);
1079 if(((TimeFrontWindow*)thread->window)->center_y)
1080 ((TimeFrontWindow*)thread->window)->center_y->update(config.center_y);
1082 ((TimeFrontWindow*)thread->window)->update_shape();
1083 thread->window->unlock_window();
1091 void TimeFrontMain::save_data(KeyFrame *keyframe)
1095 // cause data to be stored directly in text
1096 output.set_shared_output(keyframe->xbuf);
1097 output.tag.set_title("TIMEFRONT");
1099 output.tag.set_property("ANGLE", config.angle);
1100 output.tag.set_property("IN_RADIUS", config.in_radius);
1101 output.tag.set_property("OUT_RADIUS", config.out_radius);
1102 output.tag.set_property("FRAME_RANGE", config.frame_range);
1103 output.tag.set_property("SHAPE", config.shape);
1104 output.tag.set_property("TRACK_USAGE", config.track_usage);
1105 output.tag.set_property("RATE", config.rate);
1106 output.tag.set_property("CENTER_X", config.center_x);
1107 output.tag.set_property("CENTER_Y", config.center_y);
1108 output.tag.set_property("INVERT", config.invert);
1109 output.tag.set_property("SHOW_GRAYSCALE", config.show_grayscale);
1110 output.append_tag();
1111 output.tag.set_title("/TIMEFRONT");
1112 output.append_tag();
1113 output.append_newline();
1114 output.terminate_string();
1117 void TimeFrontMain::read_data(KeyFrame *keyframe)
1121 input.set_shared_input(keyframe->xbuf);
1127 result = input.read_tag();
1131 if(input.tag.title_is("TIMEFRONT"))
1133 config.angle = input.tag.get_property("ANGLE", config.angle);
1134 config.rate = input.tag.get_property("RATE", config.rate);
1135 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
1136 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
1137 config.frame_range = input.tag.get_property("FRAME_RANGE", config.frame_range);
1138 config.shape = input.tag.get_property("SHAPE", config.shape);
1139 config.track_usage = input.tag.get_property("TRACK_USAGE", config.track_usage);
1140 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
1141 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
1142 config.invert = input.tag.get_property("INVERT", config.invert);
1143 config.show_grayscale = input.tag.get_property("SHOW_GRAYSCALE", config.show_grayscale);
1154 TimeFrontPackage::TimeFrontPackage()
1162 TimeFrontUnit::TimeFrontUnit(TimeFrontServer *server, TimeFrontMain *plugin)
1163 : LoadClient(server)
1165 this->plugin = plugin;
1166 this->server = server;
1172 #define CREATE_GRADIENT \
1174 /* Synthesize linear gradient for lookups */ \
1176 a_table = (unsigned char *)malloc(sizeof(unsigned char) * gradient_size); \
1178 for(int i = 0; i < gradient_size; i++) \
1180 float opacity = 0.0; \
1181 switch(plugin->config.rate) \
1183 case TimeFrontConfig::LINEAR: \
1187 if(i >= out_radius) \
1190 opacity = (float)(i - in_radius) / (out_radius - in_radius); \
1192 case TimeFrontConfig::LOG: \
1193 opacity = 1 - exp(LOG_RANGE * -(float)(i - in_radius) / (out_radius - in_radius)); \
1195 case TimeFrontConfig::SQUARE: \
1196 opacity = SQR((float)(i - in_radius) / (out_radius - in_radius)); \
1200 CLAMP(opacity, 0, 1); \
1201 float transparency = 1.0 - opacity; \
1202 a_table[i] = (unsigned char)(out4 * opacity + in4 * transparency); \
1205 for(int i = pkg->y1; i < pkg->y2; i++) \
1207 unsigned char *out_row = plugin->gradient->get_rows()[i]; \
1209 switch(plugin->config.shape) \
1211 case TimeFrontConfig::LINEAR: \
1212 for(int j = 0; j < w; j++) \
1214 int x = j - half_w; \
1215 int y = -(i - half_h); \
1217 /* Rotate by effect angle */ \
1218 int input_y = (int)(gradient_size / 2 - \
1219 (x * sin_angle + y * cos_angle) + \
1222 /* Get gradient value from these coords */ \
1226 out_row[0] = out4; \
1229 if(input_y >= gradient_size) \
1235 out_row[0] = a_table[input_y]; \
1242 case TimeFrontConfig::RADIAL: \
1243 for(int j = 0; j < w; j++) \
1245 double x = j - center_x; \
1246 double y = i - center_y; \
1247 double magnitude = hypot(x, y); \
1248 int input_y = (int)magnitude; \
1249 out_row[0] = a_table[input_y]; \
1257 void TimeFrontUnit::process_package(LoadPackage *package)
1259 TimeFrontPackage *pkg = (TimeFrontPackage*)package;
1260 int h = plugin->input->get_h();
1261 int w = plugin->input->get_w();
1264 int gradient_size = (int)(ceil(hypot(w, h)));
1265 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
1266 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
1267 double sin_angle = sin(plugin->config.angle * (M_PI / 180));
1268 double cos_angle = cos(plugin->config.angle * (M_PI / 180));
1269 double center_x = plugin->config.center_x * w / 100;
1270 double center_y = plugin->config.center_y * h / 100;
1271 unsigned char *a_table = 0;
1273 if(in_radius > out_radius)
1275 in_radius ^= out_radius;
1276 out_radius ^= in_radius;
1277 in_radius ^= out_radius;
1281 int in4 = plugin->config.frame_range;
1285 if(a_table) free(a_table);
1293 TimeFrontServer::TimeFrontServer(TimeFrontMain *plugin,
1296 : LoadServer(total_clients, total_packages)
1298 this->plugin = plugin;
1301 void TimeFrontServer::init_packages()
1303 for(int i = 0; i < get_total_packages(); i++)
1305 TimeFrontPackage *package = (TimeFrontPackage*)get_package(i);
1306 package->y1 = plugin->input->get_h() *
1308 get_total_packages();
1309 package->y2 = plugin->input->get_h() *
1311 get_total_packages();
1315 LoadClient* TimeFrontServer::new_client()
1317 return new TimeFrontUnit(this, plugin);
1320 LoadPackage* TimeFrontServer::new_package()
1322 return new TimeFrontPackage;