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