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);
328 GradientShape::GradientShape(GradientMain *plugin,
332 : BC_PopupMenu(x, y, 100, to_text(plugin->config.shape), 1)
334 this->plugin = plugin;
337 void GradientShape::create_objects()
339 add_item(new BC_MenuItem(to_text(GradientConfig::LINEAR)));
340 add_item(new BC_MenuItem(to_text(GradientConfig::RADIAL)));
342 char* GradientShape::to_text(int shape)
346 case GradientConfig::LINEAR:
352 int GradientShape::from_text(char *text)
354 if(!strcmp(text, to_text(GradientConfig::LINEAR)))
355 return GradientConfig::LINEAR;
356 return GradientConfig::RADIAL;
358 int GradientShape::handle_event()
360 plugin->config.shape = from_text(get_text());
362 plugin->send_configure_change();
369 GradientCenterX::GradientCenterX(GradientMain *plugin, int x, int y)
370 : BC_FPot(x, y, plugin->config.center_x, 0, 100)
372 this->plugin = plugin;
374 int GradientCenterX::handle_event()
376 plugin->config.center_x = get_value();
377 plugin->send_configure_change();
383 GradientCenterY::GradientCenterY(GradientMain *plugin, int x, int y)
384 : BC_FPot(x, y, plugin->config.center_y, 0, 100)
386 this->plugin = plugin;
389 int GradientCenterY::handle_event()
391 plugin->config.center_y = get_value();
392 plugin->send_configure_change();
399 GradientAngle::GradientAngle(GradientMain *plugin, int x, int y)
402 plugin->config.angle,
406 this->plugin = plugin;
409 int GradientAngle::handle_event()
411 plugin->config.angle = get_value();
412 plugin->send_configure_change();
417 GradientRate::GradientRate(GradientMain *plugin, int x, int y)
421 to_text(plugin->config.rate),
424 this->plugin = plugin;
426 void GradientRate::create_objects()
428 add_item(new BC_MenuItem(to_text(GradientConfig::LINEAR)));
429 add_item(new BC_MenuItem(to_text(GradientConfig::LOG)));
430 add_item(new BC_MenuItem(to_text(GradientConfig::SQUARE)));
432 char* GradientRate::to_text(int shape)
436 case GradientConfig::LINEAR:
438 case GradientConfig::LOG:
444 int GradientRate::from_text(char *text)
446 if(!strcmp(text, to_text(GradientConfig::LINEAR)))
447 return GradientConfig::LINEAR;
448 if(!strcmp(text, to_text(GradientConfig::LOG)))
449 return GradientConfig::LOG;
450 return GradientConfig::SQUARE;
452 int GradientRate::handle_event()
454 plugin->config.rate = from_text(get_text());
455 plugin->send_configure_change();
461 GradientInRadius::GradientInRadius(GradientMain *plugin, int x, int y)
469 (float)plugin->config.in_radius)
471 this->plugin = plugin;
474 int GradientInRadius::handle_event()
476 plugin->config.in_radius = get_value();
477 plugin->send_configure_change();
482 GradientOutRadius::GradientOutRadius(GradientMain *plugin, int x, int y)
490 (float)plugin->config.out_radius)
492 this->plugin = plugin;
495 int GradientOutRadius::handle_event()
497 plugin->config.out_radius = get_value();
498 plugin->send_configure_change();
502 GradientInColorButton::GradientInColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
503 : BC_GenericButton(x, y, _("Inner color:"))
505 this->plugin = plugin;
506 this->window = window;
509 int GradientInColorButton::handle_event()
511 window->in_color_thread->start_window(
512 plugin->config.get_in_color(),
513 plugin->config.in_a);
518 GradientOutColorButton::GradientOutColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
519 : BC_GenericButton(x, y, _("Outer color:"))
521 this->plugin = plugin;
522 this->window = window;
525 int GradientOutColorButton::handle_event()
527 window->out_color_thread->start_window(
528 plugin->config.get_out_color(),
529 plugin->config.out_a);
535 GradientInColorThread::GradientInColorThread(GradientMain *plugin,
536 GradientWindow *window)
537 : ColorThread(1, _("Inner color"))
539 this->plugin = plugin;
540 this->window = window;
543 int GradientInColorThread::handle_new_color(int output, int alpha)
545 plugin->config.in_r = (output & 0xff0000) >> 16;
546 plugin->config.in_g = (output & 0xff00) >> 8;
547 plugin->config.in_b = (output & 0xff);
548 plugin->config.in_a = alpha;
550 window->lock_window("GradientInColorThread::handle_new_color");
551 window->update_in_color();
553 window->unlock_window();
554 plugin->send_configure_change();
555 // printf("GradientInColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
556 // plugin->config.in_r,
557 // plugin->config.in_g,
558 // plugin->config.in_b,
559 // plugin->config.in_a,
560 // plugin->config.out_r,
561 // plugin->config.out_g,
562 // plugin->config.out_b,
563 // plugin->config.out_a);
570 GradientOutColorThread::GradientOutColorThread(GradientMain *plugin,
571 GradientWindow *window)
572 : ColorThread(1, _("Outer color"))
574 this->plugin = plugin;
575 this->window = window;
578 int GradientOutColorThread::handle_new_color(int output, int alpha)
580 plugin->config.out_r = (output & 0xff0000) >> 16;
581 plugin->config.out_g = (output & 0xff00) >> 8;
582 plugin->config.out_b = (output & 0xff);
583 plugin->config.out_a = alpha;
584 window->lock_window("GradientOutColorThread::handle_new_color");
585 window->update_out_color();
587 window->unlock_window();
588 plugin->send_configure_change();
589 // printf("GradientOutColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
590 // plugin->config.in_r,
591 // plugin->config.in_g,
592 // plugin->config.in_b,
593 // plugin->config.in_a,
594 // plugin->config.out_r,
595 // plugin->config.out_g,
596 // plugin->config.out_b,
597 // plugin->config.out_a);
612 GradientMain::GradientMain(PluginServer *server)
613 : PluginVClient(server)
616 need_reconfigure = 1;
622 GradientMain::~GradientMain()
626 if(gradient) delete gradient;
627 if(engine) delete engine;
628 if(overlayer) delete overlayer;
631 const char* GradientMain::plugin_title() { return _("Gradient"); }
632 int GradientMain::is_realtime() { return 1; }
635 NEW_WINDOW_MACRO(GradientMain, GradientWindow)
637 LOAD_CONFIGURATION_MACRO(GradientMain, GradientConfig)
639 int GradientMain::is_synthesis()
645 int GradientMain::process_buffer(VFrame *frame,
646 int64_t start_position,
650 this->output = frame;
651 need_reconfigure |= load_configuration();
653 int need_alpha = config.in_a != 0xff || config.out_a != 0xff;
660 if(get_use_opengl()) return run_opengl();
662 int gradient_cmodel = input->get_color_model();
663 if(need_alpha && BC_CModels::components(gradient_cmodel) == 3)
665 switch(gradient_cmodel)
668 gradient_cmodel = BC_RGBA8888;
671 gradient_cmodel = BC_RGBA_FLOAT;
674 gradient_cmodel = BC_YUVA8888;
679 if(gradient && gradient->get_color_model() != gradient_cmodel)
685 if(!gradient) gradient = new VFrame(0,
692 if(!engine) engine = new GradientServer(this,
693 get_project_smp() + 1,
694 get_project_smp() + 1);
695 engine->process_packages();
697 // Use overlay routine in GradientServer if mismatched colormodels
698 if(gradient->get_color_model() == output->get_color_model())
700 if(!overlayer) overlayer = new OverlayFrame(get_project_smp() + 1);
701 overlayer->overlay(output,
721 void GradientMain::update_gui()
725 if(load_configuration())
727 ((GradientWindow*)thread->window)->lock_window("GradientMain::update_gui");
728 ((GradientWindow*)thread->window)->rate->set_text(GradientRate::to_text(config.rate));
729 ((GradientWindow*)thread->window)->in_radius->update(config.in_radius);
730 ((GradientWindow*)thread->window)->out_radius->update(config.out_radius);
731 ((GradientWindow*)thread->window)->shape->set_text(GradientShape::to_text(config.shape));
732 if(((GradientWindow*)thread->window)->angle)
733 ((GradientWindow*)thread->window)->angle->update(config.angle);
734 if(((GradientWindow*)thread->window)->center_x)
735 ((GradientWindow*)thread->window)->center_x->update(config.center_x);
736 if(((GradientWindow*)thread->window)->center_y)
737 ((GradientWindow*)thread->window)->center_y->update(config.center_y);
738 ((GradientWindow*)thread->window)->update_in_color();
739 ((GradientWindow*)thread->window)->update_out_color();
740 ((GradientWindow*)thread->window)->update_shape();
741 ((GradientWindow*)thread->window)->unlock_window();
742 ((GradientWindow*)thread->window)->in_color_thread->update_gui(config.get_in_color(), config.in_a);
743 ((GradientWindow*)thread->window)->out_color_thread->update_gui(config.get_out_color(), config.out_a);
751 void GradientMain::save_data(KeyFrame *keyframe)
755 // cause data to be stored directly in text
756 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
757 output.tag.set_title("GRADIENT");
759 output.tag.set_property("ANGLE", config.angle);
760 output.tag.set_property("IN_RADIUS", config.in_radius);
761 output.tag.set_property("OUT_RADIUS", config.out_radius);
762 output.tag.set_property("IN_R", config.in_r);
763 output.tag.set_property("IN_G", config.in_g);
764 output.tag.set_property("IN_B", config.in_b);
765 output.tag.set_property("IN_A", config.in_a);
766 output.tag.set_property("OUT_R", config.out_r);
767 output.tag.set_property("OUT_G", config.out_g);
768 output.tag.set_property("OUT_B", config.out_b);
769 output.tag.set_property("OUT_A", config.out_a);
770 output.tag.set_property("SHAPE", config.shape);
771 output.tag.set_property("RATE", config.rate);
772 output.tag.set_property("CENTER_X", config.center_x);
773 output.tag.set_property("CENTER_Y", config.center_y);
775 output.tag.set_title("/GRADIENT");
777 output.append_newline();
778 output.terminate_string();
781 void GradientMain::read_data(KeyFrame *keyframe)
785 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
791 result = input.read_tag();
795 if(input.tag.title_is("GRADIENT"))
797 config.angle = input.tag.get_property("ANGLE", config.angle);
798 config.rate = input.tag.get_property("RATE", config.rate);
799 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
800 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
801 config.in_r = input.tag.get_property("IN_R", config.in_r);
802 config.in_g = input.tag.get_property("IN_G", config.in_g);
803 config.in_b = input.tag.get_property("IN_B", config.in_b);
804 config.in_a = input.tag.get_property("IN_A", config.in_a);
805 config.out_r = input.tag.get_property("OUT_R", config.out_r);
806 config.out_g = input.tag.get_property("OUT_G", config.out_g);
807 config.out_b = input.tag.get_property("OUT_B", config.out_b);
808 config.out_a = input.tag.get_property("OUT_A", config.out_a);
809 config.shape = input.tag.get_property("SHAPE", config.shape);
810 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
811 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
817 int GradientMain::handle_opengl()
820 const char *head_frag =
821 "uniform sampler2D tex;\n"
822 "uniform float half_w;\n"
823 "uniform float half_h;\n"
824 "uniform float center_x;\n"
825 "uniform float center_y;\n"
826 "uniform float half_gradient_size;\n"
827 "uniform float sin_angle;\n"
828 "uniform float cos_angle;\n"
829 "uniform vec4 out_color;\n"
830 "uniform vec4 in_color;\n"
831 "uniform float in_radius;\n"
832 "uniform float out_radius;\n"
833 "uniform float radius_diff;\n"
837 " vec2 out_coord = gl_TexCoord[0].st;\n";
839 const char *linear_shape =
840 " vec2 in_coord = vec2(out_coord.x - half_w, half_h - out_coord.y);\n"
841 " float mag = half_gradient_size - \n"
842 " (in_coord.x * sin_angle + in_coord.y * cos_angle);\n";
844 const char *radial_shape =
845 " vec2 in_coord = vec2(out_coord.x - center_x, out_coord.y - center_y);\n"
846 " float mag = length(vec2(in_coord.x, in_coord.y));\n";
848 // No clamp function in NVidia
849 const char *linear_rate =
850 " mag = min(max(mag, in_radius), out_radius);\n"
851 " float opacity = (mag - in_radius) / radius_diff;\n";
853 // NVidia warns about exp, but exp is in the GLSL spec.
854 const char *log_rate =
855 " mag = max(mag, in_radius);\n"
856 " float opacity = 1.0 - \n"
857 " exp(1.0 * -(mag - in_radius) / radius_diff);\n";
859 const char *square_rate =
860 " mag = min(max(mag, in_radius), out_radius);\n"
861 " float opacity = pow((mag - in_radius) / radius_diff, 2.0);\n"
862 " opacity = min(opacity, 1.0);\n";
864 const char *tail_frag =
865 " vec4 color = mix(in_color, out_color, opacity);\n"
866 " vec4 bg_color = texture2D(tex, out_coord);\n"
867 " gl_FragColor.rgb = mix(bg_color.rgb, color.rgb, color.a);\n"
868 " gl_FragColor.a = max(bg_color.a, color.a);\n"
872 const char *shader_stack[5] = { 0, 0, 0, 0, 0 };
873 shader_stack[0] = head_frag;
877 case GradientConfig::LINEAR:
878 shader_stack[1] = linear_shape;
882 shader_stack[1] = radial_shape;
888 case GradientConfig::LINEAR:
889 shader_stack[2] = linear_rate;
891 case GradientConfig::LOG:
892 shader_stack[2] = log_rate;
894 case GradientConfig::SQUARE:
895 shader_stack[2] = square_rate;
899 shader_stack[3] = tail_frag;
900 // Force frame to create texture without copying to it if full alpha.
901 if(config.in_a >= 0xff &&
902 config.out_a >= 0xff)
903 get_output()->set_opengl_state(VFrame::TEXTURE);
904 get_output()->to_texture();
905 get_output()->enable_opengl();
906 get_output()->init_screen();
907 get_output()->bind_texture(0);
909 unsigned int frag = VFrame::make_shader(0,
919 float w = get_output()->get_w();
920 float h = get_output()->get_h();
921 float texture_w = get_output()->get_texture_w();
922 float texture_h = get_output()->get_texture_h();
923 glUniform1i(glGetUniformLocation(frag, "tex"), 0);
924 glUniform1f(glGetUniformLocation(frag, "half_w"), w / 2 / texture_w);
925 glUniform1f(glGetUniformLocation(frag, "half_h"), h / 2 / texture_h);
926 if(config.shape == GradientConfig::LINEAR)
928 glUniform1f(glGetUniformLocation(frag, "center_x"),
930 glUniform1f(glGetUniformLocation(frag, "center_y"),
935 glUniform1f(glGetUniformLocation(frag, "center_x"),
936 (float)config.center_x * w / 100 / texture_w);
937 glUniform1f(glGetUniformLocation(frag, "center_y"),
938 (float)config.center_y * h / 100 / texture_h);
940 float gradient_size = hypotf(w / texture_w, h / texture_h);
941 glUniform1f(glGetUniformLocation(frag, "half_gradient_size"),
943 glUniform1f(glGetUniformLocation(frag, "sin_angle"),
944 sin(config.angle * (M_PI / 180)));
945 glUniform1f(glGetUniformLocation(frag, "cos_angle"),
946 cos(config.angle * (M_PI / 180)));
947 float in_radius = (float)config.in_radius / 100 * gradient_size;
948 glUniform1f(glGetUniformLocation(frag, "in_radius"), in_radius);
949 float out_radius = (float)config.out_radius / 100 * gradient_size;
950 glUniform1f(glGetUniformLocation(frag, "out_radius"), out_radius);
951 glUniform1f(glGetUniformLocation(frag, "radius_diff"),
952 out_radius - in_radius);
954 switch(get_output()->get_color_model())
959 float in1, in2, in3, in4;
960 float out1, out2, out3, out4;
961 YUV::rgb_to_yuv_f((float)config.in_r / 0xff,
962 (float)config.in_g / 0xff,
963 (float)config.in_b / 0xff,
967 in4 = (float)config.in_a / 0xff;
968 YUV::rgb_to_yuv_f((float)config.out_r / 0xff,
969 (float)config.out_g / 0xff,
970 (float)config.out_b / 0xff,
978 out4 = (float)config.out_a / 0xff;
979 glUniform4f(glGetUniformLocation(frag, "out_color"),
980 out1, out2, out3, out4);
981 glUniform4f(glGetUniformLocation(frag, "in_color"),
987 glUniform4f(glGetUniformLocation(frag, "out_color"),
988 (float)config.out_r / 0xff,
989 (float)config.out_g / 0xff,
990 (float)config.out_b / 0xff,
991 (float)config.out_a / 0xff);
992 glUniform4f(glGetUniformLocation(frag, "in_color"),
993 (float)config.in_r / 0xff,
994 (float)config.in_g / 0xff,
995 (float)config.in_b / 0xff,
996 (float)config.in_a / 0xff);
1001 get_output()->draw_texture();
1003 get_output()->set_opengl_state(VFrame::SCREEN);
1019 GradientPackage::GradientPackage()
1027 GradientUnit::GradientUnit(GradientServer *server, GradientMain *plugin)
1028 : LoadClient(server)
1030 this->plugin = plugin;
1031 this->server = server;
1037 static float calculate_opacity(float mag,
1038 float in_radius, float out_radius, int rate)
1040 float opacity = 0.0;
1043 case GradientConfig::LINEAR:
1047 if(mag >= out_radius)
1050 opacity = (float)(mag - in_radius) / (out_radius - in_radius);
1053 case GradientConfig::LOG:
1057 // Let this one decay beyond out_radius
1058 opacity = 1 - exp(1.0 * -(float)(mag - in_radius) /
1059 (out_radius - in_radius));
1062 case GradientConfig::SQUARE:
1066 if(mag >= out_radius)
1069 opacity = powf((float)(mag - in_radius) /
1070 (out_radius - in_radius), 2.0);
1073 CLAMP(opacity, 0.0, 1.0);
1077 #define CREATE_GRADIENT(type, temp, components, max) \
1079 /* Synthesize linear gradient for lookups */ \
1081 r_table = malloc(sizeof(type) * gradient_size); \
1082 g_table = malloc(sizeof(type) * gradient_size); \
1083 b_table = malloc(sizeof(type) * gradient_size); \
1084 a_table = malloc(sizeof(type) * gradient_size); \
1086 for(int i = 0; i < gradient_size; i++) \
1088 float opacity = calculate_opacity(i, in_radius, out_radius, plugin->config.rate); \
1089 float transparency; \
1091 transparency = 1.0 - opacity; \
1092 ((type*)r_table)[i] = (type)(out1 * opacity + in1 * transparency); \
1093 ((type*)g_table)[i] = (type)(out2 * opacity + in2 * transparency); \
1094 ((type*)b_table)[i] = (type)(out3 * opacity + in3 * transparency); \
1095 ((type*)a_table)[i] = (type)(out4 * opacity + in4 * transparency); \
1098 for(int i = pkg->y1; i < pkg->y2; i++) \
1100 type *gradient_row = (type*)plugin->gradient->get_rows()[i]; \
1101 type *out_row = (type*)plugin->get_output()->get_rows()[i]; \
1103 switch(plugin->config.shape) \
1105 case GradientConfig::LINEAR: \
1106 for(int j = 0; j < w; j++) \
1108 int x = j - half_w; \
1109 int y = -(i - half_h); \
1111 /* Rotate by effect angle */ \
1112 int mag = (int)(gradient_size / 2 - \
1113 (x * sin_angle + y * cos_angle) + \
1116 /* Get gradient value from these coords */ \
1118 if(sizeof(type) == 4) \
1120 float opacity = calculate_opacity(mag, \
1123 plugin->config.rate); \
1124 float transparency = 1.0 - opacity; \
1125 gradient_row[0] = (type)(out1 * opacity + in1 * transparency); \
1126 gradient_row[1] = (type)(out2 * opacity + in2 * transparency); \
1127 gradient_row[2] = (type)(out3 * opacity + in3 * transparency); \
1128 if(components == 4) gradient_row[3] = (type)(out4 * opacity + in4 * transparency); \
1133 gradient_row[0] = out1; \
1134 gradient_row[1] = out2; \
1135 gradient_row[2] = out3; \
1136 if(components == 4) gradient_row[3] = out4; \
1139 if(mag >= gradient_size) \
1141 gradient_row[0] = in1; \
1142 gradient_row[1] = in2; \
1143 gradient_row[2] = in3; \
1144 if(components == 4) gradient_row[3] = in4; \
1148 gradient_row[0] = ((type*)r_table)[mag]; \
1149 gradient_row[1] = ((type*)g_table)[mag]; \
1150 gradient_row[2] = ((type*)b_table)[mag]; \
1151 if(components == 4) gradient_row[3] = ((type*)a_table)[mag]; \
1154 /* Overlay mixed colormodels onto output */ \
1155 if(gradient_cmodel != output_cmodel) \
1157 temp opacity = gradient_row[3]; \
1158 temp transparency = max - opacity; \
1159 out_row[0] = (transparency * out_row[0] + opacity * gradient_row[0]) / max; \
1160 out_row[1] = (transparency * out_row[1] + opacity * gradient_row[1]) / max; \
1161 out_row[2] = (transparency * out_row[2] + opacity * gradient_row[2]) / max; \
1165 gradient_row += components; \
1169 case GradientConfig::RADIAL: \
1170 for(int j = 0; j < w; j++) \
1172 double x = j - center_x; \
1173 double y = i - center_y; \
1174 double magnitude = hypot(x, y); \
1175 int mag = (int)magnitude; \
1176 if(sizeof(type) == 4) \
1178 float opacity = calculate_opacity(mag, \
1181 plugin->config.rate); \
1182 float transparency = 1.0 - opacity; \
1183 gradient_row[0] = (type)(out1 * opacity + in1 * transparency); \
1184 gradient_row[1] = (type)(out2 * opacity + in2 * transparency); \
1185 gradient_row[2] = (type)(out3 * opacity + in3 * transparency); \
1186 if(components == 4) gradient_row[3] = (type)(out4 * opacity + in4 * transparency); \
1190 gradient_row[0] = ((type*)r_table)[mag]; \
1191 gradient_row[1] = ((type*)g_table)[mag]; \
1192 gradient_row[2] = ((type*)b_table)[mag]; \
1193 if(components == 4) gradient_row[3] = ((type*)a_table)[mag]; \
1196 /* Overlay mixed colormodels onto output */ \
1197 if(gradient_cmodel != output_cmodel) \
1199 temp opacity = gradient_row[3]; \
1200 temp transparency = max - opacity; \
1201 out_row[0] = (transparency * out_row[0] + opacity * gradient_row[0]) / max; \
1202 out_row[1] = (transparency * out_row[1] + opacity * gradient_row[1]) / max; \
1203 out_row[2] = (transparency * out_row[2] + opacity * gradient_row[2]) / max; \
1207 gradient_row += components; \
1214 void GradientUnit::process_package(LoadPackage *package)
1216 GradientPackage *pkg = (GradientPackage*)package;
1217 int h = plugin->input->get_h();
1218 int w = plugin->input->get_w();
1221 int gradient_size = (int)(ceil(hypot(w, h)));
1222 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
1223 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
1224 double sin_angle = sin(plugin->config.angle * (M_PI / 180));
1225 double cos_angle = cos(plugin->config.angle * (M_PI / 180));
1226 double center_x = plugin->config.center_x * w / 100;
1227 double center_y = plugin->config.center_y * h / 100;
1232 int gradient_cmodel = plugin->gradient->get_color_model();
1233 int output_cmodel = plugin->get_output()->get_color_model();
1235 if(in_radius > out_radius)
1237 in_radius ^= out_radius;
1238 out_radius ^= in_radius;
1239 in_radius ^= out_radius;
1243 switch(gradient_cmodel)
1247 int in1 = plugin->config.in_r;
1248 int in2 = plugin->config.in_g;
1249 int in3 = plugin->config.in_b;
1250 int in4 = plugin->config.in_a;
1251 int out1 = plugin->config.out_r;
1252 int out2 = plugin->config.out_g;
1253 int out3 = plugin->config.out_b;
1254 int out4 = plugin->config.out_a;
1255 CREATE_GRADIENT(unsigned char, int, 3, 0xff)
1261 int in1 = plugin->config.in_r;
1262 int in2 = plugin->config.in_g;
1263 int in3 = plugin->config.in_b;
1264 int in4 = plugin->config.in_a;
1265 int out1 = plugin->config.out_r;
1266 int out2 = plugin->config.out_g;
1267 int out3 = plugin->config.out_b;
1268 int out4 = plugin->config.out_a;
1269 CREATE_GRADIENT(unsigned char, int, 4, 0xff)
1275 float in1 = (float)plugin->config.in_r / 0xff;
1276 float in2 = (float)plugin->config.in_g / 0xff;
1277 float in3 = (float)plugin->config.in_b / 0xff;
1278 float in4 = (float)plugin->config.in_a / 0xff;
1279 float out1 = (float)plugin->config.out_r / 0xff;
1280 float out2 = (float)plugin->config.out_g / 0xff;
1281 float out3 = (float)plugin->config.out_b / 0xff;
1282 float out4 = (float)plugin->config.out_a / 0xff;
1283 CREATE_GRADIENT(float, float, 3, 1.0)
1289 float in1 = (float)plugin->config.in_r / 0xff;
1290 float in2 = (float)plugin->config.in_g / 0xff;
1291 float in3 = (float)plugin->config.in_b / 0xff;
1292 float in4 = (float)plugin->config.in_a / 0xff;
1293 float out1 = (float)plugin->config.out_r / 0xff;
1294 float out2 = (float)plugin->config.out_g / 0xff;
1295 float out3 = (float)plugin->config.out_b / 0xff;
1296 float out4 = (float)plugin->config.out_a / 0xff;
1297 CREATE_GRADIENT(float, float, 4, 1.0)
1303 int in1, in2, in3, in4;
1304 int out1, out2, out3, out4;
1305 yuv.rgb_to_yuv_8(plugin->config.in_r,
1306 plugin->config.in_g,
1307 plugin->config.in_b,
1311 in4 = plugin->config.in_a;
1312 yuv.rgb_to_yuv_8(plugin->config.out_r,
1313 plugin->config.out_g,
1314 plugin->config.out_b,
1318 out4 = plugin->config.out_a;
1319 CREATE_GRADIENT(unsigned char, int, 3, 0xff)
1325 int in1, in2, in3, in4;
1326 int out1, out2, out3, out4;
1327 yuv.rgb_to_yuv_8(plugin->config.in_r,
1328 plugin->config.in_g,
1329 plugin->config.in_b,
1333 in4 = plugin->config.in_a;
1334 yuv.rgb_to_yuv_8(plugin->config.out_r,
1335 plugin->config.out_g,
1336 plugin->config.out_b,
1340 out4 = plugin->config.out_a;
1341 CREATE_GRADIENT(unsigned char, int, 4, 0xff)
1346 if(r_table) free(r_table);
1347 if(g_table) free(g_table);
1348 if(b_table) free(b_table);
1349 if(a_table) free(a_table);
1357 GradientServer::GradientServer(GradientMain *plugin,
1360 : LoadServer(total_clients, total_packages)
1362 this->plugin = plugin;
1365 void GradientServer::init_packages()
1367 for(int i = 0; i < get_total_packages(); i++)
1369 GradientPackage *package = (GradientPackage*)get_package(i);
1370 package->y1 = plugin->input->get_h() *
1372 get_total_packages();
1373 package->y2 = plugin->input->get_h() *
1375 get_total_packages();
1379 LoadClient* GradientServer::new_client()
1381 return new GradientUnit(this, plugin);
1384 LoadPackage* GradientServer::new_package()
1386 return new GradientPackage;