00001 #include "filexml.h"
00002 #include "blur.h"
00003 #include "blurwindow.h"
00004 #include "bchash.h"
00005 #include "keyframe.h"
00006 #include "language.h"
00007 #include "picon_png.h"
00008 #include "vframe.h"
00009
00010 #include <math.h>
00011 #include <stdint.h>
00012 #include <string.h>
00013
00014
00015
00016
00017
00018
00019
00020 BlurConfig::BlurConfig()
00021 {
00022 vertical = 1;
00023 horizontal = 1;
00024 radius = 5;
00025 a = r = g = b = 1;
00026 }
00027
00028 int BlurConfig::equivalent(BlurConfig &that)
00029 {
00030 return (vertical == that.vertical &&
00031 horizontal == that.horizontal &&
00032 radius == that.radius &&
00033 a == that.a &&
00034 r == that.r &&
00035 g == that.g &&
00036 b == that.b);
00037 }
00038
00039 void BlurConfig::copy_from(BlurConfig &that)
00040 {
00041 vertical = that.vertical;
00042 horizontal = that.horizontal;
00043 radius = that.radius;
00044 a = that.a;
00045 r = that.r;
00046 g = that.g;
00047 b = that.b;
00048 }
00049
00050 void BlurConfig::interpolate(BlurConfig &prev,
00051 BlurConfig &next,
00052 int64_t prev_frame,
00053 int64_t next_frame,
00054 int64_t current_frame)
00055 {
00056 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
00057 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
00058
00059
00060
00061 this->vertical = (int)(prev.vertical * prev_scale + next.vertical * next_scale);
00062 this->horizontal = (int)(prev.horizontal * prev_scale + next.horizontal * next_scale);
00063 this->radius = (int)(prev.radius * prev_scale + next.radius * next_scale);
00064 a = prev.a;
00065 r = prev.r;
00066 g = prev.g;
00067 b = prev.b;
00068 }
00069
00070
00071
00072
00073
00074
00075 REGISTER_PLUGIN(BlurMain)
00076
00077
00078
00079
00080
00081
00082
00083
00084 BlurMain::BlurMain(PluginServer *server)
00085 : PluginVClient(server)
00086 {
00087 defaults = 0;
00088 temp = 0;
00089 need_reconfigure = 1;
00090 engine = 0;
00091 PLUGIN_CONSTRUCTOR_MACRO
00092 }
00093
00094 BlurMain::~BlurMain()
00095 {
00096
00097 PLUGIN_DESTRUCTOR_MACRO
00098
00099 if(temp) delete temp;
00100 if(engine)
00101 {
00102 for(int i = 0; i < (get_project_smp() + 1); i++)
00103 delete engine[i];
00104 delete [] engine;
00105 }
00106 }
00107
00108 char* BlurMain::plugin_title() { return N_("Blur"); }
00109 int BlurMain::is_realtime() { return 1; }
00110
00111
00112 NEW_PICON_MACRO(BlurMain)
00113
00114 SHOW_GUI_MACRO(BlurMain, BlurThread)
00115
00116 SET_STRING_MACRO(BlurMain)
00117
00118 RAISE_WINDOW_MACRO(BlurMain)
00119
00120 LOAD_CONFIGURATION_MACRO(BlurMain, BlurConfig)
00121
00122
00123
00124
00125 int BlurMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
00126 {
00127 int i, j, k, l;
00128 unsigned char **input_rows, **output_rows;
00129
00130 this->input = input_ptr;
00131 this->output = output_ptr;
00132 need_reconfigure |= load_configuration();
00133
00134
00135
00136 if(need_reconfigure)
00137 {
00138 int y1, y2, y_increment;
00139
00140 if(!engine)
00141 {
00142 engine = new BlurEngine*[(get_project_smp() + 1)];
00143 for(int i = 0; i < (get_project_smp() + 1); i++)
00144 {
00145 engine[i] = new BlurEngine(this,
00146 input->get_h() * i / (get_project_smp() + 1),
00147 input->get_h() * (i + 1) / (get_project_smp() + 1));
00148 engine[i]->start();
00149 }
00150 }
00151
00152 for(i = 0; i < (get_project_smp() + 1); i++)
00153 engine[i]->reconfigure();
00154 need_reconfigure = 0;
00155 }
00156
00157
00158 if(temp &&
00159 (temp->get_w() != input_ptr->get_w() ||
00160 temp->get_h() != input_ptr->get_h()))
00161 {
00162 delete temp;
00163 temp = 0;
00164 }
00165
00166 if(!temp)
00167 temp = new VFrame(0,
00168 input_ptr->get_w(),
00169 input_ptr->get_h(),
00170 input_ptr->get_color_model());
00171
00172 input_rows = input_ptr->get_rows();
00173 output_rows = output_ptr->get_rows();
00174
00175 if(config.radius < 2 ||
00176 (!config.vertical && !config.horizontal))
00177 {
00178
00179 if(input_rows[0] != output_rows[0])
00180 {
00181 output_ptr->copy_from(input_ptr);
00182 }
00183 }
00184 else
00185 {
00186
00187
00188
00189
00190 for(i = 0; i < (get_project_smp() + 1); i++)
00191 {
00192 engine[i]->start_process_frame(output_ptr, input_ptr);
00193 }
00194
00195 for(i = 0; i < (get_project_smp() + 1); i++)
00196 {
00197 engine[i]->wait_process_frame();
00198 }
00199 }
00200
00201 return 0;
00202 }
00203
00204
00205 void BlurMain::update_gui()
00206 {
00207 if(thread)
00208 {
00209 load_configuration();
00210 thread->window->lock_window();
00211 thread->window->horizontal->update(config.horizontal);
00212 thread->window->vertical->update(config.vertical);
00213 thread->window->radius->update(config.radius);
00214 thread->window->a->update(config.a);
00215 thread->window->r->update(config.r);
00216 thread->window->g->update(config.g);
00217 thread->window->b->update(config.b);
00218 thread->window->unlock_window();
00219 }
00220 }
00221
00222
00223 int BlurMain::load_defaults()
00224 {
00225 char directory[1024], string[1024];
00226
00227 sprintf(directory, "%sblur.rc", BCASTDIR);
00228
00229
00230 defaults = new BC_Hash(directory);
00231 defaults->load();
00232
00233 config.vertical = defaults->get("VERTICAL", config.vertical);
00234 config.horizontal = defaults->get("HORIZONTAL", config.horizontal);
00235 config.radius = defaults->get("RADIUS", config.radius);
00236 config.r = defaults->get("R", config.r);
00237 config.g = defaults->get("G", config.g);
00238 config.b = defaults->get("B", config.b);
00239 config.a = defaults->get("A", config.a);
00240 return 0;
00241 }
00242
00243
00244 int BlurMain::save_defaults()
00245 {
00246 defaults->update("VERTICAL", config.vertical);
00247 defaults->update("HORIZONTAL", config.horizontal);
00248 defaults->update("RADIUS", config.radius);
00249 defaults->update("R", config.r);
00250 defaults->update("G", config.g);
00251 defaults->update("B", config.b);
00252 defaults->update("A", config.a);
00253 defaults->save();
00254 return 0;
00255 }
00256
00257
00258
00259 void BlurMain::save_data(KeyFrame *keyframe)
00260 {
00261 FileXML output;
00262
00263
00264 output.set_shared_string(keyframe->data, MESSAGESIZE);
00265 output.tag.set_title("BLUR");
00266 output.tag.set_property("VERTICAL", config.vertical);
00267 output.tag.set_property("HORIZONTAL", config.horizontal);
00268 output.tag.set_property("RADIUS", config.radius);
00269 output.tag.set_property("R", config.r);
00270 output.tag.set_property("G", config.g);
00271 output.tag.set_property("B", config.b);
00272 output.tag.set_property("A", config.a);
00273 output.append_tag();
00274 output.tag.set_title("/BLUR");
00275 output.append_tag();
00276 output.terminate_string();
00277 }
00278
00279 void BlurMain::read_data(KeyFrame *keyframe)
00280 {
00281 FileXML input;
00282
00283 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00284
00285 int result = 0;
00286
00287 while(!result)
00288 {
00289 result = input.read_tag();
00290
00291 if(!result)
00292 {
00293 if(input.tag.title_is("BLUR"))
00294 {
00295 config.vertical = input.tag.get_property("VERTICAL", config.vertical);
00296 config.horizontal = input.tag.get_property("HORIZONTAL", config.horizontal);
00297 config.radius = input.tag.get_property("RADIUS", config.radius);
00298
00299 config.r = input.tag.get_property("R", config.r);
00300 config.g = input.tag.get_property("G", config.g);
00301 config.b = input.tag.get_property("B", config.b);
00302 config.a = input.tag.get_property("A", config.a);
00303 }
00304 }
00305 }
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 BlurEngine::BlurEngine(BlurMain *plugin, int start_out, int end_out)
00317 : Thread()
00318 {
00319 int size = plugin->input->get_w() > plugin->input->get_h() ?
00320 plugin->input->get_w() : plugin->input->get_h();
00321 this->plugin = plugin;
00322 this->start_out = start_out;
00323 this->end_out = end_out;
00324 last_frame = 0;
00325 val_p = new pixel_f[size];
00326 val_m = new pixel_f[size];
00327 src = new pixel_f[size];
00328 dst = new pixel_f[size];
00329 set_synchronous(1);
00330 input_lock.lock();
00331 output_lock.lock();
00332 }
00333
00334 BlurEngine::~BlurEngine()
00335 {
00336 last_frame = 1;
00337 input_lock.unlock();
00338 join();
00339 }
00340
00341 int BlurEngine::start_process_frame(VFrame *output, VFrame *input)
00342 {
00343 this->output = output;
00344 this->input = input;
00345 input_lock.unlock();
00346 return 0;
00347 }
00348
00349 int BlurEngine::wait_process_frame()
00350 {
00351 output_lock.lock();
00352 return 0;
00353 }
00354
00355 void BlurEngine::run()
00356 {
00357 int i, j, k, l;
00358 int strip_size;
00359
00360
00361 while(1)
00362 {
00363 input_lock.lock();
00364 if(last_frame)
00365 {
00366 output_lock.unlock();
00367 return;
00368 }
00369
00370 start_in = start_out - plugin->config.radius;
00371 end_in = end_out + plugin->config.radius;
00372 if(start_in < 0) start_in = 0;
00373 if(end_in > plugin->input->get_h()) end_in = plugin->input->get_h();
00374 strip_size = end_in - start_in;
00375 color_model = input->get_color_model();
00376 int w = input->get_w();
00377 int h = input->get_h();
00378
00379
00380
00381
00382
00383 #define BLUR(type, max, components) \
00384 { \
00385 type **input_rows = (type **)input->get_rows(); \
00386 type **output_rows = (type **)output->get_rows(); \
00387 type **current_input = input_rows; \
00388 type **current_output = output_rows; \
00389 vmax = max; \
00390 \
00391 if(plugin->config.vertical) \
00392 { \
00393 \
00394 if(plugin->config.horizontal) \
00395 { \
00396 current_output = (type **)plugin->temp->get_rows(); \
00397 } \
00398 \
00399 for(j = 0; j < w; j++) \
00400 { \
00401 bzero(val_p, sizeof(pixel_f) * (end_in - start_in)); \
00402 bzero(val_m, sizeof(pixel_f) * (end_in - start_in)); \
00403 \
00404 for(l = 0, k = start_in; k < end_in; l++, k++) \
00405 { \
00406 if(plugin->config.r) src[l].r = (float)current_input[k][j * components]; \
00407 if(plugin->config.g) src[l].g = (float)current_input[k][j * components + 1]; \
00408 if(plugin->config.b) src[l].b = (float)current_input[k][j * components + 2]; \
00409 if(components == 4) \
00410 if(plugin->config.a) src[l].a = (float)current_input[k][j * components + 3]; \
00411 } \
00412 \
00413 if(components == 4) \
00414 blur_strip4(strip_size); \
00415 else \
00416 blur_strip3(strip_size); \
00417 \
00418 for(l = start_out - start_in, k = start_out; k < end_out; l++, k++) \
00419 { \
00420 if(plugin->config.r) current_output[k][j * components] = (type)dst[l].r; \
00421 if(plugin->config.g) current_output[k][j * components + 1] = (type)dst[l].g; \
00422 if(plugin->config.b) current_output[k][j * components + 2] = (type)dst[l].b; \
00423 if(components == 4) \
00424 if(plugin->config.a) current_output[k][j * components + 3] = (type)dst[l].a; \
00425 } \
00426 } \
00427 \
00428 current_input = current_output; \
00429 current_output = output_rows; \
00430 } \
00431 \
00432 \
00433 if(plugin->config.horizontal) \
00434 { \
00435 \
00436 for(j = start_out; j < end_out; j++) \
00437 { \
00438 bzero(val_p, sizeof(pixel_f) * w); \
00439 bzero(val_m, sizeof(pixel_f) * w); \
00440 \
00441 for(k = 0; k < w; k++) \
00442 { \
00443 if(plugin->config.r) src[k].r = (float)current_input[j][k * components]; \
00444 if(plugin->config.g) src[k].g = (float)current_input[j][k * components + 1]; \
00445 if(plugin->config.b) src[k].b = (float)current_input[j][k * components + 2]; \
00446 if(components == 4) \
00447 if(plugin->config.a) src[k].a = (float)current_input[j][k * components + 3]; \
00448 } \
00449 \
00450 if(components == 4) \
00451 blur_strip4(w); \
00452 else \
00453 blur_strip3(w); \
00454 \
00455 for(k = 0; k < w; k++) \
00456 { \
00457 if(plugin->config.r) current_output[j][k * components] = (type)dst[k].r; \
00458 if(plugin->config.g) current_output[j][k * components + 1] = (type)dst[k].g; \
00459 if(plugin->config.b) current_output[j][k * components + 2] = (type)dst[k].b; \
00460 if(components == 4) \
00461 if(plugin->config.a) current_output[j][k * components + 3] = (type)dst[k].a; \
00462 } \
00463 } \
00464 } \
00465 }
00466
00467
00468
00469 switch(color_model)
00470 {
00471 case BC_RGB888:
00472 case BC_YUV888:
00473 BLUR(unsigned char, 0xff, 3);
00474 break;
00475 case BC_RGB_FLOAT:
00476 BLUR(float, 1.0, 3);
00477 break;
00478 case BC_RGBA8888:
00479 case BC_YUVA8888:
00480 BLUR(unsigned char, 0xff, 4);
00481 break;
00482 case BC_RGBA_FLOAT:
00483 BLUR(float, 1.0, 4);
00484 break;
00485 case BC_RGB161616:
00486 case BC_YUV161616:
00487 BLUR(uint16_t, 0xffff, 3);
00488 break;
00489 case BC_RGBA16161616:
00490 case BC_YUVA16161616:
00491 BLUR(uint16_t, 0xffff, 4);
00492 break;
00493 }
00494
00495 output_lock.unlock();
00496 }
00497 }
00498
00499 int BlurEngine::reconfigure()
00500 {
00501 std_dev = sqrt(-(double)(plugin->config.radius * plugin->config.radius) /
00502 (2 * log (1.0 / 255.0)));
00503 get_constants();
00504 }
00505
00506 int BlurEngine::get_constants()
00507 {
00508 int i;
00509 double constants[8];
00510 double div;
00511
00512 div = sqrt(2 * M_PI) * std_dev;
00513 constants[0] = -1.783 / std_dev;
00514 constants[1] = -1.723 / std_dev;
00515 constants[2] = 0.6318 / std_dev;
00516 constants[3] = 1.997 / std_dev;
00517 constants[4] = 1.6803 / div;
00518 constants[5] = 3.735 / div;
00519 constants[6] = -0.6803 / div;
00520 constants[7] = -0.2598 / div;
00521
00522 n_p[0] = constants[4] + constants[6];
00523 n_p[1] = exp(constants[1]) *
00524 (constants[7] * sin(constants[3]) -
00525 (constants[6] + 2 * constants[4]) * cos(constants[3])) +
00526 exp(constants[0]) *
00527 (constants[5] * sin(constants[2]) -
00528 (2 * constants[6] + constants[4]) * cos(constants[2]));
00529
00530 n_p[2] = 2 * exp(constants[0] + constants[1]) *
00531 ((constants[4] + constants[6]) * cos(constants[3]) *
00532 cos(constants[2]) - constants[5] *
00533 cos(constants[3]) * sin(constants[2]) -
00534 constants[7] * cos(constants[2]) * sin(constants[3])) +
00535 constants[6] * exp(2 * constants[0]) +
00536 constants[4] * exp(2 * constants[1]);
00537
00538 n_p[3] = exp(constants[1] + 2 * constants[0]) *
00539 (constants[7] * sin(constants[3]) -
00540 constants[6] * cos(constants[3])) +
00541 exp(constants[0] + 2 * constants[1]) *
00542 (constants[5] * sin(constants[2]) - constants[4] *
00543 cos(constants[2]));
00544 n_p[4] = 0.0;
00545
00546 d_p[0] = 0.0;
00547 d_p[1] = -2 * exp(constants[1]) * cos(constants[3]) -
00548 2 * exp(constants[0]) * cos(constants[2]);
00549
00550 d_p[2] = 4 * cos(constants[3]) * cos(constants[2]) *
00551 exp(constants[0] + constants[1]) +
00552 exp(2 * constants[1]) + exp (2 * constants[0]);
00553
00554 d_p[3] = -2 * cos(constants[2]) * exp(constants[0] + 2 * constants[1]) -
00555 2 * cos(constants[3]) * exp(constants[1] + 2 * constants[0]);
00556
00557 d_p[4] = exp(2 * constants[0] + 2 * constants[1]);
00558
00559 for(i = 0; i < 5; i++) d_m[i] = d_p[i];
00560
00561 n_m[0] = 0.0;
00562 for(i = 1; i <= 4; i++)
00563 n_m[i] = n_p[i] - d_p[i] * n_p[0];
00564
00565 double sum_n_p, sum_n_m, sum_d;
00566 double a, b;
00567
00568 sum_n_p = 0.0;
00569 sum_n_m = 0.0;
00570 sum_d = 0.0;
00571 for(i = 0; i < 5; i++)
00572 {
00573 sum_n_p += n_p[i];
00574 sum_n_m += n_m[i];
00575 sum_d += d_p[i];
00576 }
00577
00578 a = sum_n_p / (1 + sum_d);
00579 b = sum_n_m / (1 + sum_d);
00580
00581 for (i = 0; i < 5; i++)
00582 {
00583 bd_p[i] = d_p[i] * a;
00584 bd_m[i] = d_m[i] * b;
00585 }
00586 return 0;
00587 }
00588
00589 #define BOUNDARY(x) if((x) > vmax) (x) = vmax; else if((x) < 0) (x) = 0;
00590
00591 int BlurEngine::transfer_pixels(pixel_f *src1, pixel_f *src2, pixel_f *dest, int size)
00592 {
00593 int i;
00594 float sum;
00595
00596
00597
00598
00599
00600
00601
00602 for(i = 0; i < size; i++)
00603 {
00604 sum = src1[i].r + src2[i].r;
00605 BOUNDARY(sum);
00606 dest[i].r = sum;
00607 sum = src1[i].g + src2[i].g;
00608 BOUNDARY(sum);
00609 dest[i].g = sum;
00610 sum = src1[i].b + src2[i].b;
00611 BOUNDARY(sum);
00612 dest[i].b = sum;
00613 sum = src1[i].a + src2[i].a;
00614 BOUNDARY(sum);
00615 dest[i].a = sum;
00616 }
00617 return 0;
00618 }
00619
00620
00621 int BlurEngine::multiply_alpha(pixel_f *row, int size)
00622 {
00623 register int i;
00624 register float alpha;
00625
00626
00627
00628
00629
00630
00631
00632
00633 return 0;
00634 }
00635
00636 int BlurEngine::separate_alpha(pixel_f *row, int size)
00637 {
00638 register int i;
00639 register float alpha;
00640 register float result;
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655 return 0;
00656 }
00657
00658 int BlurEngine::blur_strip3(int &size)
00659 {
00660 multiply_alpha(src, size);
00661
00662 sp_p = src;
00663 sp_m = src + size - 1;
00664 vp = val_p;
00665 vm = val_m + size - 1;
00666
00667 initial_p = sp_p[0];
00668 initial_m = sp_m[0];
00669
00670 int l;
00671 for(int k = 0; k < size; k++)
00672 {
00673 terms = (k < 4) ? k : 4;
00674 for(l = 0; l <= terms; l++)
00675 {
00676 if(plugin->config.r)
00677 {
00678 vp->r += n_p[l] * sp_p[-l].r - d_p[l] * vp[-l].r;
00679 vm->r += n_m[l] * sp_m[l].r - d_m[l] * vm[l].r;
00680 }
00681 if(plugin->config.g)
00682 {
00683 vp->g += n_p[l] * sp_p[-l].g - d_p[l] * vp[-l].g;
00684 vm->g += n_m[l] * sp_m[l].g - d_m[l] * vm[l].g;
00685 }
00686 if(plugin->config.b)
00687 {
00688 vp->b += n_p[l] * sp_p[-l].b - d_p[l] * vp[-l].b;
00689 vm->b += n_m[l] * sp_m[l].b - d_m[l] * vm[l].b;
00690 }
00691 }
00692 for( ; l <= 4; l++)
00693 {
00694 if(plugin->config.r)
00695 {
00696 vp->r += (n_p[l] - bd_p[l]) * initial_p.r;
00697 vm->r += (n_m[l] - bd_m[l]) * initial_m.r;
00698 }
00699 if(plugin->config.g)
00700 {
00701 vp->g += (n_p[l] - bd_p[l]) * initial_p.g;
00702 vm->g += (n_m[l] - bd_m[l]) * initial_m.g;
00703 }
00704 if(plugin->config.b)
00705 {
00706 vp->b += (n_p[l] - bd_p[l]) * initial_p.b;
00707 vm->b += (n_m[l] - bd_m[l]) * initial_m.b;
00708 }
00709 }
00710 sp_p++;
00711 sp_m--;
00712 vp++;
00713 vm--;
00714 }
00715 transfer_pixels(val_p, val_m, dst, size);
00716 separate_alpha(dst, size);
00717 return 0;
00718 }
00719
00720
00721 int BlurEngine::blur_strip4(int &size)
00722 {
00723 multiply_alpha(src, size);
00724
00725 sp_p = src;
00726 sp_m = src + size - 1;
00727 vp = val_p;
00728 vm = val_m + size - 1;
00729
00730 initial_p = sp_p[0];
00731 initial_m = sp_m[0];
00732
00733 int l;
00734 for(int k = 0; k < size; k++)
00735 {
00736 terms = (k < 4) ? k : 4;
00737
00738 for(l = 0; l <= terms; l++)
00739 {
00740 if(plugin->config.r)
00741 {
00742 vp->r += n_p[l] * sp_p[-l].r - d_p[l] * vp[-l].r;
00743 vm->r += n_m[l] * sp_m[l].r - d_m[l] * vm[l].r;
00744 }
00745 if(plugin->config.g)
00746 {
00747 vp->g += n_p[l] * sp_p[-l].g - d_p[l] * vp[-l].g;
00748 vm->g += n_m[l] * sp_m[l].g - d_m[l] * vm[l].g;
00749 }
00750 if(plugin->config.b)
00751 {
00752 vp->b += n_p[l] * sp_p[-l].b - d_p[l] * vp[-l].b;
00753 vm->b += n_m[l] * sp_m[l].b - d_m[l] * vm[l].b;
00754 }
00755 if(plugin->config.a)
00756 {
00757 vp->a += n_p[l] * sp_p[-l].a - d_p[l] * vp[-l].a;
00758 vm->a += n_m[l] * sp_m[l].a - d_m[l] * vm[l].a;
00759 }
00760 }
00761
00762 for( ; l <= 4; l++)
00763 {
00764 if(plugin->config.r)
00765 {
00766 vp->r += (n_p[l] - bd_p[l]) * initial_p.r;
00767 vm->r += (n_m[l] - bd_m[l]) * initial_m.r;
00768 }
00769 if(plugin->config.g)
00770 {
00771 vp->g += (n_p[l] - bd_p[l]) * initial_p.g;
00772 vm->g += (n_m[l] - bd_m[l]) * initial_m.g;
00773 }
00774 if(plugin->config.b)
00775 {
00776 vp->b += (n_p[l] - bd_p[l]) * initial_p.b;
00777 vm->b += (n_m[l] - bd_m[l]) * initial_m.b;
00778 }
00779 if(plugin->config.a)
00780 {
00781 vp->a += (n_p[l] - bd_p[l]) * initial_p.a;
00782 vm->a += (n_m[l] - bd_m[l]) * initial_m.a;
00783 }
00784 }
00785
00786 sp_p++;
00787 sp_m--;
00788 vp++;
00789 vm--;
00790 }
00791 transfer_pixels(val_p, val_m, dst, size);
00792 separate_alpha(dst, size);
00793 return 0;
00794 }
00795
00796
00797
00798
00799
00800