e389b082f50618325d96fde4af47986a6b4360c0
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / linearblur / linearblur.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22
23 #include <math.h>
24 #include <stdint.h>
25 #include <string.h>
26
27 #include "bcdisplayinfo.h"
28 #include "clip.h"
29 #include "bchash.h"
30 #include "filexml.h"
31 #include "linearblur.h"
32 #include "keyframe.h"
33 #include "language.h"
34 #include "loadbalance.h"
35 #include "pluginvclient.h"
36 #include "vframe.h"
37
38
39
40
41
42
43 REGISTER_PLUGIN(LinearBlurMain)
44
45
46
47
48 LinearBlurConfig::LinearBlurConfig()
49 {
50         reset();
51 }
52
53 void LinearBlurConfig::reset()
54 {
55         radius = 10;
56         angle = 0;
57         steps = 10;
58         r = 1;
59         g = 1;
60         b = 1;
61         a = 1;
62 }
63
64 int LinearBlurConfig::equivalent(LinearBlurConfig &that)
65 {
66         return
67                 radius == that.radius &&
68                 angle == that.angle &&
69                 steps == that.steps &&
70                 r == that.r &&
71                 g == that.g &&
72                 b == that.b &&
73                 a == that.a;
74 }
75
76 void LinearBlurConfig::copy_from(LinearBlurConfig &that)
77 {
78         radius = that.radius;
79         angle = that.angle;
80         steps = that.steps;
81         r = that.r;
82         g = that.g;
83         b = that.b;
84         a = that.a;
85 }
86
87 void LinearBlurConfig::interpolate(LinearBlurConfig &prev,
88         LinearBlurConfig &next,
89         long prev_frame,
90         long next_frame,
91         long current_frame)
92 {
93         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
94         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
95         this->radius = (int)(prev.radius * prev_scale + next.radius * next_scale + 0.5);
96         this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale + 0.5);
97         this->steps = (int)(prev.steps * prev_scale + next.steps * next_scale + 0.5);
98         r = prev.r;
99         g = prev.g;
100         b = prev.b;
101         a = prev.a;
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115 LinearBlurWindow::LinearBlurWindow(LinearBlurMain *plugin)
116  : PluginClientWindow(plugin,
117         230,
118         320,
119         230,
120         320,
121         0)
122 {
123         this->plugin = plugin;
124 }
125
126 LinearBlurWindow::~LinearBlurWindow()
127 {
128 }
129
130 void LinearBlurWindow::create_objects()
131 {
132         int x = 10, y = 10;
133
134         add_subwindow(new BC_Title(x, y, _("Length:")));
135         y += 20;
136         add_subwindow(radius = new LinearBlurSize(plugin, x, y, &plugin->config.radius, 0, 100));
137         y += 30;
138         add_subwindow(new BC_Title(x, y, _("Angle:")));
139         y += 20;
140         add_subwindow(angle = new LinearBlurSize(plugin, x, y, &plugin->config.angle, -180, 180));
141         y += 30;
142         add_subwindow(new BC_Title(x, y, _("Steps:")));
143         y += 20;
144         add_subwindow(steps = new LinearBlurSize(plugin, x, y, &plugin->config.steps, 1, 200));
145         y += 30;
146         add_subwindow(r = new LinearBlurToggle(plugin, x, y, &plugin->config.r, _("Red")));
147         y += 30;
148         add_subwindow(g = new LinearBlurToggle(plugin, x, y, &plugin->config.g, _("Green")));
149         y += 30;
150         add_subwindow(b = new LinearBlurToggle(plugin, x, y, &plugin->config.b, _("Blue")));
151         y += 30;
152         add_subwindow(a = new LinearBlurToggle(plugin, x, y, &plugin->config.a, _("Alpha")));
153         y += 40;
154         add_subwindow(reset = new LinearBlurReset(plugin, this, x, y));
155
156         show_window();
157         flush();
158 }
159
160
161 // for Reset button
162 void LinearBlurWindow::update()
163 {
164         radius->update(plugin->config.radius);
165         angle->update(plugin->config.angle);
166         steps->update(plugin->config.steps);
167         r->update(plugin->config.r);
168         g->update(plugin->config.g);
169         b->update(plugin->config.b);
170         a->update(plugin->config.a);
171 }
172
173
174
175
176
177
178
179
180
181
182 LinearBlurToggle::LinearBlurToggle(LinearBlurMain *plugin,
183         int x,
184         int y,
185         int *output,
186         char *string)
187  : BC_CheckBox(x, y, *output, string)
188 {
189         this->plugin = plugin;
190         this->output = output;
191 }
192
193 int LinearBlurToggle::handle_event()
194 {
195         *output = get_value();
196         plugin->send_configure_change();
197         return 1;
198 }
199
200
201
202
203
204
205
206 LinearBlurSize::LinearBlurSize(LinearBlurMain *plugin,
207         int x,
208         int y,
209         int *output,
210         int min,
211         int max)
212  : BC_ISlider(x, y, 0, 200, 200, min, max, *output)
213 {
214         this->plugin = plugin;
215         this->output = output;
216 }
217 int LinearBlurSize::handle_event()
218 {
219         *output = get_value();
220         plugin->send_configure_change();
221         return 1;
222 }
223
224
225 LinearBlurReset::LinearBlurReset(LinearBlurMain *plugin, LinearBlurWindow *gui, int x, int y)
226  : BC_GenericButton(x, y, _("Reset"))
227 {
228         this->plugin = plugin;
229         this->gui = gui;
230 }
231 LinearBlurReset::~LinearBlurReset()
232 {
233 }
234 int LinearBlurReset::handle_event()
235 {
236         plugin->config.reset();
237         gui->update();
238         plugin->send_configure_change();
239         return 1;
240 }
241
242
243
244
245
246
247
248
249 LinearBlurMain::LinearBlurMain(PluginServer *server)
250  : PluginVClient(server)
251 {
252
253         engine = 0;
254         scale_x_table = 0;
255         scale_y_table = 0;
256         table_entries = 0;
257         accum = 0;
258         need_reconfigure = 1;
259         temp = 0;
260         layer_table = 0;
261 }
262
263 LinearBlurMain::~LinearBlurMain()
264 {
265
266         if(engine) delete engine;
267         delete_tables();
268         if(accum) delete [] accum;
269         if(temp) delete temp;
270 }
271
272 const char* LinearBlurMain::plugin_title() { return N_("Linear Blur"); }
273 int LinearBlurMain::is_realtime() { return 1; }
274
275
276 NEW_WINDOW_MACRO(LinearBlurMain, LinearBlurWindow)
277 LOAD_CONFIGURATION_MACRO(LinearBlurMain, LinearBlurConfig)
278
279 void LinearBlurMain::delete_tables()
280 {
281         if(scale_x_table)
282         {
283                 for(int i = 0; i < table_entries; i++)
284                         delete [] scale_x_table[i];
285                 delete [] scale_x_table;
286         }
287
288         if(scale_y_table)
289         {
290                 for(int i = 0; i < table_entries; i++)
291                         delete [] scale_y_table[i];
292                 delete [] scale_y_table;
293         }
294         delete [] layer_table;
295         layer_table = 0;
296         scale_x_table = 0;
297         scale_y_table = 0;
298         table_entries = 0;
299 }
300
301 int LinearBlurMain::process_buffer(VFrame *frame,
302                                                         int64_t start_position,
303                                                         double frame_rate)
304 {
305         need_reconfigure |= load_configuration();
306
307         read_frame(frame,
308                 0,
309                 get_source_position(),
310                 get_framerate(),
311                 get_use_opengl());
312
313 // Generate tables here.  The same table is used by many packages to render
314 // each horizontal stripe.  Need to cover the entire output range in  each
315 // table to avoid green borders
316         if(need_reconfigure)
317         {
318                 int w = frame->get_w();
319                 int h = frame->get_h();
320                 int x_offset;
321                 int y_offset;
322                 int angle = config.angle;
323                 int radius = config.radius * MIN(w, h) / 100;
324
325                 while(angle < 0) angle += 360;
326                 switch(angle)
327                 {
328                         case 0:
329                         case 360:
330                                 x_offset = radius;
331                                 y_offset = 0;
332                                 break;
333                         case 90:
334                                 x_offset = 0;
335                                 y_offset = radius;
336                                 break;
337                         case 180:
338                                 x_offset = radius;
339                                 y_offset = 0;
340                                 break;
341                         case 270:
342                                 x_offset = 0;
343                                 y_offset = radius;
344                                 break;
345                         default:
346                                 y_offset = (int)(sin((float)config.angle / 360 * 2 * M_PI) * radius);
347                                 x_offset = (int)(cos((float)config.angle / 360 * 2 * M_PI) * radius);
348                                 break;
349                 }
350
351
352                 delete_tables();
353                 scale_x_table = new int*[config.steps];
354                 scale_y_table = new int*[config.steps];
355                 table_entries = config.steps;
356                 layer_table = new LinearBlurLayer[table_entries];
357
358 //printf("LinearBlurMain::process_realtime 1 %d %d %d\n", radius, x_offset, y_offset);
359
360                 for(int i = 0; i < config.steps; i++)
361                 {
362                         float fraction = (float)(i - config.steps / 2) / config.steps;
363                         int x = (int)(fraction * x_offset);
364                         int y = (int)(fraction * y_offset);
365
366                         int *x_table;
367                         int *y_table;
368                         scale_y_table[i] = y_table = new int[h];
369                         scale_x_table[i] = x_table = new int[w];
370
371                         layer_table[i].x = x;
372                         layer_table[i].y = y;
373                         for(int j = 0; j < h; j++)
374                         {
375                                 y_table[j] = j + y;
376                                 CLAMP(y_table[j], 0, h - 1);
377                         }
378                         for(int j = 0; j < w; j++)
379                         {
380                                 x_table[j] = j + x;
381                                 CLAMP(x_table[j], 0, w - 1);
382                         }
383                 }
384                 need_reconfigure = 0;
385         }
386
387         if(get_use_opengl()) return run_opengl();
388
389
390         if(!engine) engine = new LinearBlurEngine(this,
391                 get_project_smp() + 1,
392                 get_project_smp() + 1);
393         if(!accum) accum = new unsigned char[frame->get_w() *
394                 frame->get_h() *
395                 BC_CModels::components(frame->get_color_model()) *
396                 MAX(sizeof(int), sizeof(float))];
397
398         this->input = frame;
399         this->output = frame;
400
401
402         if(!temp)
403                 temp = new VFrame(frame->get_w(), frame->get_h(),
404                         frame->get_color_model(), 0);
405         temp->copy_from(frame);
406         this->input = temp;
407
408
409         bzero(accum,
410                 frame->get_w() *
411                 frame->get_h() *
412                 BC_CModels::components(frame->get_color_model()) *
413                 MAX(sizeof(int), sizeof(float)));
414         engine->process_packages();
415         return 0;
416 }
417
418
419 void LinearBlurMain::update_gui()
420 {
421         if(thread)
422         {
423                 load_configuration();
424                 ((LinearBlurWindow*)thread->window)->lock_window();
425                 ((LinearBlurWindow*)thread->window)->radius->update(config.radius);
426                 ((LinearBlurWindow*)thread->window)->angle->update(config.angle);
427                 ((LinearBlurWindow*)thread->window)->steps->update(config.steps);
428                 ((LinearBlurWindow*)thread->window)->r->update(config.r);
429                 ((LinearBlurWindow*)thread->window)->g->update(config.g);
430                 ((LinearBlurWindow*)thread->window)->b->update(config.b);
431                 ((LinearBlurWindow*)thread->window)->a->update(config.a);
432                 ((LinearBlurWindow*)thread->window)->unlock_window();
433         }
434 }
435
436
437
438 void LinearBlurMain::save_data(KeyFrame *keyframe)
439 {
440         FileXML output;
441
442 // cause data to be stored directly in text
443         output.set_shared_output(keyframe->xbuf);
444         output.tag.set_title("LINEARBLUR");
445
446         output.tag.set_property("RADIUS", config.radius);
447         output.tag.set_property("ANGLE", config.angle);
448         output.tag.set_property("STEPS", config.steps);
449         output.tag.set_property("R", config.r);
450         output.tag.set_property("G", config.g);
451         output.tag.set_property("B", config.b);
452         output.tag.set_property("A", config.a);
453         output.append_tag();
454         output.tag.set_title("/LINEARBLUR");
455         output.append_tag();
456         output.append_newline();
457         output.terminate_string();
458 }
459
460 void LinearBlurMain::read_data(KeyFrame *keyframe)
461 {
462         FileXML input;
463
464         input.set_shared_input(keyframe->xbuf);
465
466         int result = 0;
467
468         while(!result)
469         {
470                 result = input.read_tag();
471
472                 if(!result)
473                 {
474                         if(input.tag.title_is("LINEARBLUR"))
475                         {
476                                 config.radius = input.tag.get_property("RADIUS", config.radius);
477                                 config.angle = input.tag.get_property("ANGLE", config.angle);
478                                 config.steps = input.tag.get_property("STEPS", config.steps);
479                                 config.r = input.tag.get_property("R", config.r);
480                                 config.g = input.tag.get_property("G", config.g);
481                                 config.b = input.tag.get_property("B", config.b);
482                                 config.a = input.tag.get_property("A", config.a);
483                         }
484                 }
485         }
486 }
487
488 #ifdef HAVE_GL
489 static void draw_box(float x1, float y1, float x2, float y2)
490 {
491         glBegin(GL_QUADS);
492         glVertex3f(x1, y1, 0.0);
493         glVertex3f(x2, y1, 0.0);
494         glVertex3f(x2, y2, 0.0);
495         glVertex3f(x1, y2, 0.0);
496         glEnd();
497 }
498 #endif
499
500 int LinearBlurMain::handle_opengl()
501 {
502 #ifdef HAVE_GL
503         get_output()->to_texture();
504         get_output()->enable_opengl();
505         get_output()->init_screen();
506         get_output()->bind_texture(0);
507
508         int is_yuv = BC_CModels::is_yuv(get_output()->get_color_model());
509         glClearColor(0.0, 0.0, 0.0, 0.0);
510         glClear(GL_COLOR_BUFFER_BIT);
511
512 // Draw unselected channels
513         glEnable(GL_BLEND);
514         glBlendFunc(GL_ONE, GL_ONE);
515         glDrawBuffer(GL_BACK);
516         if(!config.r || !config.g || !config.b || !config.a)
517         {
518                 glColor4f(config.r ? 0 : 1,
519                         config.g ? 0 : 1,
520                         config.b ? 0 : 1,
521                         config.a ? 0 : 1);
522                 get_output()->draw_texture();
523         }
524         glAccum(GL_LOAD, 1.0);
525
526 // Blur selected channels
527         float fraction = 1.0 / config.steps;
528         for(int i = 0; i < config.steps; i++)
529         {
530                 glClear(GL_COLOR_BUFFER_BIT);
531                 glColor4f(config.r ? 1 : 0,
532                         config.g ? 1 : 0,
533                         config.b ? 1 : 0,
534                         config.a ? 1 : 0);
535
536                 int w = get_output()->get_w();
537                 int h = get_output()->get_h();
538                 get_output()->draw_texture(0,
539                         0,
540                         w,
541                         h,
542                         layer_table[i].x,
543                         get_output()->get_h() - layer_table[i].y,
544                         layer_table[i].x + w,
545                         get_output()->get_h() - layer_table[i].y - h,
546                         1);
547
548
549 // Fill YUV black
550                 glDisable(GL_TEXTURE_2D);
551                 if(is_yuv)
552                 {
553                         glColor4f(config.r ? 0.0 : 0,
554                                 config.g ? 0.5 : 0,
555                                 config.b ? 0.5 : 0,
556                                 config.a ? 1.0 : 0);
557                         float center_x1 = 0.0;
558                         float center_x2 = get_output()->get_w();
559                         float project_x1 = layer_table[i].x;
560                         float project_x2 = layer_table[i].x + get_output()->get_w();
561                         float project_y1 = layer_table[i].y;
562                         float project_y2 = layer_table[i].y + get_output()->get_h();
563                         if(project_x1 > 0)
564                         {
565                                 center_x1 = project_x1;
566                                 draw_box(0, 0, project_x1, -get_output()->get_h());
567                         }
568                         if(project_x2 < get_output()->get_w())
569                         {
570                                 center_x2 = project_x2;
571                                 draw_box(project_x2, 0, get_output()->get_w(), -get_output()->get_h());
572                         }
573                         if(project_y1 > 0)
574                         {
575                                 draw_box(center_x1,
576                                         -get_output()->get_h(),
577                                         center_x2,
578                                         -get_output()->get_h() + project_y1);
579                         }
580                         if(project_y2 < get_output()->get_h())
581                         {
582                                 draw_box(center_x1,
583                                         -get_output()->get_h() + project_y2,
584                                         center_x2,
585                                         0);
586                         }
587                 }
588
589
590
591
592                 glAccum(GL_ACCUM, fraction);
593                 glEnable(GL_TEXTURE_2D);
594                 glColor4f(config.r ? 1 : 0,
595                         config.g ? 1 : 0,
596                         config.b ? 1 : 0,
597                         config.a ? 1 : 0);
598         }
599
600         glDisable(GL_BLEND);
601         glDisable(GL_TEXTURE_2D);
602         glReadBuffer(GL_BACK);
603         glAccum(GL_RETURN, 1.0);
604
605         glColor4f(1, 1, 1, 1);
606         get_output()->set_opengl_state(VFrame::SCREEN);
607 #endif
608         return 0;
609 }
610
611
612
613
614
615
616 LinearBlurPackage::LinearBlurPackage()
617  : LoadPackage()
618 {
619 }
620
621
622
623
624 LinearBlurUnit::LinearBlurUnit(LinearBlurEngine *server,
625         LinearBlurMain *plugin)
626  : LoadClient(server)
627 {
628         this->plugin = plugin;
629         this->server = server;
630 }
631
632
633 #define BLEND_LAYER(COMPONENTS, TYPE, TEMP, MAX, DO_YUV) \
634 { \
635         for(int j = pkg->y1; j < pkg->y2; j++) \
636         { \
637                 TEMP *out_row = (TEMP*)plugin->accum + COMPONENTS * w * j; \
638                 int in_y = y_table[j]; \
639  \
640 /* Blend image */ \
641                 TYPE *in_row = (TYPE*)plugin->input->get_rows()[in_y]; \
642                 for(int k = 0; k < w; k++) \
643                 { \
644                         int in_x = x_table[k]; \
645 /* Blend pixel */ \
646                         int in_offset = in_x * COMPONENTS; \
647                         *out_row++ += in_row[in_offset]; \
648                         if(DO_YUV) \
649                         { \
650                                 *out_row++ += in_row[in_offset + 1]; \
651                                 *out_row++ += in_row[in_offset + 2]; \
652                         } \
653                         else \
654                         { \
655                                 *out_row++ += in_row[in_offset + 1]; \
656                                 *out_row++ += in_row[in_offset + 2]; \
657                         } \
658                         if(COMPONENTS == 4) \
659                                 *out_row++ += in_row[in_offset + 3]; \
660                 } \
661         } \
662  \
663 /* Copy to output */ \
664         if(i == plugin->config.steps - 1) \
665         { \
666                 for(int j = pkg->y1; j < pkg->y2; j++) \
667                 { \
668                         TEMP *in_row = (TEMP*)plugin->accum + COMPONENTS * w * j; \
669                         TYPE *in_backup = (TYPE*)plugin->input->get_rows()[j]; \
670                         TYPE *out_row = (TYPE*)plugin->output->get_rows()[j]; \
671                         for(int k = 0; k < w; k++) \
672                         { \
673                                 if(do_r) \
674                                 { \
675                                         *out_row++ = (*in_row++ * fraction) / 0x10000; \
676                                         in_backup++; \
677                                 } \
678                                 else \
679                                 { \
680                                         *out_row++ = *in_backup++; \
681                                         in_row++; \
682                                 } \
683  \
684                                 if(DO_YUV) \
685                                 { \
686                                         if(do_g) \
687                                         { \
688                                                 *out_row++ = (*in_row++ * fraction) / 0x10000; \
689                                                 in_backup++; \
690                                         } \
691                                         else \
692                                         { \
693                                                 *out_row++ = *in_backup++; \
694                                                 in_row++; \
695                                         } \
696  \
697                                         if(do_b) \
698                                         { \
699                                                 *out_row++ = (*in_row++ * fraction) / 0x10000; \
700                                                 in_backup++; \
701                                         } \
702                                         else \
703                                         { \
704                                                 *out_row++ = *in_backup++; \
705                                                 in_row++; \
706                                         } \
707                                 } \
708                                 else \
709                                 { \
710                                         if(do_g) \
711                                         { \
712                                                 *out_row++ = (*in_row++ * fraction) / 0x10000; \
713                                                 in_backup++; \
714                                         } \
715                                         else \
716                                         { \
717                                                 *out_row++ = *in_backup++; \
718                                                 in_row++; \
719                                         } \
720  \
721                                         if(do_b) \
722                                         { \
723                                                 *out_row++ = (*in_row++ * fraction) / 0x10000; \
724                                                 in_backup++; \
725                                         } \
726                                         else \
727                                         { \
728                                                 *out_row++ = *in_backup++; \
729                                                 in_row++; \
730                                         } \
731                                 } \
732  \
733                                 if(COMPONENTS == 4) \
734                                 { \
735                                         if(do_a) \
736                                         { \
737                                                 *out_row++ = (*in_row++ * fraction) / 0x10000; \
738                                                 in_backup++; \
739                                         } \
740                                         else \
741                                         { \
742                                                 *out_row++ = *in_backup++; \
743                                                 in_row++; \
744                                         } \
745                                 } \
746                         } \
747                 } \
748         } \
749 }
750
751 void LinearBlurUnit::process_package(LoadPackage *package)
752 {
753         LinearBlurPackage *pkg = (LinearBlurPackage*)package;
754         //int h = plugin->output->get_h();
755         int w = plugin->output->get_w();
756
757         int fraction = 0x10000 / plugin->config.steps;
758         int do_r = plugin->config.r;
759         int do_g = plugin->config.g;
760         int do_b = plugin->config.b;
761         int do_a = plugin->config.a;
762         for(int i = 0; i < plugin->config.steps; i++)
763         {
764                 int *x_table = plugin->scale_x_table[i];
765                 int *y_table = plugin->scale_y_table[i];
766
767                 switch(plugin->input->get_color_model())
768                 {
769                         case BC_RGB_FLOAT:
770                                 BLEND_LAYER(3, float, float, 1, 0)
771                                 break;
772                         case BC_RGB888:
773                                 BLEND_LAYER(3, uint8_t, int, 0xff, 0)
774                                 break;
775                         case BC_RGBA_FLOAT:
776                                 BLEND_LAYER(4, float, float, 1, 0)
777                                 break;
778                         case BC_RGBA8888:
779                                 BLEND_LAYER(4, uint8_t, int, 0xff, 0)
780                                 break;
781                         case BC_RGB161616:
782                                 BLEND_LAYER(3, uint16_t, int, 0xffff, 0)
783                                 break;
784                         case BC_RGBA16161616:
785                                 BLEND_LAYER(4, uint16_t, int, 0xffff, 0)
786                                 break;
787                         case BC_YUV888:
788                                 BLEND_LAYER(3, uint8_t, int, 0xff, 1)
789                                 break;
790                         case BC_YUVA8888:
791                                 BLEND_LAYER(4, uint8_t, int, 0xff, 1)
792                                 break;
793                         case BC_YUV161616:
794                                 BLEND_LAYER(3, uint16_t, int, 0xffff, 1)
795                                 break;
796                         case BC_YUVA16161616:
797                                 BLEND_LAYER(4, uint16_t, int, 0xffff, 1)
798                                 break;
799                 }
800         }
801 }
802
803
804
805
806
807
808 LinearBlurEngine::LinearBlurEngine(LinearBlurMain *plugin,
809         int total_clients,
810         int total_packages)
811  : LoadServer(total_clients, total_packages)
812 {
813         this->plugin = plugin;
814 }
815
816 void LinearBlurEngine::init_packages()
817 {
818         for(int i = 0; i < get_total_packages(); i++)
819         {
820                 LinearBlurPackage *package = (LinearBlurPackage*)get_package(i);
821                 package->y1 = plugin->output->get_h() * i / get_total_packages();
822                 package->y2 = plugin->output->get_h() * (i + 1) / get_total_packages();
823         }
824 }
825
826 LoadClient* LinearBlurEngine::new_client()
827 {
828         return new LinearBlurUnit(this, plugin);
829 }
830
831 LoadPackage* LinearBlurEngine::new_package()
832 {
833         return new LinearBlurPackage;
834 }
835
836
837
838
839