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