r1007: Make configure detect and work on amd64.
[cinelerra_cv/mob.git] / plugins / linearblur / linearblur.C
blob3738c1e3a0c3cc69d853a00e3842cd5c83f1a700
1 #include <math.h>
2 #include <stdint.h>
3 #include <string.h>
5 #include "bcdisplayinfo.h"
6 #include "clip.h"
7 #include "bchash.h"
8 #include "filexml.h"
9 #include "keyframe.h"
10 #include "language.h"
11 #include "loadbalance.h"
12 #include "picon_png.h"
13 #include "pluginvclient.h"
14 #include "vframe.h"
18 class LinearBlurMain;
19 class LinearBlurEngine;
25 class LinearBlurConfig
27 public:
28         LinearBlurConfig();
30         int equivalent(LinearBlurConfig &that);
31         void copy_from(LinearBlurConfig &that);
32         void interpolate(LinearBlurConfig &prev, 
33                 LinearBlurConfig &next, 
34                 long prev_frame, 
35                 long next_frame, 
36                 long current_frame);
38         int radius;
39         int steps;
40         int angle;
41         int r;
42         int g;
43         int b;
44         int a;
49 class LinearBlurSize : public BC_ISlider
51 public:
52         LinearBlurSize(LinearBlurMain *plugin, 
53                 int x, 
54                 int y, 
55                 int *output,
56                 int min,
57                 int max);
58         int handle_event();
59         LinearBlurMain *plugin;
60         int *output;
63 class LinearBlurToggle : public BC_CheckBox
65 public:
66         LinearBlurToggle(LinearBlurMain *plugin, 
67                 int x, 
68                 int y, 
69                 int *output,
70                 char *string);
71         int handle_event();
72         LinearBlurMain *plugin;
73         int *output;
76 class LinearBlurWindow : public BC_Window
78 public:
79         LinearBlurWindow(LinearBlurMain *plugin, int x, int y);
80         ~LinearBlurWindow();
82         int create_objects();
83         int close_event();
85         LinearBlurSize *angle, *steps, *radius;
86         LinearBlurToggle *r, *g, *b, *a;
87         LinearBlurMain *plugin;
92 PLUGIN_THREAD_HEADER(LinearBlurMain, LinearBlurThread, LinearBlurWindow)
95 // Output coords for a layer of blurring
96 // Used for OpenGL only
97 class LinearBlurLayer
99 public:
100         LinearBlurLayer() {};
101         int x, y;
104 class LinearBlurMain : public PluginVClient
106 public:
107         LinearBlurMain(PluginServer *server);
108         ~LinearBlurMain();
110         int process_buffer(VFrame *frame,
111                 int64_t start_position,
112                 double frame_rate);
113         int is_realtime();
114         int load_defaults();
115         int save_defaults();
116         void save_data(KeyFrame *keyframe);
117         void read_data(KeyFrame *keyframe);
118         void update_gui();
119         int handle_opengl();
121         PLUGIN_CLASS_MEMBERS(LinearBlurConfig, LinearBlurThread)
123         void delete_tables();
124         VFrame *input, *output, *temp;
125         LinearBlurEngine *engine;
126         int **scale_y_table;
127         int **scale_x_table;
128         LinearBlurLayer *layer_table;
129         int table_entries;
130         int need_reconfigure;
131 // The accumulation buffer is needed because 8 bits isn't precise enough
132         unsigned char *accum;
135 class LinearBlurPackage : public LoadPackage
137 public:
138         LinearBlurPackage();
139         int y1, y2;
142 class LinearBlurUnit : public LoadClient
144 public:
145         LinearBlurUnit(LinearBlurEngine *server, LinearBlurMain *plugin);
146         void process_package(LoadPackage *package);
147         LinearBlurEngine *server;
148         LinearBlurMain *plugin;
151 class LinearBlurEngine : public LoadServer
153 public:
154         LinearBlurEngine(LinearBlurMain *plugin, 
155                 int total_clients, 
156                 int total_packages);
157         void init_packages();
158         LoadClient* new_client();
159         LoadPackage* new_package();
160         LinearBlurMain *plugin;
181 REGISTER_PLUGIN(LinearBlurMain)
185 LinearBlurConfig::LinearBlurConfig()
187         radius = 10;
188         angle = 0;
189         steps = 10;
190         r = 1;
191         g = 1;
192         b = 1;
193         a = 1;
196 int LinearBlurConfig::equivalent(LinearBlurConfig &that)
198         return 
199                 radius == that.radius &&
200                 angle == that.angle &&
201                 steps == that.steps &&
202                 r == that.r &&
203                 g == that.g &&
204                 b == that.b &&
205                 a == that.a;
208 void LinearBlurConfig::copy_from(LinearBlurConfig &that)
210         radius = that.radius;
211         angle = that.angle;
212         steps = that.steps;
213         r = that.r;
214         g = that.g;
215         b = that.b;
216         a = that.a;
219 void LinearBlurConfig::interpolate(LinearBlurConfig &prev, 
220         LinearBlurConfig &next, 
221         long prev_frame, 
222         long next_frame, 
223         long current_frame)
225         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
226         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
227         this->radius = (int)(prev.radius * prev_scale + next.radius * next_scale + 0.5);
228         this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale + 0.5);
229         this->steps = (int)(prev.steps * prev_scale + next.steps * next_scale + 0.5);
230         r = prev.r;
231         g = prev.g;
232         b = prev.b;
233         a = prev.a;
244 PLUGIN_THREAD_OBJECT(LinearBlurMain, LinearBlurThread, LinearBlurWindow)
248 LinearBlurWindow::LinearBlurWindow(LinearBlurMain *plugin, int x, int y)
249  : BC_Window(plugin->gui_string, 
250         x,
251         y,
252         230, 
253         290, 
254         230, 
255         290, 
256         0, 
257         1)
259         this->plugin = plugin; 
262 LinearBlurWindow::~LinearBlurWindow()
266 int LinearBlurWindow::create_objects()
268         int x = 10, y = 10;
270         add_subwindow(new BC_Title(x, y, _("Length:")));
271         y += 20;
272         add_subwindow(radius = new LinearBlurSize(plugin, x, y, &plugin->config.radius, 0, 100));
273         y += 30;
274         add_subwindow(new BC_Title(x, y, _("Angle:")));
275         y += 20;
276         add_subwindow(angle = new LinearBlurSize(plugin, x, y, &plugin->config.angle, -180, 180));
277         y += 30;
278         add_subwindow(new BC_Title(x, y, _("Steps:")));
279         y += 20;
280         add_subwindow(steps = new LinearBlurSize(plugin, x, y, &plugin->config.steps, 1, 200));
281         y += 30;
282         add_subwindow(r = new LinearBlurToggle(plugin, x, y, &plugin->config.r, _("Red")));
283         y += 30;
284         add_subwindow(g = new LinearBlurToggle(plugin, x, y, &plugin->config.g, _("Green")));
285         y += 30;
286         add_subwindow(b = new LinearBlurToggle(plugin, x, y, &plugin->config.b, _("Blue")));
287         y += 30;
288         add_subwindow(a = new LinearBlurToggle(plugin, x, y, &plugin->config.a, _("Alpha")));
289         y += 30;
291         show_window();
292         flush();
293         return 0;
296 WINDOW_CLOSE_EVENT(LinearBlurWindow)
307 LinearBlurToggle::LinearBlurToggle(LinearBlurMain *plugin, 
308         int x, 
309         int y, 
310         int *output, 
311         char *string)
312  : BC_CheckBox(x, y, *output, string)
314         this->plugin = plugin;
315         this->output = output;
318 int LinearBlurToggle::handle_event()
320         *output = get_value();
321         plugin->send_configure_change();
322         return 1;
331 LinearBlurSize::LinearBlurSize(LinearBlurMain *plugin, 
332         int x, 
333         int y, 
334         int *output,
335         int min,
336         int max)
337  : BC_ISlider(x, y, 0, 200, 200, min, max, *output)
339         this->plugin = plugin;
340         this->output = output;
342 int LinearBlurSize::handle_event()
344         *output = get_value();
345         plugin->send_configure_change();
346         return 1;
358 LinearBlurMain::LinearBlurMain(PluginServer *server)
359  : PluginVClient(server)
361         PLUGIN_CONSTRUCTOR_MACRO
362         engine = 0;
363         scale_x_table = 0;
364         scale_y_table = 0;
365         table_entries = 0;
366         accum = 0;
367         need_reconfigure = 1;
368         temp = 0;
369         layer_table = 0;
372 LinearBlurMain::~LinearBlurMain()
374         PLUGIN_DESTRUCTOR_MACRO
375         if(engine) delete engine;
376         delete_tables();
377         if(accum) delete [] accum;
378         if(temp) delete temp;
381 char* LinearBlurMain::plugin_title() { return N_("Linear Blur"); }
382 int LinearBlurMain::is_realtime() { return 1; }
385 NEW_PICON_MACRO(LinearBlurMain)
387 SHOW_GUI_MACRO(LinearBlurMain, LinearBlurThread)
389 SET_STRING_MACRO(LinearBlurMain)
391 RAISE_WINDOW_MACRO(LinearBlurMain)
393 LOAD_CONFIGURATION_MACRO(LinearBlurMain, LinearBlurConfig)
395 void LinearBlurMain::delete_tables()
397         if(scale_x_table)
398         {
399                 for(int i = 0; i < table_entries; i++)
400                         delete [] scale_x_table[i];
401                 delete [] scale_x_table;
402         }
404         if(scale_y_table)
405         {
406                 for(int i = 0; i < table_entries; i++)
407                         delete [] scale_y_table[i];
408                 delete [] scale_y_table;
409         }
410         delete [] layer_table;
411         layer_table = 0;
412         scale_x_table = 0;
413         scale_y_table = 0;
414         table_entries = 0;
417 int LinearBlurMain::process_buffer(VFrame *frame,
418                                                         int64_t start_position,
419                                                         double frame_rate)
421         need_reconfigure |= load_configuration();
423         read_frame(frame,
424                 0,
425                 get_source_position(),
426                 get_framerate(),
427                 get_use_opengl());
429 // Generate tables here.  The same table is used by many packages to render
430 // each horizontal stripe.  Need to cover the entire output range in  each
431 // table to avoid green borders
432         if(need_reconfigure)
433         {
434                 int w = frame->get_w();
435                 int h = frame->get_h();
436                 int x_offset;
437                 int y_offset;
438                 int angle = config.angle;
439                 int radius = config.radius * MIN(w, h) / 100;
441                 while(angle < 0) angle += 360;
442                 switch(angle)
443                 {
444                         case 0:
445                         case 360:
446                                 x_offset = radius;
447                                 y_offset = 0;
448                                 break;
449                         case 90:
450                                 x_offset = 0;
451                                 y_offset = radius;
452                                 break;
453                         case 180:
454                                 x_offset = radius;
455                                 y_offset = 0;
456                                 break;
457                         case 270:
458                                 x_offset = 0;
459                                 y_offset = radius;
460                                 break;
461                         default:
462                                 y_offset = (int)(sin((float)config.angle / 360 * 2 * M_PI) * radius);
463                                 x_offset = (int)(cos((float)config.angle / 360 * 2 * M_PI) * radius);
464                                 break;
465                 }
468                 delete_tables();
469                 scale_x_table = new int*[config.steps];
470                 scale_y_table = new int*[config.steps];
471                 table_entries = config.steps;
472                 layer_table = new LinearBlurLayer[table_entries];
474 //printf("LinearBlurMain::process_realtime 1 %d %d %d\n", radius, x_offset, y_offset);
476                 for(int i = 0; i < config.steps; i++)
477                 {
478                         float fraction = (float)(i - config.steps / 2) / config.steps;
479                         int x = (int)(fraction * x_offset);
480                         int y = (int)(fraction * y_offset);
482                         int *x_table;
483                         int *y_table;
484                         scale_y_table[i] = y_table = new int[h];
485                         scale_x_table[i] = x_table = new int[w];
487                         layer_table[i].x = x;
488                         layer_table[i].y = y;
489                         for(int j = 0; j < h; j++)
490                         {
491                                 y_table[j] = j + y;
492                                 CLAMP(y_table[j], 0, h - 1);
493                         }
494                         for(int j = 0; j < w; j++)
495                         {
496                                 x_table[j] = j + x;
497                                 CLAMP(x_table[j], 0, w - 1);
498                         }
499                 }
500                 need_reconfigure = 0;
501         }
503         if(get_use_opengl()) return run_opengl();
506         if(!engine) engine = new LinearBlurEngine(this,
507                 get_project_smp() + 1,
508                 get_project_smp() + 1);
509         if(!accum) accum = new unsigned char[frame->get_w() * 
510                 frame->get_h() *
511                 cmodel_components(frame->get_color_model()) *
512                 MAX(sizeof(int), sizeof(float))];
514         this->input = frame;
515         this->output = frame;
518         if(!temp) temp = new VFrame(0,
519                 frame->get_w(),
520                 frame->get_h(),
521                 frame->get_color_model());
522         temp->copy_from(frame);
523         this->input = temp;
526         bzero(accum, 
527                 frame->get_w() * 
528                 frame->get_h() * 
529                 cmodel_components(frame->get_color_model()) * 
530                 MAX(sizeof(int), sizeof(float)));
531         engine->process_packages();
532         return 0;
536 void LinearBlurMain::update_gui()
538         if(thread)
539         {
540                 load_configuration();
541                 thread->window->lock_window();
542                 thread->window->radius->update(config.radius);
543                 thread->window->angle->update(config.angle);
544                 thread->window->steps->update(config.steps);
545                 thread->window->r->update(config.r);
546                 thread->window->g->update(config.g);
547                 thread->window->b->update(config.b);
548                 thread->window->a->update(config.a);
549                 thread->window->unlock_window();
550         }
554 int LinearBlurMain::load_defaults()
556         char directory[1024], string[1024];
557 // set the default directory
558         sprintf(directory, "%slinearblur.rc", BCASTDIR);
560 // load the defaults
561         defaults = new BC_Hash(directory);
562         defaults->load();
564         config.radius = defaults->get("RADIUS", config.radius);
565         config.angle = defaults->get("ANGLE", config.angle);
566         config.steps = defaults->get("STEPS", config.steps);
567         config.r = defaults->get("R", config.r);
568         config.g = defaults->get("G", config.g);
569         config.b = defaults->get("B", config.b);
570         config.a = defaults->get("A", config.a);
571         return 0;
575 int LinearBlurMain::save_defaults()
577         defaults->update("RADIUS", config.radius);
578         defaults->update("ANGLE", config.angle);
579         defaults->update("STEPS", config.steps);
580         defaults->update("R", config.r);
581         defaults->update("G", config.g);
582         defaults->update("B", config.b);
583         defaults->update("A", config.a);
584         defaults->save();
585         return 0;
590 void LinearBlurMain::save_data(KeyFrame *keyframe)
592         FileXML output;
594 // cause data to be stored directly in text
595         output.set_shared_string(keyframe->data, MESSAGESIZE);
596         output.tag.set_title("LINEARBLUR");
598         output.tag.set_property("RADIUS", config.radius);
599         output.tag.set_property("ANGLE", config.angle);
600         output.tag.set_property("STEPS", config.steps);
601         output.tag.set_property("R", config.r);
602         output.tag.set_property("G", config.g);
603         output.tag.set_property("B", config.b);
604         output.tag.set_property("A", config.a);
605         output.append_tag();
606         output.terminate_string();
609 void LinearBlurMain::read_data(KeyFrame *keyframe)
611         FileXML input;
613         input.set_shared_string(keyframe->data, strlen(keyframe->data));
615         int result = 0;
617         while(!result)
618         {
619                 result = input.read_tag();
621                 if(!result)
622                 {
623                         if(input.tag.title_is("LINEARBLUR"))
624                         {
625                                 config.radius = input.tag.get_property("RADIUS", config.radius);
626                                 config.angle = input.tag.get_property("ANGLE", config.angle);
627                                 config.steps = input.tag.get_property("STEPS", config.steps);
628                                 config.r = input.tag.get_property("R", config.r);
629                                 config.g = input.tag.get_property("G", config.g);
630                                 config.b = input.tag.get_property("B", config.b);
631                                 config.a = input.tag.get_property("A", config.a);
632                         }
633                 }
634         }
637 #ifdef HAVE_GL
638 static void draw_box(float x1, float y1, float x2, float y2)
640         glBegin(GL_QUADS);
641         glVertex3f(x1, y1, 0.0);
642         glVertex3f(x2, y1, 0.0);
643         glVertex3f(x2, y2, 0.0);
644         glVertex3f(x1, y2, 0.0);
645         glEnd();
647 #endif
649 int LinearBlurMain::handle_opengl()
651 #ifdef HAVE_GL
652         get_output()->to_texture();
653         get_output()->enable_opengl();
654         get_output()->init_screen();
655         get_output()->bind_texture(0);
657         int is_yuv = cmodel_is_yuv(get_output()->get_color_model());
658         glClearColor(0.0, 0.0, 0.0, 0.0);
659         glClear(GL_COLOR_BUFFER_BIT);
661 // Draw unselected channels
662         glEnable(GL_BLEND);
663         glBlendFunc(GL_ONE, GL_ONE);
664         glDrawBuffer(GL_BACK);
665         if(!config.r || !config.g || !config.b || !config.a)
666         {
667                 glColor4f(config.r ? 0 : 1, 
668                         config.g ? 0 : 1, 
669                         config.b ? 0 : 1, 
670                         config.a ? 0 : 1);
671                 get_output()->draw_texture();
672         }
673         glAccum(GL_LOAD, 1.0);
675 // Blur selected channels
676         float fraction = 1.0 / config.steps;
677         for(int i = 0; i < config.steps; i++)
678         {
679                 glClear(GL_COLOR_BUFFER_BIT);
680                 glColor4f(config.r ? 1 : 0, 
681                         config.g ? 1 : 0, 
682                         config.b ? 1 : 0, 
683                         config.a ? 1 : 0);
685                 int w = get_output()->get_w();
686                 int h = get_output()->get_h();
687                 get_output()->draw_texture(0,
688                         0,
689                         w,
690                         h,
691                         layer_table[i].x,
692                         get_output()->get_h() - layer_table[i].y,
693                         layer_table[i].x + w,
694                         get_output()->get_h() - layer_table[i].y - h,
695                         1);
698 // Fill YUV black
699                 glDisable(GL_TEXTURE_2D);
700                 if(is_yuv)
701                 {
702                         glColor4f(config.r ? 0.0 : 0, 
703                                 config.g ? 0.5 : 0, 
704                                 config.b ? 0.5 : 0, 
705                                 config.a ? 1.0 : 0);
706                         float center_x1 = 0.0;
707                         float center_x2 = get_output()->get_w();
708                         float project_x1 = layer_table[i].x;
709                         float project_x2 = layer_table[i].x + get_output()->get_w();
710                         float project_y1 = layer_table[i].y;
711                         float project_y2 = layer_table[i].y + get_output()->get_h();
712                         if(project_x1 > 0)
713                         {
714                                 center_x1 = project_x1;
715                                 draw_box(0, 0, project_x1, -get_output()->get_h());
716                         }
717                         if(project_x2 < get_output()->get_w())
718                         {
719                                 center_x2 = project_x2;
720                                 draw_box(project_x2, 0, get_output()->get_w(), -get_output()->get_h());
721                         }
722                         if(project_y1 > 0)
723                         {
724                                 draw_box(center_x1, 
725                                         -get_output()->get_h(), 
726                                         center_x2, 
727                                         -get_output()->get_h() + project_y1);
728                         }
729                         if(project_y2 < get_output()->get_h())
730                         {
731                                 draw_box(center_x1, 
732                                         -get_output()->get_h() + project_y2, 
733                                         center_x2, 
734                                         0);
735                         }
736                 }
741                 glAccum(GL_ACCUM, fraction);
742                 glEnable(GL_TEXTURE_2D);
743                 glColor4f(config.r ? 1 : 0, 
744                         config.g ? 1 : 0, 
745                         config.b ? 1 : 0, 
746                         config.a ? 1 : 0);
747         }
749         glDisable(GL_BLEND);
750         glDisable(GL_TEXTURE_2D);
751         glReadBuffer(GL_BACK);
752         glAccum(GL_RETURN, 1.0);
754         glColor4f(1, 1, 1, 1);
755         get_output()->set_opengl_state(VFrame::SCREEN);
756 #endif
764 LinearBlurPackage::LinearBlurPackage()
765  : LoadPackage()
772 LinearBlurUnit::LinearBlurUnit(LinearBlurEngine *server, 
773         LinearBlurMain *plugin)
774  : LoadClient(server)
776         this->plugin = plugin;
777         this->server = server;
781 #define BLEND_LAYER(COMPONENTS, TYPE, TEMP, MAX, DO_YUV) \
782 { \
783         const int chroma_offset = (DO_YUV ? ((MAX + 1) / 2) : 0); \
784         for(int j = pkg->y1; j < pkg->y2; j++) \
785         { \
786                 TEMP *out_row = (TEMP*)plugin->accum + COMPONENTS * w * j; \
787                 int in_y = y_table[j]; \
789 /* Blend image */ \
790                 TYPE *in_row = (TYPE*)plugin->input->get_rows()[in_y]; \
791                 for(int k = 0; k < w; k++) \
792                 { \
793                         int in_x = x_table[k]; \
794 /* Blend pixel */ \
795                         int in_offset = in_x * COMPONENTS; \
796                         *out_row++ += in_row[in_offset]; \
797                         if(DO_YUV) \
798                         { \
799                                 *out_row++ += in_row[in_offset + 1]; \
800                                 *out_row++ += in_row[in_offset + 2]; \
801                         } \
802                         else \
803                         { \
804                                 *out_row++ += in_row[in_offset + 1]; \
805                                 *out_row++ += in_row[in_offset + 2]; \
806                         } \
807                         if(COMPONENTS == 4) \
808                                 *out_row++ += in_row[in_offset + 3]; \
809                 } \
810         } \
812 /* Copy to output */ \
813         if(i == plugin->config.steps - 1) \
814         { \
815                 for(int j = pkg->y1; j < pkg->y2; j++) \
816                 { \
817                         TEMP *in_row = (TEMP*)plugin->accum + COMPONENTS * w * j; \
818                         TYPE *in_backup = (TYPE*)plugin->input->get_rows()[j]; \
819                         TYPE *out_row = (TYPE*)plugin->output->get_rows()[j]; \
820                         for(int k = 0; k < w; k++) \
821                         { \
822                                 if(do_r) \
823                                 { \
824                                         *out_row++ = (*in_row++ * fraction) / 0x10000; \
825                                         in_backup++; \
826                                 } \
827                                 else \
828                                 { \
829                                         *out_row++ = *in_backup++; \
830                                         in_row++; \
831                                 } \
833                                 if(DO_YUV) \
834                                 { \
835                                         if(do_g) \
836                                         { \
837                                                 *out_row++ = (*in_row++ * fraction) / 0x10000; \
838                                                 in_backup++; \
839                                         } \
840                                         else \
841                                         { \
842                                                 *out_row++ = *in_backup++; \
843                                                 in_row++; \
844                                         } \
846                                         if(do_b) \
847                                         { \
848                                                 *out_row++ = (*in_row++ * fraction) / 0x10000; \
849                                                 in_backup++; \
850                                         } \
851                                         else \
852                                         { \
853                                                 *out_row++ = *in_backup++; \
854                                                 in_row++; \
855                                         } \
856                                 } \
857                                 else \
858                                 { \
859                                         if(do_g) \
860                                         { \
861                                                 *out_row++ = (*in_row++ * fraction) / 0x10000; \
862                                                 in_backup++; \
863                                         } \
864                                         else \
865                                         { \
866                                                 *out_row++ = *in_backup++; \
867                                                 in_row++; \
868                                         } \
870                                         if(do_b) \
871                                         { \
872                                                 *out_row++ = (*in_row++ * fraction) / 0x10000; \
873                                                 in_backup++; \
874                                         } \
875                                         else \
876                                         { \
877                                                 *out_row++ = *in_backup++; \
878                                                 in_row++; \
879                                         } \
880                                 } \
882                                 if(COMPONENTS == 4) \
883                                 { \
884                                         if(do_a) \
885                                         { \
886                                                 *out_row++ = (*in_row++ * fraction) / 0x10000; \
887                                                 in_backup++; \
888                                         } \
889                                         else \
890                                         { \
891                                                 *out_row++ = *in_backup++; \
892                                                 in_row++; \
893                                         } \
894                                 } \
895                         } \
896                 } \
897         } \
900 void LinearBlurUnit::process_package(LoadPackage *package)
902         LinearBlurPackage *pkg = (LinearBlurPackage*)package;
903         int h = plugin->output->get_h();
904         int w = plugin->output->get_w();
906         int fraction = 0x10000 / plugin->config.steps;
907         int do_r = plugin->config.r;
908         int do_g = plugin->config.g;
909         int do_b = plugin->config.b;
910         int do_a = plugin->config.a;
911         for(int i = 0; i < plugin->config.steps; i++)
912         {
913                 int *x_table = plugin->scale_x_table[i];
914                 int *y_table = plugin->scale_y_table[i];
916                 switch(plugin->input->get_color_model())
917                 {
918                         case BC_RGB_FLOAT:
919                                 BLEND_LAYER(3, float, float, 1, 0)
920                                 break;
921                         case BC_RGB888:
922                                 BLEND_LAYER(3, uint8_t, int, 0xff, 0)
923                                 break;
924                         case BC_RGBA_FLOAT:
925                                 BLEND_LAYER(4, float, float, 1, 0)
926                                 break;
927                         case BC_RGBA8888:
928                                 BLEND_LAYER(4, uint8_t, int, 0xff, 0)
929                                 break;
930                         case BC_RGB161616:
931                                 BLEND_LAYER(3, uint16_t, int, 0xffff, 0)
932                                 break;
933                         case BC_RGBA16161616:
934                                 BLEND_LAYER(4, uint16_t, int, 0xffff, 0)
935                                 break;
936                         case BC_YUV888:
937                                 BLEND_LAYER(3, uint8_t, int, 0xff, 1)
938                                 break;
939                         case BC_YUVA8888:
940                                 BLEND_LAYER(4, uint8_t, int, 0xff, 1)
941                                 break;
942                         case BC_YUV161616:
943                                 BLEND_LAYER(3, uint16_t, int, 0xffff, 1)
944                                 break;
945                         case BC_YUVA16161616:
946                                 BLEND_LAYER(4, uint16_t, int, 0xffff, 1)
947                                 break;
948                 }
949         }
957 LinearBlurEngine::LinearBlurEngine(LinearBlurMain *plugin, 
958         int total_clients, 
959         int total_packages)
960  : LoadServer(total_clients, total_packages)
962         this->plugin = plugin;
965 void LinearBlurEngine::init_packages()
967         for(int i = 0; i < get_total_packages(); i++)
968         {
969                 LinearBlurPackage *package = (LinearBlurPackage*)get_package(i);
970                 package->y1 = plugin->output->get_h() * i / get_total_packages();
971                 package->y2 = plugin->output->get_h() * (i + 1) / get_total_packages();
972         }
975 LoadClient* LinearBlurEngine::new_client()
977         return new LinearBlurUnit(this, plugin);
980 LoadPackage* LinearBlurEngine::new_package()
982         return new LinearBlurPackage;