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,
304 void GradientWindow::update_in_color()
306 //printf("GradientWindow::update_in_color 1 %08x\n", plugin->config.get_in_color());
307 set_color(plugin->config.get_in_color());
308 draw_box(in_color_x, in_color_y, COLOR_W, COLOR_H);
309 flash(in_color_x, in_color_y, COLOR_W, COLOR_H);
312 void GradientWindow::update_out_color()
314 //printf("GradientWindow::update_out_color 1 %08x\n", plugin->config.get_in_color());
315 set_color(plugin->config.get_out_color());
316 draw_box(out_color_x, out_color_y, COLOR_W, COLOR_H);
317 flash(out_color_x, out_color_y, COLOR_W, COLOR_H);
320 void GradientWindow::done_event(int result)
322 in_color_thread->close_window();
323 out_color_thread->close_window();
334 GradientShape::GradientShape(GradientMain *plugin,
338 : BC_PopupMenu(x, y, 100, to_text(plugin->config.shape), 1)
340 this->plugin = plugin;
343 void GradientShape::create_objects()
345 add_item(new BC_MenuItem(to_text(GradientConfig::LINEAR)));
346 add_item(new BC_MenuItem(to_text(GradientConfig::RADIAL)));
348 char* GradientShape::to_text(int shape)
352 case GradientConfig::LINEAR:
358 int GradientShape::from_text(char *text)
360 if(!strcmp(text, to_text(GradientConfig::LINEAR)))
361 return GradientConfig::LINEAR;
362 return GradientConfig::RADIAL;
364 int GradientShape::handle_event()
366 plugin->config.shape = from_text(get_text());
368 plugin->send_configure_change();
375 GradientCenterX::GradientCenterX(GradientMain *plugin, int x, int y)
376 : BC_FPot(x, y, plugin->config.center_x, 0, 100)
378 this->plugin = plugin;
380 int GradientCenterX::handle_event()
382 plugin->config.center_x = get_value();
383 plugin->send_configure_change();
389 GradientCenterY::GradientCenterY(GradientMain *plugin, int x, int y)
390 : BC_FPot(x, y, plugin->config.center_y, 0, 100)
392 this->plugin = plugin;
395 int GradientCenterY::handle_event()
397 plugin->config.center_y = get_value();
398 plugin->send_configure_change();
405 GradientAngle::GradientAngle(GradientMain *plugin, int x, int y)
408 plugin->config.angle,
412 this->plugin = plugin;
415 int GradientAngle::handle_event()
417 plugin->config.angle = get_value();
418 plugin->send_configure_change();
423 GradientRate::GradientRate(GradientMain *plugin, int x, int y)
427 to_text(plugin->config.rate),
430 this->plugin = plugin;
432 void GradientRate::create_objects()
434 add_item(new BC_MenuItem(to_text(GradientConfig::LINEAR)));
435 add_item(new BC_MenuItem(to_text(GradientConfig::LOG)));
436 add_item(new BC_MenuItem(to_text(GradientConfig::SQUARE)));
438 char* GradientRate::to_text(int shape)
442 case GradientConfig::LINEAR:
444 case GradientConfig::LOG:
450 int GradientRate::from_text(char *text)
452 if(!strcmp(text, to_text(GradientConfig::LINEAR)))
453 return GradientConfig::LINEAR;
454 if(!strcmp(text, to_text(GradientConfig::LOG)))
455 return GradientConfig::LOG;
456 return GradientConfig::SQUARE;
458 int GradientRate::handle_event()
460 plugin->config.rate = from_text(get_text());
461 plugin->send_configure_change();
467 GradientInRadius::GradientInRadius(GradientMain *plugin, int x, int y)
475 (float)plugin->config.in_radius)
477 this->plugin = plugin;
480 int GradientInRadius::handle_event()
482 plugin->config.in_radius = get_value();
483 plugin->send_configure_change();
488 GradientOutRadius::GradientOutRadius(GradientMain *plugin, int x, int y)
496 (float)plugin->config.out_radius)
498 this->plugin = plugin;
501 int GradientOutRadius::handle_event()
503 plugin->config.out_radius = get_value();
504 plugin->send_configure_change();
508 GradientInColorButton::GradientInColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
509 : BC_GenericButton(x, y, _("Inner color:"))
511 this->plugin = plugin;
512 this->window = window;
515 int GradientInColorButton::handle_event()
517 window->in_color_thread->start_window(
518 plugin->config.get_in_color(),
519 plugin->config.in_a);
524 GradientOutColorButton::GradientOutColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
525 : BC_GenericButton(x, y, _("Outer color:"))
527 this->plugin = plugin;
528 this->window = window;
531 int GradientOutColorButton::handle_event()
533 window->out_color_thread->start_window(
534 plugin->config.get_out_color(),
535 plugin->config.out_a);
541 GradientInColorThread::GradientInColorThread(GradientMain *plugin,
542 GradientWindow *window)
543 : ColorPicker(1, _("Inner color"))
545 this->plugin = plugin;
546 this->window = window;
549 int GradientInColorThread::handle_new_color(int output, int alpha)
551 plugin->config.in_r = (output & 0xff0000) >> 16;
552 plugin->config.in_g = (output & 0xff00) >> 8;
553 plugin->config.in_b = (output & 0xff);
554 plugin->config.in_a = alpha;
556 window->lock_window("GradientInColorThread::handle_new_color");
557 window->update_in_color();
559 window->unlock_window();
560 plugin->send_configure_change();
561 // printf("GradientInColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
562 // plugin->config.in_r,
563 // plugin->config.in_g,
564 // plugin->config.in_b,
565 // plugin->config.in_a,
566 // plugin->config.out_r,
567 // plugin->config.out_g,
568 // plugin->config.out_b,
569 // plugin->config.out_a);
576 GradientOutColorThread::GradientOutColorThread(GradientMain *plugin,
577 GradientWindow *window)
578 : ColorPicker(1, _("Outer color"))
580 this->plugin = plugin;
581 this->window = window;
584 int GradientOutColorThread::handle_new_color(int output, int alpha)
586 plugin->config.out_r = (output & 0xff0000) >> 16;
587 plugin->config.out_g = (output & 0xff00) >> 8;
588 plugin->config.out_b = (output & 0xff);
589 plugin->config.out_a = alpha;
590 window->lock_window("GradientOutColorThread::handle_new_color");
591 window->update_out_color();
593 window->unlock_window();
594 plugin->send_configure_change();
595 // printf("GradientOutColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
596 // plugin->config.in_r,
597 // plugin->config.in_g,
598 // plugin->config.in_b,
599 // plugin->config.in_a,
600 // plugin->config.out_r,
601 // plugin->config.out_g,
602 // plugin->config.out_b,
603 // plugin->config.out_a);
618 GradientMain::GradientMain(PluginServer *server)
619 : PluginVClient(server)
622 need_reconfigure = 1;
628 GradientMain::~GradientMain()
632 if(gradient) delete gradient;
633 if(engine) delete engine;
634 if(overlayer) delete overlayer;
637 const char* GradientMain::plugin_title() { return _("Gradient"); }
638 int GradientMain::is_realtime() { return 1; }
641 NEW_WINDOW_MACRO(GradientMain, GradientWindow)
643 LOAD_CONFIGURATION_MACRO(GradientMain, GradientConfig)
645 int GradientMain::is_synthesis()
651 int GradientMain::process_buffer(VFrame *frame,
652 int64_t start_position,
656 this->output = frame;
657 need_reconfigure |= load_configuration();
659 int need_alpha = config.in_a != 0xff || config.out_a != 0xff;
666 if(get_use_opengl()) return run_opengl();
668 int gradient_cmodel = input->get_color_model();
669 if(need_alpha && BC_CModels::components(gradient_cmodel) == 3)
671 switch(gradient_cmodel)
674 gradient_cmodel = BC_RGBA8888;
677 gradient_cmodel = BC_RGBA_FLOAT;
680 gradient_cmodel = BC_YUVA8888;
685 if(gradient && gradient->get_color_model() != gradient_cmodel)
691 if(!gradient) gradient = new VFrame(0,
698 if(!engine) engine = new GradientServer(this,
699 get_project_smp() + 1,
700 get_project_smp() + 1);
701 engine->process_packages();
703 // Use overlay routine in GradientServer if mismatched colormodels
704 if(gradient->get_color_model() == output->get_color_model())
706 if(!overlayer) overlayer = new OverlayFrame(get_project_smp() + 1);
707 overlayer->overlay(output,
727 void GradientMain::update_gui()
731 if(load_configuration())
733 ((GradientWindow*)thread->window)->lock_window("GradientMain::update_gui");
734 ((GradientWindow*)thread->window)->rate->set_text(GradientRate::to_text(config.rate));
735 ((GradientWindow*)thread->window)->in_radius->update(config.in_radius);
736 ((GradientWindow*)thread->window)->out_radius->update(config.out_radius);
737 ((GradientWindow*)thread->window)->shape->set_text(GradientShape::to_text(config.shape));
738 if(((GradientWindow*)thread->window)->angle)
739 ((GradientWindow*)thread->window)->angle->update(config.angle);
740 if(((GradientWindow*)thread->window)->center_x)
741 ((GradientWindow*)thread->window)->center_x->update(config.center_x);
742 if(((GradientWindow*)thread->window)->center_y)
743 ((GradientWindow*)thread->window)->center_y->update(config.center_y);
744 ((GradientWindow*)thread->window)->update_in_color();
745 ((GradientWindow*)thread->window)->update_out_color();
746 ((GradientWindow*)thread->window)->update_shape();
747 ((GradientWindow*)thread->window)->unlock_window();
748 ((GradientWindow*)thread->window)->in_color_thread->update_gui(config.get_in_color(), config.in_a);
749 ((GradientWindow*)thread->window)->out_color_thread->update_gui(config.get_out_color(), config.out_a);
757 void GradientMain::save_data(KeyFrame *keyframe)
761 // cause data to be stored directly in text
762 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
763 output.tag.set_title("GRADIENT");
765 output.tag.set_property("ANGLE", config.angle);
766 output.tag.set_property("IN_RADIUS", config.in_radius);
767 output.tag.set_property("OUT_RADIUS", config.out_radius);
768 output.tag.set_property("IN_R", config.in_r);
769 output.tag.set_property("IN_G", config.in_g);
770 output.tag.set_property("IN_B", config.in_b);
771 output.tag.set_property("IN_A", config.in_a);
772 output.tag.set_property("OUT_R", config.out_r);
773 output.tag.set_property("OUT_G", config.out_g);
774 output.tag.set_property("OUT_B", config.out_b);
775 output.tag.set_property("OUT_A", config.out_a);
776 output.tag.set_property("SHAPE", config.shape);
777 output.tag.set_property("RATE", config.rate);
778 output.tag.set_property("CENTER_X", config.center_x);
779 output.tag.set_property("CENTER_Y", config.center_y);
781 output.tag.set_title("/GRADIENT");
783 output.append_newline();
784 output.terminate_string();
787 void GradientMain::read_data(KeyFrame *keyframe)
791 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
797 result = input.read_tag();
801 if(input.tag.title_is("GRADIENT"))
803 config.angle = input.tag.get_property("ANGLE", config.angle);
804 config.rate = input.tag.get_property("RATE", config.rate);
805 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
806 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
807 config.in_r = input.tag.get_property("IN_R", config.in_r);
808 config.in_g = input.tag.get_property("IN_G", config.in_g);
809 config.in_b = input.tag.get_property("IN_B", config.in_b);
810 config.in_a = input.tag.get_property("IN_A", config.in_a);
811 config.out_r = input.tag.get_property("OUT_R", config.out_r);
812 config.out_g = input.tag.get_property("OUT_G", config.out_g);
813 config.out_b = input.tag.get_property("OUT_B", config.out_b);
814 config.out_a = input.tag.get_property("OUT_A", config.out_a);
815 config.shape = input.tag.get_property("SHAPE", config.shape);
816 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
817 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
823 int GradientMain::handle_opengl()
826 const char *head_frag =
827 "uniform sampler2D tex;\n"
828 "uniform float half_w;\n"
829 "uniform float half_h;\n"
830 "uniform float center_x;\n"
831 "uniform float center_y;\n"
832 "uniform float half_gradient_size;\n"
833 "uniform float sin_angle;\n"
834 "uniform float cos_angle;\n"
835 "uniform vec4 out_color;\n"
836 "uniform vec4 in_color;\n"
837 "uniform float in_radius;\n"
838 "uniform float out_radius;\n"
839 "uniform float radius_diff;\n"
843 " vec2 out_coord = gl_TexCoord[0].st;\n";
845 const char *linear_shape =
846 " vec2 in_coord = vec2(out_coord.x - half_w, half_h - out_coord.y);\n"
847 " float mag = half_gradient_size - \n"
848 " (in_coord.x * sin_angle + in_coord.y * cos_angle);\n";
850 const char *radial_shape =
851 " vec2 in_coord = vec2(out_coord.x - center_x, out_coord.y - center_y);\n"
852 " float mag = length(vec2(in_coord.x, in_coord.y));\n";
854 // No clamp function in NVidia
855 const char *linear_rate =
856 " mag = min(max(mag, in_radius), out_radius);\n"
857 " float opacity = (mag - in_radius) / radius_diff;\n";
859 // NVidia warns about exp, but exp is in the GLSL spec.
860 const char *log_rate =
861 " mag = max(mag, in_radius);\n"
862 " float opacity = 1.0 - \n"
863 " exp(1.0 * -(mag - in_radius) / radius_diff);\n";
865 const char *square_rate =
866 " mag = min(max(mag, in_radius), out_radius);\n"
867 " float opacity = pow((mag - in_radius) / radius_diff, 2.0);\n"
868 " opacity = min(opacity, 1.0);\n";
870 const char *tail_frag =
871 " vec4 color = mix(in_color, out_color, opacity);\n"
872 " vec4 bg_color = texture2D(tex, out_coord);\n"
873 " gl_FragColor.rgb = mix(bg_color.rgb, color.rgb, color.a);\n"
874 " gl_FragColor.a = max(bg_color.a, color.a);\n"
878 const char *shader_stack[5] = { 0, 0, 0, 0, 0 };
879 shader_stack[0] = head_frag;
883 case GradientConfig::LINEAR:
884 shader_stack[1] = linear_shape;
888 shader_stack[1] = radial_shape;
894 case GradientConfig::LINEAR:
895 shader_stack[2] = linear_rate;
897 case GradientConfig::LOG:
898 shader_stack[2] = log_rate;
900 case GradientConfig::SQUARE:
901 shader_stack[2] = square_rate;
905 shader_stack[3] = tail_frag;
906 // Force frame to create texture without copying to it if full alpha.
907 if(config.in_a >= 0xff &&
908 config.out_a >= 0xff)
909 get_output()->set_opengl_state(VFrame::TEXTURE);
910 get_output()->to_texture();
911 get_output()->enable_opengl();
912 get_output()->init_screen();
913 get_output()->bind_texture(0);
915 unsigned int frag = VFrame::make_shader(0,
925 float w = get_output()->get_w();
926 float h = get_output()->get_h();
927 float texture_w = get_output()->get_texture_w();
928 float texture_h = get_output()->get_texture_h();
929 glUniform1i(glGetUniformLocation(frag, "tex"), 0);
930 glUniform1f(glGetUniformLocation(frag, "half_w"), w / 2 / texture_w);
931 glUniform1f(glGetUniformLocation(frag, "half_h"), h / 2 / texture_h);
932 if(config.shape == GradientConfig::LINEAR)
934 glUniform1f(glGetUniformLocation(frag, "center_x"),
936 glUniform1f(glGetUniformLocation(frag, "center_y"),
941 glUniform1f(glGetUniformLocation(frag, "center_x"),
942 (float)config.center_x * w / 100 / texture_w);
943 glUniform1f(glGetUniformLocation(frag, "center_y"),
944 (float)config.center_y * h / 100 / texture_h);
946 float gradient_size = hypotf(w / texture_w, h / texture_h);
947 glUniform1f(glGetUniformLocation(frag, "half_gradient_size"),
949 glUniform1f(glGetUniformLocation(frag, "sin_angle"),
950 sin(config.angle * (M_PI / 180)));
951 glUniform1f(glGetUniformLocation(frag, "cos_angle"),
952 cos(config.angle * (M_PI / 180)));
953 float in_radius = (float)config.in_radius / 100 * gradient_size;
954 glUniform1f(glGetUniformLocation(frag, "in_radius"), in_radius);
955 float out_radius = (float)config.out_radius / 100 * gradient_size;
956 glUniform1f(glGetUniformLocation(frag, "out_radius"), out_radius);
957 glUniform1f(glGetUniformLocation(frag, "radius_diff"),
958 out_radius - in_radius);
960 switch(get_output()->get_color_model())
965 float in1, in2, in3, in4;
966 float out1, out2, out3, out4;
967 YUV::rgb_to_yuv_f((float)config.in_r / 0xff,
968 (float)config.in_g / 0xff,
969 (float)config.in_b / 0xff,
973 in4 = (float)config.in_a / 0xff;
974 YUV::rgb_to_yuv_f((float)config.out_r / 0xff,
975 (float)config.out_g / 0xff,
976 (float)config.out_b / 0xff,
984 out4 = (float)config.out_a / 0xff;
985 glUniform4f(glGetUniformLocation(frag, "out_color"),
986 out1, out2, out3, out4);
987 glUniform4f(glGetUniformLocation(frag, "in_color"),
993 glUniform4f(glGetUniformLocation(frag, "out_color"),
994 (float)config.out_r / 0xff,
995 (float)config.out_g / 0xff,
996 (float)config.out_b / 0xff,
997 (float)config.out_a / 0xff);
998 glUniform4f(glGetUniformLocation(frag, "in_color"),
999 (float)config.in_r / 0xff,
1000 (float)config.in_g / 0xff,
1001 (float)config.in_b / 0xff,
1002 (float)config.in_a / 0xff);
1007 get_output()->draw_texture();
1009 get_output()->set_opengl_state(VFrame::SCREEN);
1025 GradientPackage::GradientPackage()
1033 GradientUnit::GradientUnit(GradientServer *server, GradientMain *plugin)
1034 : LoadClient(server)
1036 this->plugin = plugin;
1037 this->server = server;
1043 static float calculate_opacity(float mag,
1044 float in_radius, float out_radius, int rate)
1046 float opacity = 0.0;
1049 case GradientConfig::LINEAR:
1053 if(mag >= out_radius)
1056 opacity = (float)(mag - in_radius) / (out_radius - in_radius);
1059 case GradientConfig::LOG:
1063 // Let this one decay beyond out_radius
1064 opacity = 1 - exp(1.0 * -(float)(mag - in_radius) /
1065 (out_radius - in_radius));
1068 case GradientConfig::SQUARE:
1072 if(mag >= out_radius)
1075 opacity = powf((float)(mag - in_radius) /
1076 (out_radius - in_radius), 2.0);
1079 CLAMP(opacity, 0.0, 1.0);
1083 #define CREATE_GRADIENT(type, temp, components, max) \
1085 /* Synthesize linear gradient for lookups */ \
1087 r_table = malloc(sizeof(type) * gradient_size); \
1088 g_table = malloc(sizeof(type) * gradient_size); \
1089 b_table = malloc(sizeof(type) * gradient_size); \
1090 a_table = malloc(sizeof(type) * gradient_size); \
1092 for(int i = 0; i < gradient_size; i++) \
1094 float opacity = calculate_opacity(i, in_radius, out_radius, plugin->config.rate); \
1095 float transparency; \
1097 transparency = 1.0 - opacity; \
1098 ((type*)r_table)[i] = (type)(out1 * opacity + in1 * transparency); \
1099 ((type*)g_table)[i] = (type)(out2 * opacity + in2 * transparency); \
1100 ((type*)b_table)[i] = (type)(out3 * opacity + in3 * transparency); \
1101 ((type*)a_table)[i] = (type)(out4 * opacity + in4 * transparency); \
1104 for(int i = pkg->y1; i < pkg->y2; i++) \
1106 type *gradient_row = (type*)plugin->gradient->get_rows()[i]; \
1107 type *out_row = (type*)plugin->get_output()->get_rows()[i]; \
1109 switch(plugin->config.shape) \
1111 case GradientConfig::LINEAR: \
1112 for(int j = 0; j < w; j++) \
1114 int x = j - half_w; \
1115 int y = -(i - half_h); \
1117 /* Rotate by effect angle */ \
1118 int mag = (int)(gradient_size / 2 - \
1119 (x * sin_angle + y * cos_angle) + \
1122 /* Get gradient value from these coords */ \
1124 if(sizeof(type) == 4) \
1126 float opacity = calculate_opacity(mag, \
1129 plugin->config.rate); \
1130 float transparency = 1.0 - opacity; \
1131 gradient_row[0] = (type)(out1 * opacity + in1 * transparency); \
1132 gradient_row[1] = (type)(out2 * opacity + in2 * transparency); \
1133 gradient_row[2] = (type)(out3 * opacity + in3 * transparency); \
1134 if(components == 4) gradient_row[3] = (type)(out4 * opacity + in4 * transparency); \
1139 gradient_row[0] = out1; \
1140 gradient_row[1] = out2; \
1141 gradient_row[2] = out3; \
1142 if(components == 4) gradient_row[3] = out4; \
1145 if(mag >= gradient_size) \
1147 gradient_row[0] = in1; \
1148 gradient_row[1] = in2; \
1149 gradient_row[2] = in3; \
1150 if(components == 4) gradient_row[3] = in4; \
1154 gradient_row[0] = ((type*)r_table)[mag]; \
1155 gradient_row[1] = ((type*)g_table)[mag]; \
1156 gradient_row[2] = ((type*)b_table)[mag]; \
1157 if(components == 4) gradient_row[3] = ((type*)a_table)[mag]; \
1160 /* Overlay mixed colormodels onto output */ \
1161 if(gradient_cmodel != output_cmodel) \
1163 temp opacity = gradient_row[3]; \
1164 temp transparency = max - opacity; \
1165 out_row[0] = (transparency * out_row[0] + opacity * gradient_row[0]) / max; \
1166 out_row[1] = (transparency * out_row[1] + opacity * gradient_row[1]) / max; \
1167 out_row[2] = (transparency * out_row[2] + opacity * gradient_row[2]) / max; \
1171 gradient_row += components; \
1175 case GradientConfig::RADIAL: \
1176 for(int j = 0; j < w; j++) \
1178 double x = j - center_x; \
1179 double y = i - center_y; \
1180 double magnitude = hypot(x, y); \
1181 int mag = (int)magnitude; \
1182 if(sizeof(type) == 4) \
1184 float opacity = calculate_opacity(mag, \
1187 plugin->config.rate); \
1188 float transparency = 1.0 - opacity; \
1189 gradient_row[0] = (type)(out1 * opacity + in1 * transparency); \
1190 gradient_row[1] = (type)(out2 * opacity + in2 * transparency); \
1191 gradient_row[2] = (type)(out3 * opacity + in3 * transparency); \
1192 if(components == 4) gradient_row[3] = (type)(out4 * opacity + in4 * transparency); \
1196 gradient_row[0] = ((type*)r_table)[mag]; \
1197 gradient_row[1] = ((type*)g_table)[mag]; \
1198 gradient_row[2] = ((type*)b_table)[mag]; \
1199 if(components == 4) gradient_row[3] = ((type*)a_table)[mag]; \
1202 /* Overlay mixed colormodels onto output */ \
1203 if(gradient_cmodel != output_cmodel) \
1205 temp opacity = gradient_row[3]; \
1206 temp transparency = max - opacity; \
1207 out_row[0] = (transparency * out_row[0] + opacity * gradient_row[0]) / max; \
1208 out_row[1] = (transparency * out_row[1] + opacity * gradient_row[1]) / max; \
1209 out_row[2] = (transparency * out_row[2] + opacity * gradient_row[2]) / max; \
1213 gradient_row += components; \
1220 void GradientUnit::process_package(LoadPackage *package)
1222 GradientPackage *pkg = (GradientPackage*)package;
1223 int h = plugin->input->get_h();
1224 int w = plugin->input->get_w();
1227 int gradient_size = (int)(ceil(hypot(w, h)));
1228 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
1229 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
1230 double sin_angle = sin(plugin->config.angle * (M_PI / 180));
1231 double cos_angle = cos(plugin->config.angle * (M_PI / 180));
1232 double center_x = plugin->config.center_x * w / 100;
1233 double center_y = plugin->config.center_y * h / 100;
1238 int gradient_cmodel = plugin->gradient->get_color_model();
1239 int output_cmodel = plugin->get_output()->get_color_model();
1241 if(in_radius > out_radius)
1243 in_radius ^= out_radius;
1244 out_radius ^= in_radius;
1245 in_radius ^= out_radius;
1249 switch(gradient_cmodel)
1253 int in1 = plugin->config.in_r;
1254 int in2 = plugin->config.in_g;
1255 int in3 = plugin->config.in_b;
1256 int in4 = plugin->config.in_a;
1257 int out1 = plugin->config.out_r;
1258 int out2 = plugin->config.out_g;
1259 int out3 = plugin->config.out_b;
1260 int out4 = plugin->config.out_a;
1261 CREATE_GRADIENT(unsigned char, int, 3, 0xff)
1267 int in1 = plugin->config.in_r;
1268 int in2 = plugin->config.in_g;
1269 int in3 = plugin->config.in_b;
1270 int in4 = plugin->config.in_a;
1271 int out1 = plugin->config.out_r;
1272 int out2 = plugin->config.out_g;
1273 int out3 = plugin->config.out_b;
1274 int out4 = plugin->config.out_a;
1275 CREATE_GRADIENT(unsigned char, int, 4, 0xff)
1281 float in1 = (float)plugin->config.in_r / 0xff;
1282 float in2 = (float)plugin->config.in_g / 0xff;
1283 float in3 = (float)plugin->config.in_b / 0xff;
1284 float in4 = (float)plugin->config.in_a / 0xff;
1285 float out1 = (float)plugin->config.out_r / 0xff;
1286 float out2 = (float)plugin->config.out_g / 0xff;
1287 float out3 = (float)plugin->config.out_b / 0xff;
1288 float out4 = (float)plugin->config.out_a / 0xff;
1289 CREATE_GRADIENT(float, float, 3, 1.0)
1295 float in1 = (float)plugin->config.in_r / 0xff;
1296 float in2 = (float)plugin->config.in_g / 0xff;
1297 float in3 = (float)plugin->config.in_b / 0xff;
1298 float in4 = (float)plugin->config.in_a / 0xff;
1299 float out1 = (float)plugin->config.out_r / 0xff;
1300 float out2 = (float)plugin->config.out_g / 0xff;
1301 float out3 = (float)plugin->config.out_b / 0xff;
1302 float out4 = (float)plugin->config.out_a / 0xff;
1303 CREATE_GRADIENT(float, float, 4, 1.0)
1309 int in1, in2, in3, in4;
1310 int out1, out2, out3, out4;
1311 yuv.rgb_to_yuv_8(plugin->config.in_r,
1312 plugin->config.in_g,
1313 plugin->config.in_b,
1317 in4 = plugin->config.in_a;
1318 yuv.rgb_to_yuv_8(plugin->config.out_r,
1319 plugin->config.out_g,
1320 plugin->config.out_b,
1324 out4 = plugin->config.out_a;
1325 CREATE_GRADIENT(unsigned char, int, 3, 0xff)
1331 int in1, in2, in3, in4;
1332 int out1, out2, out3, out4;
1333 yuv.rgb_to_yuv_8(plugin->config.in_r,
1334 plugin->config.in_g,
1335 plugin->config.in_b,
1339 in4 = plugin->config.in_a;
1340 yuv.rgb_to_yuv_8(plugin->config.out_r,
1341 plugin->config.out_g,
1342 plugin->config.out_b,
1346 out4 = plugin->config.out_a;
1347 CREATE_GRADIENT(unsigned char, int, 4, 0xff)
1352 if(r_table) free(r_table);
1353 if(g_table) free(g_table);
1354 if(b_table) free(b_table);
1355 if(a_table) free(a_table);
1363 GradientServer::GradientServer(GradientMain *plugin,
1366 : LoadServer(total_clients, total_packages)
1368 this->plugin = plugin;
1371 void GradientServer::init_packages()
1373 for(int i = 0; i < get_total_packages(); i++)
1375 GradientPackage *package = (GradientPackage*)get_package(i);
1376 package->y1 = plugin->input->get_h() *
1378 get_total_packages();
1379 package->y2 = plugin->input->get_h() *
1381 get_total_packages();
1385 LoadClient* GradientServer::new_client()
1387 return new GradientUnit(this, plugin);
1390 LoadPackage* GradientServer::new_package()
1392 return new GradientPackage;