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()
60 shape = GradientConfig::LINEAR;
61 rate = GradientConfig::LINEAR;
66 int GradientConfig::equivalent(GradientConfig &that)
68 return (EQUIV(angle, that.angle) &&
69 EQUIV(in_radius, that.in_radius) &&
70 EQUIV(out_radius, that.out_radius) &&
75 out_r == that.out_r &&
76 out_g == that.out_g &&
77 out_b == that.out_b &&
78 out_a == that.out_a &&
79 shape == that.shape &&
81 EQUIV(center_x, that.center_x) &&
82 EQUIV(center_y, that.center_y));
85 void GradientConfig::copy_from(GradientConfig &that)
88 in_radius = that.in_radius;
89 out_radius = that.out_radius;
100 center_x = that.center_x;
101 center_y = that.center_y;
104 void GradientConfig::interpolate(GradientConfig &prev,
105 GradientConfig &next,
110 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
111 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
114 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale);
115 this->in_radius = (int)(prev.in_radius * prev_scale + next.in_radius * next_scale);
116 this->out_radius = (int)(prev.out_radius * prev_scale + next.out_radius * next_scale);
117 in_r = (int)(prev.in_r * prev_scale + next.in_r * next_scale);
118 in_g = (int)(prev.in_g * prev_scale + next.in_g * next_scale);
119 in_b = (int)(prev.in_b * prev_scale + next.in_b * next_scale);
120 in_a = (int)(prev.in_a * prev_scale + next.in_a * next_scale);
121 out_r = (int)(prev.out_r * prev_scale + next.out_r * next_scale);
122 out_g = (int)(prev.out_g * prev_scale + next.out_g * next_scale);
123 out_b = (int)(prev.out_b * prev_scale + next.out_b * next_scale);
124 out_a = (int)(prev.out_a * prev_scale + next.out_a * next_scale);
127 center_x = prev.center_x * prev_scale + next.center_x * next_scale;
128 center_y = prev.center_y * prev_scale + next.center_y * next_scale;
131 int GradientConfig::get_in_color()
133 int result = (in_r << 16) | (in_g << 8) | (in_b);
137 int GradientConfig::get_out_color()
139 int result = (out_r << 16) | (out_g << 8) | (out_b);
156 GradientWindow::GradientWindow(GradientMain *plugin)
157 : PluginClientWindow(plugin,
164 this->plugin = plugin;
173 GradientWindow::~GradientWindow()
175 delete in_color_thread;
176 delete out_color_thread;
179 void GradientWindow::create_objects()
181 int margin = plugin->get_theme()->widget_border;
185 add_subwindow(title = new BC_Title(x, y, _("Shape:")));
186 add_subwindow(shape = new GradientShape(plugin,
188 x + title->get_w() + margin,
190 shape->create_objects();
191 y += shape->get_h() + margin;
194 y += BC_Pot::calculate_h() + margin;
196 add_subwindow(title = new BC_Title(x, y, _("Rate:")));
197 add_subwindow(rate = new GradientRate(plugin,
198 x + title->get_w() + margin,
200 rate->create_objects();
201 y += rate->get_h() + margin;
207 add_subwindow(title1 = new BC_Title(x, y, _("Inner radius:")));
209 y += BC_Slider::get_span(0) + margin;
212 add_subwindow(title2 = new BC_Title(x, y, _("Outer radius:")));
215 x += MAX(title1->get_w(), title2->get_w()) + margin;
217 add_subwindow(in_radius = new GradientInRadius(plugin, x, y));
218 y += in_radius->get_h() + margin;
220 add_subwindow(out_radius = new GradientOutRadius(plugin, x, y));
221 y += out_radius->get_h() + margin;
225 add_subwindow(in_color = new GradientInColorButton(plugin, this, x, y));
226 y += COLOR_H + margin;
229 add_subwindow(out_color = new GradientOutColorButton(plugin, this, x, y));
230 x += MAX(in_color->get_w(), out_color->get_w()) + margin;
235 y += COLOR_H + margin;
238 in_color_thread = new GradientInColorThread(plugin, this);
239 out_color_thread = new GradientOutColorThread(plugin, this);
244 draw_3d_border(in_color_x - 2,
250 draw_3d_border(out_color_x - 2,
259 void GradientWindow::update_shape()
261 int x = shape_x, y = shape_y;
263 if(plugin->config.shape == GradientConfig::LINEAR)
265 delete center_x_title;
266 delete center_y_title;
276 add_subwindow(angle_title = new BC_Title(x, y, _("Angle:")));
277 add_subwindow(angle = new GradientAngle(plugin, x + angle_title->get_w() + 10, y));
288 add_subwindow(center_x_title = new BC_Title(x, y, _("Center X:")));
289 add_subwindow(center_x = new GradientCenterX(plugin,
290 x + center_x_title->get_w() + 10,
292 x += center_x_title->get_w() + 10 + center_x->get_w() + 10;
293 add_subwindow(center_y_title = new BC_Title(x, y, _("Center Y:")));
294 add_subwindow(center_y = new GradientCenterY(plugin,
295 x + center_y_title->get_w() + 10,
305 void GradientWindow::update_in_color()
307 //printf("GradientWindow::update_in_color 1 %08x\n", plugin->config.get_in_color());
308 set_color(plugin->config.get_in_color());
309 draw_box(in_color_x, in_color_y, COLOR_W, COLOR_H);
310 flash(in_color_x, in_color_y, COLOR_W, COLOR_H);
313 void GradientWindow::update_out_color()
315 //printf("GradientWindow::update_out_color 1 %08x\n", plugin->config.get_in_color());
316 set_color(plugin->config.get_out_color());
317 draw_box(out_color_x, out_color_y, COLOR_W, COLOR_H);
318 flash(out_color_x, out_color_y, COLOR_W, COLOR_H);
321 void GradientWindow::done_event(int result)
323 in_color_thread->close_window();
324 out_color_thread->close_window();
335 GradientShape::GradientShape(GradientMain *plugin,
339 : BC_PopupMenu(x, y, 100, to_text(plugin->config.shape), 1)
341 this->plugin = plugin;
344 void GradientShape::create_objects()
346 add_item(new BC_MenuItem(to_text(GradientConfig::LINEAR)));
347 add_item(new BC_MenuItem(to_text(GradientConfig::RADIAL)));
349 char* GradientShape::to_text(int shape)
353 case GradientConfig::LINEAR:
359 int GradientShape::from_text(char *text)
361 if(!strcmp(text, to_text(GradientConfig::LINEAR)))
362 return GradientConfig::LINEAR;
363 return GradientConfig::RADIAL;
365 int GradientShape::handle_event()
367 plugin->config.shape = from_text(get_text());
369 plugin->send_configure_change();
376 GradientCenterX::GradientCenterX(GradientMain *plugin, int x, int y)
377 : BC_FPot(x, y, plugin->config.center_x, 0, 100)
379 this->plugin = plugin;
381 int GradientCenterX::handle_event()
383 plugin->config.center_x = get_value();
384 plugin->send_configure_change();
390 GradientCenterY::GradientCenterY(GradientMain *plugin, int x, int y)
391 : BC_FPot(x, y, plugin->config.center_y, 0, 100)
393 this->plugin = plugin;
396 int GradientCenterY::handle_event()
398 plugin->config.center_y = get_value();
399 plugin->send_configure_change();
406 GradientAngle::GradientAngle(GradientMain *plugin, int x, int y)
409 plugin->config.angle,
413 this->plugin = plugin;
416 int GradientAngle::handle_event()
418 plugin->config.angle = get_value();
419 plugin->send_configure_change();
424 GradientRate::GradientRate(GradientMain *plugin, int x, int y)
428 to_text(plugin->config.rate),
431 this->plugin = plugin;
433 void GradientRate::create_objects()
435 add_item(new BC_MenuItem(to_text(GradientConfig::LINEAR)));
436 add_item(new BC_MenuItem(to_text(GradientConfig::LOG)));
437 add_item(new BC_MenuItem(to_text(GradientConfig::SQUARE)));
439 char* GradientRate::to_text(int shape)
443 case GradientConfig::LINEAR:
445 case GradientConfig::LOG:
451 int GradientRate::from_text(char *text)
453 if(!strcmp(text, to_text(GradientConfig::LINEAR)))
454 return GradientConfig::LINEAR;
455 if(!strcmp(text, to_text(GradientConfig::LOG)))
456 return GradientConfig::LOG;
457 return GradientConfig::SQUARE;
459 int GradientRate::handle_event()
461 plugin->config.rate = from_text(get_text());
462 plugin->send_configure_change();
468 GradientInRadius::GradientInRadius(GradientMain *plugin, int x, int y)
476 (float)plugin->config.in_radius)
478 this->plugin = plugin;
481 int GradientInRadius::handle_event()
483 plugin->config.in_radius = get_value();
484 plugin->send_configure_change();
489 GradientOutRadius::GradientOutRadius(GradientMain *plugin, int x, int y)
497 (float)plugin->config.out_radius)
499 this->plugin = plugin;
502 int GradientOutRadius::handle_event()
504 plugin->config.out_radius = get_value();
505 plugin->send_configure_change();
509 GradientInColorButton::GradientInColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
510 : BC_GenericButton(x, y, _("Inner color:"))
512 this->plugin = plugin;
513 this->window = window;
516 int GradientInColorButton::handle_event()
518 window->in_color_thread->start_window(
519 plugin->config.get_in_color(),
520 plugin->config.in_a);
525 GradientOutColorButton::GradientOutColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
526 : BC_GenericButton(x, y, _("Outer color:"))
528 this->plugin = plugin;
529 this->window = window;
532 int GradientOutColorButton::handle_event()
534 window->out_color_thread->start_window(
535 plugin->config.get_out_color(),
536 plugin->config.out_a);
542 GradientInColorThread::GradientInColorThread(GradientMain *plugin,
543 GradientWindow *window)
544 : ColorPicker(1, _("Inner color"))
546 this->plugin = plugin;
547 this->window = window;
550 int GradientInColorThread::handle_new_color(int output, int alpha)
552 plugin->config.in_r = (output & 0xff0000) >> 16;
553 plugin->config.in_g = (output & 0xff00) >> 8;
554 plugin->config.in_b = (output & 0xff);
555 plugin->config.in_a = alpha;
557 window->lock_window("GradientInColorThread::handle_new_color");
558 window->update_in_color();
560 window->unlock_window();
561 plugin->send_configure_change();
562 // printf("GradientInColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
563 // plugin->config.in_r,
564 // plugin->config.in_g,
565 // plugin->config.in_b,
566 // plugin->config.in_a,
567 // plugin->config.out_r,
568 // plugin->config.out_g,
569 // plugin->config.out_b,
570 // plugin->config.out_a);
577 GradientOutColorThread::GradientOutColorThread(GradientMain *plugin,
578 GradientWindow *window)
579 : ColorPicker(1, _("Outer color"))
581 this->plugin = plugin;
582 this->window = window;
585 int GradientOutColorThread::handle_new_color(int output, int alpha)
587 plugin->config.out_r = (output & 0xff0000) >> 16;
588 plugin->config.out_g = (output & 0xff00) >> 8;
589 plugin->config.out_b = (output & 0xff);
590 plugin->config.out_a = alpha;
591 window->lock_window("GradientOutColorThread::handle_new_color");
592 window->update_out_color();
594 window->unlock_window();
595 plugin->send_configure_change();
596 // printf("GradientOutColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
597 // plugin->config.in_r,
598 // plugin->config.in_g,
599 // plugin->config.in_b,
600 // plugin->config.in_a,
601 // plugin->config.out_r,
602 // plugin->config.out_g,
603 // plugin->config.out_b,
604 // plugin->config.out_a);
619 GradientMain::GradientMain(PluginServer *server)
620 : PluginVClient(server)
623 need_reconfigure = 1;
629 GradientMain::~GradientMain()
633 if(gradient) delete gradient;
634 if(engine) delete engine;
635 if(overlayer) delete overlayer;
638 const char* GradientMain::plugin_title() { return _("Gradient"); }
639 int GradientMain::is_realtime() { return 1; }
642 NEW_WINDOW_MACRO(GradientMain, GradientWindow)
644 LOAD_CONFIGURATION_MACRO(GradientMain, GradientConfig)
646 int GradientMain::is_synthesis()
652 int GradientMain::process_buffer(VFrame *frame,
653 int64_t start_position,
657 this->output = frame;
658 need_reconfigure |= load_configuration();
660 int need_alpha = config.in_a != 0xff || config.out_a != 0xff;
667 if(get_use_opengl()) return run_opengl();
669 int gradient_cmodel = input->get_color_model();
670 if(need_alpha && BC_CModels::components(gradient_cmodel) == 3)
672 switch(gradient_cmodel)
675 gradient_cmodel = BC_RGBA8888;
678 gradient_cmodel = BC_RGBA_FLOAT;
681 gradient_cmodel = BC_YUVA8888;
686 if(gradient && gradient->get_color_model() != gradient_cmodel)
692 if(!gradient) gradient = new VFrame(0,
699 if(!engine) engine = new GradientServer(this,
700 get_project_smp() + 1,
701 get_project_smp() + 1);
702 engine->process_packages();
704 // Use overlay routine in GradientServer if mismatched colormodels
705 if(gradient->get_color_model() == output->get_color_model())
707 if(!overlayer) overlayer = new OverlayFrame(get_project_smp() + 1);
708 overlayer->overlay(output,
728 void GradientMain::update_gui()
732 if(load_configuration())
734 ((GradientWindow*)thread->window)->lock_window("GradientMain::update_gui");
735 ((GradientWindow*)thread->window)->rate->set_text(GradientRate::to_text(config.rate));
736 ((GradientWindow*)thread->window)->in_radius->update(config.in_radius);
737 ((GradientWindow*)thread->window)->out_radius->update(config.out_radius);
738 ((GradientWindow*)thread->window)->shape->set_text(GradientShape::to_text(config.shape));
739 if(((GradientWindow*)thread->window)->angle)
740 ((GradientWindow*)thread->window)->angle->update(config.angle);
741 if(((GradientWindow*)thread->window)->center_x)
742 ((GradientWindow*)thread->window)->center_x->update(config.center_x);
743 if(((GradientWindow*)thread->window)->center_y)
744 ((GradientWindow*)thread->window)->center_y->update(config.center_y);
745 ((GradientWindow*)thread->window)->update_in_color();
746 ((GradientWindow*)thread->window)->update_out_color();
747 ((GradientWindow*)thread->window)->update_shape();
748 ((GradientWindow*)thread->window)->unlock_window();
749 ((GradientWindow*)thread->window)->in_color_thread->update_gui(config.get_in_color(), config.in_a);
750 ((GradientWindow*)thread->window)->out_color_thread->update_gui(config.get_out_color(), config.out_a);
758 void GradientMain::save_data(KeyFrame *keyframe)
762 // cause data to be stored directly in text
763 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
764 output.tag.set_title("GRADIENT");
766 output.tag.set_property("ANGLE", config.angle);
767 output.tag.set_property("IN_RADIUS", config.in_radius);
768 output.tag.set_property("OUT_RADIUS", config.out_radius);
769 output.tag.set_property("IN_R", config.in_r);
770 output.tag.set_property("IN_G", config.in_g);
771 output.tag.set_property("IN_B", config.in_b);
772 output.tag.set_property("IN_A", config.in_a);
773 output.tag.set_property("OUT_R", config.out_r);
774 output.tag.set_property("OUT_G", config.out_g);
775 output.tag.set_property("OUT_B", config.out_b);
776 output.tag.set_property("OUT_A", config.out_a);
777 output.tag.set_property("SHAPE", config.shape);
778 output.tag.set_property("RATE", config.rate);
779 output.tag.set_property("CENTER_X", config.center_x);
780 output.tag.set_property("CENTER_Y", config.center_y);
782 output.tag.set_title("/GRADIENT");
784 output.append_newline();
785 output.terminate_string();
788 void GradientMain::read_data(KeyFrame *keyframe)
792 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
798 result = input.read_tag();
802 if(input.tag.title_is("GRADIENT"))
804 config.angle = input.tag.get_property("ANGLE", config.angle);
805 config.rate = input.tag.get_property("RATE", config.rate);
806 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
807 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
808 config.in_r = input.tag.get_property("IN_R", config.in_r);
809 config.in_g = input.tag.get_property("IN_G", config.in_g);
810 config.in_b = input.tag.get_property("IN_B", config.in_b);
811 config.in_a = input.tag.get_property("IN_A", config.in_a);
812 config.out_r = input.tag.get_property("OUT_R", config.out_r);
813 config.out_g = input.tag.get_property("OUT_G", config.out_g);
814 config.out_b = input.tag.get_property("OUT_B", config.out_b);
815 config.out_a = input.tag.get_property("OUT_A", config.out_a);
816 config.shape = input.tag.get_property("SHAPE", config.shape);
817 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
818 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
824 int GradientMain::handle_opengl()
827 const char *head_frag =
828 "uniform sampler2D tex;\n"
829 "uniform float half_w;\n"
830 "uniform float half_h;\n"
831 "uniform float center_x;\n"
832 "uniform float center_y;\n"
833 "uniform float half_gradient_size;\n"
834 "uniform float sin_angle;\n"
835 "uniform float cos_angle;\n"
836 "uniform vec4 out_color;\n"
837 "uniform vec4 in_color;\n"
838 "uniform float in_radius;\n"
839 "uniform float out_radius;\n"
840 "uniform float radius_diff;\n"
844 " vec2 out_coord = gl_TexCoord[0].st;\n";
846 const char *linear_shape =
847 " vec2 in_coord = vec2(out_coord.x - half_w, half_h - out_coord.y);\n"
848 " float mag = half_gradient_size - \n"
849 " (in_coord.x * sin_angle + in_coord.y * cos_angle);\n";
851 const char *radial_shape =
852 " vec2 in_coord = vec2(out_coord.x - center_x, out_coord.y - center_y);\n"
853 " float mag = length(vec2(in_coord.x, in_coord.y));\n";
855 // No clamp function in NVidia
856 const char *linear_rate =
857 " mag = min(max(mag, in_radius), out_radius);\n"
858 " float opacity = (mag - in_radius) / radius_diff;\n";
860 // NVidia warns about exp, but exp is in the GLSL spec.
861 const char *log_rate =
862 " mag = max(mag, in_radius);\n"
863 " float opacity = 1.0 - \n"
864 " exp(1.0 * -(mag - in_radius) / radius_diff);\n";
866 const char *square_rate =
867 " mag = min(max(mag, in_radius), out_radius);\n"
868 " float opacity = pow((mag - in_radius) / radius_diff, 2.0);\n"
869 " opacity = min(opacity, 1.0);\n";
871 const char *tail_frag =
872 " vec4 color = mix(in_color, out_color, opacity);\n"
873 " vec4 bg_color = texture2D(tex, out_coord);\n"
874 " gl_FragColor.rgb = mix(bg_color.rgb, color.rgb, color.a);\n"
875 " gl_FragColor.a = max(bg_color.a, color.a);\n"
879 const char *shader_stack[5] = { 0, 0, 0, 0, 0 };
880 shader_stack[0] = head_frag;
884 case GradientConfig::LINEAR:
885 shader_stack[1] = linear_shape;
889 shader_stack[1] = radial_shape;
895 case GradientConfig::LINEAR:
896 shader_stack[2] = linear_rate;
898 case GradientConfig::LOG:
899 shader_stack[2] = log_rate;
901 case GradientConfig::SQUARE:
902 shader_stack[2] = square_rate;
906 shader_stack[3] = tail_frag;
907 // Force frame to create texture without copying to it if full alpha.
908 if(config.in_a >= 0xff &&
909 config.out_a >= 0xff)
910 get_output()->set_opengl_state(VFrame::TEXTURE);
911 get_output()->to_texture();
912 get_output()->enable_opengl();
913 get_output()->init_screen();
914 get_output()->bind_texture(0);
916 unsigned int frag = VFrame::make_shader(0,
926 float w = get_output()->get_w();
927 float h = get_output()->get_h();
928 float texture_w = get_output()->get_texture_w();
929 float texture_h = get_output()->get_texture_h();
930 glUniform1i(glGetUniformLocation(frag, "tex"), 0);
931 glUniform1f(glGetUniformLocation(frag, "half_w"), w / 2 / texture_w);
932 glUniform1f(glGetUniformLocation(frag, "half_h"), h / 2 / texture_h);
933 if(config.shape == GradientConfig::LINEAR)
935 glUniform1f(glGetUniformLocation(frag, "center_x"),
937 glUniform1f(glGetUniformLocation(frag, "center_y"),
942 glUniform1f(glGetUniformLocation(frag, "center_x"),
943 (float)config.center_x * w / 100 / texture_w);
944 glUniform1f(glGetUniformLocation(frag, "center_y"),
945 (float)config.center_y * h / 100 / texture_h);
947 float gradient_size = hypotf(w / texture_w, h / texture_h);
948 glUniform1f(glGetUniformLocation(frag, "half_gradient_size"),
950 glUniform1f(glGetUniformLocation(frag, "sin_angle"),
951 sin(config.angle * (M_PI / 180)));
952 glUniform1f(glGetUniformLocation(frag, "cos_angle"),
953 cos(config.angle * (M_PI / 180)));
954 float in_radius = (float)config.in_radius / 100 * gradient_size;
955 glUniform1f(glGetUniformLocation(frag, "in_radius"), in_radius);
956 float out_radius = (float)config.out_radius / 100 * gradient_size;
957 glUniform1f(glGetUniformLocation(frag, "out_radius"), out_radius);
958 glUniform1f(glGetUniformLocation(frag, "radius_diff"),
959 out_radius - in_radius);
961 switch(get_output()->get_color_model())
966 float in1, in2, in3, in4;
967 float out1, out2, out3, out4;
968 YUV::rgb_to_yuv_f((float)config.in_r / 0xff,
969 (float)config.in_g / 0xff,
970 (float)config.in_b / 0xff,
974 in4 = (float)config.in_a / 0xff;
975 YUV::rgb_to_yuv_f((float)config.out_r / 0xff,
976 (float)config.out_g / 0xff,
977 (float)config.out_b / 0xff,
985 out4 = (float)config.out_a / 0xff;
986 glUniform4f(glGetUniformLocation(frag, "out_color"),
987 out1, out2, out3, out4);
988 glUniform4f(glGetUniformLocation(frag, "in_color"),
994 glUniform4f(glGetUniformLocation(frag, "out_color"),
995 (float)config.out_r / 0xff,
996 (float)config.out_g / 0xff,
997 (float)config.out_b / 0xff,
998 (float)config.out_a / 0xff);
999 glUniform4f(glGetUniformLocation(frag, "in_color"),
1000 (float)config.in_r / 0xff,
1001 (float)config.in_g / 0xff,
1002 (float)config.in_b / 0xff,
1003 (float)config.in_a / 0xff);
1008 get_output()->draw_texture();
1010 get_output()->set_opengl_state(VFrame::SCREEN);
1026 GradientPackage::GradientPackage()
1034 GradientUnit::GradientUnit(GradientServer *server, GradientMain *plugin)
1035 : LoadClient(server)
1037 this->plugin = plugin;
1038 this->server = server;
1044 static float calculate_opacity(float mag,
1045 float in_radius, float out_radius, int rate)
1047 float opacity = 0.0;
1050 case GradientConfig::LINEAR:
1054 if(mag >= out_radius)
1057 opacity = (float)(mag - in_radius) / (out_radius - in_radius);
1060 case GradientConfig::LOG:
1064 // Let this one decay beyond out_radius
1065 opacity = 1 - exp(1.0 * -(float)(mag - in_radius) /
1066 (out_radius - in_radius));
1069 case GradientConfig::SQUARE:
1073 if(mag >= out_radius)
1076 opacity = powf((float)(mag - in_radius) /
1077 (out_radius - in_radius), 2.0);
1080 CLAMP(opacity, 0.0, 1.0);
1084 #define CREATE_GRADIENT(type, temp, components, max) \
1086 /* Synthesize linear gradient for lookups */ \
1088 r_table = malloc(sizeof(type) * gradient_size); \
1089 g_table = malloc(sizeof(type) * gradient_size); \
1090 b_table = malloc(sizeof(type) * gradient_size); \
1091 a_table = malloc(sizeof(type) * gradient_size); \
1093 for(int i = 0; i < gradient_size; i++) \
1095 float opacity = calculate_opacity(i, in_radius, out_radius, plugin->config.rate); \
1096 float transparency; \
1098 transparency = 1.0 - opacity; \
1099 ((type*)r_table)[i] = (type)(out1 * opacity + in1 * transparency); \
1100 ((type*)g_table)[i] = (type)(out2 * opacity + in2 * transparency); \
1101 ((type*)b_table)[i] = (type)(out3 * opacity + in3 * transparency); \
1102 ((type*)a_table)[i] = (type)(out4 * opacity + in4 * transparency); \
1105 for(int i = pkg->y1; i < pkg->y2; i++) \
1107 type *gradient_row = (type*)plugin->gradient->get_rows()[i]; \
1108 type *out_row = (type*)plugin->get_output()->get_rows()[i]; \
1110 switch(plugin->config.shape) \
1112 case GradientConfig::LINEAR: \
1113 for(int j = 0; j < w; j++) \
1115 int x = j - half_w; \
1116 int y = -(i - half_h); \
1118 /* Rotate by effect angle */ \
1119 int mag = (int)(gradient_size / 2 - \
1120 (x * sin_angle + y * cos_angle) + \
1123 /* Get gradient value from these coords */ \
1125 if(sizeof(type) == 4) \
1127 float opacity = calculate_opacity(mag, \
1130 plugin->config.rate); \
1131 float transparency = 1.0 - opacity; \
1132 gradient_row[0] = (type)(out1 * opacity + in1 * transparency); \
1133 gradient_row[1] = (type)(out2 * opacity + in2 * transparency); \
1134 gradient_row[2] = (type)(out3 * opacity + in3 * transparency); \
1135 if(components == 4) gradient_row[3] = (type)(out4 * opacity + in4 * transparency); \
1140 gradient_row[0] = out1; \
1141 gradient_row[1] = out2; \
1142 gradient_row[2] = out3; \
1143 if(components == 4) gradient_row[3] = out4; \
1146 if(mag >= gradient_size) \
1148 gradient_row[0] = in1; \
1149 gradient_row[1] = in2; \
1150 gradient_row[2] = in3; \
1151 if(components == 4) gradient_row[3] = in4; \
1155 gradient_row[0] = ((type*)r_table)[mag]; \
1156 gradient_row[1] = ((type*)g_table)[mag]; \
1157 gradient_row[2] = ((type*)b_table)[mag]; \
1158 if(components == 4) gradient_row[3] = ((type*)a_table)[mag]; \
1161 /* Overlay mixed colormodels onto output */ \
1162 if(gradient_cmodel != output_cmodel) \
1164 temp opacity = gradient_row[3]; \
1165 temp transparency = max - opacity; \
1166 out_row[0] = (transparency * out_row[0] + opacity * gradient_row[0]) / max; \
1167 out_row[1] = (transparency * out_row[1] + opacity * gradient_row[1]) / max; \
1168 out_row[2] = (transparency * out_row[2] + opacity * gradient_row[2]) / max; \
1172 gradient_row += components; \
1176 case GradientConfig::RADIAL: \
1177 for(int j = 0; j < w; j++) \
1179 double x = j - center_x; \
1180 double y = i - center_y; \
1181 double magnitude = hypot(x, y); \
1182 int mag = (int)magnitude; \
1183 if(sizeof(type) == 4) \
1185 float opacity = calculate_opacity(mag, \
1188 plugin->config.rate); \
1189 float transparency = 1.0 - opacity; \
1190 gradient_row[0] = (type)(out1 * opacity + in1 * transparency); \
1191 gradient_row[1] = (type)(out2 * opacity + in2 * transparency); \
1192 gradient_row[2] = (type)(out3 * opacity + in3 * transparency); \
1193 if(components == 4) gradient_row[3] = (type)(out4 * opacity + in4 * transparency); \
1197 gradient_row[0] = ((type*)r_table)[mag]; \
1198 gradient_row[1] = ((type*)g_table)[mag]; \
1199 gradient_row[2] = ((type*)b_table)[mag]; \
1200 if(components == 4) gradient_row[3] = ((type*)a_table)[mag]; \
1203 /* Overlay mixed colormodels onto output */ \
1204 if(gradient_cmodel != output_cmodel) \
1206 temp opacity = gradient_row[3]; \
1207 temp transparency = max - opacity; \
1208 out_row[0] = (transparency * out_row[0] + opacity * gradient_row[0]) / max; \
1209 out_row[1] = (transparency * out_row[1] + opacity * gradient_row[1]) / max; \
1210 out_row[2] = (transparency * out_row[2] + opacity * gradient_row[2]) / max; \
1214 gradient_row += components; \
1221 void GradientUnit::process_package(LoadPackage *package)
1223 GradientPackage *pkg = (GradientPackage*)package;
1224 int h = plugin->input->get_h();
1225 int w = plugin->input->get_w();
1228 int gradient_size = (int)(ceil(hypot(w, h)));
1229 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
1230 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
1231 double sin_angle = sin(plugin->config.angle * (M_PI / 180));
1232 double cos_angle = cos(plugin->config.angle * (M_PI / 180));
1233 double center_x = plugin->config.center_x * w / 100;
1234 double center_y = plugin->config.center_y * h / 100;
1239 int gradient_cmodel = plugin->gradient->get_color_model();
1240 int output_cmodel = plugin->get_output()->get_color_model();
1242 if(in_radius > out_radius)
1244 in_radius ^= out_radius;
1245 out_radius ^= in_radius;
1246 in_radius ^= out_radius;
1250 switch(gradient_cmodel)
1254 int in1 = plugin->config.in_r;
1255 int in2 = plugin->config.in_g;
1256 int in3 = plugin->config.in_b;
1257 int in4 = plugin->config.in_a;
1258 int out1 = plugin->config.out_r;
1259 int out2 = plugin->config.out_g;
1260 int out3 = plugin->config.out_b;
1261 int out4 = plugin->config.out_a;
1262 CREATE_GRADIENT(unsigned char, int, 3, 0xff)
1268 int in1 = plugin->config.in_r;
1269 int in2 = plugin->config.in_g;
1270 int in3 = plugin->config.in_b;
1271 int in4 = plugin->config.in_a;
1272 int out1 = plugin->config.out_r;
1273 int out2 = plugin->config.out_g;
1274 int out3 = plugin->config.out_b;
1275 int out4 = plugin->config.out_a;
1276 CREATE_GRADIENT(unsigned char, int, 4, 0xff)
1282 float in1 = (float)plugin->config.in_r / 0xff;
1283 float in2 = (float)plugin->config.in_g / 0xff;
1284 float in3 = (float)plugin->config.in_b / 0xff;
1285 float in4 = (float)plugin->config.in_a / 0xff;
1286 float out1 = (float)plugin->config.out_r / 0xff;
1287 float out2 = (float)plugin->config.out_g / 0xff;
1288 float out3 = (float)plugin->config.out_b / 0xff;
1289 float out4 = (float)plugin->config.out_a / 0xff;
1290 CREATE_GRADIENT(float, float, 3, 1.0)
1296 float in1 = (float)plugin->config.in_r / 0xff;
1297 float in2 = (float)plugin->config.in_g / 0xff;
1298 float in3 = (float)plugin->config.in_b / 0xff;
1299 float in4 = (float)plugin->config.in_a / 0xff;
1300 float out1 = (float)plugin->config.out_r / 0xff;
1301 float out2 = (float)plugin->config.out_g / 0xff;
1302 float out3 = (float)plugin->config.out_b / 0xff;
1303 float out4 = (float)plugin->config.out_a / 0xff;
1304 CREATE_GRADIENT(float, float, 4, 1.0)
1310 int in1, in2, in3, in4;
1311 int out1, out2, out3, out4;
1312 yuv.rgb_to_yuv_8(plugin->config.in_r,
1313 plugin->config.in_g,
1314 plugin->config.in_b,
1318 in4 = plugin->config.in_a;
1319 yuv.rgb_to_yuv_8(plugin->config.out_r,
1320 plugin->config.out_g,
1321 plugin->config.out_b,
1325 out4 = plugin->config.out_a;
1326 CREATE_GRADIENT(unsigned char, int, 3, 0xff)
1332 int in1, in2, in3, in4;
1333 int out1, out2, out3, out4;
1334 yuv.rgb_to_yuv_8(plugin->config.in_r,
1335 plugin->config.in_g,
1336 plugin->config.in_b,
1340 in4 = plugin->config.in_a;
1341 yuv.rgb_to_yuv_8(plugin->config.out_r,
1342 plugin->config.out_g,
1343 plugin->config.out_b,
1347 out4 = plugin->config.out_a;
1348 CREATE_GRADIENT(unsigned char, int, 4, 0xff)
1353 if(r_table) free(r_table);
1354 if(g_table) free(g_table);
1355 if(b_table) free(b_table);
1356 if(a_table) free(a_table);
1364 GradientServer::GradientServer(GradientMain *plugin,
1367 : LoadServer(total_clients, total_packages)
1369 this->plugin = plugin;
1372 void GradientServer::init_packages()
1374 for(int i = 0; i < get_total_packages(); i++)
1376 GradientPackage *package = (GradientPackage*)get_package(i);
1377 package->y1 = plugin->input->get_h() *
1379 get_total_packages();
1380 package->y2 = plugin->input->get_h() *
1382 get_total_packages();
1386 LoadClient* GradientServer::new_client()
1388 return new GradientUnit(this, plugin);
1391 LoadPackage* GradientServer::new_package()
1393 return new GradientPackage;