00001 #include "bcdisplayinfo.h"
00002 #include "bchash.h"
00003 #include "edl.inc"
00004 #include "filexml.h"
00005 #include "language.h"
00006 #include "overlayframe.h"
00007 #include "picon_png.h"
00008 #include "vframe.h"
00009 #include "shapewipe.h"
00010
00011 #include <png.h>
00012 #include <math.h>
00013 #include <stdint.h>
00014 #include <string.h>
00015
00016 REGISTER_PLUGIN(ShapeWipeMain)
00017
00018 ShapeWipeW2B::ShapeWipeW2B(ShapeWipeMain *plugin,
00019 ShapeWipeWindow *window,
00020 int x,
00021 int y)
00022 : BC_Radial(x,
00023 y,
00024 plugin->direction == 0,
00025 _("White to Black"))
00026 {
00027 this->plugin = plugin;
00028 this->window = window;
00029 }
00030
00031 int ShapeWipeW2B::handle_event()
00032 {
00033 update(1);
00034 plugin->direction = 0;
00035 window->right->update(0);
00036 plugin->send_configure_change();
00037 return 0;
00038 }
00039
00040 ShapeWipeB2W::ShapeWipeB2W(ShapeWipeMain *plugin,
00041 ShapeWipeWindow *window,
00042 int x,
00043 int y)
00044 : BC_Radial(x,
00045 y,
00046 plugin->direction == 1,
00047 _("Black to White"))
00048 {
00049 this->plugin = plugin;
00050 this->window = window;
00051 }
00052
00053 int ShapeWipeB2W::handle_event()
00054 {
00055 update(1);
00056 plugin->direction = 1;
00057 window->left->update(0);
00058 plugin->send_configure_change();
00059 return 0;
00060 }
00061
00062 ShapeWipeAntiAlias::ShapeWipeAntiAlias(ShapeWipeMain *plugin,
00063 ShapeWipeWindow *window,
00064 int x,
00065 int y)
00066 : BC_CheckBox (x,y,plugin->antialias, _("Anti-aliasing"))
00067 {
00068 this->plugin = plugin;
00069 this->window = window;
00070 }
00071
00072 int ShapeWipeAntiAlias::handle_event()
00073 {
00074 plugin->antialias = get_value();
00075 plugin->send_configure_change();
00076 return 0;
00077 }
00078
00079 ShapeWipePreserveAspectRatio::ShapeWipePreserveAspectRatio(ShapeWipeMain *plugin,
00080 ShapeWipeWindow *window,
00081 int x,
00082 int y)
00083 : BC_CheckBox (x,y,plugin->preserve_aspect, _("Preserve shape aspect ratio"))
00084 {
00085 this->plugin = plugin;
00086 this->window = window;
00087 }
00088
00089 int ShapeWipePreserveAspectRatio::handle_event()
00090 {
00091 plugin->preserve_aspect = get_value();
00092 plugin->send_configure_change();
00093 return 0;
00094 }
00095
00096 ShapeWipeFilename::ShapeWipeFilename(
00097 ShapeWipeMain *plugin,
00098 ShapeWipeWindow *window,
00099 char *value,
00100 int x,
00101 int y)
00102 : BC_TextBox(x,y,180,1, value)
00103 {
00104 this->plugin = plugin;
00105 this->window = window;
00106 this->value = value;
00107 }
00108
00109 int ShapeWipeFilename::handle_event()
00110 {
00111 value = get_text();
00112 strcpy(plugin->filename, get_text());
00113 plugin->send_configure_change();
00114 return 0;
00115 }
00116
00117 ShapeWipeBrowseButton::ShapeWipeBrowseButton(
00118 ShapeWipeMain *plugin,
00119 ShapeWipeWindow *window,
00120 ShapeWipeFilename *filename,
00121 int x,
00122 int y)
00123 : BC_GenericButton(x,y,_("Browse..."))
00124 {
00125 this->plugin = plugin;
00126 this->window = window;
00127 this->filename = filename;
00128 }
00129
00130 int ShapeWipeBrowseButton::handle_event()
00131 {
00132 int result;
00133 ShapeWipeLoad window(filename, filename->get_text());
00134 window.create_objects();
00135 window.update_filter("*.png");
00136 result = window.run_window();
00137
00138 if (!result)
00139 {
00140 filename->update(window.get_submitted_path());
00141 strcpy(plugin->filename, window.get_submitted_path());
00142 plugin->send_configure_change();
00143 }
00144
00145 return 0;
00146 }
00147
00148 ShapeWipeLoad::ShapeWipeLoad(
00149 ShapeWipeFilename *filename,
00150 char *init_directory)
00151 : BC_FileBox(
00152 1,
00153 1,
00154 init_directory,
00155 _("Choose Shape"),
00156 _("Choose a Wipe Shape"))
00157 {
00158 this->filename = filename;
00159 }
00160
00161 ShapeWipeWindow::ShapeWipeWindow(ShapeWipeMain *plugin, int x, int y)
00162 : BC_Window(plugin->gui_string,
00163 x,
00164 y,
00165 450,
00166 125,
00167 450,
00168 125,
00169 0,
00170 0,
00171 1)
00172 {
00173 this->plugin = plugin;
00174 }
00175
00176 int ShapeWipeWindow::close_event()
00177 {
00178 set_done(1);
00179 return 1;
00180 }
00181
00182 void ShapeWipeWindow::create_objects()
00183 {
00184 int x = 10, y = 10;
00185 add_subwindow(new BC_Title(x, y, _("Direction:")));
00186 x += 100;
00187 add_subwindow(left = new ShapeWipeW2B(plugin,
00188 this,
00189 x,
00190 y));
00191 x += 200;
00192 add_subwindow(right = new ShapeWipeB2W(plugin,
00193 this,
00194 x,
00195 y));
00196 x = 10; y += 25;
00197 add_subwindow(new BC_Title(x, y, _("Shape:")));
00198 x += 100;
00199
00200 add_subwindow(filename_widget = new
00201 ShapeWipeFilename(plugin,
00202 this,
00203 plugin->filename,
00204 x,
00205 y));
00206 x += 200;
00207 add_subwindow(new ShapeWipeBrowseButton(
00208 plugin,
00209 this,
00210 filename_widget,
00211 x,
00212 y));
00213 x = 110; y += 25;
00214 add_subwindow(new ShapeWipeAntiAlias(
00215 plugin,
00216 this,
00217 x,
00218 y));
00219 x = 110; y += 25;
00220 add_subwindow(new ShapeWipePreserveAspectRatio(
00221 plugin,
00222 this,
00223 x,
00224 y));
00225 show_window();
00226 flush();
00227 }
00228
00229 PLUGIN_THREAD_OBJECT(ShapeWipeMain, ShapeWipeThread, ShapeWipeWindow)
00230
00231 ShapeWipeMain::ShapeWipeMain(PluginServer *server)
00232 : PluginVClient(server)
00233 {
00234 direction = 0;
00235 strcpy(filename, DEFAULT_SHAPE);
00236 last_read_filename[0] = '\0';
00237 pattern_image = NULL;
00238 min_value = 256;
00239 max_value = 0;
00240 antialias = 0;
00241 preserve_aspect = 0;
00242 last_preserve_aspect = 0;
00243 PLUGIN_CONSTRUCTOR_MACRO
00244 }
00245
00246 ShapeWipeMain::~ShapeWipeMain()
00247 {
00248 reset_pattern_image();
00249 PLUGIN_DESTRUCTOR_MACRO
00250 }
00251
00252 char* ShapeWipeMain::plugin_title() { return N_("Shape Wipe"); }
00253 int ShapeWipeMain::is_video() { return 1; }
00254 int ShapeWipeMain::is_transition() { return 1; }
00255 int ShapeWipeMain::uses_gui() { return 1; }
00256
00257 SHOW_GUI_MACRO(ShapeWipeMain, ShapeWipeThread);
00258 SET_STRING_MACRO(ShapeWipeMain)
00259 RAISE_WINDOW_MACRO(ShapeWipeMain)
00260
00261
00262 VFrame* ShapeWipeMain::new_picon()
00263 {
00264 return new VFrame(picon_png);
00265 }
00266
00267 int ShapeWipeMain::load_defaults()
00268 {
00269 char directory[BCTEXTLEN];
00270
00271 sprintf(directory, "%sshapewipe.rc", BCASTDIR);
00272
00273
00274 defaults = new BC_Hash(directory);
00275 defaults->load();
00276
00277 direction = defaults->get("DIRECTION", direction);
00278 antialias = defaults->get("ANTIALIAS", antialias);
00279 preserve_aspect = defaults->get("PRESERVE_ASPECT", preserve_aspect);
00280 defaults->get("FILENAME", filename);
00281 return 0;
00282 }
00283
00284 int ShapeWipeMain::save_defaults()
00285 {
00286 defaults->update("DIRECTION", direction);
00287 defaults->update("ANTIALIAS", antialias);
00288 defaults->update("PRESERVE_ASPECT", preserve_aspect);
00289 defaults->update("FILENAME", filename);
00290 defaults->save();
00291 return 0;
00292 }
00293
00294 void ShapeWipeMain::save_data(KeyFrame *keyframe)
00295 {
00296 FileXML output;
00297 output.set_shared_string(keyframe->data, MESSAGESIZE);
00298 output.tag.set_title("SHAPEWIPE");
00299 output.tag.set_property("DIRECTION", direction);
00300 output.tag.set_property("ANTIALIAS", antialias);
00301 output.tag.set_property("PRESERVE_ASPECT", preserve_aspect);
00302 output.tag.set_property("FILENAME", filename);
00303 output.append_tag();
00304 output.tag.set_title("/SHAPEWIPE");
00305 output.append_tag();
00306 output.terminate_string();
00307 }
00308
00309 void ShapeWipeMain::read_data(KeyFrame *keyframe)
00310 {
00311 FileXML input;
00312
00313 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00314
00315 while(!input.read_tag())
00316 {
00317 if(input.tag.title_is("SHAPEWIPE"))
00318 {
00319 direction = input.tag.get_property("DIRECTION", direction);
00320 antialias = input.tag.get_property("ANTIALIAS", antialias);
00321 preserve_aspect = input.tag.get_property("PRESERVE_ASPECT", preserve_aspect);
00322 input.tag.get_property("FILENAME", filename);
00323 }
00324 }
00325 }
00326
00327 void ShapeWipeMain::load_configuration()
00328 {
00329 read_data(get_prev_keyframe(get_source_position()));
00330 }
00331
00332 int ShapeWipeMain::read_pattern_image(int new_frame_width, int new_frame_height)
00333 {
00334 png_byte header[8];
00335 int is_png;
00336 int row;
00337 int col;
00338 int scaled_row;
00339 int scaled_col;
00340 int pixel_width;
00341 unsigned char value;
00342 png_uint_32 width;
00343 png_uint_32 height;
00344 png_byte color_type;
00345 png_byte bit_depth;
00346 png_structp png_ptr;
00347 png_infop info_ptr;
00348 png_infop end_info;
00349 png_bytep *image;
00350 frame_width = new_frame_width;
00351 frame_height = new_frame_height;
00352
00353 FILE *fp = fopen(filename, "rb");
00354 if (!fp)
00355 {
00356 return 1;
00357 }
00358
00359 fread(header, 1, 8, fp);
00360 is_png = !png_sig_cmp(header, 0, 8);
00361
00362 if (!is_png)
00363 {
00364 return 1;
00365 }
00366
00367 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
00368 png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL);
00369
00370 if (!png_ptr)
00371 {
00372 return 1;
00373 }
00374
00375
00376 png_set_sig_bytes(png_ptr, 8);
00377
00378 info_ptr = png_create_info_struct(png_ptr);
00379 if (!info_ptr)
00380 {
00381 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
00382 return 1;
00383 }
00384
00385 end_info = png_create_info_struct(png_ptr);
00386 if (!end_info)
00387 {
00388 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00389 return 1;
00390 }
00391
00392 png_init_io(png_ptr, fp);
00393 png_read_info(png_ptr, info_ptr);
00394
00395 color_type = png_get_color_type(png_ptr, info_ptr);
00396 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
00397 width = png_get_image_width (png_ptr, info_ptr);
00398 height = png_get_image_height(png_ptr, info_ptr);
00399
00400
00401
00402
00403 if (color_type & PNG_COLOR_MASK_ALPHA)
00404 pixel_width = 2;
00405 else
00406 pixel_width = 1;
00407
00408
00409 if (bit_depth == 16) png_set_strip_16(png_ptr);
00410
00411
00412 if (bit_depth < 8) png_set_packing(png_ptr);
00413
00414
00415 if (color_type == PNG_COLOR_TYPE_RGB ||
00416 color_type == PNG_COLOR_TYPE_RGB_ALPHA)
00417 png_set_rgb_to_gray_fixed(png_ptr, 1, -1, -1);
00418
00419
00420 image = (png_bytep*)malloc(sizeof(png_bytep)*height);
00421 for (row = 0; row < height; row++)
00422 {
00423 image[row] = (png_byte*)malloc(sizeof(png_byte)*width*pixel_width);
00424 }
00425
00426
00427
00428 pattern_image = (unsigned char**)malloc(sizeof(unsigned char*)*frame_height);
00429
00430
00431 png_read_image(png_ptr, image);
00432 png_read_end(png_ptr, end_info);
00433
00434 double row_factor, col_factor;
00435 double row_offset = 0.5, col_offset = 0.5;
00436
00437 if (preserve_aspect && aspect_w != 0 && aspect_h != 0)
00438 {
00439 row_factor = (height-1)/aspect_h;
00440 col_factor = (width-1)/aspect_w;
00441 if (row_factor < col_factor)
00442 col_factor = row_factor;
00443 else
00444 row_factor = col_factor;
00445 row_factor *= aspect_h/(double)(frame_height-1);
00446 col_factor *= aspect_w/(double)(frame_width-1);
00447
00448
00449 row_offset += (height-1-(frame_height-1)*row_factor)/2;
00450 col_offset += (width-1-(frame_width-1)*col_factor)/2;
00451 }
00452 else
00453 {
00454
00455 row_factor = (double)(height-1)/(double)(frame_height-1);
00456 col_factor = (double)(width-1)/(double)(frame_width-1);
00457 }
00458
00459 for (scaled_row = 0; scaled_row < frame_height; scaled_row++)
00460 {
00461 row = (int)(row_factor*scaled_row + row_offset);
00462 pattern_image[scaled_row] = (unsigned char*)malloc(sizeof(unsigned char)*frame_width);
00463 for (scaled_col = 0; scaled_col < frame_width; scaled_col++)
00464 {
00465 col = (int)(col_factor*scaled_col + col_offset)*pixel_width;
00466 value = image[row][col];
00467 pattern_image[scaled_row][scaled_col] = value;
00468 if (value < min_value) min_value = value;
00469 if (value > max_value) max_value = value;
00470
00471 }
00472 }
00473
00474 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00475 fclose(fp);
00476
00477 for (row = 0; row < height; row++)
00478 {
00479 free(image[row]);
00480 }
00481 free (image);
00482 return 0;
00483 }
00484
00485 void ShapeWipeMain::reset_pattern_image()
00486 {
00487 int row;
00488 if (pattern_image != NULL)
00489 {
00490 for (row = 0; row < frame_height; row++)
00491 {
00492 free (pattern_image[row]);
00493 }
00494 free (pattern_image);
00495 pattern_image = NULL;
00496 min_value = 256, max_value = 0;
00497 }
00498 }
00499
00500 #define SHAPEWIPE(type, components) \
00501 { \
00502 \
00503 type **in_rows = (type**)incoming->get_rows(); \
00504 type **out_rows = (type**)outgoing->get_rows(); \
00505 \
00506 type *in_row; \
00507 type *out_row; \
00508 \
00509 for(j = 0; j < h; j++) \
00510 { \
00511 in_row = (type*) in_rows[j]; \
00512 out_row = (type*)out_rows[j]; \
00513 pattern_row = pattern_image[j]; \
00514 \
00515 col_offset = 0; \
00516 for(k = 0; k < w; k++) \
00517 { \
00518 value = pattern_row[k]; \
00519 if ((direction == 0 && value >= threshold) || \
00520 (direction == 1 && value <= threshold)) \
00521 { \
00522 out_row[col_offset] = in_row[col_offset]; \
00523 out_row[col_offset + 1] = in_row[col_offset + 1]; \
00524 out_row[col_offset + 2] = in_row[col_offset + 2]; \
00525 if(components == 4) \
00526 out_row[col_offset + 3] = in_row[col_offset + 3]; \
00527 } \
00528 col_offset += components; \
00529 } \
00530 } \
00531 }
00532
00533 #define COMPARE1(x,y) \
00534 { \
00535 if (pattern_image[x][y] <= threshold) opacity++; \
00536 }
00537
00538 #define COMPARE2(x,y) \
00539 { \
00540 if (pattern_image[x][y] >= threshold) opacity++; \
00541 }
00542
00543
00544 #define BLEND_ONLY_4_NORMAL(temp_type, type, max, chroma_offset,x,y) \
00545 { \
00546 const int bits = sizeof(type) * 8; \
00547 temp_type blend_opacity = (temp_type)(alpha * ((temp_type)1 << bits) + 0.5); \
00548 temp_type blend_transparency = ((temp_type)1 << bits) - blend_opacity; \
00549 \
00550 col = y * 4; \
00551 type* in_row = (type*)incoming->get_rows()[x]; \
00552 type* output = (type*)outgoing->get_rows()[x]; \
00553 \
00554 output[col] = ((temp_type)in_row[col] * blend_opacity + output[col] * blend_transparency) >> bits; \
00555 output[col+1] = ((temp_type)in_row[col+1] * blend_opacity + output[col+1] * blend_transparency) >> bits; \
00556 output[col+2] = ((temp_type)in_row[col+2] * blend_opacity + output[col+2] * blend_transparency) >> bits; \
00557 }
00558
00559
00560
00561 #define BLEND_ONLY_3_NORMAL(temp_type, type, max, chroma_offset,x,y) \
00562 { \
00563 const int bits = sizeof(type) * 8; \
00564 temp_type blend_opacity = (temp_type)(alpha * ((temp_type)1 << bits) + 0.5); \
00565 temp_type blend_transparency = ((temp_type)1 << bits) - blend_opacity; \
00566 \
00567 col = y * 3; \
00568 type* in_row = (type*)incoming->get_rows()[x]; \
00569 type* output = (type*)outgoing->get_rows()[x]; \
00570 \
00571 output[col] = ((temp_type)in_row[col] * blend_opacity + output[col] * blend_transparency) >> bits; \
00572 output[col+1] = ((temp_type)in_row[col+1] * blend_opacity + output[col+1] * blend_transparency) >> bits; \
00573 output[col+2] = ((temp_type)in_row[col+2] * blend_opacity + output[col+2] * blend_transparency) >> bits; \
00574 }
00575
00576
00577 #define BLEND(x,y,total) \
00578 { \
00579 float pixel_opacity = (float)opacity / total; \
00580 float alpha = pixel_opacity; \
00581 float pixel_transparency = 1.0 - pixel_opacity; \
00582 int col; \
00583 \
00584 if (pixel_opacity > 0.0) \
00585 { \
00586 switch(incoming->get_color_model()) \
00587 { \
00588 case BC_RGB_FLOAT: \
00589 { \
00590 float *in_row = (float*)incoming->get_rows()[x]; \
00591 float *out_row = (float*)outgoing->get_rows()[x]; \
00592 col = y * 3; \
00593 out_row[col] = in_row[col] * pixel_opacity + \
00594 out_row[col] * pixel_transparency; \
00595 out_row[col+1] = in_row[col+1] * pixel_opacity + \
00596 out_row[col+1] * pixel_transparency; \
00597 out_row[col+2] = in_row[col+2] * pixel_opacity + \
00598 out_row[col+2] * pixel_transparency; \
00599 break; \
00600 } \
00601 case BC_RGBA_FLOAT: \
00602 { \
00603 float *in_row = (float*)incoming->get_rows()[x]; \
00604 float *out_row = (float*)outgoing->get_rows()[x]; \
00605 col = y * 4; \
00606 out_row[col] = in_row[col] * pixel_opacity + \
00607 out_row[col] * pixel_transparency; \
00608 out_row[col+1] = in_row[col+1] * pixel_opacity + \
00609 out_row[col+1] * pixel_transparency; \
00610 out_row[col+2] = in_row[col+2] * pixel_opacity + \
00611 out_row[col+2] * pixel_transparency; \
00612 break; \
00613 } \
00614 case BC_RGB888: \
00615 BLEND_ONLY_3_NORMAL(uint32_t, unsigned char, 0xff, 0,x,y); \
00616 break; \
00617 case BC_YUV888: \
00618 BLEND_ONLY_3_NORMAL(int32_t, unsigned char, 0xff, 0x80,x,y); \
00619 break; \
00620 case BC_RGBA8888: \
00621 BLEND_ONLY_4_NORMAL(uint32_t, unsigned char, 0xff, 0,x,y); \
00622 break; \
00623 case BC_YUVA8888: \
00624 BLEND_ONLY_4_NORMAL(int32_t, unsigned char, 0xff, 0x80,x,y); \
00625 break; \
00626 case BC_RGB161616: \
00627 BLEND_ONLY_3_NORMAL(uint64_t, uint16_t, 0xffff, 0,x,y); \
00628 break; \
00629 case BC_YUV161616: \
00630 BLEND_ONLY_3_NORMAL(int64_t, uint16_t, 0xffff, 0x8000,x,y); \
00631 break; \
00632 case BC_RGBA16161616: \
00633 BLEND_ONLY_4_NORMAL(uint64_t, uint16_t, 0xffff, 0,x,y); \
00634 break; \
00635 case BC_YUVA16161616: \
00636 BLEND_ONLY_4_NORMAL(int64_t, uint16_t, 0xffff, 0x8000,x,y); \
00637 break; \
00638 } \
00639 } \
00640 }
00641
00642 int ShapeWipeMain::process_realtime(VFrame *incoming, VFrame *outgoing)
00643 {
00644 unsigned char *pattern_row;
00645 int col_offset;
00646 unsigned char threshold;
00647 unsigned char value;
00648 int i,j,k;
00649 int opacity;
00650
00651 load_configuration();
00652
00653 int w = incoming->get_w();
00654 int h = incoming->get_h();
00655
00656 if (strncmp(filename,last_read_filename,BCTEXTLEN)
00657 || preserve_aspect != last_preserve_aspect)
00658 {
00659 reset_pattern_image();
00660 }
00661
00662 if (!pattern_image) {
00663 read_pattern_image(w, h);
00664 strncpy(last_read_filename, filename, BCTEXTLEN);
00665 last_preserve_aspect = preserve_aspect;
00666 }
00667
00668 if (!pattern_image)
00669 {
00670 fprintf(stderr, "Shape Wipe: cannot load shape %s\n", filename);
00671 return 0;
00672 }
00673
00674 if (direction)
00675 {
00676 threshold = (unsigned char)(
00677 (float)PluginClient::get_source_position() /
00678 (float)PluginClient::get_total_len() *
00679 (float)(max_value - min_value))
00680 + min_value;
00681 }
00682 else
00683 {
00684 threshold = (unsigned char)((max_value - min_value) - (
00685 (float)PluginClient::get_source_position() /
00686 (float)PluginClient::get_total_len() *
00687 (float)(max_value - min_value)))
00688 + min_value;
00689 }
00690
00691 if (antialias)
00692 {
00693 if (direction)
00694 {
00695
00696 opacity = 0;
00697 COMPARE1(0,0);
00698 COMPARE1(0,1);
00699 COMPARE1(1,0);
00700 COMPARE1(1,1);
00701 BLEND(0,0,4.0);
00702
00703
00704 for (k = 1; k < w-1; k++)
00705 {
00706 opacity = 0;
00707 COMPARE1(0,k-1);
00708 COMPARE1(0,k);
00709 COMPARE1(0,k+1);
00710 COMPARE1(1,k-1);
00711 COMPARE1(1,k);
00712 COMPARE1(1,k+1);
00713 BLEND(0,k,6.0);
00714 }
00715
00716
00717 opacity = 0;
00718 COMPARE1(0,w-1);
00719 COMPARE1(0,w-2);
00720 COMPARE1(1,w-1);
00721 COMPARE1(1,w-2);
00722 BLEND(0,w-1,4.0);
00723
00724
00725 for (j = 1; j < h-1; j++)
00726 {
00727 opacity = 0;
00728 COMPARE1(j-1,0);
00729 COMPARE1(j,0);
00730 COMPARE1(j+1,0);
00731 COMPARE1(j-1,1);
00732 COMPARE1(j,1);
00733 COMPARE1(j+1,1);
00734 BLEND(j,0,6.0);
00735 }
00736
00737
00738 for (j = 1; j < h-1; j++)
00739 {
00740 for (k = 1; k < w-1; k++)
00741 {
00742 opacity = 0;
00743 COMPARE1(j-1,k-1);
00744 COMPARE1(j,k-1);
00745 COMPARE1(j+1,k-1);
00746 COMPARE1(j-1,k);
00747 COMPARE1(j,k);
00748 COMPARE1(j+1,k);
00749 COMPARE1(j-1,k+1);
00750 COMPARE1(j,k+1);
00751 COMPARE1(j+1,k+1);
00752 BLEND(j,k,9.0);
00753 }
00754 }
00755
00756
00757 for (j = 1; j < h-1; j++)
00758 {
00759 opacity = 0;
00760 COMPARE1(j-1,w-1);
00761 COMPARE1(j,w-1);
00762 COMPARE1(j+1,w-1);
00763 COMPARE1(j-1,w-2);
00764 COMPARE1(j,w-2);
00765 COMPARE1(j+1,w-2);
00766 BLEND(j,w-1,6.0);
00767 }
00768
00769
00770 opacity = 0;
00771 COMPARE1(h-1,0);
00772 COMPARE1(h-1,1);
00773 COMPARE1(h-2,0);
00774 COMPARE1(h-2,1);
00775 BLEND(h-1,0,4.0);
00776
00777
00778 for (k = 1; k < w-1; k++)
00779 {
00780 opacity = 0;
00781 COMPARE1(h-1,k-1);
00782 COMPARE1(h-1,k);
00783 COMPARE1(h-1,k+1);
00784 COMPARE1(h-2,k-1);
00785 COMPARE1(h-2,k);
00786 COMPARE1(h-2,k+1);
00787 BLEND(h-1,k,6.0);
00788 }
00789
00790
00791 opacity = 0;
00792 COMPARE1(h-1,w-1);
00793 COMPARE1(h-1,w-2);
00794 COMPARE1(h-2,w-1);
00795 COMPARE1(h-2,w-2);
00796 BLEND(h-1,w-1,4.0);
00797 }
00798 else
00799 {
00800
00801 opacity = 0;
00802 COMPARE2(0,0);
00803 COMPARE2(0,1);
00804 COMPARE2(1,0);
00805 COMPARE2(1,1);
00806 BLEND(0,0,4.0);
00807
00808
00809 for (k = 1; k < w-1; k++)
00810 {
00811 opacity = 0;
00812 COMPARE2(0,k-1);
00813 COMPARE2(0,k);
00814 COMPARE2(0,k+1);
00815 COMPARE2(1,k-1);
00816 COMPARE2(1,k);
00817 COMPARE2(1,k+1);
00818 BLEND(0,k,6.0);
00819 }
00820
00821
00822 opacity = 0;
00823 COMPARE2(0,w-1);
00824 COMPARE2(0,w-2);
00825 COMPARE2(1,w-1);
00826 COMPARE2(1,w-2);
00827 BLEND(0,w-1,4.0);
00828
00829
00830 for (j = 1; j < h-1; j++)
00831 {
00832 opacity = 0;
00833 COMPARE2(j-1,0);
00834 COMPARE2(j,0);
00835 COMPARE2(j+1,0);
00836 COMPARE2(j-1,1);
00837 COMPARE2(j,1);
00838 COMPARE2(j+1,1);
00839 BLEND(j,0,6.0);
00840 }
00841
00842
00843 for (j = 1; j < h-1; j++)
00844 {
00845 for (k = 1; k < w-1; k++)
00846 {
00847 opacity = 0;
00848 COMPARE2(j-1,k-1);
00849 COMPARE2(j,k-1);
00850 COMPARE2(j+1,k-1);
00851 COMPARE2(j-1,k);
00852 COMPARE2(j,k);
00853 COMPARE2(j+1,k);
00854 COMPARE2(j-1,k+1);
00855 COMPARE2(j,k+1);
00856 COMPARE2(j+1,k+1);
00857 BLEND(j,k,9.0);
00858 }
00859 }
00860
00861
00862 for (j = 1; j < h-1; j++)
00863 {
00864 opacity = 0;
00865 COMPARE2(j-1,w-1);
00866 COMPARE2(j,w-1);
00867 COMPARE2(j+1,w-1);
00868 COMPARE2(j-1,w-2);
00869 COMPARE2(j,w-2);
00870 COMPARE2(j+1,w-2);
00871 BLEND(j,w-1,6.0);
00872 }
00873
00874
00875 opacity = 0;
00876 COMPARE2(h-1,0);
00877 COMPARE2(h-1,1);
00878 COMPARE2(h-2,0);
00879 COMPARE2(h-2,1);
00880 BLEND(h-1,0,4.0);
00881
00882
00883 for (k = 1; k < w-1; k++)
00884 {
00885 opacity = 0;
00886 COMPARE2(h-1,k-1);
00887 COMPARE2(h-1,k);
00888 COMPARE2(h-1,k+1);
00889 COMPARE2(h-2,k-1);
00890 COMPARE2(h-2,k);
00891 COMPARE2(h-2,k+1);
00892 BLEND(h-1,k,6.0);
00893 }
00894
00895
00896 opacity = 0;
00897 COMPARE2(h-1,w-1);
00898 COMPARE2(h-1,w-2);
00899 COMPARE2(h-2,w-1);
00900 COMPARE2(h-2,w-2);
00901 BLEND(h-1,w-1,4.0);
00902 }
00903 }
00904 else
00905 {
00906 switch(incoming->get_color_model())
00907 {
00908 case BC_RGB_FLOAT:
00909 SHAPEWIPE(float, 3)
00910 break;
00911 case BC_RGB888:
00912 case BC_YUV888:
00913 SHAPEWIPE(unsigned char, 3)
00914 break;
00915 case BC_RGBA_FLOAT:
00916 SHAPEWIPE(float, 4)
00917 break;
00918 case BC_RGBA8888:
00919 case BC_YUVA8888:
00920 SHAPEWIPE(unsigned char, 4)
00921 break;
00922 case BC_RGB161616:
00923 case BC_YUV161616:
00924 SHAPEWIPE(uint16_t, 3)
00925 break;
00926 case BC_RGBA16161616:
00927 case BC_YUVA16161616:
00928 SHAPEWIPE(uint16_t, 4)
00929 break;
00930 }
00931 }
00932 return 0;
00933 }