4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
27 REGISTER_PLUGIN(ZoomBlurMain)
31 ZoomBlurConfig::ZoomBlurConfig()
33 reset(RESET_DEFAULT_SETTINGS);
36 void ZoomBlurConfig::reset(int clear)
49 case RESET_XSLIDER : x = 50;
51 case RESET_YSLIDER : y = 50;
53 case RESET_RADIUS : radius = 0;
55 case RESET_STEPS : steps = 1;
57 case RESET_DEFAULT_SETTINGS :
71 int ZoomBlurConfig::equivalent(ZoomBlurConfig &that)
76 radius == that.radius &&
77 steps == that.steps &&
84 void ZoomBlurConfig::copy_from(ZoomBlurConfig &that)
96 void ZoomBlurConfig::interpolate(ZoomBlurConfig &prev,
102 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
103 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
104 this->x = (int)(prev.x * prev_scale + next.x * next_scale + 0.5);
105 this->y = (int)(prev.y * prev_scale + next.y * next_scale + 0.5);
106 this->radius = (int)(prev.radius * prev_scale + next.radius * next_scale + 0.5);
107 this->steps = (int)(prev.steps * prev_scale + next.steps * next_scale + 0.5);
125 ZoomBlurWindow::ZoomBlurWindow(ZoomBlurMain *plugin)
126 : PluginClientWindow(plugin,
133 this->plugin = plugin;
136 ZoomBlurWindow::~ZoomBlurWindow()
140 void ZoomBlurWindow::create_objects()
142 int xs10 = xS(10), xs100 = xS(100), xs200 = xS(200);
143 int ys10 = yS(10), ys30 = yS(30), ys40 = yS(40);
144 int x = xs10, y = ys10;
145 int x2 = xS(80), x3 = xS(180);
146 int clr_x = get_w()-x - xS(22); // note: clrBtn_w = 22
147 int defaultBtn_w = xs100;
152 add_subwindow(new BC_Title(x, y, _("X:")));
153 x_text = new ZoomBlurIText(this, plugin,
154 0, &plugin->config.x, (x + x2), y, XY_MIN, XY_MAX);
155 x_text->create_objects();
156 x_slider = new ZoomBlurISlider(plugin,
157 x_text, &plugin->config.x, x3, y, XY_MIN, XY_MAX, xs200);
158 add_subwindow(x_slider);
159 x_text->slider = x_slider;
160 clr_x = x3 + x_slider->get_w() + x;
161 add_subwindow(x_Clr = new ZoomBlurClr(plugin, this, clr_x, y, RESET_XSLIDER));
164 add_subwindow(new BC_Title(x, y, _("Y:")));
165 y_text = new ZoomBlurIText(this, plugin,
166 0, &plugin->config.y, (x + x2), y, XY_MIN, XY_MAX);
167 y_text->create_objects();
168 y_slider = new ZoomBlurISlider(plugin,
169 y_text, &plugin->config.y, x3, y, XY_MIN, XY_MAX, xs200);
170 add_subwindow(y_slider);
171 y_text->slider = y_slider;
172 add_subwindow(y_Clr = new ZoomBlurClr(plugin, this, clr_x, y, RESET_YSLIDER));
175 add_subwindow(new BC_Title(x, y, _("Radius:")));
176 radius_text = new ZoomBlurIText(this, plugin,
177 0, &plugin->config.radius, (x + x2), y, -RADIUS_MAX, RADIUS_MAX);
178 radius_text->create_objects();
179 radius_slider = new ZoomBlurISlider(plugin,
180 radius_text, &plugin->config.radius, x3, y, -RADIUS_MAX, RADIUS_MAX, xs200);
181 add_subwindow(radius_slider);
182 radius_text->slider = radius_slider;
183 add_subwindow(radius_Clr = new ZoomBlurClr(plugin, this, clr_x, y, RESET_RADIUS));
186 add_subwindow(new BC_Title(x, y, _("Steps:")));
187 steps_text = new ZoomBlurIText(this, plugin,
188 0, &plugin->config.steps, (x + x2), y, STEPS_MIN, STEPS_MAX);
189 steps_text->create_objects();
190 steps_slider = new ZoomBlurISlider(plugin,
191 steps_text, &plugin->config.steps, x3, y, STEPS_MIN, STEPS_MAX, xs200);
192 add_subwindow(steps_slider);
193 steps_text->slider = steps_slider;
194 add_subwindow(steps_Clr = new ZoomBlurClr(plugin, this, clr_x, y, RESET_STEPS));
197 add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
200 int toggle_w = (get_w()-2*x) / 4;
201 add_subwindow(r = new ZoomBlurToggle(plugin, x1, y, &plugin->config.r, _("Red")));
203 add_subwindow(g = new ZoomBlurToggle(plugin, x1, y, &plugin->config.g, _("Green")));
205 add_subwindow(b = new ZoomBlurToggle(plugin, x1, y, &plugin->config.b, _("Blue")));
207 add_subwindow(a = new ZoomBlurToggle(plugin, x1, y, &plugin->config.a, _("Alpha")));
211 add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
213 add_subwindow(reset = new ZoomBlurReset(plugin, this, x, y));
214 add_subwindow(default_settings = new ZoomBlurDefaultSettings(plugin, this,
215 (get_w() - xs10 - defaultBtn_w), y, defaultBtn_w));
222 void ZoomBlurWindow::update_gui(int clear)
226 x_text->update((int64_t)plugin->config.x);
227 x_slider->update(plugin->config.x);
230 y_text->update((int64_t)plugin->config.y);
231 y_slider->update(plugin->config.y);
234 radius_text->update((int64_t)plugin->config.radius);
235 radius_slider->update(plugin->config.radius);
238 steps_text->update((int64_t)plugin->config.steps);
239 steps_slider->update(plugin->config.steps);
242 case RESET_DEFAULT_SETTINGS :
244 x_text->update((int64_t)plugin->config.x);
245 x_slider->update(plugin->config.x);
246 y_text->update((int64_t)plugin->config.y);
247 y_slider->update(plugin->config.y);
248 radius_text->update((int64_t)plugin->config.radius);
249 radius_slider->update(plugin->config.radius);
250 steps_text->update((int64_t)plugin->config.steps);
251 steps_slider->update(plugin->config.steps);
252 r->update(plugin->config.r);
253 g->update(plugin->config.g);
254 b->update(plugin->config.b);
255 a->update(plugin->config.a);
269 ZoomBlurToggle::ZoomBlurToggle(ZoomBlurMain *plugin,
274 : BC_CheckBox(x, y, *output, string)
276 this->plugin = plugin;
277 this->output = output;
280 int ZoomBlurToggle::handle_event()
282 *output = get_value();
283 plugin->send_configure_change();
288 ZoomBlurIText::ZoomBlurIText(ZoomBlurWindow *window, ZoomBlurMain *plugin,
289 ZoomBlurISlider *slider, int *output, int x, int y, int min, int max)
290 : BC_TumbleTextBox(window, *output,
291 min, max, x, y, xS(60), 0)
293 this->window = window;
294 this->plugin = plugin;
295 this->output = output;
296 this->slider = slider;
302 ZoomBlurIText::~ZoomBlurIText()
306 int ZoomBlurIText::handle_event()
308 *output = atoi(get_text());
309 if(*output > max) *output = max;
310 if(*output < min) *output = min;
311 slider->update(*output);
312 plugin->send_configure_change();
317 ZoomBlurISlider::ZoomBlurISlider(ZoomBlurMain *plugin,
318 ZoomBlurIText *text, int *output, int x, int y, int min, int max, int w)
319 : BC_ISlider(x, y, 0, w, w, min, max, *output)
321 this->plugin = plugin;
322 this->output = output;
324 enable_show_value(0); // Hide caption
327 ZoomBlurISlider::~ZoomBlurISlider()
331 int ZoomBlurISlider::handle_event()
333 *output = get_value();
334 text->update((int64_t)*output);
335 plugin->send_configure_change();
340 ZoomBlurReset::ZoomBlurReset(ZoomBlurMain *plugin, ZoomBlurWindow *window, int x, int y)
341 : BC_GenericButton(x, y, _("Reset"))
343 this->plugin = plugin;
344 this->window = window;
346 ZoomBlurReset::~ZoomBlurReset()
349 int ZoomBlurReset::handle_event()
351 plugin->config.reset(RESET_ALL);
352 window->update_gui(RESET_ALL);
353 plugin->send_configure_change();
358 ZoomBlurDefaultSettings::ZoomBlurDefaultSettings(ZoomBlurMain *plugin, ZoomBlurWindow *window, int x, int y, int w)
359 : BC_GenericButton(x, y, w, _("Default"))
361 this->plugin = plugin;
362 this->window = window;
364 ZoomBlurDefaultSettings::~ZoomBlurDefaultSettings()
367 int ZoomBlurDefaultSettings::handle_event()
369 plugin->config.reset(RESET_DEFAULT_SETTINGS);
370 window->update_gui(RESET_DEFAULT_SETTINGS);
371 plugin->send_configure_change();
376 ZoomBlurClr::ZoomBlurClr(ZoomBlurMain *plugin, ZoomBlurWindow *window, int x, int y, int clear)
377 : BC_Button(x, y, plugin->get_theme()->get_image_set("reset_button"))
379 this->plugin = plugin;
380 this->window = window;
383 ZoomBlurClr::~ZoomBlurClr()
386 int ZoomBlurClr::handle_event()
388 // clear==1 ==> X slider
389 // clear==2 ==> Y slider
390 // clear==3 ==> Radius slider
391 // clear==4 ==> Steps slider
392 plugin->config.reset(clear);
393 window->update_gui(clear);
394 plugin->send_configure_change();
401 ZoomBlurMain::ZoomBlurMain(PluginServer *server)
402 : PluginVClient(server)
411 need_reconfigure = 1;
415 ZoomBlurMain::~ZoomBlurMain()
418 if(engine) delete engine;
420 if(accum) delete [] accum;
421 if(temp) delete temp;
424 const char* ZoomBlurMain::plugin_title() { return N_("Zoom Blur"); }
425 int ZoomBlurMain::is_realtime() { return 1; }
429 NEW_WINDOW_MACRO(ZoomBlurMain, ZoomBlurWindow)
431 LOAD_CONFIGURATION_MACRO(ZoomBlurMain, ZoomBlurConfig)
433 void ZoomBlurMain::delete_tables()
437 for(int i = 0; i < table_entries; i++)
438 delete [] scale_x_table[i];
439 delete [] scale_x_table;
444 for(int i = 0; i < table_entries; i++)
445 delete [] scale_y_table[i];
446 delete [] scale_y_table;
449 delete [] layer_table;
456 int ZoomBlurMain::process_buffer(VFrame *frame,
457 int64_t start_position,
460 need_reconfigure |= load_configuration();
466 get_source_position(),
472 // Generate tables here. The same table is used by many packages to render
473 // each horizontal stripe. Need to cover the entire output range in each
474 // table to avoid green borders
478 float w = frame->get_w();
479 float h = frame->get_h();
480 float center_x = (float)config.x / 100 * w;
481 float center_y = (float)config.y / 100 * h;
482 float radius = (float)(100 + config.radius) / 100;
484 //float max_w, max_h;
485 int steps = config.steps ? config.steps : 1;
497 // printf("ZoomBlurMain::process_realtime 1 %d %d\n",
501 center_x = (center_x - w / 2) * (1.0 - radius) + w / 2;
502 center_y = (center_y - h / 2) * (1.0 - radius) + h / 2;
507 min_x1 = center_x - min_w / 2;
508 min_y1 = center_y - min_h / 2;
509 min_x2 = center_x + min_w / 2;
510 min_y2 = center_y + min_h / 2;
517 // printf("ZoomBlurMain::process_realtime 2 w=%f radius=%f center_x=%f\n",
523 // Dimensions of outermost rectangle
526 table_entries = steps;
527 scale_x_table = new int*[steps];
528 scale_y_table = new int*[steps];
529 layer_table = new ZoomBlurLayer[table_entries];
532 for(int i = 0; i < steps; i++)
534 float fraction = (float)i / steps;
535 float inv_fraction = 1.0 - fraction;
536 float out_x1 = min_x1 * fraction + max_x1 * inv_fraction;
537 float out_x2 = min_x2 * fraction + max_x2 * inv_fraction;
538 float out_y1 = min_y1 * fraction + max_y1 * inv_fraction;
539 float out_y2 = min_y2 * fraction + max_y2 * inv_fraction;
540 float out_w = out_x2 - out_x1;
541 float out_h = out_y2 - out_y1;
542 if(out_w < 0) out_w = 0;
543 if(out_h < 0) out_h = 0;
544 float scale_x = (float)w / out_w;
545 float scale_y = (float)h / out_h;
549 scale_y_table[i] = y_table = new int[(int)(h + 1)];
550 scale_x_table[i] = x_table = new int[(int)(w + 1)];
552 layer_table[i].x1 = out_x1;
553 layer_table[i].y1 = out_y1;
554 layer_table[i].x2 = out_x2;
555 layer_table[i].y2 = out_y2;
558 for(int j = 0; j < h; j++)
560 y_table[j] = (int)((j - out_y1) * scale_y);
562 for(int j = 0; j < w; j++)
564 x_table[j] = (int)((j - out_x1) * scale_x);
565 //printf("ZoomBlurMain::process_realtime %d %d\n", j, x_table[j]);
569 need_reconfigure = 0;
573 if(get_use_opengl()) return run_opengl();
579 if(!engine) engine = new ZoomBlurEngine(this,
580 get_project_smp() + 1,
581 get_project_smp() + 1);
582 if(!accum) accum = new unsigned char[frame->get_w() *
584 BC_CModels::components(frame->get_color_model()) *
585 MAX(sizeof(int), sizeof(float))];
588 this->output = frame;
591 if(!temp) temp = new VFrame(frame->get_w(), frame->get_h(),
592 frame->get_color_model(), 0);
593 temp->copy_from(frame);
599 BC_CModels::components(frame->get_color_model()) *
600 MAX(sizeof(int), sizeof(float)));
601 engine->process_packages();
606 void ZoomBlurMain::update_gui()
610 load_configuration();
611 thread->window->lock_window();
612 ((ZoomBlurWindow*)thread->window)->x_text->update((int64_t)config.x);
613 ((ZoomBlurWindow*)thread->window)->x_slider->update(config.x);
614 ((ZoomBlurWindow*)thread->window)->y_text->update((int64_t)config.y);
615 ((ZoomBlurWindow*)thread->window)->y_slider->update(config.y);
616 ((ZoomBlurWindow*)thread->window)->radius_text->update((int64_t)config.radius);
617 ((ZoomBlurWindow*)thread->window)->radius_slider->update(config.radius);
618 ((ZoomBlurWindow*)thread->window)->steps_text->update((int64_t)config.steps);
619 ((ZoomBlurWindow*)thread->window)->steps_slider->update(config.steps);
620 ((ZoomBlurWindow*)thread->window)->r->update(config.r);
621 ((ZoomBlurWindow*)thread->window)->g->update(config.g);
622 ((ZoomBlurWindow*)thread->window)->b->update(config.b);
623 ((ZoomBlurWindow*)thread->window)->a->update(config.a);
624 thread->window->unlock_window();
632 void ZoomBlurMain::save_data(KeyFrame *keyframe)
636 // cause data to be stored directly in text
637 output.set_shared_output(keyframe->xbuf);
638 output.tag.set_title("ZOOMBLUR");
640 output.tag.set_property("X", config.x);
641 output.tag.set_property("Y", config.y);
642 output.tag.set_property("RADIUS", config.radius);
643 output.tag.set_property("STEPS", config.steps);
644 output.tag.set_property("R", config.r);
645 output.tag.set_property("G", config.g);
646 output.tag.set_property("B", config.b);
647 output.tag.set_property("A", config.a);
649 output.tag.set_title("/ZOOMBLUR");
651 output.append_newline();
652 output.terminate_string();
655 void ZoomBlurMain::read_data(KeyFrame *keyframe)
659 input.set_shared_input(keyframe->xbuf);
665 result = input.read_tag();
669 if(input.tag.title_is("ZOOMBLUR"))
671 config.x = input.tag.get_property("X", config.x);
672 config.y = input.tag.get_property("Y", config.y);
673 config.radius = input.tag.get_property("RADIUS", config.radius);
674 config.steps = input.tag.get_property("STEPS", config.steps);
675 config.r = input.tag.get_property("R", config.r);
676 config.g = input.tag.get_property("G", config.g);
677 config.b = input.tag.get_property("B", config.b);
678 config.a = input.tag.get_property("A", config.a);
685 static void draw_box(float x1, float y1, float x2, float y2)
688 glVertex3f(x1, y1, 0.0);
689 glVertex3f(x2, y1, 0.0);
690 glVertex3f(x2, y2, 0.0);
691 glVertex3f(x1, y2, 0.0);
696 int ZoomBlurMain::handle_opengl()
699 get_output()->to_texture();
700 get_output()->enable_opengl();
701 get_output()->init_screen();
702 get_output()->bind_texture(0);
704 //int is_yuv = BC_CModels::is_yuv(get_output()->get_color_model());
705 glClearColor(0.0, 0.0, 0.0, 0.0);
706 glClear(GL_COLOR_BUFFER_BIT);
708 // Draw unselected channels
710 glBlendFunc(GL_ONE, GL_ONE);
711 glDrawBuffer(GL_BACK);
713 if(!config.r || !config.g || !config.b || !config.a)
715 glColor4f(config.r ? 0 : 1,
719 get_output()->draw_texture();
721 glAccum(GL_LOAD, 1.0);
723 // Blur selected channels
724 float fraction = 1.0 / config.steps;
725 for(int i = 0; i < config.steps; i++)
727 glClear(GL_COLOR_BUFFER_BIT);
728 glColor4f(config.r ? 1 : 0,
733 get_output()->draw_texture(0,
735 get_output()->get_w(),
736 get_output()->get_h(),
738 get_output()->get_h() - layer_table[i].y1,
740 get_output()->get_h() - layer_table[i].y2,
744 glDisable(GL_TEXTURE_2D);
745 if(BC_CModels::is_yuv(get_output()->get_color_model()))
747 glColor4f(config.r ? 0.0 : 0,
751 float center_x1 = 0.0;
752 float center_x2 = get_output()->get_w();
753 if(layer_table[i].x1 > 0)
755 center_x1 = layer_table[i].x1;
756 draw_box(0, 0, layer_table[i].x1, -get_output()->get_h());
758 if(layer_table[i].x2 < get_output()->get_w())
760 center_x2 = layer_table[i].x2;
761 draw_box(layer_table[i].x2, 0, get_output()->get_w(), -get_output()->get_h());
763 if(layer_table[i].y1 > 0)
766 -get_output()->get_h(),
768 -get_output()->get_h() + layer_table[i].y1);
770 if(layer_table[i].y2 < get_output()->get_h())
773 -get_output()->get_h() + layer_table[i].y2,
780 glAccum(GL_ACCUM, fraction);
781 glEnable(GL_TEXTURE_2D);
782 glColor4f(config.r ? 1 : 0,
789 glReadBuffer(GL_BACK);
790 glDisable(GL_TEXTURE_2D);
791 glAccum(GL_RETURN, 1.0);
793 glColor4f(1, 1, 1, 1);
794 get_output()->set_opengl_state(VFrame::SCREEN);
812 ZoomBlurPackage::ZoomBlurPackage()
820 ZoomBlurUnit::ZoomBlurUnit(ZoomBlurEngine *server,
821 ZoomBlurMain *plugin)
824 this->plugin = plugin;
825 this->server = server;
829 #define BLEND_LAYER(COMPONENTS, TYPE, TEMP_TYPE, MAX, DO_YUV) \
831 const int chroma_offset = (DO_YUV ? ((MAX + 1) / 2) : 0); \
832 for(int j = pkg->y1; j < pkg->y2; j++) \
834 TEMP_TYPE *out_row = (TEMP_TYPE*)plugin->accum + COMPONENTS * w * j; \
835 int in_y = y_table[j]; \
838 if(in_y >= 0 && in_y < h) \
840 TYPE *in_row = (TYPE*)plugin->input->get_rows()[in_y]; \
841 for(int k = 0; k < w; k++) \
843 int in_x = x_table[k]; \
845 if(in_x >= 0 && in_x < w) \
847 int in_offset = in_x * COMPONENTS; \
848 *out_row++ += in_row[in_offset]; \
851 *out_row++ += in_row[in_offset + 1]; \
852 *out_row++ += in_row[in_offset + 2]; \
856 *out_row++ += (TEMP_TYPE)in_row[in_offset + 1]; \
857 *out_row++ += (TEMP_TYPE)in_row[in_offset + 2]; \
859 if(COMPONENTS == 4) \
860 *out_row++ += in_row[in_offset + 3]; \
862 /* Blend nothing */ \
868 *out_row++ += chroma_offset; \
869 *out_row++ += chroma_offset; \
875 if(COMPONENTS == 4) out_row++; \
882 for(int k = 0; k < w; k++) \
885 *out_row++ += chroma_offset; \
886 *out_row++ += chroma_offset; \
887 if(COMPONENTS == 4) out_row++; \
892 /* Copy just selected blurred channels to output and combine with original \
893 unblurred channels */ \
894 if(i == plugin->config.steps - 1) \
896 for(int j = pkg->y1; j < pkg->y2; j++) \
898 TEMP_TYPE *in_row = (TEMP_TYPE*)plugin->accum + COMPONENTS * w * j; \
899 TYPE *in_backup = (TYPE*)plugin->input->get_rows()[j]; \
900 TYPE *out_row = (TYPE*)plugin->output->get_rows()[j]; \
901 for(int k = 0; k < w; k++) \
905 *out_row++ = (*in_row++ * fraction) / 0x10000; \
910 *out_row++ = *in_backup++; \
918 *out_row++ = ((*in_row++ * fraction) / 0x10000); \
923 *out_row++ = *in_backup++; \
929 *out_row++ = ((*in_row++ * fraction) / 0x10000); \
934 *out_row++ = *in_backup++; \
942 *out_row++ = (*in_row++ * fraction) / 0x10000; \
947 *out_row++ = *in_backup++; \
953 *out_row++ = (*in_row++ * fraction) / 0x10000; \
958 *out_row++ = *in_backup++; \
963 if(COMPONENTS == 4) \
967 *out_row++ = (*in_row++ * fraction) / 0x10000; \
972 *out_row++ = *in_backup++; \
981 void ZoomBlurUnit::process_package(LoadPackage *package)
983 ZoomBlurPackage *pkg = (ZoomBlurPackage*)package;
984 int h = plugin->output->get_h();
985 int w = plugin->output->get_w();
986 int do_r = plugin->config.r;
987 int do_g = plugin->config.g;
988 int do_b = plugin->config.b;
989 int do_a = plugin->config.a;
991 int fraction = 0x10000 / plugin->config.steps;
992 for(int i = 0; i < plugin->config.steps; i++)
994 int *x_table = plugin->scale_x_table[i];
995 int *y_table = plugin->scale_y_table[i];
997 switch(plugin->input->get_color_model())
1000 BLEND_LAYER(3, uint8_t, int, 0xff, 0)
1003 BLEND_LAYER(3, float, float, 1, 0)
1006 BLEND_LAYER(4, float, float, 1, 0)
1009 BLEND_LAYER(4, uint8_t, int, 0xff, 0)
1012 BLEND_LAYER(3, uint16_t, int, 0xffff, 0)
1014 case BC_RGBA16161616:
1015 BLEND_LAYER(4, uint16_t, int, 0xffff, 0)
1018 BLEND_LAYER(3, uint8_t, int, 0xff, 1)
1021 BLEND_LAYER(4, uint8_t, int, 0xff, 1)
1024 BLEND_LAYER(3, uint16_t, int, 0xffff, 1)
1026 case BC_YUVA16161616:
1027 BLEND_LAYER(4, uint16_t, int, 0xffff, 1)
1038 ZoomBlurEngine::ZoomBlurEngine(ZoomBlurMain *plugin,
1041 : LoadServer(total_clients, total_packages)
1043 this->plugin = plugin;
1046 void ZoomBlurEngine::init_packages()
1048 for(int i = 0; i < get_total_packages(); i++)
1050 ZoomBlurPackage *package = (ZoomBlurPackage*)get_package(i);
1051 package->y1 = plugin->output->get_h() * i / get_total_packages();
1052 package->y2 = plugin->output->get_h() * (i + 1) / get_total_packages();
1056 LoadClient* ZoomBlurEngine::new_client()
1058 return new ZoomBlurUnit(this, plugin);
1061 LoadPackage* ZoomBlurEngine::new_package()
1063 return new ZoomBlurPackage;