r123: Merged HEAD and TEST. New stuff shall be committed to HEAD from now on.
[cinelerra_cv/mob.git] / plugins / gradient / gradient.C
blob5c31ab91112657f385f598d5cbae7aa4fc70ff58
1 #include <math.h>
2 #include <stdint.h>
3 #include <string.h>
5 #include "bcdisplayinfo.h"
6 #include "clip.h"
7 #include "defaults.h"
8 #include "filexml.h"
9 #include "gradient.h"
10 #include "keyframe.h"
11 #include "overlayframe.h"
12 #include "picon_png.h"
13 #include "vframe.h"
15 #include <libintl.h>
16 #define _(String) gettext(String)
17 #define gettext_noop(String) String
18 #define N_(String) gettext_noop (String)
22 REGISTER_PLUGIN(GradientMain)
29 GradientConfig::GradientConfig()
31         angle = 0;
32         in_radius = 0;
33         out_radius = 100;
34         in_r = 0xff;
35         in_g = 0xff;
36         in_b = 0xff;
37         in_a = 0xff;
38         out_r = 0x0;
39         out_g = 0x0;
40         out_b = 0x0;
41         out_a = 0x0;
44 int GradientConfig::equivalent(GradientConfig &that)
46         return (EQUIV(angle, that.angle) &&
47                 EQUIV(in_radius, that.in_radius) &&
48                 EQUIV(out_radius, that.out_radius) &&
49                 in_r == that.in_r &&
50                 in_g == that.in_g &&
51                 in_b == that.in_b &&
52                 in_a == that.in_a &&
53                 out_r == that.out_r &&
54                 out_g == that.out_g &&
55                 out_b == that.out_b &&
56                 out_a == that.out_a);
59 void GradientConfig::copy_from(GradientConfig &that)
61         angle = that.angle;
62         in_radius = that.in_radius;
63         out_radius = that.out_radius;
64         in_r = that.in_r;
65         in_g = that.in_g;
66         in_b = that.in_b;
67         in_a = that.in_a;
68         out_r = that.out_r;
69         out_g = that.out_g;
70         out_b = that.out_b;
71         out_a = that.out_a;
74 void GradientConfig::interpolate(GradientConfig &prev, 
75         GradientConfig &next, 
76         long prev_frame, 
77         long next_frame, 
78         long current_frame)
80         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
81         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
84         this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale);
85         this->in_radius = (int)(prev.in_radius * prev_scale + next.in_radius * next_scale);
86         this->out_radius = (int)(prev.out_radius * prev_scale + next.out_radius * next_scale);
87         in_r = (int)(prev.in_r * prev_scale + next.in_r * next_scale);
88         in_g = (int)(prev.in_g * prev_scale + next.in_g * next_scale);
89         in_b = (int)(prev.in_b * prev_scale + next.in_b * next_scale);
90         in_a = (int)(prev.in_a * prev_scale + next.in_a * next_scale);
91         out_r = (int)(prev.out_r * prev_scale + next.out_r * next_scale);
92         out_g = (int)(prev.out_g * prev_scale + next.out_g * next_scale);
93         out_b = (int)(prev.out_b * prev_scale + next.out_b * next_scale);
94         out_a = (int)(prev.out_a * prev_scale + next.out_a * next_scale);
97 int GradientConfig::get_in_color()
99         int result = (in_r << 16) | (in_g << 8) | (in_b);
100         return result;
103 int GradientConfig::get_out_color()
105         int result = (out_r << 16) | (out_g << 8) | (out_b);
106         return result;
117 PLUGIN_THREAD_OBJECT(GradientMain, GradientThread, GradientWindow)
120 #define COLOR_W 100
121 #define COLOR_H 30
123 GradientWindow::GradientWindow(GradientMain *plugin, int x, int y)
124  : BC_Window(plugin->gui_string, 
125         x,
126         y,
127         350, 
128         210, 
129         350, 
130         210, 
131         0, 
132         1)
134         this->plugin = plugin; 
137 GradientWindow::~GradientWindow()
139         delete in_color_thread;
140         delete out_color_thread;
143 int GradientWindow::create_objects()
145         int x = 10, y = 10, x2 = 130;
147         add_subwindow(new BC_Title(x, y, _("Angle:")));
148         add_subwindow(angle = new GradientAngle(plugin, x2, y));
149         y += 40;
150         add_subwindow(new BC_Title(x, y, _("Inner radius:")));
151         add_subwindow(in_radius = new GradientInRadius(plugin, x2, y));
152         y += 30;
153         add_subwindow(new BC_Title(x, y, _("Outer radius:")));
154         add_subwindow(out_radius = new GradientOutRadius(plugin, x2, y));
155         y += 35;
156         add_subwindow(in_color = new GradientInColorButton(plugin, this, x, y));
157         in_color_x = x2;
158         in_color_y = y;
159         y += 35;
160         add_subwindow(out_color = new GradientOutColorButton(plugin, this, x, y));
161         out_color_x = x2;
162         out_color_y = y;
163         in_color_thread = new GradientInColorThread(plugin, this);
164         out_color_thread = new GradientOutColorThread(plugin, this);
165         update_in_color();
166         update_out_color();
168         show_window();
169         flush();
170         return 0;
173 int GradientWindow::close_event()
175 // Set result to 1 to indicate a plugin side close
176         set_done(1);
177         return 1;
180 void GradientWindow::update_in_color()
182 //printf("GradientWindow::update_in_color 1 %08x\n", plugin->config.get_in_color());
183         set_color(plugin->config.get_in_color());
184         draw_box(in_color_x, in_color_y, COLOR_W, COLOR_H);
185         flash(in_color_x, in_color_y, COLOR_W, COLOR_H);
188 void GradientWindow::update_out_color()
190 //printf("GradientWindow::update_out_color 1 %08x\n", plugin->config.get_in_color());
191         set_color(plugin->config.get_out_color());
192         draw_box(out_color_x, out_color_y, COLOR_W, COLOR_H);
193         flash(out_color_x, out_color_y, COLOR_W, COLOR_H);
204 GradientAngle::GradientAngle(GradientMain *plugin, int x, int y)
205  : BC_FPot(x,
206         y,
207         plugin->config.angle,
208         -180,
209         180)
211         this->plugin = plugin;
214 int GradientAngle::handle_event()
216         plugin->config.angle = get_value();
217         plugin->send_configure_change();
218         return 1;
222 GradientInRadius::GradientInRadius(GradientMain *plugin, int x, int y)
223  : BC_FSlider(x,
224         y,
225         0,
226         200,
227         200,
228         (float)0,
229         (float)100,
230         (float)plugin->config.in_radius)
232         this->plugin = plugin;
235 int GradientInRadius::handle_event()
237         plugin->config.in_radius = get_value();
238         plugin->send_configure_change();
239         return 1;
243 GradientOutRadius::GradientOutRadius(GradientMain *plugin, int x, int y)
244  : BC_FSlider(x,
245         y,
246         0,
247         200,
248         200,
249         (float)0,
250         (float)100,
251         (float)plugin->config.out_radius)
253         this->plugin = plugin;
256 int GradientOutRadius::handle_event()
258         plugin->config.out_radius = get_value();
259         plugin->send_configure_change();
260         return 1;
263 GradientInColorButton::GradientInColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
264  : BC_GenericButton(x, y, _("Inner color:"))
266         this->plugin = plugin;
267         this->window = window;
270 int GradientInColorButton::handle_event()
272         window->in_color_thread->start_window(
273                 plugin->config.get_in_color(),
274                 plugin->config.in_a);
275         return 1;
279 GradientOutColorButton::GradientOutColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
280  : BC_GenericButton(x, y, _("Outer color:"))
282         this->plugin = plugin;
283         this->window = window;
286 int GradientOutColorButton::handle_event()
288         window->out_color_thread->start_window(
289                 plugin->config.get_out_color(),
290                 plugin->config.out_a);
291         return 1;
296 GradientInColorThread::GradientInColorThread(GradientMain *plugin, 
297         GradientWindow *window)
298  : ColorThread(1, _("Inner color"))
300         this->plugin = plugin;
301         this->window = window;
304 int GradientInColorThread::handle_event(int output)
306         plugin->config.in_r = (output & 0xff0000) >> 16;
307         plugin->config.in_g = (output & 0xff00) >> 8;
308         plugin->config.in_b = (output & 0xff);
309         plugin->config.in_a = alpha;
310         window->update_in_color();
311         window->flush();
312         plugin->send_configure_change();
313 // printf("GradientInColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
314 // plugin->config.in_r,
315 // plugin->config.in_g,
316 // plugin->config.in_b,
317 // plugin->config.in_a,
318 // plugin->config.out_r,
319 // plugin->config.out_g,
320 // plugin->config.out_b,
321 // plugin->config.out_a);
323         return 1;
328 GradientOutColorThread::GradientOutColorThread(GradientMain *plugin, 
329         GradientWindow *window)
330  : ColorThread(1, _("Outer color"))
332         this->plugin = plugin;
333         this->window = window;
336 int GradientOutColorThread::handle_event(int output)
338         plugin->config.out_r = (output & 0xff0000) >> 16;
339         plugin->config.out_g = (output & 0xff00) >> 8;
340         plugin->config.out_b = (output & 0xff);
341         plugin->config.out_a = alpha;
342         window->update_out_color();
343         window->flush();
344         plugin->send_configure_change();
345 // printf("GradientOutColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
346 // plugin->config.in_r,
347 // plugin->config.in_g,
348 // plugin->config.in_b,
349 // plugin->config.in_a,
350 // plugin->config.out_r,
351 // plugin->config.out_g,
352 // plugin->config.out_b,
353 // plugin->config.out_a);
354         return 1;
368 GradientMain::GradientMain(PluginServer *server)
369  : PluginVClient(server)
371         PLUGIN_CONSTRUCTOR_MACRO
372         need_reconfigure = 1;
373         gradient = 0;
374         engine = 0;
375         overlayer = 0;
378 GradientMain::~GradientMain()
380         PLUGIN_DESTRUCTOR_MACRO
382         if(gradient) delete gradient;
383         if(engine) delete engine;
384         if(overlayer) delete overlayer;
387 char* GradientMain::plugin_title() { return _("Gradient"); }
388 int GradientMain::is_realtime() { return 1; }
391 NEW_PICON_MACRO(GradientMain)
393 SHOW_GUI_MACRO(GradientMain, GradientThread)
395 SET_STRING_MACRO(GradientMain)
397 RAISE_WINDOW_MACRO(GradientMain)
399 LOAD_CONFIGURATION_MACRO(GradientMain, GradientConfig)
401 int GradientMain::is_synthesis()
403         return 1;
407 int GradientMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
409         this->input = input_ptr;
410         this->output = output_ptr;
411         need_reconfigure |= load_configuration();
413 // printf("GradientMain::process_realtime 1 %d %d %d %d %d %d %d %d\n",
414 // config.in_r,
415 // config.in_g,
416 // config.in_b,
417 // config.in_a,
418 // config.out_r,
419 // config.out_g,
420 // config.out_b,
421 // config.out_a);
425 // Generate new gradient
426         if(need_reconfigure)
427         {
428                 need_reconfigure = 0;
430 //printf("GradientMain::process_realtime 1\n");
431                 if(!gradient) gradient = new VFrame(0, 
432                         input->get_w(),
433                         input->get_h(),
434                         input->get_color_model());
436                 if(!engine) engine = new GradientServer(this,
437                         get_project_smp() + 1,
438                         get_project_smp() + 1);
439                 engine->process_packages();
440         }
442 //printf("GradientMain::process_realtime 2\n");
443 // Overlay new gradient
444         if(output->get_rows()[0] != input->get_rows()[0])
445         {
446                 output->copy_from(input);
447         }
449 //printf("GradientMain::process_realtime 2\n");
450         if(!overlayer) overlayer = new OverlayFrame(get_project_smp() + 1);
451         overlayer->overlay(output, 
452                 gradient,
453                 0, 
454                 0, 
455                 input->get_w(), 
456                 input->get_h(),
457                 0, 
458                 0, 
459                 input->get_w(), 
460                 input->get_h(), 
461                 1.0, 
462                 TRANSFER_NORMAL,
463                 NEAREST_NEIGHBOR);
464 //printf("GradientMain::process_realtime 2\n");
466         return 0;
470 void GradientMain::update_gui()
472         if(thread)
473         {
474                 load_configuration();
475                 thread->window->lock_window();
476                 thread->window->angle->update(config.angle);
477                 thread->window->in_radius->update(config.in_radius);
478                 thread->window->out_radius->update(config.out_radius);
479                 thread->window->update_in_color();
480                 thread->window->update_out_color();
481                 thread->window->unlock_window();
482         }
486 int GradientMain::load_defaults()
488         char directory[1024], string[1024];
489 // set the default directory
490         sprintf(directory, "%sgradient.rc", BCASTDIR);
492 // load the defaults
493         defaults = new Defaults(directory);
494         defaults->load();
496 // printf("GradientMain::load_defaults %d %d %d %d\n",
497 // config.out_r,
498 // config.out_g,
499 // config.out_b,
500 // config.out_a);
501         config.angle = defaults->get("ANGLE", config.angle);
502         config.in_radius = defaults->get("IN_RADIUS", config.in_radius);
503         config.out_radius = defaults->get("OUT_RADIUS", config.out_radius);
504         config.in_r = defaults->get("IN_R", config.in_r);
505         config.in_g = defaults->get("IN_G", config.in_g);
506         config.in_b = defaults->get("IN_B", config.in_b);
507         config.in_a = defaults->get("IN_A", config.in_a);
508         config.out_r = defaults->get("OUT_R", config.out_r);
509         config.out_g = defaults->get("OUT_G", config.out_g);
510         config.out_b = defaults->get("OUT_B", config.out_b);
511         config.out_a = defaults->get("OUT_A", config.out_a);
512         return 0;
516 int GradientMain::save_defaults()
518         defaults->update("ANGLE", config.angle);
519         defaults->update("IN_RADIUS", config.in_radius);
520         defaults->update("OUT_RADIUS", config.out_radius);
521         defaults->update("IN_R", config.in_r);
522         defaults->update("IN_G", config.in_g);
523         defaults->update("IN_B", config.in_b);
524         defaults->update("IN_A", config.in_a);
525         defaults->update("OUT_R", config.out_r);
526         defaults->update("OUT_G", config.out_g);
527         defaults->update("OUT_B", config.out_b);
528         defaults->update("OUT_A", config.out_a);
529         defaults->save();
530         return 0;
535 void GradientMain::save_data(KeyFrame *keyframe)
537         FileXML output;
539 // cause data to be stored directly in text
540         output.set_shared_string(keyframe->data, MESSAGESIZE);
541         output.tag.set_title("GRADIENT");
543         output.tag.set_property("ANGLE", config.angle);
544         output.tag.set_property("IN_RADIUS", config.in_radius);
545         output.tag.set_property("OUT_RADIUS", config.out_radius);
546         output.tag.set_property("IN_R", config.in_r);
547         output.tag.set_property("IN_G", config.in_g);
548         output.tag.set_property("IN_B", config.in_b);
549         output.tag.set_property("IN_A", config.in_a);
550         output.tag.set_property("OUT_R", config.out_r);
551         output.tag.set_property("OUT_G", config.out_g);
552         output.tag.set_property("OUT_B", config.out_b);
553         output.tag.set_property("OUT_A", config.out_a);
554         output.append_tag();
555         output.terminate_string();
558 void GradientMain::read_data(KeyFrame *keyframe)
560         FileXML input;
562         input.set_shared_string(keyframe->data, strlen(keyframe->data));
564         int result = 0;
566         while(!result)
567         {
568                 result = input.read_tag();
570                 if(!result)
571                 {
572                         if(input.tag.title_is("GRADIENT"))
573                         {
574                                 config.angle = input.tag.get_property("ANGLE", config.angle);
575                                 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
576                                 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
577                                 config.in_r = input.tag.get_property("IN_R", config.in_r);
578                                 config.in_g = input.tag.get_property("IN_G", config.in_g);
579                                 config.in_b = input.tag.get_property("IN_B", config.in_b);
580                                 config.in_a = input.tag.get_property("IN_A", config.in_a);
581                                 config.out_r = input.tag.get_property("OUT_R", config.out_r);
582                                 config.out_g = input.tag.get_property("OUT_G", config.out_g);
583                                 config.out_b = input.tag.get_property("OUT_B", config.out_b);
584                                 config.out_a = input.tag.get_property("OUT_A", config.out_a);
585                         }
586                 }
587         }
595 GradientPackage::GradientPackage()
596  : LoadPackage()
603 GradientUnit::GradientUnit(GradientServer *server, GradientMain *plugin)
604  : LoadClient(server)
606         this->plugin = plugin;
607         this->server = server;
611 #define SQR(x) ((x) * (x))
614 #define CREATE_GRADIENT(type, components, max) \
615 { \
616 /* Synthesize linear gradient for lookups */ \
618         for(int i = 0; i < gradient_size; i++) \
619         { \
620                 float opacity; \
621                 float transparency; \
622                 if(i < in_radius) \
623                         opacity = 0.0; \
624                 else \
625                 if(i < out_radius) \
626                         opacity = (float)(i - in_radius) / (out_radius - in_radius); \
627                 else \
628                         opacity = 1.0; \
629                 transparency = 1.0 - opacity; \
630                 r_table[i] = (int)(out1 * opacity + in1 * transparency); \
631                 g_table[i] = (int)(out2 * opacity + in2 * transparency); \
632                 b_table[i] = (int)(out3 * opacity + in3 * transparency); \
633                 a_table[i] = (int)(out4 * opacity + in4 * transparency); \
634         } \
636         for(int i = pkg->y1; i < pkg->y2; i++) \
637         { \
638                 type *out_row = (type*)plugin->gradient->get_rows()[i]; \
640                 for(int j = 0; j < w; j++) \
641                 { \
642 /* Convert to polar coords */ \
643                         int x = j - half_w; \
644                         int y = -(i - half_h); \
645                         double magnitude = sqrt(SQR(x) + SQR(y)); \
646                         double angle; \
647                         if(x != 0) \
648                         { \
649                                 angle = atan((float)y / x); \
650                                 if(x > 0 && y < 0) angle = M_PI / 2 - angle; \
651                                 if(x > 0 && y > 0) angle = M_PI / 2 - angle; \
652                                 if(x < 0 && y > 0) angle = -M_PI / 2 - angle; \
653                                 if(x < 0 && y < 0) angle = -M_PI / 2 - angle; \
654                                 if(y == 0 && x > 0) angle = M_PI / 2; \
655                                 if(y == 0 && x < 0) angle = -M_PI / 2; \
656                         } \
657                         else \
658                         if(y > 0) \
659                                 angle = 0; \
660                         else \
661                                 angle = M_PI; \
665 /* Rotate by effect angle */ \
666                         angle -= effect_angle; \
668 /* Convert to cartesian coords */ \
669                         int input_y = (int)(gradient_size / 2 - magnitude * cos(angle)); \
671 /* Get gradient value from these coords */ \
673                         if(input_y < 0) \
674                         { \
675                                 out_row[0] = out1; \
676                                 out_row[1] = out2; \
677                                 out_row[2] = out3; \
678                                 if(components == 4) out_row[3] = out4; \
679                         } \
680                         else \
681                         if(input_y >= gradient_size) \
682                         { \
683                                 out_row[0] = in1; \
684                                 out_row[1] = in2; \
685                                 out_row[2] = in3; \
686                                 if(components == 4) out_row[3] = in4; \
687                         } \
688                         else \
689                         { \
690                                 out_row[0] = r_table[input_y]; \
691                                 out_row[1] = g_table[input_y]; \
692                                 out_row[2] = b_table[input_y]; \
693                                 if(components == 4) out_row[3] = a_table[input_y]; \
694                         } \
696                         out_row += components; \
697                 } \
698         } \
701 void GradientUnit::process_package(LoadPackage *package)
703         GradientPackage *pkg = (GradientPackage*)package;
704         int in1, in2, in3, in4;
705         int out1, out2, out3, out4;
706         int h = plugin->input->get_h();
707         int w = plugin->input->get_w();
708         int half_w = w / 2;
709         int half_h = h / 2;
710         int gradient_size = (int)(sqrt(SQR(w) + SQR(h)) + 1);
711         int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
712         int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
713         double effect_angle = plugin->config.angle / 360 * 2 * M_PI;
714         int r_table[gradient_size];
715         int g_table[gradient_size];
716         int b_table[gradient_size];
717         int a_table[gradient_size];
719         if(in_radius > out_radius)
720         {
721                 in_radius ^= out_radius ^= in_radius ^= out_radius;
722         }
725         switch(plugin->input->get_color_model())
726         {
727                 case BC_RGB888:
728                         in1 = plugin->config.in_r;
729                         in2 = plugin->config.in_g;
730                         in3 = plugin->config.in_b;
731                         in4 = plugin->config.in_a;
732                         out1 = plugin->config.out_r;
733                         out2 = plugin->config.out_g;
734                         out3 = plugin->config.out_b;
735                         out4 = plugin->config.out_a;
736                         CREATE_GRADIENT(unsigned char, 3, 0xff)
737                         break;
738                 case BC_RGBA8888:
739                         in1 = plugin->config.in_r;
740                         in2 = plugin->config.in_g;
741                         in3 = plugin->config.in_b;
742                         in4 = plugin->config.in_a;
743                         out1 = plugin->config.out_r;
744                         out2 = plugin->config.out_g;
745                         out3 = plugin->config.out_b;
746                         out4 = plugin->config.out_a;
747                         CREATE_GRADIENT(unsigned char, 4, 0xff)
748                         break;
749                 case BC_RGB161616:
750                         in1 = (plugin->config.in_r << 8) | plugin->config.in_r;
751                         in2 = (plugin->config.in_g << 8) | plugin->config.in_g;
752                         in3 = (plugin->config.in_b << 8) | plugin->config.in_b;
753                         in4 = (plugin->config.in_a << 8) | plugin->config.in_a;
754                         out1 = (plugin->config.out_r << 8) | plugin->config.out_r;
755                         out2 = (plugin->config.out_g << 8) | plugin->config.out_g;
756                         out3 = (plugin->config.out_b << 8) | plugin->config.out_b;
757                         out4 = (plugin->config.out_a << 8) | plugin->config.out_a;
758                         CREATE_GRADIENT(uint16_t, 3, 0xffff)
759                         break;
760                 case BC_RGBA16161616:
761                         in1 = (plugin->config.in_r << 8) | plugin->config.in_r;
762                         in2 = (plugin->config.in_g << 8) | plugin->config.in_g;
763                         in3 = (plugin->config.in_b << 8) | plugin->config.in_b;
764                         in4 = (plugin->config.in_a << 8) | plugin->config.in_a;
765                         out1 = (plugin->config.out_r << 8) | plugin->config.out_r;
766                         out2 = (plugin->config.out_g << 8) | plugin->config.out_g;
767                         out3 = (plugin->config.out_b << 8) | plugin->config.out_b;
768                         out4 = (plugin->config.out_a << 8) | plugin->config.out_a;
769                         CREATE_GRADIENT(uint16_t, 4, 0xffff)
770                         break;
771                 case BC_YUV888:
772                         yuv.rgb_to_yuv_8(plugin->config.in_r,
773                                 plugin->config.in_g,
774                                 plugin->config.in_b,
775                                 in1,
776                                 in2,
777                                 in3);
778                         in4 = plugin->config.in_a;
779                         yuv.rgb_to_yuv_8(plugin->config.out_r,
780                                 plugin->config.out_g,
781                                 plugin->config.out_b,
782                                 out1,
783                                 out2,
784                                 out3);
785                         out4 = plugin->config.out_a;
786                         CREATE_GRADIENT(unsigned char, 3, 0xff)
787                         break;
788                 case BC_YUVA8888:
789                         yuv.rgb_to_yuv_8(plugin->config.in_r,
790                                 plugin->config.in_g,
791                                 plugin->config.in_b,
792                                 in1,
793                                 in2,
794                                 in3);
795                         in4 = plugin->config.in_a;
796                         yuv.rgb_to_yuv_8(plugin->config.out_r,
797                                 plugin->config.out_g,
798                                 plugin->config.out_b,
799                                 out1,
800                                 out2,
801                                 out3);
802                         out4 = plugin->config.out_a;
803                         CREATE_GRADIENT(unsigned char, 4, 0xff)
804                         break;
805                 case BC_YUV161616:
806                         yuv.rgb_to_yuv_16(
807                                 plugin->config.in_r,
808                                 plugin->config.in_g,
809                                 plugin->config.in_b,
810                                 in1,
811                                 in2,
812                                 in3);
813                         in4 = plugin->config.in_a;
814                         yuv.rgb_to_yuv_16(
815                                 (plugin->config.out_r << 8) | plugin->config.out_r,
816                                 (plugin->config.out_g << 8) | plugin->config.out_g,
817                                 (plugin->config.out_b << 8) | plugin->config.out_b,
818                                 out1,
819                                 out2,
820                                 out3);
821                         out4 = (plugin->config.out_a << 8) | plugin->config.out_a;
822                         CREATE_GRADIENT(uint16_t, 3, 0xffff)
823                         break;
824                 case BC_YUVA16161616:
825                         yuv.rgb_to_yuv_16(
826                                 (plugin->config.in_r << 8) | plugin->config.in_r,
827                                 (plugin->config.in_g << 8) | plugin->config.in_g,
828                                 (plugin->config.in_b << 8) | plugin->config.in_b,
829                                 in1,
830                                 in2,
831                                 in3);
832                         in4 = (plugin->config.in_a << 8) | plugin->config.in_a;
833                         yuv.rgb_to_yuv_16(
834                                 (plugin->config.out_r << 8) | plugin->config.out_r,
835                                 (plugin->config.out_g << 8) | plugin->config.out_g,
836                                 (plugin->config.out_b << 8) | plugin->config.out_b,
837                                 out1,
838                                 out2,
839                                 out3);
840                         out4 = (plugin->config.out_a << 8) | plugin->config.out_a;
841                         CREATE_GRADIENT(uint16_t, 4, 0xffff)
842                         break;
843         }
851 GradientServer::GradientServer(GradientMain *plugin, 
852         int total_clients, 
853         int total_packages)
854  : LoadServer(total_clients, total_packages)
856         this->plugin = plugin;
859 void GradientServer::init_packages()
861         for(int i = 0; i < total_packages; i++)
862         {
863                 GradientPackage *package = (GradientPackage*)packages[i];
864                 package->y1 = plugin->input->get_h() * 
865                         i / 
866                         total_packages;
867                 package->y2 = package->y1 +
868                         plugin->input->get_h() /
869                         total_packages;
870                 if(i >= total_packages - 1) package->y2 = plugin->input->get_h();
871         }
874 LoadClient* GradientServer::new_client()
876         return new GradientUnit(this, plugin);
879 LoadPackage* GradientServer::new_package()
881         return new GradientPackage;