00001 #include <math.h>
00002 #include <stdint.h>
00003 #include <string.h>
00004
00005 #include "bcdisplayinfo.h"
00006 #include "bcsignals.h"
00007 #include "clip.h"
00008 #include "bchash.h"
00009 #include "filexml.h"
00010 #include "keyframe.h"
00011 #include "language.h"
00012 #include "loadbalance.h"
00013 #include "picon_png.h"
00014 #include "pluginvclient.h"
00015 #include "vframe.h"
00016
00017
00018
00019 class ZoomBlurMain;
00020 class ZoomBlurEngine;
00021
00022
00023
00024
00025
00026 class ZoomBlurConfig
00027 {
00028 public:
00029 ZoomBlurConfig();
00030
00031 int equivalent(ZoomBlurConfig &that);
00032 void copy_from(ZoomBlurConfig &that);
00033 void interpolate(ZoomBlurConfig &prev,
00034 ZoomBlurConfig &next,
00035 long prev_frame,
00036 long next_frame,
00037 long current_frame);
00038
00039 int x;
00040 int y;
00041 int radius;
00042 int steps;
00043 int r;
00044 int g;
00045 int b;
00046 int a;
00047 };
00048
00049
00050
00051 class ZoomBlurSize : public BC_ISlider
00052 {
00053 public:
00054 ZoomBlurSize(ZoomBlurMain *plugin,
00055 int x,
00056 int y,
00057 int *output,
00058 int min,
00059 int max);
00060 int handle_event();
00061 ZoomBlurMain *plugin;
00062 int *output;
00063 };
00064
00065 class ZoomBlurToggle : public BC_CheckBox
00066 {
00067 public:
00068 ZoomBlurToggle(ZoomBlurMain *plugin,
00069 int x,
00070 int y,
00071 int *output,
00072 char *string);
00073 int handle_event();
00074 ZoomBlurMain *plugin;
00075 int *output;
00076 };
00077
00078 class ZoomBlurWindow : public BC_Window
00079 {
00080 public:
00081 ZoomBlurWindow(ZoomBlurMain *plugin, int x, int y);
00082 ~ZoomBlurWindow();
00083
00084 int create_objects();
00085 int close_event();
00086
00087 ZoomBlurSize *x, *y, *radius, *steps;
00088 ZoomBlurToggle *r, *g, *b, *a;
00089 ZoomBlurMain *plugin;
00090 };
00091
00092
00093
00094 PLUGIN_THREAD_HEADER(ZoomBlurMain, ZoomBlurThread, ZoomBlurWindow)
00095
00096
00097
00098
00099 class ZoomBlurLayer
00100 {
00101 public:
00102 ZoomBlurLayer() {};
00103 float x1, y1, x2, y2;
00104 };
00105
00106 class ZoomBlurMain : public PluginVClient
00107 {
00108 public:
00109 ZoomBlurMain(PluginServer *server);
00110 ~ZoomBlurMain();
00111
00112 int process_buffer(VFrame *frame,
00113 int64_t start_position,
00114 double frame_rate);
00115 int is_realtime();
00116 int load_defaults();
00117 int save_defaults();
00118 void save_data(KeyFrame *keyframe);
00119 void read_data(KeyFrame *keyframe);
00120 void update_gui();
00121 int handle_opengl();
00122
00123 PLUGIN_CLASS_MEMBERS(ZoomBlurConfig, ZoomBlurThread)
00124
00125 void delete_tables();
00126 VFrame *input, *output, *temp;
00127 ZoomBlurEngine *engine;
00128 int **scale_y_table;
00129 int **scale_x_table;
00130 ZoomBlurLayer *layer_table;
00131 int table_entries;
00132 int need_reconfigure;
00133
00134 unsigned char *accum;
00135 };
00136
00137 class ZoomBlurPackage : public LoadPackage
00138 {
00139 public:
00140 ZoomBlurPackage();
00141 int y1, y2;
00142 };
00143
00144 class ZoomBlurUnit : public LoadClient
00145 {
00146 public:
00147 ZoomBlurUnit(ZoomBlurEngine *server, ZoomBlurMain *plugin);
00148 void process_package(LoadPackage *package);
00149 ZoomBlurEngine *server;
00150 ZoomBlurMain *plugin;
00151 };
00152
00153 class ZoomBlurEngine : public LoadServer
00154 {
00155 public:
00156 ZoomBlurEngine(ZoomBlurMain *plugin,
00157 int total_clients,
00158 int total_packages);
00159 void init_packages();
00160 LoadClient* new_client();
00161 LoadPackage* new_package();
00162 ZoomBlurMain *plugin;
00163 };
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 REGISTER_PLUGIN(ZoomBlurMain)
00184
00185
00186
00187 ZoomBlurConfig::ZoomBlurConfig()
00188 {
00189 x = 50;
00190 y = 50;
00191 radius = 10;
00192 steps = 10;
00193 r = 1;
00194 g = 1;
00195 b = 1;
00196 a = 1;
00197 }
00198
00199 int ZoomBlurConfig::equivalent(ZoomBlurConfig &that)
00200 {
00201 return
00202 x == that.x &&
00203 y == that.y &&
00204 radius == that.radius &&
00205 steps == that.steps &&
00206 r == that.r &&
00207 g == that.g &&
00208 b == that.b &&
00209 a == that.a;
00210 }
00211
00212 void ZoomBlurConfig::copy_from(ZoomBlurConfig &that)
00213 {
00214 x = that.x;
00215 y = that.y;
00216 radius = that.radius;
00217 steps = that.steps;
00218 r = that.r;
00219 g = that.g;
00220 b = that.b;
00221 a = that.a;
00222 }
00223
00224 void ZoomBlurConfig::interpolate(ZoomBlurConfig &prev,
00225 ZoomBlurConfig &next,
00226 long prev_frame,
00227 long next_frame,
00228 long current_frame)
00229 {
00230 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
00231 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
00232 this->x = (int)(prev.x * prev_scale + next.x * next_scale + 0.5);
00233 this->y = (int)(prev.y * prev_scale + next.y * next_scale + 0.5);
00234 this->radius = (int)(prev.radius * prev_scale + next.radius * next_scale + 0.5);
00235 this->steps = (int)(prev.steps * prev_scale + next.steps * next_scale + 0.5);
00236 r = prev.r;
00237 g = prev.g;
00238 b = prev.b;
00239 a = prev.a;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 PLUGIN_THREAD_OBJECT(ZoomBlurMain, ZoomBlurThread, ZoomBlurWindow)
00251
00252
00253
00254 ZoomBlurWindow::ZoomBlurWindow(ZoomBlurMain *plugin, int x, int y)
00255 : BC_Window(plugin->gui_string,
00256 x,
00257 y,
00258 230,
00259 340,
00260 230,
00261 340,
00262 0,
00263 1)
00264 {
00265 this->plugin = plugin;
00266 }
00267
00268 ZoomBlurWindow::~ZoomBlurWindow()
00269 {
00270 }
00271
00272 int ZoomBlurWindow::create_objects()
00273 {
00274 int x = 10, y = 10;
00275
00276 add_subwindow(new BC_Title(x, y, _("X:")));
00277 y += 20;
00278 add_subwindow(this->x = new ZoomBlurSize(plugin, x, y, &plugin->config.x, 0, 100));
00279 y += 30;
00280 add_subwindow(new BC_Title(x, y, _("Y:")));
00281 y += 20;
00282 add_subwindow(this->y = new ZoomBlurSize(plugin, x, y, &plugin->config.y, 0, 100));
00283 y += 30;
00284 add_subwindow(new BC_Title(x, y, _("Radius:")));
00285 y += 20;
00286 add_subwindow(radius = new ZoomBlurSize(plugin, x, y, &plugin->config.radius, -100, 100));
00287 y += 30;
00288 add_subwindow(new BC_Title(x, y, _("Steps:")));
00289 y += 20;
00290 add_subwindow(steps = new ZoomBlurSize(plugin, x, y, &plugin->config.steps, 1, 100));
00291 y += 30;
00292 add_subwindow(r = new ZoomBlurToggle(plugin, x, y, &plugin->config.r, _("Red")));
00293 y += 30;
00294 add_subwindow(g = new ZoomBlurToggle(plugin, x, y, &plugin->config.g, _("Green")));
00295 y += 30;
00296 add_subwindow(b = new ZoomBlurToggle(plugin, x, y, &plugin->config.b, _("Blue")));
00297 y += 30;
00298 add_subwindow(a = new ZoomBlurToggle(plugin, x, y, &plugin->config.a, _("Alpha")));
00299 y += 30;
00300
00301 show_window();
00302 flush();
00303 return 0;
00304 }
00305
00306 int ZoomBlurWindow::close_event()
00307 {
00308
00309 set_done(1);
00310 return 1;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 ZoomBlurToggle::ZoomBlurToggle(ZoomBlurMain *plugin,
00323 int x,
00324 int y,
00325 int *output,
00326 char *string)
00327 : BC_CheckBox(x, y, *output, string)
00328 {
00329 this->plugin = plugin;
00330 this->output = output;
00331 }
00332
00333 int ZoomBlurToggle::handle_event()
00334 {
00335 *output = get_value();
00336 plugin->send_configure_change();
00337 return 1;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346 ZoomBlurSize::ZoomBlurSize(ZoomBlurMain *plugin,
00347 int x,
00348 int y,
00349 int *output,
00350 int min,
00351 int max)
00352 : BC_ISlider(x, y, 0, 200, 200, min, max, *output)
00353 {
00354 this->plugin = plugin;
00355 this->output = output;
00356 }
00357 int ZoomBlurSize::handle_event()
00358 {
00359 *output = get_value();
00360 plugin->send_configure_change();
00361 return 1;
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 ZoomBlurMain::ZoomBlurMain(PluginServer *server)
00374 : PluginVClient(server)
00375 {
00376 PLUGIN_CONSTRUCTOR_MACRO
00377 engine = 0;
00378 scale_x_table = 0;
00379 scale_y_table = 0;
00380 layer_table = 0;
00381 table_entries = 0;
00382 accum = 0;
00383 need_reconfigure = 1;
00384 temp = 0;
00385 }
00386
00387 ZoomBlurMain::~ZoomBlurMain()
00388 {
00389 PLUGIN_DESTRUCTOR_MACRO
00390 if(engine) delete engine;
00391 delete_tables();
00392 if(accum) delete [] accum;
00393 if(temp) delete temp;
00394 }
00395
00396 char* ZoomBlurMain::plugin_title() { return N_("Zoom Blur"); }
00397 int ZoomBlurMain::is_realtime() { return 1; }
00398
00399
00400 NEW_PICON_MACRO(ZoomBlurMain)
00401
00402 SHOW_GUI_MACRO(ZoomBlurMain, ZoomBlurThread)
00403
00404 SET_STRING_MACRO(ZoomBlurMain)
00405
00406 RAISE_WINDOW_MACRO(ZoomBlurMain)
00407
00408 LOAD_CONFIGURATION_MACRO(ZoomBlurMain, ZoomBlurConfig)
00409
00410 void ZoomBlurMain::delete_tables()
00411 {
00412 if(scale_x_table)
00413 {
00414 for(int i = 0; i < table_entries; i++)
00415 delete [] scale_x_table[i];
00416 delete [] scale_x_table;
00417 }
00418
00419 if(scale_y_table)
00420 {
00421 for(int i = 0; i < table_entries; i++)
00422 delete [] scale_y_table[i];
00423 delete [] scale_y_table;
00424 }
00425
00426 delete [] layer_table;
00427 scale_x_table = 0;
00428 scale_y_table = 0;
00429 layer_table = 0;
00430 table_entries = 0;
00431 }
00432
00433 int ZoomBlurMain::process_buffer(VFrame *frame,
00434 int64_t start_position,
00435 double frame_rate)
00436 {
00437 need_reconfigure |= load_configuration();
00438
00439
00440 SET_TRACE
00441 read_frame(frame,
00442 0,
00443 get_source_position(),
00444 get_framerate(),
00445 get_use_opengl());
00446
00447 SET_TRACE
00448
00449
00450
00451
00452 if(need_reconfigure)
00453 {
00454 SET_TRACE
00455 float w = frame->get_w();
00456 float h = frame->get_h();
00457 float center_x = (float)config.x / 100 * w;
00458 float center_y = (float)config.y / 100 * h;
00459 float radius = (float)(100 + config.radius) / 100;
00460 float min_w, min_h;
00461 float max_w, max_h;
00462 int steps = config.steps ? config.steps : 1;
00463 float min_x1;
00464 float min_y1;
00465 float min_x2;
00466 float min_y2;
00467 float max_x1;
00468 float max_y1;
00469 float max_x2;
00470 float max_y2;
00471
00472 SET_TRACE
00473
00474
00475
00476
00477
00478 center_x = (center_x - w / 2) * (1.0 - radius) + w / 2;
00479 center_y = (center_y - h / 2) * (1.0 - radius) + h / 2;
00480 min_w = w * radius;
00481 min_h = h * radius;
00482 max_w = w;
00483 max_h = h;
00484 min_x1 = center_x - min_w / 2;
00485 min_y1 = center_y - min_h / 2;
00486 min_x2 = center_x + min_w / 2;
00487 min_y2 = center_y + min_h / 2;
00488 max_x1 = 0;
00489 max_y1 = 0;
00490 max_x2 = w;
00491 max_y2 = h;
00492
00493 SET_TRACE
00494
00495
00496
00497
00498
00499
00500
00501
00502 delete_tables();
00503 table_entries = steps;
00504 scale_x_table = new int*[steps];
00505 scale_y_table = new int*[steps];
00506 layer_table = new ZoomBlurLayer[table_entries];
00507
00508 SET_TRACE
00509 for(int i = 0; i < steps; i++)
00510 {
00511 float fraction = (float)i / steps;
00512 float inv_fraction = 1.0 - fraction;
00513 float out_x1 = min_x1 * fraction + max_x1 * inv_fraction;
00514 float out_x2 = min_x2 * fraction + max_x2 * inv_fraction;
00515 float out_y1 = min_y1 * fraction + max_y1 * inv_fraction;
00516 float out_y2 = min_y2 * fraction + max_y2 * inv_fraction;
00517 float out_w = out_x2 - out_x1;
00518 float out_h = out_y2 - out_y1;
00519 if(out_w < 0) out_w = 0;
00520 if(out_h < 0) out_h = 0;
00521 float scale_x = (float)w / out_w;
00522 float scale_y = (float)h / out_h;
00523
00524 int *x_table;
00525 int *y_table;
00526 scale_y_table[i] = y_table = new int[(int)(h + 1)];
00527 scale_x_table[i] = x_table = new int[(int)(w + 1)];
00528 SET_TRACE
00529 layer_table[i].x1 = out_x1;
00530 layer_table[i].y1 = out_y1;
00531 layer_table[i].x2 = out_x2;
00532 layer_table[i].y2 = out_y2;
00533 SET_TRACE
00534
00535 for(int j = 0; j < h; j++)
00536 {
00537 y_table[j] = (int)((j - out_y1) * scale_y);
00538 }
00539 for(int j = 0; j < w; j++)
00540 {
00541 x_table[j] = (int)((j - out_x1) * scale_x);
00542
00543 }
00544 }
00545 SET_TRACE
00546 need_reconfigure = 0;
00547 }
00548
00549 SET_TRACE
00550 if(get_use_opengl()) return run_opengl();
00551
00552 SET_TRACE
00553
00554
00555
00556 if(!engine) engine = new ZoomBlurEngine(this,
00557 get_project_smp() + 1,
00558 get_project_smp() + 1);
00559 if(!accum) accum = new unsigned char[frame->get_w() *
00560 frame->get_h() *
00561 cmodel_components(frame->get_color_model()) *
00562 MAX(sizeof(int), sizeof(float))];
00563
00564 this->input = frame;
00565 this->output = frame;
00566
00567
00568 if(!temp) temp = new VFrame(0,
00569 frame->get_w(),
00570 frame->get_h(),
00571 frame->get_color_model());
00572 temp->copy_from(frame);
00573 this->input = temp;
00574
00575 bzero(accum,
00576 frame->get_w() *
00577 frame->get_h() *
00578 cmodel_components(frame->get_color_model()) *
00579 MAX(sizeof(int), sizeof(float)));
00580 engine->process_packages();
00581 return 0;
00582 }
00583
00584
00585 void ZoomBlurMain::update_gui()
00586 {
00587 if(thread)
00588 {
00589 load_configuration();
00590 thread->window->lock_window();
00591 thread->window->x->update(config.x);
00592 thread->window->y->update(config.y);
00593 thread->window->radius->update(config.radius);
00594 thread->window->steps->update(config.steps);
00595 thread->window->r->update(config.r);
00596 thread->window->g->update(config.g);
00597 thread->window->b->update(config.b);
00598 thread->window->a->update(config.a);
00599 thread->window->unlock_window();
00600 }
00601 }
00602
00603
00604 int ZoomBlurMain::load_defaults()
00605 {
00606 char directory[1024], string[1024];
00607
00608 sprintf(directory, "%szoomblur.rc", BCASTDIR);
00609
00610
00611 defaults = new BC_Hash(directory);
00612 defaults->load();
00613
00614 config.x = defaults->get("X", config.x);
00615 config.y = defaults->get("Y", config.y);
00616 config.radius = defaults->get("RADIUS", config.radius);
00617 config.steps = defaults->get("STEPS", config.steps);
00618 config.r = defaults->get("R", config.r);
00619 config.g = defaults->get("G", config.g);
00620 config.b = defaults->get("B", config.b);
00621 config.a = defaults->get("A", config.a);
00622 return 0;
00623 }
00624
00625
00626 int ZoomBlurMain::save_defaults()
00627 {
00628 defaults->update("X", config.x);
00629 defaults->update("Y", config.y);
00630 defaults->update("RADIUS", config.radius);
00631 defaults->update("STEPS", config.steps);
00632 defaults->update("R", config.r);
00633 defaults->update("G", config.g);
00634 defaults->update("B", config.b);
00635 defaults->update("A", config.a);
00636 defaults->save();
00637 return 0;
00638 }
00639
00640
00641
00642 void ZoomBlurMain::save_data(KeyFrame *keyframe)
00643 {
00644 FileXML output;
00645
00646
00647 output.set_shared_string(keyframe->data, MESSAGESIZE);
00648 output.tag.set_title("ZOOMBLUR");
00649
00650 output.tag.set_property("X", config.x);
00651 output.tag.set_property("Y", config.y);
00652 output.tag.set_property("RADIUS", config.radius);
00653 output.tag.set_property("STEPS", config.steps);
00654 output.tag.set_property("R", config.r);
00655 output.tag.set_property("G", config.g);
00656 output.tag.set_property("B", config.b);
00657 output.tag.set_property("A", config.a);
00658 output.append_tag();
00659 output.tag.set_title("/ZOOMBLUR");
00660 output.append_tag();
00661 output.terminate_string();
00662 }
00663
00664 void ZoomBlurMain::read_data(KeyFrame *keyframe)
00665 {
00666 FileXML input;
00667
00668 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00669
00670 int result = 0;
00671
00672 while(!result)
00673 {
00674 result = input.read_tag();
00675
00676 if(!result)
00677 {
00678 if(input.tag.title_is("ZOOMBLUR"))
00679 {
00680 config.x = input.tag.get_property("X", config.x);
00681 config.y = input.tag.get_property("Y", config.y);
00682 config.radius = input.tag.get_property("RADIUS", config.radius);
00683 config.steps = input.tag.get_property("STEPS", config.steps);
00684 config.r = input.tag.get_property("R", config.r);
00685 config.g = input.tag.get_property("G", config.g);
00686 config.b = input.tag.get_property("B", config.b);
00687 config.a = input.tag.get_property("A", config.a);
00688 }
00689 }
00690 }
00691 }
00692
00693 #ifdef HAVE_GL
00694 static void draw_box(float x1, float y1, float x2, float y2)
00695 {
00696 glBegin(GL_QUADS);
00697 glVertex3f(x1, y1, 0.0);
00698 glVertex3f(x2, y1, 0.0);
00699 glVertex3f(x2, y2, 0.0);
00700 glVertex3f(x1, y2, 0.0);
00701 glEnd();
00702 }
00703 #endif
00704
00705 int ZoomBlurMain::handle_opengl()
00706 {
00707 #ifdef HAVE_GL
00708 get_output()->to_texture();
00709 get_output()->enable_opengl();
00710 get_output()->init_screen();
00711 get_output()->bind_texture(0);
00712
00713 int is_yuv = cmodel_is_yuv(get_output()->get_color_model());
00714 glClearColor(0.0, 0.0, 0.0, 0.0);
00715 glClear(GL_COLOR_BUFFER_BIT);
00716
00717
00718 glEnable(GL_BLEND);
00719 glBlendFunc(GL_ONE, GL_ONE);
00720 glDrawBuffer(GL_BACK);
00721
00722 if(!config.r || !config.g || !config.b || !config.a)
00723 {
00724 glColor4f(config.r ? 0 : 1,
00725 config.g ? 0 : 1,
00726 config.b ? 0 : 1,
00727 config.a ? 0 : 1);
00728 get_output()->draw_texture();
00729 }
00730 glAccum(GL_LOAD, 1.0);
00731
00732
00733 float fraction = 1.0 / config.steps;
00734 for(int i = 0; i < config.steps; i++)
00735 {
00736 glClear(GL_COLOR_BUFFER_BIT);
00737 glColor4f(config.r ? 1 : 0,
00738 config.g ? 1 : 0,
00739 config.b ? 1 : 0,
00740 config.a ? 1 : 0);
00741
00742 get_output()->draw_texture(0,
00743 0,
00744 get_output()->get_w(),
00745 get_output()->get_h(),
00746 layer_table[i].x1,
00747 get_output()->get_h() - layer_table[i].y1,
00748 layer_table[i].x2,
00749 get_output()->get_h() - layer_table[i].y2,
00750 1);
00751
00752
00753 glDisable(GL_TEXTURE_2D);
00754 if(cmodel_is_yuv(get_output()->get_color_model()))
00755 {
00756 glColor4f(config.r ? 0.0 : 0,
00757 config.g ? 0.5 : 0,
00758 config.b ? 0.5 : 0,
00759 config.a ? 1.0 : 0);
00760 float center_x1 = 0.0;
00761 float center_x2 = get_output()->get_w();
00762 if(layer_table[i].x1 > 0)
00763 {
00764 center_x1 = layer_table[i].x1;
00765 draw_box(0, 0, layer_table[i].x1, -get_output()->get_h());
00766 }
00767 if(layer_table[i].x2 < get_output()->get_w())
00768 {
00769 center_x2 = layer_table[i].x2;
00770 draw_box(layer_table[i].x2, 0, get_output()->get_w(), -get_output()->get_h());
00771 }
00772 if(layer_table[i].y1 > 0)
00773 {
00774 draw_box(center_x1,
00775 -get_output()->get_h(),
00776 center_x2,
00777 -get_output()->get_h() + layer_table[i].y1);
00778 }
00779 if(layer_table[i].y2 < get_output()->get_h())
00780 {
00781 draw_box(center_x1,
00782 -get_output()->get_h() + layer_table[i].y2,
00783 center_x2,
00784 0);
00785 }
00786 }
00787
00788
00789 glAccum(GL_ACCUM, fraction);
00790 glEnable(GL_TEXTURE_2D);
00791 glColor4f(config.r ? 1 : 0,
00792 config.g ? 1 : 0,
00793 config.b ? 1 : 0,
00794 config.a ? 1 : 0);
00795 }
00796
00797 glDisable(GL_BLEND);
00798 glReadBuffer(GL_BACK);
00799 glDisable(GL_TEXTURE_2D);
00800 glAccum(GL_RETURN, 1.0);
00801
00802 glColor4f(1, 1, 1, 1);
00803 get_output()->set_opengl_state(VFrame::SCREEN);
00804 #endif
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820 ZoomBlurPackage::ZoomBlurPackage()
00821 : LoadPackage()
00822 {
00823 }
00824
00825
00826
00827
00828 ZoomBlurUnit::ZoomBlurUnit(ZoomBlurEngine *server,
00829 ZoomBlurMain *plugin)
00830 : LoadClient(server)
00831 {
00832 this->plugin = plugin;
00833 this->server = server;
00834 }
00835
00836
00837 #define BLEND_LAYER(COMPONENTS, TYPE, TEMP_TYPE, MAX, DO_YUV) \
00838 { \
00839 const int chroma_offset = (DO_YUV ? ((MAX + 1) / 2) : 0); \
00840 for(int j = pkg->y1; j < pkg->y2; j++) \
00841 { \
00842 TEMP_TYPE *out_row = (TEMP_TYPE*)plugin->accum + COMPONENTS * w * j; \
00843 int in_y = y_table[j]; \
00844 \
00845 \
00846 if(in_y >= 0 && in_y < h) \
00847 { \
00848 TYPE *in_row = (TYPE*)plugin->input->get_rows()[in_y]; \
00849 for(int k = 0; k < w; k++) \
00850 { \
00851 int in_x = x_table[k]; \
00852 \
00853 if(in_x >= 0 && in_x < w) \
00854 { \
00855 int in_offset = in_x * COMPONENTS; \
00856 *out_row++ += in_row[in_offset]; \
00857 if(DO_YUV) \
00858 { \
00859 *out_row++ += in_row[in_offset + 1]; \
00860 *out_row++ += in_row[in_offset + 2]; \
00861 } \
00862 else \
00863 { \
00864 *out_row++ += (TEMP_TYPE)in_row[in_offset + 1]; \
00865 *out_row++ += (TEMP_TYPE)in_row[in_offset + 2]; \
00866 } \
00867 if(COMPONENTS == 4) \
00868 *out_row++ += in_row[in_offset + 3]; \
00869 } \
00870 \
00871 else \
00872 { \
00873 out_row++; \
00874 if(DO_YUV) \
00875 { \
00876 *out_row++ += chroma_offset; \
00877 *out_row++ += chroma_offset; \
00878 } \
00879 else \
00880 { \
00881 out_row += 2; \
00882 } \
00883 if(COMPONENTS == 4) out_row++; \
00884 } \
00885 } \
00886 } \
00887 else \
00888 if(DO_YUV) \
00889 { \
00890 for(int k = 0; k < w; k++) \
00891 { \
00892 out_row++; \
00893 *out_row++ += chroma_offset; \
00894 *out_row++ += chroma_offset; \
00895 if(COMPONENTS == 4) out_row++; \
00896 } \
00897 } \
00898 } \
00899 \
00900
00901 \
00902 if(i == plugin->config.steps - 1) \
00903 { \
00904 for(int j = pkg->y1; j < pkg->y2; j++) \
00905 { \
00906 TEMP_TYPE *in_row = (TEMP_TYPE*)plugin->accum + COMPONENTS * w * j; \
00907 TYPE *in_backup = (TYPE*)plugin->input->get_rows()[j]; \
00908 TYPE *out_row = (TYPE*)plugin->output->get_rows()[j]; \
00909 for(int k = 0; k < w; k++) \
00910 { \
00911 if(do_r) \
00912 { \
00913 *out_row++ = (*in_row++ * fraction) / 0x10000; \
00914 in_backup++; \
00915 } \
00916 else \
00917 { \
00918 *out_row++ = *in_backup++; \
00919 in_row++; \
00920 } \
00921 \
00922 if(DO_YUV) \
00923 { \
00924 if(do_g) \
00925 { \
00926 *out_row++ = ((*in_row++ * fraction) / 0x10000); \
00927 in_backup++; \
00928 } \
00929 else \
00930 { \
00931 *out_row++ = *in_backup++; \
00932 in_row++; \
00933 } \
00934 \
00935 if(do_b) \
00936 { \
00937 *out_row++ = ((*in_row++ * fraction) / 0x10000); \
00938 in_backup++; \
00939 } \
00940 else \
00941 { \
00942 *out_row++ = *in_backup++; \
00943 in_row++; \
00944 } \
00945 } \
00946 else \
00947 { \
00948 if(do_g) \
00949 { \
00950 *out_row++ = (*in_row++ * fraction) / 0x10000; \
00951 in_backup++; \
00952 } \
00953 else \
00954 { \
00955 *out_row++ = *in_backup++; \
00956 in_row++; \
00957 } \
00958 \
00959 if(do_b) \
00960 { \
00961 *out_row++ = (*in_row++ * fraction) / 0x10000; \
00962 in_backup++; \
00963 } \
00964 else \
00965 { \
00966 *out_row++ = *in_backup++; \
00967 in_row++; \
00968 } \
00969 } \
00970 \
00971 if(COMPONENTS == 4) \
00972 { \
00973 if(do_a) \
00974 { \
00975 *out_row++ = (*in_row++ * fraction) / 0x10000; \
00976 in_backup++; \
00977 } \
00978 else \
00979 { \
00980 *out_row++ = *in_backup++; \
00981 in_row++; \
00982 } \
00983 } \
00984 } \
00985 } \
00986 } \
00987 }
00988
00989 void ZoomBlurUnit::process_package(LoadPackage *package)
00990 {
00991 ZoomBlurPackage *pkg = (ZoomBlurPackage*)package;
00992 int h = plugin->output->get_h();
00993 int w = plugin->output->get_w();
00994 int do_r = plugin->config.r;
00995 int do_g = plugin->config.g;
00996 int do_b = plugin->config.b;
00997 int do_a = plugin->config.a;
00998
00999 int fraction = 0x10000 / plugin->config.steps;
01000 for(int i = 0; i < plugin->config.steps; i++)
01001 {
01002 int *x_table = plugin->scale_x_table[i];
01003 int *y_table = plugin->scale_y_table[i];
01004
01005 switch(plugin->input->get_color_model())
01006 {
01007 case BC_RGB888:
01008 BLEND_LAYER(3, uint8_t, int, 0xff, 0)
01009 break;
01010 case BC_RGB_FLOAT:
01011 BLEND_LAYER(3, float, float, 1, 0)
01012 break;
01013 case BC_RGBA_FLOAT:
01014 BLEND_LAYER(4, float, float, 1, 0)
01015 break;
01016 case BC_RGBA8888:
01017 BLEND_LAYER(4, uint8_t, int, 0xff, 0)
01018 break;
01019 case BC_RGB161616:
01020 BLEND_LAYER(3, uint16_t, int, 0xffff, 0)
01021 break;
01022 case BC_RGBA16161616:
01023 BLEND_LAYER(4, uint16_t, int, 0xffff, 0)
01024 break;
01025 case BC_YUV888:
01026 BLEND_LAYER(3, uint8_t, int, 0xff, 1)
01027 break;
01028 case BC_YUVA8888:
01029 BLEND_LAYER(4, uint8_t, int, 0xff, 1)
01030 break;
01031 case BC_YUV161616:
01032 BLEND_LAYER(3, uint16_t, int, 0xffff, 1)
01033 break;
01034 case BC_YUVA16161616:
01035 BLEND_LAYER(4, uint16_t, int, 0xffff, 1)
01036 break;
01037 }
01038 }
01039 }
01040
01041
01042
01043
01044
01045
01046 ZoomBlurEngine::ZoomBlurEngine(ZoomBlurMain *plugin,
01047 int total_clients,
01048 int total_packages)
01049 : LoadServer(total_clients, total_packages)
01050 {
01051 this->plugin = plugin;
01052 }
01053
01054 void ZoomBlurEngine::init_packages()
01055 {
01056 for(int i = 0; i < get_total_packages(); i++)
01057 {
01058 ZoomBlurPackage *package = (ZoomBlurPackage*)get_package(i);
01059 package->y1 = plugin->output->get_h() * i / get_total_packages();
01060 package->y2 = plugin->output->get_h() * (i + 1) / get_total_packages();
01061 }
01062 }
01063
01064 LoadClient* ZoomBlurEngine::new_client()
01065 {
01066 return new ZoomBlurUnit(this, plugin);
01067 }
01068
01069 LoadPackage* ZoomBlurEngine::new_package()
01070 {
01071 return new ZoomBlurPackage;
01072 }
01073
01074
01075
01076
01077