4 * Copyright (C) 2008 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 "bcdisplayinfo.h"
33 #include "overlayframe.h"
40 REGISTER_PLUGIN(GradientMain)
47 GradientConfig::GradientConfig()
52 void GradientConfig::reset()
66 shape = GradientConfig::LINEAR;
67 rate = GradientConfig::LINEAR;
72 int GradientConfig::equivalent(GradientConfig &that)
74 return (EQUIV(angle, that.angle) &&
75 EQUIV(in_radius, that.in_radius) &&
76 EQUIV(out_radius, that.out_radius) &&
81 out_r == that.out_r &&
82 out_g == that.out_g &&
83 out_b == that.out_b &&
84 out_a == that.out_a &&
85 shape == that.shape &&
87 EQUIV(center_x, that.center_x) &&
88 EQUIV(center_y, that.center_y));
91 void GradientConfig::copy_from(GradientConfig &that)
94 in_radius = that.in_radius;
95 out_radius = that.out_radius;
106 center_x = that.center_x;
107 center_y = that.center_y;
110 void GradientConfig::interpolate(GradientConfig &prev,
111 GradientConfig &next,
116 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
117 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
120 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale);
121 this->in_radius = (int)(prev.in_radius * prev_scale + next.in_radius * next_scale);
122 this->out_radius = (int)(prev.out_radius * prev_scale + next.out_radius * next_scale);
123 in_r = (int)(prev.in_r * prev_scale + next.in_r * next_scale);
124 in_g = (int)(prev.in_g * prev_scale + next.in_g * next_scale);
125 in_b = (int)(prev.in_b * prev_scale + next.in_b * next_scale);
126 in_a = (int)(prev.in_a * prev_scale + next.in_a * next_scale);
127 out_r = (int)(prev.out_r * prev_scale + next.out_r * next_scale);
128 out_g = (int)(prev.out_g * prev_scale + next.out_g * next_scale);
129 out_b = (int)(prev.out_b * prev_scale + next.out_b * next_scale);
130 out_a = (int)(prev.out_a * prev_scale + next.out_a * next_scale);
133 center_x = prev.center_x * prev_scale + next.center_x * next_scale;
134 center_y = prev.center_y * prev_scale + next.center_y * next_scale;
137 int GradientConfig::get_in_color()
139 int result = (in_r << 16) | (in_g << 8) | (in_b);
143 int GradientConfig::get_out_color()
145 int result = (out_r << 16) | (out_g << 8) | (out_b);
162 GradientWindow::GradientWindow(GradientMain *plugin)
163 : PluginClientWindow(plugin,
170 this->plugin = plugin;
179 GradientWindow::~GradientWindow()
181 delete in_color_thread;
182 delete out_color_thread;
185 void GradientWindow::create_objects()
187 int margin = plugin->get_theme()->widget_border;
191 add_subwindow(title = new BC_Title(x, y, _("Shape:")));
192 add_subwindow(shape = new GradientShape(plugin,
194 x + title->get_w() + margin,
196 shape->create_objects();
197 y += shape->get_h() + margin;
200 y += BC_Pot::calculate_h() + margin;
202 add_subwindow(title = new BC_Title(x, y, _("Rate:")));
203 add_subwindow(rate = new GradientRate(plugin,
204 x + title->get_w() + margin,
206 rate->create_objects();
207 y += rate->get_h() + margin;
213 add_subwindow(title1 = new BC_Title(x, y, _("Inner radius:")));
215 y += BC_Slider::get_span(0) + margin;
218 add_subwindow(title2 = new BC_Title(x, y, _("Outer radius:")));
220 add_subwindow(reset = new GradientReset(plugin, this, x, y+100));
223 x += MAX(title1->get_w(), title2->get_w()) + margin;
225 add_subwindow(in_radius = new GradientInRadius(plugin, x, y));
226 y += in_radius->get_h() + margin;
228 add_subwindow(out_radius = new GradientOutRadius(plugin, x, y));
229 y += out_radius->get_h() + margin;
233 add_subwindow(in_color = new GradientInColorButton(plugin, this, x, y));
234 y += COLOR_H + margin;
236 add_subwindow(out_color = new GradientOutColorButton(plugin, this, x, y));
237 x += MAX(in_color->get_w(), out_color->get_w()) + margin;
242 y += COLOR_H + margin;
245 in_color_thread = new GradientInColorThread(plugin, this);
246 out_color_thread = new GradientOutColorThread(plugin, this);
251 draw_3d_border(in_color_x - 2,
257 draw_3d_border(out_color_x - 2,
267 void GradientWindow::update_shape()
269 int x = shape_x, y = shape_y;
271 if(plugin->config.shape == GradientConfig::LINEAR)
273 delete center_x_title;
274 delete center_y_title;
284 add_subwindow(angle_title = new BC_Title(x, y, _("Angle:")));
285 add_subwindow(angle = new GradientAngle(plugin, x + angle_title->get_w() + 10, y));
296 add_subwindow(center_x_title = new BC_Title(x, y, _("Center X:")));
297 add_subwindow(center_x = new GradientCenterX(plugin,
298 x + center_x_title->get_w() + 10,
300 x += center_x_title->get_w() + 10 + center_x->get_w() + 10;
301 add_subwindow(center_y_title = new BC_Title(x, y, _("Center Y:")));
302 add_subwindow(center_y = new GradientCenterY(plugin,
303 x + center_y_title->get_w() + 10,
313 void GradientWindow::update_in_color()
315 //printf("GradientWindow::update_in_color 1 %08x\n", plugin->config.get_in_color());
316 set_color(plugin->config.get_in_color());
317 draw_box(in_color_x, in_color_y, COLOR_W, COLOR_H);
318 flash(in_color_x, in_color_y, COLOR_W, COLOR_H);
321 void GradientWindow::update_out_color()
323 //printf("GradientWindow::update_out_color 1 %08x\n", plugin->config.get_in_color());
324 set_color(plugin->config.get_out_color());
325 draw_box(out_color_x, out_color_y, COLOR_W, COLOR_H);
326 flash(out_color_x, out_color_y, COLOR_W, COLOR_H);
329 void GradientWindow::done_event(int result)
331 in_color_thread->close_window();
332 out_color_thread->close_window();
343 GradientShape::GradientShape(GradientMain *plugin,
347 : BC_PopupMenu(x, y, 100, to_text(plugin->config.shape), 1)
349 this->plugin = plugin;
352 void GradientShape::create_objects()
354 add_item(new BC_MenuItem(to_text(GradientConfig::LINEAR)));
355 add_item(new BC_MenuItem(to_text(GradientConfig::RADIAL)));
357 char* GradientShape::to_text(int shape)
361 case GradientConfig::LINEAR:
367 int GradientShape::from_text(char *text)
369 if(!strcmp(text, to_text(GradientConfig::LINEAR)))
370 return GradientConfig::LINEAR;
371 return GradientConfig::RADIAL;
373 int GradientShape::handle_event()
375 plugin->config.shape = from_text(get_text());
377 plugin->send_configure_change();
384 GradientCenterX::GradientCenterX(GradientMain *plugin, int x, int y)
385 : BC_FPot(x, y, plugin->config.center_x, 0, 100)
387 this->plugin = plugin;
389 int GradientCenterX::handle_event()
391 plugin->config.center_x = get_value();
392 plugin->send_configure_change();
398 GradientCenterY::GradientCenterY(GradientMain *plugin, int x, int y)
399 : BC_FPot(x, y, plugin->config.center_y, 0, 100)
401 this->plugin = plugin;
404 int GradientCenterY::handle_event()
406 plugin->config.center_y = get_value();
407 plugin->send_configure_change();
414 GradientAngle::GradientAngle(GradientMain *plugin, int x, int y)
417 plugin->config.angle,
421 this->plugin = plugin;
424 int GradientAngle::handle_event()
426 plugin->config.angle = get_value();
427 plugin->send_configure_change();
432 GradientRate::GradientRate(GradientMain *plugin, int x, int y)
436 to_text(plugin->config.rate),
439 this->plugin = plugin;
441 void GradientRate::create_objects()
443 add_item(new BC_MenuItem(to_text(GradientConfig::LINEAR)));
444 add_item(new BC_MenuItem(to_text(GradientConfig::LOG)));
445 add_item(new BC_MenuItem(to_text(GradientConfig::SQUARE)));
447 char* GradientRate::to_text(int shape)
451 case GradientConfig::LINEAR:
453 case GradientConfig::LOG:
459 int GradientRate::from_text(char *text)
461 if(!strcmp(text, to_text(GradientConfig::LINEAR)))
462 return GradientConfig::LINEAR;
463 if(!strcmp(text, to_text(GradientConfig::LOG)))
464 return GradientConfig::LOG;
465 return GradientConfig::SQUARE;
467 int GradientRate::handle_event()
469 plugin->config.rate = from_text(get_text());
470 plugin->send_configure_change();
476 GradientInRadius::GradientInRadius(GradientMain *plugin, int x, int y)
484 (float)plugin->config.in_radius)
486 this->plugin = plugin;
489 int GradientInRadius::handle_event()
491 plugin->config.in_radius = get_value();
492 plugin->send_configure_change();
497 GradientOutRadius::GradientOutRadius(GradientMain *plugin, int x, int y)
505 (float)plugin->config.out_radius)
507 this->plugin = plugin;
510 int GradientOutRadius::handle_event()
512 plugin->config.out_radius = get_value();
513 plugin->send_configure_change();
517 GradientInColorButton::GradientInColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
518 : BC_GenericButton(x, y, _("Inner color:"))
520 this->plugin = plugin;
521 this->window = window;
524 int GradientInColorButton::handle_event()
526 window->in_color_thread->start_window(
527 plugin->config.get_in_color(),
528 plugin->config.in_a);
533 GradientOutColorButton::GradientOutColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
534 : BC_GenericButton(x, y, _("Outer color:"))
536 this->plugin = plugin;
537 this->window = window;
540 int GradientOutColorButton::handle_event()
542 window->out_color_thread->start_window(
543 plugin->config.get_out_color(),
544 plugin->config.out_a);
548 GradientReset::GradientReset(GradientMain *plugin, GradientWindow *window, int x, int y)
549 : BC_GenericButton(x, y, _("Reset"))
551 this->plugin = plugin;
552 this->window = window;
555 int GradientReset::handle_event()
557 plugin->config.reset();
558 window->update_gui();
559 plugin->send_configure_change();
563 GradientInColorThread::GradientInColorThread(GradientMain *plugin,
564 GradientWindow *window)
565 : ColorPicker(1, _("Inner color"))
567 this->plugin = plugin;
568 this->window = window;
571 int GradientInColorThread::handle_new_color(int output, int alpha)
573 plugin->config.in_r = (output & 0xff0000) >> 16;
574 plugin->config.in_g = (output & 0xff00) >> 8;
575 plugin->config.in_b = (output & 0xff);
576 plugin->config.in_a = alpha;
578 window->lock_window("GradientInColorThread::handle_new_color");
579 window->update_in_color();
581 window->unlock_window();
582 plugin->send_configure_change();
583 // printf("GradientInColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
584 // plugin->config.in_r,
585 // plugin->config.in_g,
586 // plugin->config.in_b,
587 // plugin->config.in_a,
588 // plugin->config.out_r,
589 // plugin->config.out_g,
590 // plugin->config.out_b,
591 // plugin->config.out_a);
598 GradientOutColorThread::GradientOutColorThread(GradientMain *plugin,
599 GradientWindow *window)
600 : ColorPicker(1, _("Outer color"))
602 this->plugin = plugin;
603 this->window = window;
606 int GradientOutColorThread::handle_new_color(int output, int alpha)
608 plugin->config.out_r = (output & 0xff0000) >> 16;
609 plugin->config.out_g = (output & 0xff00) >> 8;
610 plugin->config.out_b = (output & 0xff);
611 plugin->config.out_a = alpha;
612 window->lock_window("GradientOutColorThread::handle_new_color");
613 window->update_out_color();
615 window->unlock_window();
616 plugin->send_configure_change();
617 // printf("GradientOutColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
618 // plugin->config.in_r,
619 // plugin->config.in_g,
620 // plugin->config.in_b,
621 // plugin->config.in_a,
622 // plugin->config.out_r,
623 // plugin->config.out_g,
624 // plugin->config.out_b,
625 // plugin->config.out_a);
640 GradientMain::GradientMain(PluginServer *server)
641 : PluginVClient(server)
644 need_reconfigure = 1;
650 GradientMain::~GradientMain()
654 if(gradient) delete gradient;
655 if(engine) delete engine;
656 if(overlayer) delete overlayer;
659 const char* GradientMain::plugin_title() { return _("Gradient"); }
660 int GradientMain::is_realtime() { return 1; }
663 NEW_WINDOW_MACRO(GradientMain, GradientWindow)
665 LOAD_CONFIGURATION_MACRO(GradientMain, GradientConfig)
667 int GradientMain::is_synthesis()
673 int GradientMain::process_buffer(VFrame *frame,
674 int64_t start_position,
678 this->output = frame;
679 need_reconfigure |= load_configuration();
681 int need_alpha = config.in_a != 0xff || config.out_a != 0xff;
688 if(get_use_opengl()) return run_opengl();
690 int gradient_cmodel = input->get_color_model();
691 if(need_alpha && BC_CModels::components(gradient_cmodel) == 3)
693 switch(gradient_cmodel)
696 gradient_cmodel = BC_RGBA8888;
699 gradient_cmodel = BC_RGBA_FLOAT;
702 gradient_cmodel = BC_YUVA8888;
707 if(gradient && gradient->get_color_model() != gradient_cmodel)
714 gradient = new VFrame(input->get_w(), input->get_h(),
717 if(!engine) engine = new GradientServer(this,
718 get_project_smp() + 1,
719 get_project_smp() + 1);
720 engine->process_packages();
722 // Use overlay routine in GradientServer if mismatched colormodels
723 if(gradient->get_color_model() == output->get_color_model())
725 if(!overlayer) overlayer = new OverlayFrame(get_project_smp() + 1);
726 overlayer->overlay(output,
746 void GradientMain::update_gui()
748 if( !thread ) return;
749 if( !load_configuration() ) return;
750 ((GradientWindow*)thread->window)->lock_window("GradientMain::update_gui");
751 GradientWindow *window = (GradientWindow *)thread->window;
752 window->update_gui();
753 window->unlock_window();
756 void GradientWindow::update_gui()
758 GradientConfig &config = plugin->config;
759 rate->set_text(GradientRate::to_text(config.rate));
760 in_radius->update(config.in_radius);
761 out_radius->update(config.out_radius);
762 shape->set_text(GradientShape::to_text(config.shape));
763 if( angle ) angle->update(config.angle);
764 if( center_x ) center_x->update(config.center_x);
765 if( center_y ) center_y->update(config.center_y);
770 in_color_thread->update_gui(config.get_in_color(), config.in_a);
771 out_color_thread->update_gui(config.get_out_color(), config.out_a);
772 lock_window("GradientWindow::update_gui");
776 void GradientMain::save_data(KeyFrame *keyframe)
780 // cause data to be stored directly in text
781 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
782 output.tag.set_title("GRADIENT");
784 output.tag.set_property("ANGLE", config.angle);
785 output.tag.set_property("IN_RADIUS", config.in_radius);
786 output.tag.set_property("OUT_RADIUS", config.out_radius);
787 output.tag.set_property("IN_R", config.in_r);
788 output.tag.set_property("IN_G", config.in_g);
789 output.tag.set_property("IN_B", config.in_b);
790 output.tag.set_property("IN_A", config.in_a);
791 output.tag.set_property("OUT_R", config.out_r);
792 output.tag.set_property("OUT_G", config.out_g);
793 output.tag.set_property("OUT_B", config.out_b);
794 output.tag.set_property("OUT_A", config.out_a);
795 output.tag.set_property("SHAPE", config.shape);
796 output.tag.set_property("RATE", config.rate);
797 output.tag.set_property("CENTER_X", config.center_x);
798 output.tag.set_property("CENTER_Y", config.center_y);
800 output.tag.set_title("/GRADIENT");
802 output.append_newline();
803 output.terminate_string();
806 void GradientMain::read_data(KeyFrame *keyframe)
810 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
816 result = input.read_tag();
820 if(input.tag.title_is("GRADIENT"))
822 config.angle = input.tag.get_property("ANGLE", config.angle);
823 config.rate = input.tag.get_property("RATE", config.rate);
824 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
825 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
826 config.in_r = input.tag.get_property("IN_R", config.in_r);
827 config.in_g = input.tag.get_property("IN_G", config.in_g);
828 config.in_b = input.tag.get_property("IN_B", config.in_b);
829 config.in_a = input.tag.get_property("IN_A", config.in_a);
830 config.out_r = input.tag.get_property("OUT_R", config.out_r);
831 config.out_g = input.tag.get_property("OUT_G", config.out_g);
832 config.out_b = input.tag.get_property("OUT_B", config.out_b);
833 config.out_a = input.tag.get_property("OUT_A", config.out_a);
834 config.shape = input.tag.get_property("SHAPE", config.shape);
835 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
836 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
842 int GradientMain::handle_opengl()
845 const char *head_frag =
846 "uniform sampler2D tex;\n"
847 "uniform float half_w;\n"
848 "uniform float half_h;\n"
849 "uniform float center_x;\n"
850 "uniform float center_y;\n"
851 "uniform float half_gradient_size;\n"
852 "uniform float sin_angle;\n"
853 "uniform float cos_angle;\n"
854 "uniform vec4 out_color;\n"
855 "uniform vec4 in_color;\n"
856 "uniform float in_radius;\n"
857 "uniform float out_radius;\n"
858 "uniform float radius_diff;\n"
862 " vec2 out_coord = gl_TexCoord[0].st;\n";
864 const char *linear_shape =
865 " vec2 in_coord = vec2(out_coord.x - half_w, half_h - out_coord.y);\n"
866 " float mag = half_gradient_size - \n"
867 " (in_coord.x * sin_angle + in_coord.y * cos_angle);\n";
869 const char *radial_shape =
870 " vec2 in_coord = vec2(out_coord.x - center_x, out_coord.y - center_y);\n"
871 " float mag = length(vec2(in_coord.x, in_coord.y));\n";
873 // No clamp function in NVidia
874 const char *linear_rate =
875 " mag = min(max(mag, in_radius), out_radius);\n"
876 " float opacity = (mag - in_radius) / radius_diff;\n";
878 // NVidia warns about exp, but exp is in the GLSL spec.
879 const char *log_rate =
880 " mag = max(mag, in_radius);\n"
881 " float opacity = 1.0 - \n"
882 " exp(1.0 * -(mag - in_radius) / radius_diff);\n";
884 const char *square_rate =
885 " mag = min(max(mag, in_radius), out_radius);\n"
886 " float opacity = pow((mag - in_radius) / radius_diff, 2.0);\n"
887 " opacity = min(opacity, 1.0);\n";
889 const char *tail_frag =
890 " vec4 color = mix(in_color, out_color, opacity);\n"
891 " vec4 bg_color = texture2D(tex, out_coord);\n"
892 " gl_FragColor.rgb = mix(bg_color.rgb, color.rgb, color.a);\n"
893 " gl_FragColor.a = max(bg_color.a, color.a);\n"
897 const char *shader_stack[5] = { 0, 0, 0, 0, 0 };
898 shader_stack[0] = head_frag;
902 case GradientConfig::LINEAR:
903 shader_stack[1] = linear_shape;
907 shader_stack[1] = radial_shape;
913 case GradientConfig::LINEAR:
914 shader_stack[2] = linear_rate;
916 case GradientConfig::LOG:
917 shader_stack[2] = log_rate;
919 case GradientConfig::SQUARE:
920 shader_stack[2] = square_rate;
924 shader_stack[3] = tail_frag;
925 // Force frame to create texture without copying to it if full alpha.
926 if(config.in_a >= 0xff &&
927 config.out_a >= 0xff)
928 get_output()->set_opengl_state(VFrame::TEXTURE);
929 get_output()->to_texture();
930 get_output()->enable_opengl();
931 get_output()->init_screen();
932 get_output()->bind_texture(0);
934 unsigned int frag = VFrame::make_shader(0,
944 float w = get_output()->get_w();
945 float h = get_output()->get_h();
946 float texture_w = get_output()->get_texture_w();
947 float texture_h = get_output()->get_texture_h();
948 glUniform1i(glGetUniformLocation(frag, "tex"), 0);
949 glUniform1f(glGetUniformLocation(frag, "half_w"), w / 2 / texture_w);
950 glUniform1f(glGetUniformLocation(frag, "half_h"), h / 2 / texture_h);
951 if(config.shape == GradientConfig::LINEAR)
953 glUniform1f(glGetUniformLocation(frag, "center_x"),
955 glUniform1f(glGetUniformLocation(frag, "center_y"),
960 glUniform1f(glGetUniformLocation(frag, "center_x"),
961 (float)config.center_x * w / 100 / texture_w);
962 glUniform1f(glGetUniformLocation(frag, "center_y"),
963 (float)config.center_y * h / 100 / texture_h);
965 float gradient_size = hypotf(w / texture_w, h / texture_h);
966 glUniform1f(glGetUniformLocation(frag, "half_gradient_size"),
968 glUniform1f(glGetUniformLocation(frag, "sin_angle"),
969 sin(config.angle * (M_PI / 180)));
970 glUniform1f(glGetUniformLocation(frag, "cos_angle"),
971 cos(config.angle * (M_PI / 180)));
972 float in_radius = (float)config.in_radius / 100 * gradient_size;
973 glUniform1f(glGetUniformLocation(frag, "in_radius"), in_radius);
974 float out_radius = (float)config.out_radius / 100 * gradient_size;
975 glUniform1f(glGetUniformLocation(frag, "out_radius"), out_radius);
976 glUniform1f(glGetUniformLocation(frag, "radius_diff"),
977 out_radius - in_radius);
979 switch(get_output()->get_color_model())
984 float in1, in2, in3, in4;
985 float out1, out2, out3, out4;
986 YUV::rgb_to_yuv_f((float)config.in_r / 0xff,
987 (float)config.in_g / 0xff,
988 (float)config.in_b / 0xff,
992 in4 = (float)config.in_a / 0xff;
993 YUV::rgb_to_yuv_f((float)config.out_r / 0xff,
994 (float)config.out_g / 0xff,
995 (float)config.out_b / 0xff,
1003 out4 = (float)config.out_a / 0xff;
1004 glUniform4f(glGetUniformLocation(frag, "out_color"),
1005 out1, out2, out3, out4);
1006 glUniform4f(glGetUniformLocation(frag, "in_color"),
1007 in1, in2, in3, in4);
1012 glUniform4f(glGetUniformLocation(frag, "out_color"),
1013 (float)config.out_r / 0xff,
1014 (float)config.out_g / 0xff,
1015 (float)config.out_b / 0xff,
1016 (float)config.out_a / 0xff);
1017 glUniform4f(glGetUniformLocation(frag, "in_color"),
1018 (float)config.in_r / 0xff,
1019 (float)config.in_g / 0xff,
1020 (float)config.in_b / 0xff,
1021 (float)config.in_a / 0xff);
1026 get_output()->draw_texture();
1028 get_output()->set_opengl_state(VFrame::SCREEN);
1044 GradientPackage::GradientPackage()
1052 GradientUnit::GradientUnit(GradientServer *server, GradientMain *plugin)
1053 : LoadClient(server)
1055 this->plugin = plugin;
1056 this->server = server;
1062 static float calculate_opacity(float mag,
1063 float in_radius, float out_radius, int rate)
1065 float opacity = 0.0;
1068 case GradientConfig::LINEAR:
1072 if(mag >= out_radius)
1075 opacity = (float)(mag - in_radius) / (out_radius - in_radius);
1078 case GradientConfig::LOG:
1082 // Let this one decay beyond out_radius
1083 opacity = 1 - exp(1.0 * -(float)(mag - in_radius) /
1084 (out_radius - in_radius));
1087 case GradientConfig::SQUARE:
1091 if(mag >= out_radius)
1094 opacity = powf((float)(mag - in_radius) /
1095 (out_radius - in_radius), 2.0);
1098 CLAMP(opacity, 0.0, 1.0);
1102 #define CREATE_GRADIENT(type, temp, components, max) \
1104 /* Synthesize linear gradient for lookups */ \
1106 r_table = malloc(sizeof(type) * gradient_size); \
1107 g_table = malloc(sizeof(type) * gradient_size); \
1108 b_table = malloc(sizeof(type) * gradient_size); \
1109 a_table = malloc(sizeof(type) * gradient_size); \
1111 for(int i = 0; i < gradient_size; i++) \
1113 float opacity = calculate_opacity(i, in_radius, out_radius, plugin->config.rate); \
1114 float transparency; \
1116 transparency = 1.0 - opacity; \
1117 ((type*)r_table)[i] = (type)(out1 * opacity + in1 * transparency); \
1118 ((type*)g_table)[i] = (type)(out2 * opacity + in2 * transparency); \
1119 ((type*)b_table)[i] = (type)(out3 * opacity + in3 * transparency); \
1120 ((type*)a_table)[i] = (type)(out4 * opacity + in4 * transparency); \
1123 for(int i = pkg->y1; i < pkg->y2; i++) \
1125 type *gradient_row = (type*)plugin->gradient->get_rows()[i]; \
1126 type *out_row = (type*)plugin->get_output()->get_rows()[i]; \
1128 switch(plugin->config.shape) \
1130 case GradientConfig::LINEAR: \
1131 for(int j = 0; j < w; j++) \
1133 int x = j - half_w; \
1134 int y = -(i - half_h); \
1136 /* Rotate by effect angle */ \
1137 int mag = (int)(gradient_size / 2 - \
1138 (x * sin_angle + y * cos_angle) + \
1141 /* Get gradient value from these coords */ \
1143 if(sizeof(type) == 4) \
1145 float opacity = calculate_opacity(mag, \
1148 plugin->config.rate); \
1149 float transparency = 1.0 - opacity; \
1150 gradient_row[0] = (type)(out1 * opacity + in1 * transparency); \
1151 gradient_row[1] = (type)(out2 * opacity + in2 * transparency); \
1152 gradient_row[2] = (type)(out3 * opacity + in3 * transparency); \
1153 if(components == 4) gradient_row[3] = (type)(out4 * opacity + in4 * transparency); \
1158 gradient_row[0] = out1; \
1159 gradient_row[1] = out2; \
1160 gradient_row[2] = out3; \
1161 if(components == 4) gradient_row[3] = out4; \
1164 if(mag >= gradient_size) \
1166 gradient_row[0] = in1; \
1167 gradient_row[1] = in2; \
1168 gradient_row[2] = in3; \
1169 if(components == 4) gradient_row[3] = in4; \
1173 gradient_row[0] = ((type*)r_table)[mag]; \
1174 gradient_row[1] = ((type*)g_table)[mag]; \
1175 gradient_row[2] = ((type*)b_table)[mag]; \
1176 if(components == 4) gradient_row[3] = ((type*)a_table)[mag]; \
1179 /* Overlay mixed colormodels onto output */ \
1180 if(gradient_cmodel != output_cmodel) \
1182 temp opacity = gradient_row[3]; \
1183 temp transparency = max - opacity; \
1184 out_row[0] = (transparency * out_row[0] + opacity * gradient_row[0]) / max; \
1185 out_row[1] = (transparency * out_row[1] + opacity * gradient_row[1]) / max; \
1186 out_row[2] = (transparency * out_row[2] + opacity * gradient_row[2]) / max; \
1190 gradient_row += components; \
1194 case GradientConfig::RADIAL: \
1195 for(int j = 0; j < w; j++) \
1197 double x = j - center_x; \
1198 double y = i - center_y; \
1199 double magnitude = hypot(x, y); \
1200 int mag = (int)magnitude; \
1201 if(sizeof(type) == 4) \
1203 float opacity = calculate_opacity(mag, \
1206 plugin->config.rate); \
1207 float transparency = 1.0 - opacity; \
1208 gradient_row[0] = (type)(out1 * opacity + in1 * transparency); \
1209 gradient_row[1] = (type)(out2 * opacity + in2 * transparency); \
1210 gradient_row[2] = (type)(out3 * opacity + in3 * transparency); \
1211 if(components == 4) gradient_row[3] = (type)(out4 * opacity + in4 * transparency); \
1215 gradient_row[0] = ((type*)r_table)[mag]; \
1216 gradient_row[1] = ((type*)g_table)[mag]; \
1217 gradient_row[2] = ((type*)b_table)[mag]; \
1218 if(components == 4) gradient_row[3] = ((type*)a_table)[mag]; \
1221 /* Overlay mixed colormodels onto output */ \
1222 if(gradient_cmodel != output_cmodel) \
1224 temp opacity = gradient_row[3]; \
1225 temp transparency = max - opacity; \
1226 out_row[0] = (transparency * out_row[0] + opacity * gradient_row[0]) / max; \
1227 out_row[1] = (transparency * out_row[1] + opacity * gradient_row[1]) / max; \
1228 out_row[2] = (transparency * out_row[2] + opacity * gradient_row[2]) / max; \
1232 gradient_row += components; \
1239 void GradientUnit::process_package(LoadPackage *package)
1241 GradientPackage *pkg = (GradientPackage*)package;
1242 int h = plugin->input->get_h();
1243 int w = plugin->input->get_w();
1246 int gradient_size = (int)(ceil(hypot(w, h)));
1247 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
1248 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
1249 double sin_angle = sin(plugin->config.angle * (M_PI / 180));
1250 double cos_angle = cos(plugin->config.angle * (M_PI / 180));
1251 double center_x = plugin->config.center_x * w / 100;
1252 double center_y = plugin->config.center_y * h / 100;
1257 int gradient_cmodel = plugin->gradient->get_color_model();
1258 int output_cmodel = plugin->get_output()->get_color_model();
1260 if(in_radius > out_radius)
1262 in_radius ^= out_radius;
1263 out_radius ^= in_radius;
1264 in_radius ^= out_radius;
1268 switch(gradient_cmodel)
1272 int in1 = plugin->config.in_r;
1273 int in2 = plugin->config.in_g;
1274 int in3 = plugin->config.in_b;
1275 int in4 = plugin->config.in_a;
1276 int out1 = plugin->config.out_r;
1277 int out2 = plugin->config.out_g;
1278 int out3 = plugin->config.out_b;
1279 int out4 = plugin->config.out_a;
1280 CREATE_GRADIENT(unsigned char, int, 3, 0xff)
1286 int in1 = plugin->config.in_r;
1287 int in2 = plugin->config.in_g;
1288 int in3 = plugin->config.in_b;
1289 int in4 = plugin->config.in_a;
1290 int out1 = plugin->config.out_r;
1291 int out2 = plugin->config.out_g;
1292 int out3 = plugin->config.out_b;
1293 int out4 = plugin->config.out_a;
1294 CREATE_GRADIENT(unsigned char, int, 4, 0xff)
1300 float in1 = (float)plugin->config.in_r / 0xff;
1301 float in2 = (float)plugin->config.in_g / 0xff;
1302 float in3 = (float)plugin->config.in_b / 0xff;
1303 float in4 = (float)plugin->config.in_a / 0xff;
1304 float out1 = (float)plugin->config.out_r / 0xff;
1305 float out2 = (float)plugin->config.out_g / 0xff;
1306 float out3 = (float)plugin->config.out_b / 0xff;
1307 float out4 = (float)plugin->config.out_a / 0xff;
1308 CREATE_GRADIENT(float, float, 3, 1.0)
1314 float in1 = (float)plugin->config.in_r / 0xff;
1315 float in2 = (float)plugin->config.in_g / 0xff;
1316 float in3 = (float)plugin->config.in_b / 0xff;
1317 float in4 = (float)plugin->config.in_a / 0xff;
1318 float out1 = (float)plugin->config.out_r / 0xff;
1319 float out2 = (float)plugin->config.out_g / 0xff;
1320 float out3 = (float)plugin->config.out_b / 0xff;
1321 float out4 = (float)plugin->config.out_a / 0xff;
1322 CREATE_GRADIENT(float, float, 4, 1.0)
1328 int in1, in2, in3, in4;
1329 int out1, out2, out3, out4;
1330 yuv.rgb_to_yuv_8(plugin->config.in_r,
1331 plugin->config.in_g,
1332 plugin->config.in_b,
1336 in4 = plugin->config.in_a;
1337 yuv.rgb_to_yuv_8(plugin->config.out_r,
1338 plugin->config.out_g,
1339 plugin->config.out_b,
1343 out4 = plugin->config.out_a;
1344 CREATE_GRADIENT(unsigned char, int, 3, 0xff)
1350 int in1, in2, in3, in4;
1351 int out1, out2, out3, out4;
1352 yuv.rgb_to_yuv_8(plugin->config.in_r,
1353 plugin->config.in_g,
1354 plugin->config.in_b,
1358 in4 = plugin->config.in_a;
1359 yuv.rgb_to_yuv_8(plugin->config.out_r,
1360 plugin->config.out_g,
1361 plugin->config.out_b,
1365 out4 = plugin->config.out_a;
1366 CREATE_GRADIENT(unsigned char, int, 4, 0xff)
1371 if(r_table) free(r_table);
1372 if(g_table) free(g_table);
1373 if(b_table) free(b_table);
1374 if(a_table) free(a_table);
1382 GradientServer::GradientServer(GradientMain *plugin,
1385 : LoadServer(total_clients, total_packages)
1387 this->plugin = plugin;
1390 void GradientServer::init_packages()
1392 for(int i = 0; i < get_total_packages(); i++)
1394 GradientPackage *package = (GradientPackage*)get_package(i);
1395 package->y1 = plugin->input->get_h() *
1397 get_total_packages();
1398 package->y2 = plugin->input->get_h() *
1400 get_total_packages();
1404 LoadClient* GradientServer::new_client()
1406 return new GradientUnit(this, plugin);
1409 LoadPackage* GradientServer::new_package()
1411 return new GradientPackage;