5 #include "bcdisplayinfo.h"
12 #include "overlayframe.h"
13 #include "picon_png.h"
19 REGISTER_PLUGIN(GradientMain)
26 GradientConfig::GradientConfig()
39 shape = GradientConfig::LINEAR;
40 rate = GradientConfig::LINEAR;
45 int GradientConfig::equivalent(GradientConfig &that)
47 return (EQUIV(angle, that.angle) &&
48 EQUIV(in_radius, that.in_radius) &&
49 EQUIV(out_radius, that.out_radius) &&
54 out_r == that.out_r &&
55 out_g == that.out_g &&
56 out_b == that.out_b &&
57 out_a == that.out_a &&
58 shape == that.shape &&
60 EQUIV(center_x, that.center_x) &&
61 EQUIV(center_y, that.center_y));
64 void GradientConfig::copy_from(GradientConfig &that)
67 in_radius = that.in_radius;
68 out_radius = that.out_radius;
79 center_x = that.center_x;
80 center_y = that.center_y;
83 void GradientConfig::interpolate(GradientConfig &prev,
89 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
90 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
93 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale);
94 this->in_radius = (int)(prev.in_radius * prev_scale + next.in_radius * next_scale);
95 this->out_radius = (int)(prev.out_radius * prev_scale + next.out_radius * next_scale);
96 in_r = (int)(prev.in_r * prev_scale + next.in_r * next_scale);
97 in_g = (int)(prev.in_g * prev_scale + next.in_g * next_scale);
98 in_b = (int)(prev.in_b * prev_scale + next.in_b * next_scale);
99 in_a = (int)(prev.in_a * prev_scale + next.in_a * next_scale);
100 out_r = (int)(prev.out_r * prev_scale + next.out_r * next_scale);
101 out_g = (int)(prev.out_g * prev_scale + next.out_g * next_scale);
102 out_b = (int)(prev.out_b * prev_scale + next.out_b * next_scale);
103 out_a = (int)(prev.out_a * prev_scale + next.out_a * next_scale);
106 center_x = prev.center_x * prev_scale + next.center_x * next_scale;
107 center_y = prev.center_y * prev_scale + next.center_y * next_scale;
110 int GradientConfig::get_in_color()
112 int result = (in_r << 16) | (in_g << 8) | (in_b);
116 int GradientConfig::get_out_color()
118 int result = (out_r << 16) | (out_g << 8) | (out_b);
130 PLUGIN_THREAD_OBJECT(GradientMain, GradientThread, GradientWindow)
136 GradientWindow::GradientWindow(GradientMain *plugin, int x, int y)
137 : BC_Window(plugin->gui_string,
147 this->plugin = plugin;
156 GradientWindow::~GradientWindow()
158 delete in_color_thread;
159 delete out_color_thread;
162 int GradientWindow::create_objects()
167 add_subwindow(title = new BC_Title(x, y, _("Shape:")));
168 add_subwindow(shape = new GradientShape(plugin,
170 x + title->get_w() + 10,
172 shape->create_objects();
177 add_subwindow(title = new BC_Title(x, y, _("Rate:")));
178 add_subwindow(rate = new GradientRate(plugin,
179 x + title->get_w() + 10,
181 rate->create_objects();
183 add_subwindow(title = new BC_Title(x, y, _("Inner radius:")));
184 add_subwindow(in_radius = new GradientInRadius(plugin, x + title->get_w() + 10, y));
186 add_subwindow(title = new BC_Title(x, y, _("Outer radius:")));
187 add_subwindow(out_radius = new GradientOutRadius(plugin, x + title->get_w() + 10, y));
189 add_subwindow(in_color = new GradientInColorButton(plugin, this, x, y));
190 in_color_x = x + in_color->get_w() + 10;
193 add_subwindow(out_color = new GradientOutColorButton(plugin, this, x, y));
194 out_color_x = x + out_color->get_w() + 10;
196 in_color_thread = new GradientInColorThread(plugin, this);
197 out_color_thread = new GradientOutColorThread(plugin, this);
207 void GradientWindow::update_shape()
209 int x = shape_x, y = shape_y;
211 if(plugin->config.shape == GradientConfig::LINEAR)
213 delete center_x_title;
214 delete center_y_title;
224 add_subwindow(angle_title = new BC_Title(x, y, _("Angle:")));
225 add_subwindow(angle = new GradientAngle(plugin, x + angle_title->get_w() + 10, y));
236 add_subwindow(center_x_title = new BC_Title(x, y, _("Center X:")));
237 add_subwindow(center_x = new GradientCenterX(plugin,
238 x + center_x_title->get_w() + 10,
240 x += center_x_title->get_w() + 10 + center_x->get_w() + 10;
241 add_subwindow(center_y_title = new BC_Title(x, y, _("Center Y:")));
242 add_subwindow(center_y = new GradientCenterY(plugin,
243 x + center_y_title->get_w() + 10,
249 int GradientWindow::close_event()
251 // Set result to 1 to indicate a plugin side close
256 void GradientWindow::update_in_color()
258 //printf("GradientWindow::update_in_color 1 %08x\n", plugin->config.get_in_color());
259 set_color(plugin->config.get_in_color());
260 draw_box(in_color_x, in_color_y, COLOR_W, COLOR_H);
261 flash(in_color_x, in_color_y, COLOR_W, COLOR_H);
264 void GradientWindow::update_out_color()
266 //printf("GradientWindow::update_out_color 1 %08x\n", plugin->config.get_in_color());
267 set_color(plugin->config.get_out_color());
268 draw_box(out_color_x, out_color_y, COLOR_W, COLOR_H);
269 flash(out_color_x, out_color_y, COLOR_W, COLOR_H);
280 GradientShape::GradientShape(GradientMain *plugin,
284 : BC_PopupMenu(x, y, 100, to_text(plugin->config.shape), 1)
286 this->plugin = plugin;
289 void GradientShape::create_objects()
291 add_item(new BC_MenuItem(to_text(GradientConfig::LINEAR)));
292 add_item(new BC_MenuItem(to_text(GradientConfig::RADIAL)));
294 char* GradientShape::to_text(int shape)
298 case GradientConfig::LINEAR:
304 int GradientShape::from_text(char *text)
306 if(!strcmp(text, to_text(GradientConfig::LINEAR)))
307 return GradientConfig::LINEAR;
308 return GradientConfig::RADIAL;
310 int GradientShape::handle_event()
312 plugin->config.shape = from_text(get_text());
314 plugin->send_configure_change();
320 GradientCenterX::GradientCenterX(GradientMain *plugin, int x, int y)
321 : BC_FPot(x, y, plugin->config.center_x, 0, 100)
323 this->plugin = plugin;
325 int GradientCenterX::handle_event()
327 plugin->config.center_x = get_value();
328 plugin->send_configure_change();
334 GradientCenterY::GradientCenterY(GradientMain *plugin, int x, int y)
335 : BC_FPot(x, y, plugin->config.center_y, 0, 100)
337 this->plugin = plugin;
340 int GradientCenterY::handle_event()
342 plugin->config.center_y = get_value();
343 plugin->send_configure_change();
350 GradientAngle::GradientAngle(GradientMain *plugin, int x, int y)
353 plugin->config.angle,
357 this->plugin = plugin;
360 int GradientAngle::handle_event()
362 plugin->config.angle = get_value();
363 plugin->send_configure_change();
368 GradientRate::GradientRate(GradientMain *plugin, int x, int y)
372 to_text(plugin->config.rate),
375 this->plugin = plugin;
377 void GradientRate::create_objects()
379 add_item(new BC_MenuItem(to_text(GradientConfig::LINEAR)));
380 add_item(new BC_MenuItem(to_text(GradientConfig::LOG)));
381 add_item(new BC_MenuItem(to_text(GradientConfig::SQUARE)));
383 char* GradientRate::to_text(int shape)
387 case GradientConfig::LINEAR:
389 case GradientConfig::LOG:
395 int GradientRate::from_text(char *text)
397 if(!strcmp(text, to_text(GradientConfig::LINEAR)))
398 return GradientConfig::LINEAR;
399 if(!strcmp(text, to_text(GradientConfig::LOG)))
400 return GradientConfig::LOG;
401 return GradientConfig::SQUARE;
403 int GradientRate::handle_event()
405 plugin->config.rate = from_text(get_text());
406 plugin->send_configure_change();
412 GradientInRadius::GradientInRadius(GradientMain *plugin, int x, int y)
420 (float)plugin->config.in_radius)
422 this->plugin = plugin;
425 int GradientInRadius::handle_event()
427 plugin->config.in_radius = get_value();
428 plugin->send_configure_change();
433 GradientOutRadius::GradientOutRadius(GradientMain *plugin, int x, int y)
441 (float)plugin->config.out_radius)
443 this->plugin = plugin;
446 int GradientOutRadius::handle_event()
448 plugin->config.out_radius = get_value();
449 plugin->send_configure_change();
453 GradientInColorButton::GradientInColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
454 : BC_GenericButton(x, y, _("Inner color:"))
456 this->plugin = plugin;
457 this->window = window;
460 int GradientInColorButton::handle_event()
462 window->in_color_thread->start_window(
463 plugin->config.get_in_color(),
464 plugin->config.in_a);
469 GradientOutColorButton::GradientOutColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
470 : BC_GenericButton(x, y, _("Outer color:"))
472 this->plugin = plugin;
473 this->window = window;
476 int GradientOutColorButton::handle_event()
478 window->out_color_thread->start_window(
479 plugin->config.get_out_color(),
480 plugin->config.out_a);
486 GradientInColorThread::GradientInColorThread(GradientMain *plugin,
487 GradientWindow *window)
488 : ColorThread(1, _("Inner color"))
490 this->plugin = plugin;
491 this->window = window;
494 int GradientInColorThread::handle_new_color(int output, int alpha)
496 plugin->config.in_r = (output & 0xff0000) >> 16;
497 plugin->config.in_g = (output & 0xff00) >> 8;
498 plugin->config.in_b = (output & 0xff);
499 plugin->config.in_a = alpha;
500 window->update_in_color();
502 plugin->send_configure_change();
503 // printf("GradientInColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
504 // plugin->config.in_r,
505 // plugin->config.in_g,
506 // plugin->config.in_b,
507 // plugin->config.in_a,
508 // plugin->config.out_r,
509 // plugin->config.out_g,
510 // plugin->config.out_b,
511 // plugin->config.out_a);
518 GradientOutColorThread::GradientOutColorThread(GradientMain *plugin,
519 GradientWindow *window)
520 : ColorThread(1, _("Outer color"))
522 this->plugin = plugin;
523 this->window = window;
526 int GradientOutColorThread::handle_new_color(int output, int alpha)
528 plugin->config.out_r = (output & 0xff0000) >> 16;
529 plugin->config.out_g = (output & 0xff00) >> 8;
530 plugin->config.out_b = (output & 0xff);
531 plugin->config.out_a = alpha;
532 window->update_out_color();
534 plugin->send_configure_change();
535 // printf("GradientOutColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
536 // plugin->config.in_r,
537 // plugin->config.in_g,
538 // plugin->config.in_b,
539 // plugin->config.in_a,
540 // plugin->config.out_r,
541 // plugin->config.out_g,
542 // plugin->config.out_b,
543 // plugin->config.out_a);
558 GradientMain::GradientMain(PluginServer *server)
559 : PluginVClient(server)
561 PLUGIN_CONSTRUCTOR_MACRO
562 need_reconfigure = 1;
568 GradientMain::~GradientMain()
570 PLUGIN_DESTRUCTOR_MACRO
572 if(gradient) delete gradient;
573 if(engine) delete engine;
574 if(overlayer) delete overlayer;
577 char* GradientMain::plugin_title() { return N_("Gradient"); }
578 int GradientMain::is_realtime() { return 1; }
581 NEW_PICON_MACRO(GradientMain)
583 SHOW_GUI_MACRO(GradientMain, GradientThread)
585 SET_STRING_MACRO(GradientMain)
587 RAISE_WINDOW_MACRO(GradientMain)
589 LOAD_CONFIGURATION_MACRO(GradientMain, GradientConfig)
591 int GradientMain::is_synthesis()
597 int GradientMain::process_buffer(VFrame *frame,
598 int64_t start_position,
602 this->output = frame;
603 need_reconfigure |= load_configuration();
605 int need_alpha = config.in_a != 0xff || config.out_a != 0xff;
612 if(get_use_opengl()) return run_opengl();
614 int gradient_cmodel = input->get_color_model();
615 if(need_alpha && cmodel_components(gradient_cmodel) == 3)
617 switch(gradient_cmodel)
620 gradient_cmodel = BC_RGBA8888;
623 gradient_cmodel = BC_RGBA_FLOAT;
626 gradient_cmodel = BC_YUVA8888;
631 if(gradient && gradient->get_color_model() != gradient_cmodel)
637 if(!gradient) gradient = new VFrame(0,
642 if(!engine) engine = new GradientServer(this,
643 get_project_smp() + 1,
644 get_project_smp() + 1);
645 engine->process_packages();
647 // Use overlay routine in GradientServer if mismatched colormodels
648 if(gradient->get_color_model() == output->get_color_model())
650 if(!overlayer) overlayer = new OverlayFrame(get_project_smp() + 1);
651 overlayer->overlay(output,
671 void GradientMain::update_gui()
675 if(load_configuration())
677 thread->window->lock_window("GradientMain::update_gui");
678 thread->window->rate->set_text(GradientRate::to_text(config.rate));
679 thread->window->in_radius->update(config.in_radius);
680 thread->window->out_radius->update(config.out_radius);
681 thread->window->shape->set_text(GradientShape::to_text(config.shape));
682 if(thread->window->angle)
683 thread->window->angle->update(config.angle);
684 if(thread->window->center_x)
685 thread->window->center_x->update(config.center_x);
686 if(thread->window->center_y)
687 thread->window->center_y->update(config.center_y);
688 thread->window->update_in_color();
689 thread->window->update_out_color();
690 thread->window->update_shape();
691 thread->window->unlock_window();
692 thread->window->in_color_thread->update_gui(config.get_in_color(), config.in_a);
693 thread->window->out_color_thread->update_gui(config.get_out_color(), config.out_a);
699 int GradientMain::load_defaults()
701 char directory[1024], string[1024];
702 // set the default directory
703 sprintf(directory, "%sgradient.rc", BCASTDIR);
706 defaults = new BC_Hash(directory);
709 // printf("GradientMain::load_defaults %d %d %d %d\n",
714 config.angle = defaults->get("ANGLE", config.angle);
715 config.in_radius = defaults->get("IN_RADIUS", config.in_radius);
716 config.out_radius = defaults->get("OUT_RADIUS", config.out_radius);
717 config.in_r = defaults->get("IN_R", config.in_r);
718 config.in_g = defaults->get("IN_G", config.in_g);
719 config.in_b = defaults->get("IN_B", config.in_b);
720 config.in_a = defaults->get("IN_A", config.in_a);
721 config.out_r = defaults->get("OUT_R", config.out_r);
722 config.out_g = defaults->get("OUT_G", config.out_g);
723 config.out_b = defaults->get("OUT_B", config.out_b);
724 config.out_a = defaults->get("OUT_A", config.out_a);
725 config.shape = defaults->get("SHAPE", config.shape);
726 config.rate = defaults->get("RATE", config.rate);
727 config.center_x = defaults->get("CENTER_X", config.center_x);
728 config.center_y = defaults->get("CENTER_Y", config.center_y);
733 int GradientMain::save_defaults()
735 defaults->update("ANGLE", config.angle);
736 defaults->update("IN_RADIUS", config.in_radius);
737 defaults->update("OUT_RADIUS", config.out_radius);
738 defaults->update("IN_R", config.in_r);
739 defaults->update("IN_G", config.in_g);
740 defaults->update("IN_B", config.in_b);
741 defaults->update("IN_A", config.in_a);
742 defaults->update("OUT_R", config.out_r);
743 defaults->update("OUT_G", config.out_g);
744 defaults->update("OUT_B", config.out_b);
745 defaults->update("OUT_A", config.out_a);
746 defaults->update("RATE", config.rate);
747 defaults->update("SHAPE", config.shape);
748 defaults->update("CENTER_X", config.center_x);
749 defaults->update("CENTER_Y", config.center_y);
756 void GradientMain::save_data(KeyFrame *keyframe)
760 // cause data to be stored directly in text
761 output.set_shared_string(keyframe->data, MESSAGESIZE);
762 output.tag.set_title("GRADIENT");
764 output.tag.set_property("ANGLE", config.angle);
765 output.tag.set_property("IN_RADIUS", config.in_radius);
766 output.tag.set_property("OUT_RADIUS", config.out_radius);
767 output.tag.set_property("IN_R", config.in_r);
768 output.tag.set_property("IN_G", config.in_g);
769 output.tag.set_property("IN_B", config.in_b);
770 output.tag.set_property("IN_A", config.in_a);
771 output.tag.set_property("OUT_R", config.out_r);
772 output.tag.set_property("OUT_G", config.out_g);
773 output.tag.set_property("OUT_B", config.out_b);
774 output.tag.set_property("OUT_A", config.out_a);
775 output.tag.set_property("SHAPE", config.shape);
776 output.tag.set_property("RATE", config.rate);
777 output.tag.set_property("CENTER_X", config.center_x);
778 output.tag.set_property("CENTER_Y", config.center_y);
780 output.terminate_string();
783 void GradientMain::read_data(KeyFrame *keyframe)
787 input.set_shared_string(keyframe->data, strlen(keyframe->data));
793 result = input.read_tag();
797 if(input.tag.title_is("GRADIENT"))
799 config.angle = input.tag.get_property("ANGLE", config.angle);
800 config.rate = input.tag.get_property("RATE", config.rate);
801 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
802 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
803 config.in_r = input.tag.get_property("IN_R", config.in_r);
804 config.in_g = input.tag.get_property("IN_G", config.in_g);
805 config.in_b = input.tag.get_property("IN_B", config.in_b);
806 config.in_a = input.tag.get_property("IN_A", config.in_a);
807 config.out_r = input.tag.get_property("OUT_R", config.out_r);
808 config.out_g = input.tag.get_property("OUT_G", config.out_g);
809 config.out_b = input.tag.get_property("OUT_B", config.out_b);
810 config.out_a = input.tag.get_property("OUT_A", config.out_a);
811 config.shape = input.tag.get_property("SHAPE", config.shape);
812 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
813 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
819 int GradientMain::handle_opengl()
823 "uniform sampler2D tex;\n"
824 "uniform float half_w;\n"
825 "uniform float half_h;\n"
826 "uniform float center_x;\n"
827 "uniform float center_y;\n"
828 "uniform float half_gradient_size;\n"
829 "uniform float sin_angle;\n"
830 "uniform float cos_angle;\n"
831 "uniform vec4 out_color;\n"
832 "uniform vec4 in_color;\n"
833 "uniform float in_radius;\n"
834 "uniform float out_radius;\n"
835 "uniform float radius_diff;\n"
839 " vec2 out_coord = gl_TexCoord[0].st;\n";
842 " vec2 in_coord = vec2(out_coord.x - half_w, half_h - out_coord.y);\n"
843 " float mag = half_gradient_size - \n"
844 " (in_coord.x * sin_angle + in_coord.y * cos_angle);\n";
847 " vec2 in_coord = vec2(out_coord.x - center_x, out_coord.y - center_y);\n"
848 " float mag = length(vec2(in_coord.x, in_coord.y));\n";
850 // No clamp function in NVidia
852 " mag = min(max(mag, in_radius), out_radius);\n"
853 " float opacity = (mag - in_radius) / radius_diff;\n";
855 // NVidia warns about exp, but exp is in the GLSL spec.
857 " mag = max(mag, in_radius);\n"
858 " float opacity = 1.0 - \n"
859 " exp(1.0 * -(mag - in_radius) / radius_diff);\n";
862 " mag = min(max(mag, in_radius), out_radius);\n"
863 " float opacity = pow((mag - in_radius) / radius_diff, 2.0);\n"
864 " opacity = min(opacity, 1.0);\n";
867 " vec4 color = mix(in_color, out_color, opacity);\n"
868 " vec4 bg_color = texture2D(tex, out_coord);\n"
869 " gl_FragColor.rgb = mix(bg_color.rgb, color.rgb, color.a);\n"
870 " gl_FragColor.a = max(bg_color.a, color.a);\n"
874 char *shader_stack[5] = { 0, 0, 0, 0, 0 };
875 shader_stack[0] = head_frag;
879 case GradientConfig::LINEAR:
880 shader_stack[1] = linear_shape;
884 shader_stack[1] = radial_shape;
890 case GradientConfig::LINEAR:
891 shader_stack[2] = linear_rate;
893 case GradientConfig::LOG:
894 shader_stack[2] = log_rate;
896 case GradientConfig::SQUARE:
897 shader_stack[2] = square_rate;
901 shader_stack[3] = tail_frag;
902 // Force frame to create texture without copying to it if full alpha.
903 if(config.in_a >= 0xff &&
904 config.out_a >= 0xff)
905 get_output()->set_opengl_state(VFrame::TEXTURE);
906 get_output()->to_texture();
907 get_output()->enable_opengl();
908 get_output()->init_screen();
909 get_output()->bind_texture(0);
911 unsigned int frag = VFrame::make_shader(0,
921 float w = get_output()->get_w();
922 float h = get_output()->get_h();
923 float texture_w = get_output()->get_texture_w();
924 float texture_h = get_output()->get_texture_h();
925 glUniform1i(glGetUniformLocation(frag, "tex"), 0);
926 glUniform1f(glGetUniformLocation(frag, "half_w"), w / 2 / texture_w);
927 glUniform1f(glGetUniformLocation(frag, "half_h"), h / 2 / texture_h);
928 if(config.shape == GradientConfig::LINEAR)
930 glUniform1f(glGetUniformLocation(frag, "center_x"),
932 glUniform1f(glGetUniformLocation(frag, "center_y"),
937 glUniform1f(glGetUniformLocation(frag, "center_x"),
938 (float)config.center_x * w / 100 / texture_w);
939 glUniform1f(glGetUniformLocation(frag, "center_y"),
940 (float)config.center_y * h / 100 / texture_h);
942 float gradient_size = hypotf(w / texture_w, h / texture_h);
943 glUniform1f(glGetUniformLocation(frag, "half_gradient_size"),
945 glUniform1f(glGetUniformLocation(frag, "sin_angle"),
946 sin(config.angle * (M_PI / 180)));
947 glUniform1f(glGetUniformLocation(frag, "cos_angle"),
948 cos(config.angle * (M_PI / 180)));
949 float in_radius = (float)config.in_radius / 100 * gradient_size;
950 glUniform1f(glGetUniformLocation(frag, "in_radius"), in_radius);
951 float out_radius = (float)config.out_radius / 100 * gradient_size;
952 glUniform1f(glGetUniformLocation(frag, "out_radius"), out_radius);
953 glUniform1f(glGetUniformLocation(frag, "radius_diff"),
954 out_radius - in_radius);
956 switch(get_output()->get_color_model())
961 float in1, in2, in3, in4;
962 float out1, out2, out3, out4;
963 YUV::rgb_to_yuv_f((float)config.in_r / 0xff,
964 (float)config.in_g / 0xff,
965 (float)config.in_b / 0xff,
969 in4 = (float)config.in_a / 0xff;
970 YUV::rgb_to_yuv_f((float)config.out_r / 0xff,
971 (float)config.out_g / 0xff,
972 (float)config.out_b / 0xff,
980 out4 = (float)config.out_a / 0xff;
981 glUniform4f(glGetUniformLocation(frag, "out_color"),
982 out1, out2, out3, out4);
983 glUniform4f(glGetUniformLocation(frag, "in_color"),
989 glUniform4f(glGetUniformLocation(frag, "out_color"),
990 (float)config.out_r / 0xff,
991 (float)config.out_g / 0xff,
992 (float)config.out_b / 0xff,
993 (float)config.out_a / 0xff);
994 glUniform4f(glGetUniformLocation(frag, "in_color"),
995 (float)config.in_r / 0xff,
996 (float)config.in_g / 0xff,
997 (float)config.in_b / 0xff,
998 (float)config.in_a / 0xff);
1003 get_output()->draw_texture();
1005 get_output()->set_opengl_state(VFrame::SCREEN);
1020 GradientPackage::GradientPackage()
1028 GradientUnit::GradientUnit(GradientServer *server, GradientMain *plugin)
1029 : LoadClient(server)
1031 this->plugin = plugin;
1032 this->server = server;
1036 #define SQR(x) ((x) * (x))
1039 static float calculate_opacity(float mag,
1047 case GradientConfig::LINEAR:
1051 if(mag >= out_radius)
1054 opacity = (float)(mag - in_radius) / (out_radius - in_radius);
1057 case GradientConfig::LOG:
1061 // Let this one decay beyond out_radius
1062 opacity = 1 - exp(1.0 * -(float)(mag - in_radius) /
1063 (out_radius - in_radius));
1066 case GradientConfig::SQUARE:
1070 if(mag >= out_radius)
1073 opacity = powf((float)(mag - in_radius) /
1074 (out_radius - in_radius), 2.0);
1077 CLAMP(opacity, 0.0, 1.0);
1081 #define CREATE_GRADIENT(type, temp, components, max) \
1083 /* Synthesize linear gradient for lookups */ \
1085 r_table = malloc(sizeof(type) * gradient_size); \
1086 g_table = malloc(sizeof(type) * gradient_size); \
1087 b_table = malloc(sizeof(type) * gradient_size); \
1088 a_table = malloc(sizeof(type) * gradient_size); \
1090 for(int i = 0; i < gradient_size; i++) \
1092 float opacity = calculate_opacity(i, in_radius, out_radius, plugin->config.rate); \
1093 float transparency; \
1095 transparency = 1.0 - opacity; \
1096 ((type*)r_table)[i] = (type)(out1 * opacity + in1 * transparency); \
1097 ((type*)g_table)[i] = (type)(out2 * opacity + in2 * transparency); \
1098 ((type*)b_table)[i] = (type)(out3 * opacity + in3 * transparency); \
1099 ((type*)a_table)[i] = (type)(out4 * opacity + in4 * transparency); \
1102 for(int i = pkg->y1; i < pkg->y2; i++) \
1104 type *gradient_row = (type*)plugin->gradient->get_rows()[i]; \
1105 type *out_row = (type*)plugin->get_output()->get_rows()[i]; \
1107 switch(plugin->config.shape) \
1109 case GradientConfig::LINEAR: \
1110 for(int j = 0; j < w; j++) \
1112 int x = j - half_w; \
1113 int y = -(i - half_h); \
1115 /* Rotate by effect angle */ \
1116 int mag = (int)(gradient_size / 2 - \
1117 (x * sin_angle + y * cos_angle) + \
1120 /* Get gradient value from these coords */ \
1122 if(sizeof(type) == 4) \
1124 float opacity = calculate_opacity(mag, \
1127 plugin->config.rate); \
1128 float transparency = 1.0 - opacity; \
1129 gradient_row[0] = (type)(out1 * opacity + in1 * transparency); \
1130 gradient_row[1] = (type)(out2 * opacity + in2 * transparency); \
1131 gradient_row[2] = (type)(out3 * opacity + in3 * transparency); \
1132 if(components == 4) gradient_row[3] = (type)(out4 * opacity + in4 * transparency); \
1137 gradient_row[0] = out1; \
1138 gradient_row[1] = out2; \
1139 gradient_row[2] = out3; \
1140 if(components == 4) gradient_row[3] = out4; \
1143 if(mag >= gradient_size) \
1145 gradient_row[0] = in1; \
1146 gradient_row[1] = in2; \
1147 gradient_row[2] = in3; \
1148 if(components == 4) gradient_row[3] = in4; \
1152 gradient_row[0] = ((type*)r_table)[mag]; \
1153 gradient_row[1] = ((type*)g_table)[mag]; \
1154 gradient_row[2] = ((type*)b_table)[mag]; \
1155 if(components == 4) gradient_row[3] = ((type*)a_table)[mag]; \
1158 /* Overlay mixed colormodels onto output */ \
1159 if(gradient_cmodel != output_cmodel) \
1161 temp opacity = gradient_row[3]; \
1162 temp transparency = max - opacity; \
1163 out_row[0] = (transparency * out_row[0] + opacity * gradient_row[0]) / max; \
1164 out_row[1] = (transparency * out_row[1] + opacity * gradient_row[1]) / max; \
1165 out_row[2] = (transparency * out_row[2] + opacity * gradient_row[2]) / max; \
1169 gradient_row += components; \
1173 case GradientConfig::RADIAL: \
1174 for(int j = 0; j < w; j++) \
1176 double x = j - center_x; \
1177 double y = i - center_y; \
1178 double magnitude = hypot(x, y); \
1179 int mag = (int)magnitude; \
1180 if(sizeof(type) == 4) \
1182 float opacity = calculate_opacity(mag, \
1185 plugin->config.rate); \
1186 float transparency = 1.0 - opacity; \
1187 gradient_row[0] = (type)(out1 * opacity + in1 * transparency); \
1188 gradient_row[1] = (type)(out2 * opacity + in2 * transparency); \
1189 gradient_row[2] = (type)(out3 * opacity + in3 * transparency); \
1190 if(components == 4) gradient_row[3] = (type)(out4 * opacity + in4 * transparency); \
1194 gradient_row[0] = ((type*)r_table)[mag]; \
1195 gradient_row[1] = ((type*)g_table)[mag]; \
1196 gradient_row[2] = ((type*)b_table)[mag]; \
1197 if(components == 4) gradient_row[3] = ((type*)a_table)[mag]; \
1200 /* Overlay mixed colormodels onto output */ \
1201 if(gradient_cmodel != output_cmodel) \
1203 temp opacity = gradient_row[3]; \
1204 temp transparency = max - opacity; \
1205 out_row[0] = (transparency * out_row[0] + opacity * gradient_row[0]) / max; \
1206 out_row[1] = (transparency * out_row[1] + opacity * gradient_row[1]) / max; \
1207 out_row[2] = (transparency * out_row[2] + opacity * gradient_row[2]) / max; \
1211 gradient_row += components; \
1218 void GradientUnit::process_package(LoadPackage *package)
1220 GradientPackage *pkg = (GradientPackage*)package;
1221 int h = plugin->input->get_h();
1222 int w = plugin->input->get_w();
1225 int gradient_size = (int)(ceil(hypot(w, h)));
1226 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
1227 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
1228 double sin_angle = sin(plugin->config.angle * (M_PI / 180));
1229 double cos_angle = cos(plugin->config.angle * (M_PI / 180));
1230 double center_x = plugin->config.center_x * w / 100;
1231 double center_y = plugin->config.center_y * h / 100;
1236 int gradient_cmodel = plugin->gradient->get_color_model();
1237 int output_cmodel = plugin->get_output()->get_color_model();
1239 if(in_radius > out_radius)
1241 in_radius ^= out_radius;
1242 out_radius ^= in_radius;
1243 in_radius ^= out_radius;
1247 switch(gradient_cmodel)
1251 int in1 = plugin->config.in_r;
1252 int in2 = plugin->config.in_g;
1253 int in3 = plugin->config.in_b;
1254 int in4 = plugin->config.in_a;
1255 int out1 = plugin->config.out_r;
1256 int out2 = plugin->config.out_g;
1257 int out3 = plugin->config.out_b;
1258 int out4 = plugin->config.out_a;
1259 CREATE_GRADIENT(unsigned char, int, 3, 0xff)
1265 int in1 = plugin->config.in_r;
1266 int in2 = plugin->config.in_g;
1267 int in3 = plugin->config.in_b;
1268 int in4 = plugin->config.in_a;
1269 int out1 = plugin->config.out_r;
1270 int out2 = plugin->config.out_g;
1271 int out3 = plugin->config.out_b;
1272 int out4 = plugin->config.out_a;
1273 CREATE_GRADIENT(unsigned char, int, 4, 0xff)
1279 float in1 = (float)plugin->config.in_r / 0xff;
1280 float in2 = (float)plugin->config.in_g / 0xff;
1281 float in3 = (float)plugin->config.in_b / 0xff;
1282 float in4 = (float)plugin->config.in_a / 0xff;
1283 float out1 = (float)plugin->config.out_r / 0xff;
1284 float out2 = (float)plugin->config.out_g / 0xff;
1285 float out3 = (float)plugin->config.out_b / 0xff;
1286 float out4 = (float)plugin->config.out_a / 0xff;
1287 CREATE_GRADIENT(float, float, 3, 1.0)
1293 float in1 = (float)plugin->config.in_r / 0xff;
1294 float in2 = (float)plugin->config.in_g / 0xff;
1295 float in3 = (float)plugin->config.in_b / 0xff;
1296 float in4 = (float)plugin->config.in_a / 0xff;
1297 float out1 = (float)plugin->config.out_r / 0xff;
1298 float out2 = (float)plugin->config.out_g / 0xff;
1299 float out3 = (float)plugin->config.out_b / 0xff;
1300 float out4 = (float)plugin->config.out_a / 0xff;
1301 CREATE_GRADIENT(float, float, 4, 1.0)
1307 int in1, in2, in3, in4;
1308 int out1, out2, out3, out4;
1309 yuv.rgb_to_yuv_8(plugin->config.in_r,
1310 plugin->config.in_g,
1311 plugin->config.in_b,
1315 in4 = plugin->config.in_a;
1316 yuv.rgb_to_yuv_8(plugin->config.out_r,
1317 plugin->config.out_g,
1318 plugin->config.out_b,
1322 out4 = plugin->config.out_a;
1323 CREATE_GRADIENT(unsigned char, int, 3, 0xff)
1329 int in1, in2, in3, in4;
1330 int out1, out2, out3, out4;
1331 yuv.rgb_to_yuv_8(plugin->config.in_r,
1332 plugin->config.in_g,
1333 plugin->config.in_b,
1337 in4 = plugin->config.in_a;
1338 yuv.rgb_to_yuv_8(plugin->config.out_r,
1339 plugin->config.out_g,
1340 plugin->config.out_b,
1344 out4 = plugin->config.out_a;
1345 CREATE_GRADIENT(unsigned char, int, 4, 0xff)
1350 if(r_table) free(r_table);
1351 if(g_table) free(g_table);
1352 if(b_table) free(b_table);
1353 if(a_table) free(a_table);
1361 GradientServer::GradientServer(GradientMain *plugin,
1364 : LoadServer(total_clients, total_packages)
1366 this->plugin = plugin;
1369 void GradientServer::init_packages()
1371 for(int i = 0; i < get_total_packages(); i++)
1373 GradientPackage *package = (GradientPackage*)get_package(i);
1374 package->y1 = plugin->input->get_h() *
1376 get_total_packages();
1377 package->y2 = plugin->input->get_h() *
1379 get_total_packages();
1383 LoadClient* GradientServer::new_client()
1385 return new GradientUnit(this, plugin);
1388 LoadPackage* GradientServer::new_package()
1390 return new GradientPackage;