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