00001 #include "bcdisplayinfo.h"
00002 #include "clip.h"
00003 #include "bchash.h"
00004 #include "filexml.h"
00005 #include "guicast.h"
00006 #include "keyframe.h"
00007 #include "language.h"
00008 #include "loadbalance.h"
00009 #include "picon_png.h"
00010 #include "pluginvclient.h"
00011 #include "vframe.h"
00012
00013
00014
00015 #include <string.h>
00016 #include <stdint.h>
00017
00018
00019 #define SQR(x) ((x) * (x))
00020 #define WITHIN(a, b, c) ((((a) <= (b)) && ((b) <= (c))) ? 1 : 0)
00021
00022
00023 class PolarEffect;
00024 class PolarEngine;
00025 class PolarWindow;
00026
00027
00028 class PolarConfig
00029 {
00030 public:
00031 PolarConfig();
00032
00033 void copy_from(PolarConfig &src);
00034 int equivalent(PolarConfig &src);
00035 void interpolate(PolarConfig &prev,
00036 PolarConfig &next,
00037 long prev_frame,
00038 long next_frame,
00039 long current_frame);
00040
00041 int polar_to_rectangular;
00042 float depth;
00043 float angle;
00044 int backwards;
00045 int invert;
00046 };
00047
00048
00049
00050 class PolarDepth : public BC_FSlider
00051 {
00052 public:
00053 PolarDepth(PolarEffect *plugin, int x, int y);
00054 int handle_event();
00055 PolarEffect *plugin;
00056 };
00057
00058 class PolarAngle : public BC_FSlider
00059 {
00060 public:
00061 PolarAngle(PolarEffect *plugin, int x, int y);
00062 int handle_event();
00063 PolarEffect *plugin;
00064 };
00065
00066 class PolarWindow : public BC_Window
00067 {
00068 public:
00069 PolarWindow(PolarEffect *plugin, int x, int y);
00070 void create_objects();
00071 int close_event();
00072 PolarEffect *plugin;
00073 PolarDepth *depth;
00074 PolarAngle *angle;
00075 };
00076
00077
00078 PLUGIN_THREAD_HEADER(PolarEffect, PolarThread, PolarWindow)
00079
00080
00081 class PolarPackage : public LoadPackage
00082 {
00083 public:
00084 PolarPackage();
00085 int row1, row2;
00086 };
00087
00088 class PolarUnit : public LoadClient
00089 {
00090 public:
00091 PolarUnit(PolarEffect *plugin, PolarEngine *server);
00092 void process_package(LoadPackage *package);
00093 PolarEffect *plugin;
00094 };
00095
00096 class PolarEngine : public LoadServer
00097 {
00098 public:
00099 PolarEngine(PolarEffect *plugin, int cpus);
00100 void init_packages();
00101 LoadClient* new_client();
00102 LoadPackage* new_package();
00103 PolarEffect *plugin;
00104 };
00105
00106 class PolarEffect : public PluginVClient
00107 {
00108 public:
00109 PolarEffect(PluginServer *server);
00110 ~PolarEffect();
00111
00112 int process_realtime(VFrame *input, VFrame *output);
00113 int is_realtime();
00114 char* plugin_title();
00115 VFrame* new_picon();
00116 int load_configuration();
00117 int load_defaults();
00118 int save_defaults();
00119 void save_data(KeyFrame *keyframe);
00120 void read_data(KeyFrame *keyframe);
00121 int show_gui();
00122 int set_string();
00123 void raise_window();
00124 void update_gui();
00125
00126 PolarConfig config;
00127 BC_Hash *defaults;
00128 PolarThread *thread;
00129 PolarEngine *engine;
00130 VFrame *temp_frame;
00131 VFrame *input, *output;
00132 int need_reconfigure;
00133 };
00134
00135
00136
00137 REGISTER_PLUGIN(PolarEffect)
00138
00139
00140
00141 PolarConfig::PolarConfig()
00142 {
00143 angle = 0.0;
00144 depth = 0.0;
00145 backwards = 0;
00146 invert = 0;
00147 polar_to_rectangular = 1;
00148 }
00149
00150
00151 void PolarConfig::copy_from(PolarConfig &src)
00152 {
00153 this->angle = src.angle;
00154 this->depth = src.depth;
00155 this->backwards = src.backwards;
00156 this->invert = src.invert;
00157 this->polar_to_rectangular = src.polar_to_rectangular;
00158 }
00159
00160 int PolarConfig::equivalent(PolarConfig &src)
00161 {
00162 return EQUIV(this->angle, src.angle) && EQUIV(this->depth, src.depth);
00163 }
00164
00165 void PolarConfig::interpolate(PolarConfig &prev,
00166 PolarConfig &next,
00167 long prev_frame,
00168 long next_frame,
00169 long current_frame)
00170 {
00171 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
00172 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
00173
00174 this->depth = prev.depth * prev_scale + next.depth * next_scale;
00175 this->angle = prev.angle * prev_scale + next.angle * next_scale;
00176 }
00177
00178
00179
00180
00181
00182
00183 PolarWindow::PolarWindow(PolarEffect *plugin, int x, int y)
00184 : BC_Window(plugin->gui_string,
00185 x,
00186 y,
00187 270,
00188 100,
00189 270,
00190 100,
00191 0,
00192 0,
00193 1)
00194 {
00195 this->plugin = plugin;
00196 }
00197
00198 void PolarWindow::create_objects()
00199 {
00200 int x = 10, y = 10;
00201 add_subwindow(new BC_Title(x, y, _("Depth:")));
00202 add_subwindow(depth = new PolarDepth(plugin, x + 50, y));
00203 y += 40;
00204 add_subwindow(new BC_Title(x, y, _("Angle:")));
00205 add_subwindow(angle = new PolarAngle(plugin, x + 50, y));
00206
00207 show_window();
00208 flush();
00209 }
00210
00211 WINDOW_CLOSE_EVENT(PolarWindow)
00212
00213 PLUGIN_THREAD_OBJECT(PolarEffect, PolarThread, PolarWindow)
00214
00215
00216 PolarDepth::PolarDepth(PolarEffect *plugin, int x, int y)
00217 : BC_FSlider(x,
00218 y,
00219 0,
00220 200,
00221 200,
00222 (float)1,
00223 (float)100,
00224 plugin->config.depth)
00225 {
00226 this->plugin = plugin;
00227 }
00228 int PolarDepth::handle_event()
00229 {
00230 plugin->config.depth = get_value();
00231 plugin->send_configure_change();
00232 return 1;
00233 }
00234
00235
00236
00237
00238
00239 PolarAngle::PolarAngle(PolarEffect *plugin, int x, int y)
00240 : BC_FSlider(x,
00241 y,
00242 0,
00243 200,
00244 200,
00245 (float)1,
00246 (float)360,
00247 plugin->config.angle)
00248 {
00249 this->plugin = plugin;
00250 }
00251 int PolarAngle::handle_event()
00252 {
00253 plugin->config.angle = get_value();
00254 plugin->send_configure_change();
00255 return 1;
00256 }
00257
00258
00259
00260
00261
00262 PolarEffect::PolarEffect(PluginServer *server)
00263 : PluginVClient(server)
00264 {
00265 need_reconfigure = 1;
00266 temp_frame = 0;
00267 engine = 0;
00268 PLUGIN_CONSTRUCTOR_MACRO
00269 }
00270
00271 PolarEffect::~PolarEffect()
00272 {
00273 PLUGIN_DESTRUCTOR_MACRO
00274 if(temp_frame) delete temp_frame;
00275 if(engine) delete engine;
00276 }
00277
00278
00279
00280 char* PolarEffect::plugin_title() { return N_("Polar"); }
00281 int PolarEffect::is_realtime() { return 1; }
00282
00283
00284
00285 NEW_PICON_MACRO(PolarEffect)
00286
00287 SHOW_GUI_MACRO(PolarEffect, PolarThread)
00288
00289 RAISE_WINDOW_MACRO(PolarEffect)
00290
00291 SET_STRING_MACRO(PolarEffect)
00292
00293 void PolarEffect::update_gui()
00294 {
00295 if(thread)
00296 {
00297 load_configuration();
00298 thread->window->lock_window();
00299 thread->window->angle->update(config.angle);
00300 thread->window->depth->update(config.depth);
00301 thread->window->unlock_window();
00302 }
00303 }
00304
00305 LOAD_CONFIGURATION_MACRO(PolarEffect, PolarConfig)
00306
00307
00308 int PolarEffect::load_defaults()
00309 {
00310 char directory[BCTEXTLEN];
00311
00312 sprintf(directory, "%spolar.rc", BCASTDIR);
00313
00314
00315 defaults = new BC_Hash(directory);
00316 defaults->load();
00317
00318 config.depth = defaults->get("DEPTH", config.depth);
00319 config.angle = defaults->get("ANGLE", config.angle);
00320 return 0;
00321 }
00322
00323 int PolarEffect::save_defaults()
00324 {
00325 defaults->update("DEPTH", config.depth);
00326 defaults->update("ANGLE", config.angle);
00327 defaults->save();
00328 return 0;
00329 }
00330
00331 void PolarEffect::save_data(KeyFrame *keyframe)
00332 {
00333 FileXML output;
00334
00335
00336 output.set_shared_string(keyframe->data, MESSAGESIZE);
00337 output.tag.set_title("POLAR");
00338 output.tag.set_property("DEPTH", config.depth);
00339 output.tag.set_property("ANGLE", config.angle);
00340 output.append_tag();
00341 output.tag.set_title("/POLAR");
00342 output.append_tag();
00343 output.terminate_string();
00344 }
00345
00346 void PolarEffect::read_data(KeyFrame *keyframe)
00347 {
00348 FileXML input;
00349
00350 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00351
00352 int result = 0;
00353
00354 while(!input.read_tag())
00355 {
00356 if(input.tag.title_is("POLAR"))
00357 {
00358 config.depth = input.tag.get_property("DEPTH", config.depth);
00359 config.angle = input.tag.get_property("ANGLE", config.angle);
00360 }
00361 }
00362 }
00363
00364 int PolarEffect::process_realtime(VFrame *input, VFrame *output)
00365 {
00366 need_reconfigure |= load_configuration();
00367
00368 this->input = input;
00369 this->output = output;
00370
00371 if(EQUIV(config.depth, 0) || EQUIV(config.angle, 0))
00372 {
00373 if(input->get_rows()[0] != output->get_rows()[0])
00374 output->copy_from(input);
00375 }
00376 else
00377 {
00378 if(input->get_rows()[0] == output->get_rows()[0])
00379 {
00380 if(!temp_frame) temp_frame = new VFrame(0,
00381 input->get_w(),
00382 input->get_h(),
00383 input->get_color_model());
00384 temp_frame->copy_from(input);
00385 this->input = temp_frame;
00386 }
00387
00388
00389 if(!engine) engine = new PolarEngine(this, PluginClient::smp + 1);
00390
00391 engine->process_packages();
00392 }
00393 return 0;
00394 }
00395
00396
00397
00398
00399
00400 PolarPackage::PolarPackage()
00401 : LoadPackage()
00402 {
00403 }
00404
00405
00406
00407
00408 PolarUnit::PolarUnit(PolarEffect *plugin, PolarEngine *server)
00409 : LoadClient(server)
00410 {
00411 this->plugin = plugin;
00412 }
00413
00414
00415 static int calc_undistorted_coords(int wx,
00416 int wy,
00417 int w,
00418 int h,
00419 float depth,
00420 double angle,
00421 int polar_to_rectangular,
00422 int backwards,
00423 int inverse,
00424 double cen_x,
00425 double cen_y,
00426 double &x,
00427 double &y)
00428 {
00429 int inside;
00430 double phi, phi2;
00431 double xx, xm, ym, yy;
00432 int xdiff, ydiff;
00433 double r;
00434 double m;
00435 double xmax, ymax, rmax;
00436 double x_calc, y_calc;
00437 double xi, yi;
00438 double circle, angl, t;
00439 int x1, x2, y1, y2;
00440
00441
00442
00443 phi = 0.0;
00444 r = 0.0;
00445
00446 x1 = 0;
00447 y1 = 0;
00448 x2 = w;
00449 y2 = h;
00450 xdiff = x2 - x1;
00451 ydiff = y2 - y1;
00452 xm = xdiff / 2.0;
00453 ym = ydiff / 2.0;
00454 circle = depth;
00455 angle = angle;
00456 angl = (double)angle / 180.0 * M_PI;
00457
00458 if(polar_to_rectangular)
00459 {
00460 if(wx >= cen_x)
00461 {
00462 if(wy > cen_y)
00463 {
00464 phi = M_PI -
00465 atan(((double)(wx - cen_x)) /
00466 ((double)(wy - cen_y)));
00467 r = sqrt(SQR(wx - cen_x) +
00468 SQR(wy - cen_y));
00469 }
00470 else
00471 if(wy < cen_y)
00472 {
00473 phi = atan(((double)(wx - cen_x)) /
00474 ((double)(cen_y - wy)));
00475 r = sqrt(SQR(wx - cen_x) +
00476 SQR(cen_y - wy));
00477 }
00478 else
00479 {
00480 phi = M_PI / 2;
00481 r = wx - cen_x;
00482 }
00483 }
00484 else
00485 if(wx < cen_x)
00486 {
00487 if(wy < cen_y)
00488 {
00489 phi = 2 * M_PI -
00490 atan(((double)(cen_x -wx)) /
00491 ((double)(cen_y - wy)));
00492 r = sqrt(SQR(cen_x - wx) +
00493 SQR(cen_y - wy));
00494 }
00495 else
00496 if(wy > cen_y)
00497 {
00498 phi = M_PI +
00499 atan(((double)(cen_x - wx)) /
00500 ((double)(wy - cen_y)));
00501 r = sqrt(SQR(cen_x - wx) +
00502 SQR(wy - cen_y));
00503 }
00504 else
00505 {
00506 phi = 1.5 * M_PI;
00507 r = cen_x - wx;
00508 }
00509 }
00510 if (wx != cen_x)
00511 {
00512 m = fabs(((double)(wy - cen_y)) /
00513 ((double)(wx - cen_x)));
00514 }
00515 else
00516 {
00517 m = 0;
00518 }
00519
00520 if(m <= ((double)(y2 - y1) /
00521 (double)(x2 - x1)))
00522 {
00523 if(wx == cen_x)
00524 {
00525 xmax = 0;
00526 ymax = cen_y - y1;
00527 }
00528 else
00529 {
00530 xmax = cen_x - x1;
00531 ymax = m * xmax;
00532 }
00533 }
00534 else
00535 {
00536 ymax = cen_y - y1;
00537 xmax = ymax / m;
00538 }
00539
00540 rmax = sqrt((double)(SQR(xmax) + SQR(ymax)));
00541
00542 t = ((cen_y - y1) < (cen_x - x1)) ? (cen_y - y1) : (cen_x - x1);
00543 rmax = (rmax - t) / 100 * (100 - circle) + t;
00544
00545 phi = fmod(phi + angl, 2 * M_PI);
00546
00547 if(backwards)
00548 x_calc = x2 - 1 - (x2 - x1 - 1) / (2 * M_PI) * phi;
00549 else
00550 x_calc = (x2 - x1 - 1) / (2 * M_PI) * phi + x1;
00551
00552 if(inverse)
00553 y_calc = (y2 - y1) / rmax * r + y1;
00554 else
00555 y_calc = y2 - (y2 - y1) / rmax * r;
00556
00557 xi = (int)(x_calc + 0.5);
00558 yi = (int)(y_calc + 0.5);
00559
00560 if(WITHIN(0, xi, w - 1) && WITHIN(0, yi, h - 1))
00561 {
00562 x = x_calc;
00563 y = y_calc;
00564
00565 inside = 1;
00566 }
00567 else
00568 {
00569 inside = 0;
00570 }
00571 }
00572 else
00573 {
00574 if(backwards)
00575 phi = (2 * M_PI) * (x2 - wx) / xdiff;
00576 else
00577 phi = (2 * M_PI) * (wx - x1) / xdiff;
00578
00579 phi = fmod (phi + angl, 2 * M_PI);
00580
00581 if(phi >= 1.5 * M_PI)
00582 phi2 = 2 * M_PI - phi;
00583 else
00584 if (phi >= M_PI)
00585 phi2 = phi - M_PI;
00586 else
00587 if(phi >= 0.5 * M_PI)
00588 phi2 = M_PI - phi;
00589 else
00590 phi2 = phi;
00591
00592 xx = tan (phi2);
00593 if(xx != 0)
00594 m = (double)1.0 / xx;
00595 else
00596 m = 0;
00597
00598 if(m <= ((double)(ydiff) / (double)(xdiff)))
00599 {
00600 if(phi2 == 0)
00601 {
00602 xmax = 0;
00603 ymax = ym - y1;
00604 }
00605 else
00606 {
00607 xmax = xm - x1;
00608 ymax = m * xmax;
00609 }
00610 }
00611 else
00612 {
00613 ymax = ym - y1;
00614 xmax = ymax / m;
00615 }
00616
00617 rmax = sqrt((double)(SQR(xmax) + SQR(ymax)));
00618
00619 t = ((ym - y1) < (xm - x1)) ? (ym - y1) : (xm - x1);
00620
00621 rmax = (rmax - t) / 100.0 * (100 - circle) + t;
00622
00623 if(inverse)
00624 r = rmax * (double)((wy - y1) / (double)(ydiff));
00625 else
00626 r = rmax * (double)((y2 - wy) / (double)(ydiff));
00627
00628 xx = r * sin (phi2);
00629 yy = r * cos (phi2);
00630
00631 if(phi >= 1.5 * M_PI)
00632 {
00633 x_calc = (double)xm - xx;
00634 y_calc = (double)ym - yy;
00635 }
00636 else
00637 if(phi >= M_PI)
00638 {
00639 x_calc = (double)xm - xx;
00640 y_calc = (double)ym + yy;
00641 }
00642 else
00643 if(phi >= 0.5 * M_PI)
00644 {
00645 x_calc = (double)xm + xx;
00646 y_calc = (double)ym + yy;
00647 }
00648 else
00649 {
00650 x_calc = (double)xm + xx;
00651 y_calc = (double)ym - yy;
00652 }
00653
00654 xi = (int)(x_calc + 0.5);
00655 yi = (int)(y_calc + 0.5);
00656
00657 if(WITHIN(0, xi, w - 1) &&
00658 WITHIN(0, yi, h - 1))
00659 {
00660 x = x_calc;
00661 y = y_calc;
00662
00663 inside = 1;
00664 }
00665 else
00666 {
00667 inside = 0;
00668 }
00669 }
00670
00671 return inside;
00672 }
00673
00674 static double bilinear(double x, double y, double *values)
00675 {
00676 double m0, m1;
00677 x = fmod(x, 1.0);
00678 y = fmod(y, 1.0);
00679
00680 if(x < 0.0) x += 1.0;
00681 if(y < 0.0) y += 1.0;
00682
00683 m0 = values[0] + x * (values[1] - values[0]);
00684 m1 = values[2] + x * (values[3] - values[2]);
00685 return m0 + y * (m1 - m0);
00686 }
00687
00688 #define GET_PIXEL(x, y, components, input_rows) \
00689 input_rows[CLIP((y), 0, ((h) - 1))] + components * CLIP((x), 0, ((w) - 1))
00690
00691 #define POLAR_MACRO(type, max, components, chroma_offset) \
00692 { \
00693 type **in_rows = (type**)plugin->input->get_rows(); \
00694 type **out_rows = (type**)plugin->output->get_rows(); \
00695 double values[4]; \
00696 \
00697 for(int y = pkg->row1; y < pkg->row2; y++) \
00698 { \
00699 type *output_row = out_rows[y]; \
00700 \
00701 for(int x = 0; x < w; x++) \
00702 { \
00703 type *output_pixel = output_row + x * components; \
00704 if(calc_undistorted_coords(x, \
00705 y, \
00706 w, \
00707 h, \
00708 plugin->config.depth, \
00709 plugin->config.angle, \
00710 plugin->config.polar_to_rectangular, \
00711 plugin->config.backwards, \
00712 plugin->config.invert, \
00713 cen_x, \
00714 cen_y, \
00715 cx, \
00716 cy)) \
00717 { \
00718 type *pixel1 = GET_PIXEL((int)cx, (int)cy, components, in_rows); \
00719 type *pixel2 = GET_PIXEL((int)cx + 1, (int)cy, components, in_rows); \
00720 type *pixel3 = GET_PIXEL((int)cx, (int)cy + 1, components, in_rows); \
00721 type *pixel4 = GET_PIXEL((int)cx + 1, (int)cy + 1, components, in_rows); \
00722 \
00723 values[0] = pixel1[0]; \
00724 values[1] = pixel2[0]; \
00725 values[2] = pixel3[0]; \
00726 values[3] = pixel4[0]; \
00727 output_pixel[0] = (type)bilinear(cx, cy, values); \
00728 \
00729 values[0] = pixel1[1]; \
00730 values[1] = pixel2[1]; \
00731 values[2] = pixel3[1]; \
00732 values[3] = pixel4[1]; \
00733 output_pixel[1] = (type)bilinear(cx, cy, values); \
00734 \
00735 values[0] = pixel1[2]; \
00736 values[1] = pixel2[2]; \
00737 values[2] = pixel3[2]; \
00738 values[3] = pixel4[2]; \
00739 output_pixel[2] = (type)bilinear(cx, cy, values); \
00740 \
00741 if(components == 4) \
00742 { \
00743 values[0] = pixel1[3]; \
00744 values[1] = pixel2[3]; \
00745 values[2] = pixel3[3]; \
00746 values[3] = pixel4[3]; \
00747 output_pixel[3] = (type)bilinear(cx, cy, values); \
00748 } \
00749 } \
00750 else \
00751 { \
00752 output_pixel[0] = 0; \
00753 output_pixel[1] = chroma_offset; \
00754 output_pixel[2] = chroma_offset; \
00755 if(components == 4) output_pixel[3] = max; \
00756 } \
00757 } \
00758 } \
00759 }
00760
00761
00762 void PolarUnit::process_package(LoadPackage *package)
00763 {
00764 PolarPackage *pkg = (PolarPackage*)package;
00765 int w = plugin->input->get_w();
00766 int h = plugin->input->get_h();
00767 double cx;
00768 double cy;
00769 double cen_x = (double)(w - 1) / 2.0;
00770 double cen_y = (double)(h - 1) / 2.0;
00771
00772 switch(plugin->input->get_color_model())
00773 {
00774 case BC_RGB_FLOAT:
00775 POLAR_MACRO(float, 1, 3, 0x0)
00776 break;
00777 case BC_RGBA_FLOAT:
00778 POLAR_MACRO(float, 1, 4, 0x0)
00779 break;
00780 case BC_RGB888:
00781 POLAR_MACRO(unsigned char, 0xff, 3, 0x0)
00782 break;
00783 case BC_RGBA8888:
00784 POLAR_MACRO(unsigned char, 0xff, 4, 0x0)
00785 break;
00786 case BC_RGB161616:
00787 POLAR_MACRO(uint16_t, 0xffff, 3, 0x0)
00788 break;
00789 case BC_RGBA16161616:
00790 POLAR_MACRO(uint16_t, 0xffff, 4, 0x0)
00791 break;
00792 case BC_YUV888:
00793 POLAR_MACRO(unsigned char, 0xff, 3, 0x80)
00794 break;
00795 case BC_YUVA8888:
00796 POLAR_MACRO(unsigned char, 0xff, 4, 0x80)
00797 break;
00798 case BC_YUV161616:
00799 POLAR_MACRO(uint16_t, 0xffff, 3, 0x8000)
00800 break;
00801 case BC_YUVA16161616:
00802 POLAR_MACRO(uint16_t, 0xffff, 4, 0x8000)
00803 break;
00804 }
00805 }
00806
00807
00808
00809
00810 PolarEngine::PolarEngine(PolarEffect *plugin, int cpus)
00811 : LoadServer(cpus, cpus)
00812 {
00813 this->plugin = plugin;
00814 }
00815
00816 void PolarEngine::init_packages()
00817 {
00818 for(int i = 0; i < LoadServer::get_total_packages(); i++)
00819 {
00820 PolarPackage *pkg = (PolarPackage*)get_package(i);
00821 pkg->row1 = plugin->input->get_h() * i / LoadServer::get_total_packages();
00822 pkg->row2 = plugin->input->get_h() * (i + 1) / LoadServer::get_total_packages();
00823 }
00824 }
00825
00826 LoadClient* PolarEngine::new_client()
00827 {
00828 return new PolarUnit(plugin, this);
00829 }
00830
00831 LoadPackage* PolarEngine::new_package()
00832 {
00833 return new PolarPackage;
00834 }
00835
00836
00837