00001 #include "../motion/affine.h"
00002 #include "cursors.h"
00003 #include "language.h"
00004 #include "perspective.h"
00005
00006
00007
00008
00009
00010
00011
00012 REGISTER_PLUGIN(PerspectiveMain)
00013
00014
00015
00016 PerspectiveConfig::PerspectiveConfig()
00017 {
00018 x1 = 0;
00019 y1 = 0;
00020 x2 = 100;
00021 y2 = 0;
00022 x3 = 100;
00023 y3 = 100;
00024 x4 = 0;
00025 y4 = 100;
00026 mode = AffineEngine::PERSPECTIVE;
00027 window_w = 400;
00028 window_h = 450;
00029 current_point = 0;
00030 forward = 1;
00031 }
00032
00033 int PerspectiveConfig::equivalent(PerspectiveConfig &that)
00034 {
00035 return
00036 EQUIV(x1, that.x1) &&
00037 EQUIV(y1, that.y1) &&
00038 EQUIV(x2, that.x2) &&
00039 EQUIV(y2, that.y2) &&
00040 EQUIV(x3, that.x3) &&
00041 EQUIV(y3, that.y3) &&
00042 EQUIV(x4, that.x4) &&
00043 EQUIV(y4, that.y4) &&
00044 mode == that.mode &&
00045 forward == that.forward;
00046 }
00047
00048 void PerspectiveConfig::copy_from(PerspectiveConfig &that)
00049 {
00050 x1 = that.x1;
00051 y1 = that.y1;
00052 x2 = that.x2;
00053 y2 = that.y2;
00054 x3 = that.x3;
00055 y3 = that.y3;
00056 x4 = that.x4;
00057 y4 = that.y4;
00058 mode = that.mode;
00059 window_w = that.window_w;
00060 window_h = that.window_h;
00061 current_point = that.current_point;
00062 forward = that.forward;
00063 }
00064
00065 void PerspectiveConfig::interpolate(PerspectiveConfig &prev,
00066 PerspectiveConfig &next,
00067 int64_t prev_frame,
00068 int64_t next_frame,
00069 int64_t current_frame)
00070 {
00071 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
00072 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
00073 this->x1 = prev.x1 * prev_scale + next.x1 * next_scale;
00074 this->y1 = prev.y1 * prev_scale + next.y1 * next_scale;
00075 this->x2 = prev.x2 * prev_scale + next.x2 * next_scale;
00076 this->y2 = prev.y2 * prev_scale + next.y2 * next_scale;
00077 this->x3 = prev.x3 * prev_scale + next.x3 * next_scale;
00078 this->y3 = prev.y3 * prev_scale + next.y3 * next_scale;
00079 this->x4 = prev.x4 * prev_scale + next.x4 * next_scale;
00080 this->y4 = prev.y4 * prev_scale + next.y4 * next_scale;
00081 mode = prev.mode;
00082 forward = prev.forward;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 PLUGIN_THREAD_OBJECT(PerspectiveMain, PerspectiveThread, PerspectiveWindow)
00094
00095
00096
00097 PerspectiveWindow::PerspectiveWindow(PerspectiveMain *plugin, int x, int y)
00098 : BC_Window(plugin->gui_string,
00099 x,
00100 y,
00101 plugin->config.window_w,
00102 plugin->config.window_h,
00103 plugin->config.window_w,
00104 plugin->config.window_h,
00105 0,
00106 1)
00107 {
00108
00109 this->plugin = plugin;
00110 }
00111
00112 PerspectiveWindow::~PerspectiveWindow()
00113 {
00114 }
00115
00116 int PerspectiveWindow::create_objects()
00117 {
00118 int x = 10, y = 10;
00119
00120 add_subwindow(canvas = new PerspectiveCanvas(plugin,
00121 x,
00122 y,
00123 get_w() - 20,
00124 get_h() - 140));
00125 canvas->set_cursor(CROSS_CURSOR);
00126 y += canvas->get_h() + 10;
00127 add_subwindow(new BC_Title(x, y, _("Current X:")));
00128 x += 80;
00129 this->x = new PerspectiveCoord(this,
00130 plugin,
00131 x,
00132 y,
00133 plugin->get_current_x(),
00134 1);
00135 this->x->create_objects();
00136 x += 140;
00137 add_subwindow(new BC_Title(x, y, _("Y:")));
00138 x += 20;
00139 this->y = new PerspectiveCoord(this,
00140 plugin,
00141 x,
00142 y,
00143 plugin->get_current_y(),
00144 0);
00145 this->y->create_objects();
00146 y += 30;
00147 x = 10;
00148 add_subwindow(new PerspectiveReset(plugin, x, y));
00149 x += 100;
00150 add_subwindow(mode_perspective = new PerspectiveMode(plugin,
00151 x,
00152 y,
00153 AffineEngine::PERSPECTIVE,
00154 _("Perspective")));
00155 x += 120;
00156 add_subwindow(mode_sheer = new PerspectiveMode(plugin,
00157 x,
00158 y,
00159 AffineEngine::SHEER,
00160 _("Sheer")));
00161 x = 110;
00162 y += 30;
00163 add_subwindow(mode_stretch = new PerspectiveMode(plugin,
00164 x,
00165 y,
00166 AffineEngine::STRETCH,
00167 _("Stretch")));
00168 update_canvas();
00169 y += 30;
00170 x = 10;
00171 add_subwindow(new BC_Title(x, y, _("Perspective direction:")));
00172 x += 170;
00173 add_subwindow(forward = new PerspectiveDirection(plugin,
00174 x,
00175 y,
00176 1,
00177 _("Forward")));
00178 x += 100;
00179 add_subwindow(reverse = new PerspectiveDirection(plugin,
00180 x,
00181 y,
00182 0,
00183 _("Reverse")));
00184
00185 show_window();
00186 flush();
00187 return 0;
00188 }
00189
00190 WINDOW_CLOSE_EVENT(PerspectiveWindow)
00191
00192 int PerspectiveWindow::resize_event(int w, int h)
00193 {
00194 return 1;
00195 }
00196
00197 void PerspectiveWindow::update_canvas()
00198 {
00199 canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h());
00200 int x1, y1, x2, y2, x3, y3, x4, y4;
00201 calculate_canvas_coords(x1, y1, x2, y2, x3, y3, x4, y4);
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 canvas->set_color(BLACK);
00213
00214 #define DIVISIONS 10
00215 for(int i = 0; i <= DIVISIONS; i++)
00216 {
00217
00218 canvas->draw_line(
00219 x1 + (x4 - x1) * i / DIVISIONS,
00220 y1 + (y4 - y1) * i / DIVISIONS,
00221 x2 + (x3 - x2) * i / DIVISIONS,
00222 y2 + (y3 - y2) * i / DIVISIONS);
00223
00224 canvas->draw_line(
00225 x1 + (x2 - x1) * i / DIVISIONS,
00226 y1 + (y2 - y1) * i / DIVISIONS,
00227 x4 + (x3 - x4) * i / DIVISIONS,
00228 y4 + (y3 - y4) * i / DIVISIONS);
00229 }
00230
00231
00232 #define RADIUS 5
00233 if(plugin->config.current_point == 0)
00234 canvas->draw_disc(x1 - RADIUS, y1 - RADIUS, RADIUS * 2, RADIUS * 2);
00235 else
00236 canvas->draw_circle(x1 - RADIUS, y1 - RADIUS, RADIUS * 2, RADIUS * 2);
00237
00238 if(plugin->config.current_point == 1)
00239 canvas->draw_disc(x2 - RADIUS, y2 - RADIUS, RADIUS * 2, RADIUS * 2);
00240 else
00241 canvas->draw_circle(x2 - RADIUS, y2 - RADIUS, RADIUS * 2, RADIUS * 2);
00242
00243 if(plugin->config.current_point == 2)
00244 canvas->draw_disc(x3 - RADIUS, y3 - RADIUS, RADIUS * 2, RADIUS * 2);
00245 else
00246 canvas->draw_circle(x3 - RADIUS, y3 - RADIUS, RADIUS * 2, RADIUS * 2);
00247
00248 if(plugin->config.current_point == 3)
00249 canvas->draw_disc(x4 - RADIUS, y4 - RADIUS, RADIUS * 2, RADIUS * 2);
00250 else
00251 canvas->draw_circle(x4 - RADIUS, y4 - RADIUS, RADIUS * 2, RADIUS * 2);
00252
00253 canvas->flash();
00254 canvas->flush();
00255 }
00256
00257 void PerspectiveWindow::update_mode()
00258 {
00259 mode_perspective->update(plugin->config.mode == AffineEngine::PERSPECTIVE);
00260 mode_sheer->update(plugin->config.mode == AffineEngine::SHEER);
00261 mode_stretch->update(plugin->config.mode == AffineEngine::STRETCH);
00262 forward->update(plugin->config.forward);
00263 reverse->update(!plugin->config.forward);
00264 }
00265
00266 void PerspectiveWindow::update_coord()
00267 {
00268 x->update(plugin->get_current_x());
00269 y->update(plugin->get_current_y());
00270 }
00271
00272 void PerspectiveWindow::calculate_canvas_coords(int &x1,
00273 int &y1,
00274 int &x2,
00275 int &y2,
00276 int &x3,
00277 int &y3,
00278 int &x4,
00279 int &y4)
00280 {
00281 int w = canvas->get_w() - 1;
00282 int h = canvas->get_h() - 1;
00283 if(plugin->config.mode == AffineEngine::PERSPECTIVE ||
00284 plugin->config.mode == AffineEngine::STRETCH)
00285 {
00286 x1 = (int)(plugin->config.x1 * w / 100);
00287 y1 = (int)(plugin->config.y1 * h / 100);
00288 x2 = (int)(plugin->config.x2 * w / 100);
00289 y2 = (int)(plugin->config.y2 * h / 100);
00290 x3 = (int)(plugin->config.x3 * w / 100);
00291 y3 = (int)(plugin->config.y3 * h / 100);
00292 x4 = (int)(plugin->config.x4 * w / 100);
00293 y4 = (int)(plugin->config.y4 * h / 100);
00294 }
00295 else
00296 {
00297 x1 = (int)(plugin->config.x1 * w) / 100;
00298 y1 = 0;
00299 x2 = x1 + w;
00300 y2 = 0;
00301 x4 = (int)(plugin->config.x4 * w) / 100;
00302 y4 = h;
00303 x3 = x4 + w;
00304 y3 = h;
00305 }
00306 }
00307
00308
00309
00310
00311 PerspectiveCanvas::PerspectiveCanvas(PerspectiveMain *plugin,
00312 int x,
00313 int y,
00314 int w,
00315 int h)
00316 : BC_SubWindow(x, y, w, h, 0xffffff)
00317 {
00318 this->plugin = plugin;
00319 state = PerspectiveCanvas::NONE;
00320 }
00321
00322
00323
00324
00325 int PerspectiveCanvas::button_press_event()
00326 {
00327 if(is_event_win() && cursor_inside())
00328 {
00329
00330 int x1, y1, x2, y2, x3, y3, x4, y4;
00331 int cursor_x = get_cursor_x();
00332 int cursor_y = get_cursor_y();
00333 plugin->thread->window->calculate_canvas_coords(x1, y1, x2, y2, x3, y3, x4, y4);
00334
00335 float distance1 = DISTANCE(cursor_x, cursor_y, x1, y1);
00336 float distance2 = DISTANCE(cursor_x, cursor_y, x2, y2);
00337 float distance3 = DISTANCE(cursor_x, cursor_y, x3, y3);
00338 float distance4 = DISTANCE(cursor_x, cursor_y, x4, y4);
00339
00340
00341
00342
00343
00344
00345 float min = distance1;
00346 plugin->config.current_point = 0;
00347 if(distance2 < min)
00348 {
00349 min = distance2;
00350 plugin->config.current_point = 1;
00351 }
00352 if(distance3 < min)
00353 {
00354 min = distance3;
00355 plugin->config.current_point = 2;
00356 }
00357 if(distance4 < min)
00358 {
00359 min = distance4;
00360 plugin->config.current_point = 3;
00361 }
00362
00363 if(plugin->config.mode == AffineEngine::SHEER)
00364 {
00365 if(plugin->config.current_point == 1)
00366 plugin->config.current_point = 0;
00367 else
00368 if(plugin->config.current_point == 2)
00369 plugin->config.current_point = 3;
00370 }
00371 start_cursor_x = cursor_x;
00372 start_cursor_y = cursor_y;
00373
00374 if(alt_down() || shift_down())
00375 {
00376 if(alt_down())
00377 state = PerspectiveCanvas::DRAG_FULL;
00378 else
00379 state = PerspectiveCanvas::ZOOM;
00380
00381
00382 start_x1 = plugin->config.x1;
00383 start_y1 = plugin->config.y1;
00384 start_x2 = plugin->config.x2;
00385 start_y2 = plugin->config.y2;
00386 start_x3 = plugin->config.x3;
00387 start_y3 = plugin->config.y3;
00388 start_x4 = plugin->config.x4;
00389 start_y4 = plugin->config.y4;
00390 }
00391 else
00392 {
00393 state = PerspectiveCanvas::DRAG;
00394
00395
00396 start_x1 = plugin->get_current_x();
00397 start_y1 = plugin->get_current_y();
00398 }
00399 plugin->thread->window->update_coord();
00400 plugin->thread->window->update_canvas();
00401 return 1;
00402 }
00403
00404 return 0;
00405 }
00406
00407 int PerspectiveCanvas::button_release_event()
00408 {
00409 if(state != PerspectiveCanvas::NONE)
00410 {
00411 state = PerspectiveCanvas::NONE;
00412 return 1;
00413 }
00414 return 0;
00415 }
00416
00417 int PerspectiveCanvas::cursor_motion_event()
00418 {
00419 if(state != PerspectiveCanvas::NONE)
00420 {
00421 int w = get_w() - 1;
00422 int h = get_h() - 1;
00423 if(state == PerspectiveCanvas::DRAG)
00424 {
00425 plugin->set_current_x((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x1);
00426 plugin->set_current_y((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y1);
00427 }
00428 else
00429 if(state == PerspectiveCanvas::DRAG_FULL)
00430 {
00431 plugin->config.x1 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x1);
00432 plugin->config.y1 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y1);
00433 plugin->config.x2 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x2);
00434 plugin->config.y2 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y2);
00435 plugin->config.x3 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x3);
00436 plugin->config.y3 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y3);
00437 plugin->config.x4 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x4);
00438 plugin->config.y4 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y4);
00439 }
00440 else
00441 if(state == PerspectiveCanvas::ZOOM)
00442 {
00443 float center_x = (start_x1 +
00444 start_x2 +
00445 start_x3 +
00446 start_x4) / 4;
00447 float center_y = (start_y1 +
00448 start_y2 +
00449 start_y3 +
00450 start_y4) / 4;
00451 float zoom = (float)(get_cursor_y() - start_cursor_y + 640) / 640;
00452 plugin->config.x1 = center_x + (start_x1 - center_x) * zoom;
00453 plugin->config.y1 = center_y + (start_y1 - center_y) * zoom;
00454 plugin->config.x2 = center_x + (start_x2 - center_x) * zoom;
00455 plugin->config.y2 = center_y + (start_y2 - center_y) * zoom;
00456 plugin->config.x3 = center_x + (start_x3 - center_x) * zoom;
00457 plugin->config.y3 = center_y + (start_y3 - center_y) * zoom;
00458 plugin->config.x4 = center_x + (start_x4 - center_x) * zoom;
00459 plugin->config.y4 = center_y + (start_y4 - center_y) * zoom;
00460 }
00461 plugin->thread->window->update_canvas();
00462 plugin->thread->window->update_coord();
00463 plugin->send_configure_change();
00464 return 1;
00465 }
00466
00467 return 0;
00468 }
00469
00470
00471
00472
00473
00474
00475 PerspectiveCoord::PerspectiveCoord(PerspectiveWindow *gui,
00476 PerspectiveMain *plugin,
00477 int x,
00478 int y,
00479 float value,
00480 int is_x)
00481 : BC_TumbleTextBox(gui, value, (float)0, (float)100, x, y, 100)
00482 {
00483 this->plugin = plugin;
00484 this->is_x = is_x;
00485 }
00486
00487 int PerspectiveCoord::handle_event()
00488 {
00489 if(is_x)
00490 plugin->set_current_x(atof(get_text()));
00491 else
00492 plugin->set_current_y(atof(get_text()));
00493 plugin->thread->window->update_canvas();
00494 plugin->send_configure_change();
00495 return 1;
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505 PerspectiveReset::PerspectiveReset(PerspectiveMain *plugin,
00506 int x,
00507 int y)
00508 : BC_GenericButton(x, y, _("Reset"))
00509 {
00510 this->plugin = plugin;
00511 }
00512 int PerspectiveReset::handle_event()
00513 {
00514 plugin->config.x1 = 0;
00515 plugin->config.y1 = 0;
00516 plugin->config.x2 = 100;
00517 plugin->config.y2 = 0;
00518 plugin->config.x3 = 100;
00519 plugin->config.y3 = 100;
00520 plugin->config.x4 = 0;
00521 plugin->config.y4 = 100;
00522 plugin->thread->window->update_canvas();
00523 plugin->thread->window->update_coord();
00524 plugin->send_configure_change();
00525 return 1;
00526 }
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 PerspectiveMode::PerspectiveMode(PerspectiveMain *plugin,
00539 int x,
00540 int y,
00541 int value,
00542 char *text)
00543 : BC_Radial(x, y, plugin->config.mode == value, text)
00544 {
00545 this->plugin = plugin;
00546 this->value = value;
00547 }
00548 int PerspectiveMode::handle_event()
00549 {
00550 plugin->config.mode = value;
00551 plugin->thread->window->update_mode();
00552 plugin->thread->window->update_canvas();
00553 plugin->send_configure_change();
00554 return 1;
00555 }
00556
00557
00558
00559
00560 PerspectiveDirection::PerspectiveDirection(PerspectiveMain *plugin,
00561 int x,
00562 int y,
00563 int value,
00564 char *text)
00565 : BC_Radial(x, y, plugin->config.forward == value, text)
00566 {
00567 this->plugin = plugin;
00568 this->value = value;
00569 }
00570 int PerspectiveDirection::handle_event()
00571 {
00572 plugin->config.forward = value;
00573 plugin->thread->window->update_mode();
00574 plugin->send_configure_change();
00575 return 1;
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 PerspectiveMain::PerspectiveMain(PluginServer *server)
00590 : PluginVClient(server)
00591 {
00592 PLUGIN_CONSTRUCTOR_MACRO
00593 engine = 0;
00594 temp = 0;
00595 }
00596
00597 PerspectiveMain::~PerspectiveMain()
00598 {
00599 PLUGIN_DESTRUCTOR_MACRO
00600 if(engine) delete engine;
00601 if(temp) delete temp;
00602 }
00603
00604 char* PerspectiveMain::plugin_title() { return N_("Perspective"); }
00605 int PerspectiveMain::is_realtime() { return 1; }
00606
00607
00608 NEW_PICON_MACRO(PerspectiveMain)
00609
00610 SHOW_GUI_MACRO(PerspectiveMain, PerspectiveThread)
00611
00612 SET_STRING_MACRO(PerspectiveMain)
00613
00614 RAISE_WINDOW_MACRO(PerspectiveMain)
00615
00616 LOAD_CONFIGURATION_MACRO(PerspectiveMain, PerspectiveConfig)
00617
00618
00619
00620 void PerspectiveMain::update_gui()
00621 {
00622 if(thread)
00623 {
00624
00625 thread->window->lock_window();
00626
00627 load_configuration();
00628 thread->window->update_coord();
00629 thread->window->update_mode();
00630 thread->window->update_canvas();
00631 thread->window->unlock_window();
00632
00633 }
00634 }
00635
00636
00637 int PerspectiveMain::load_defaults()
00638 {
00639 char directory[1024], string[1024];
00640
00641 sprintf(directory, "%sperspective.rc", BCASTDIR);
00642
00643
00644 defaults = new BC_Hash(directory);
00645 defaults->load();
00646
00647 config.x1 = defaults->get("X1", config.x1);
00648 config.x2 = defaults->get("X2", config.x2);
00649 config.x3 = defaults->get("X3", config.x3);
00650 config.x4 = defaults->get("X4", config.x4);
00651 config.y1 = defaults->get("Y1", config.y1);
00652 config.y2 = defaults->get("Y2", config.y2);
00653 config.y3 = defaults->get("Y3", config.y3);
00654 config.y4 = defaults->get("Y4", config.y4);
00655
00656 config.mode = defaults->get("MODE", config.mode);
00657 config.forward = defaults->get("FORWARD", config.forward);
00658 config.window_w = defaults->get("WINDOW_W", config.window_w);
00659 config.window_h = defaults->get("WINDOW_H", config.window_h);
00660 return 0;
00661 }
00662
00663
00664 int PerspectiveMain::save_defaults()
00665 {
00666 defaults->update("X1", config.x1);
00667 defaults->update("X2", config.x2);
00668 defaults->update("X3", config.x3);
00669 defaults->update("X4", config.x4);
00670 defaults->update("Y1", config.y1);
00671 defaults->update("Y2", config.y2);
00672 defaults->update("Y3", config.y3);
00673 defaults->update("Y4", config.y4);
00674
00675 defaults->update("MODE", config.mode);
00676 defaults->update("FORWARD", config.forward);
00677 defaults->update("WINDOW_W", config.window_w);
00678 defaults->update("WINDOW_H", config.window_h);
00679 defaults->save();
00680 return 0;
00681 }
00682
00683
00684
00685 void PerspectiveMain::save_data(KeyFrame *keyframe)
00686 {
00687 FileXML output;
00688
00689
00690 output.set_shared_string(keyframe->data, MESSAGESIZE);
00691 output.tag.set_title("PERSPECTIVE");
00692
00693 output.tag.set_property("X1", config.x1);
00694 output.tag.set_property("X2", config.x2);
00695 output.tag.set_property("X3", config.x3);
00696 output.tag.set_property("X4", config.x4);
00697 output.tag.set_property("Y1", config.y1);
00698 output.tag.set_property("Y2", config.y2);
00699 output.tag.set_property("Y3", config.y3);
00700 output.tag.set_property("Y4", config.y4);
00701
00702 output.tag.set_property("MODE", config.mode);
00703 output.tag.set_property("FORWARD", config.forward);
00704 output.tag.set_property("WINDOW_W", config.window_w);
00705 output.tag.set_property("WINDOW_H", config.window_h);
00706 output.append_tag();
00707 output.tag.set_title("/PERSPECTIVE");
00708 output.append_tag();
00709 output.terminate_string();
00710 }
00711
00712 void PerspectiveMain::read_data(KeyFrame *keyframe)
00713 {
00714 FileXML input;
00715
00716 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00717
00718 int result = 0;
00719
00720 while(!result)
00721 {
00722 result = input.read_tag();
00723
00724 if(!result)
00725 {
00726 if(input.tag.title_is("PERSPECTIVE"))
00727 {
00728 config.x1 = input.tag.get_property("X1", config.x1);
00729 config.x2 = input.tag.get_property("X2", config.x2);
00730 config.x3 = input.tag.get_property("X3", config.x3);
00731 config.x4 = input.tag.get_property("X4", config.x4);
00732 config.y1 = input.tag.get_property("Y1", config.y1);
00733 config.y2 = input.tag.get_property("Y2", config.y2);
00734 config.y3 = input.tag.get_property("Y3", config.y3);
00735 config.y4 = input.tag.get_property("Y4", config.y4);
00736
00737 config.mode = input.tag.get_property("MODE", config.mode);
00738 config.forward = input.tag.get_property("FORWARD", config.forward);
00739 config.window_w = input.tag.get_property("WINDOW_W", config.window_w);
00740 config.window_h = input.tag.get_property("WINDOW_H", config.window_h);
00741 }
00742 }
00743 }
00744 }
00745
00746 float PerspectiveMain::get_current_x()
00747 {
00748 switch(config.current_point)
00749 {
00750 case 0:
00751 return config.x1;
00752 break;
00753 case 1:
00754 return config.x2;
00755 break;
00756 case 2:
00757 return config.x3;
00758 break;
00759 case 3:
00760 return config.x4;
00761 break;
00762 }
00763 }
00764
00765 float PerspectiveMain::get_current_y()
00766 {
00767 switch(config.current_point)
00768 {
00769 case 0:
00770 return config.y1;
00771 break;
00772 case 1:
00773 return config.y2;
00774 break;
00775 case 2:
00776 return config.y3;
00777 break;
00778 case 3:
00779 return config.y4;
00780 break;
00781 }
00782 }
00783
00784 void PerspectiveMain::set_current_x(float value)
00785 {
00786 switch(config.current_point)
00787 {
00788 case 0:
00789 config.x1 = value;
00790 break;
00791 case 1:
00792 config.x2 = value;
00793 break;
00794 case 2:
00795 config.x3 = value;
00796 break;
00797 case 3:
00798 config.x4 = value;
00799 break;
00800 }
00801 }
00802
00803 void PerspectiveMain::set_current_y(float value)
00804 {
00805 switch(config.current_point)
00806 {
00807 case 0:
00808 config.y1 = value;
00809 break;
00810 case 1:
00811 config.y2 = value;
00812 break;
00813 case 2:
00814 config.y3 = value;
00815 break;
00816 case 3:
00817 config.y4 = value;
00818 break;
00819 }
00820 }
00821
00822
00823
00824 int PerspectiveMain::process_buffer(VFrame *frame,
00825 int64_t start_position,
00826 double frame_rate)
00827 {
00828 int need_reconfigure = load_configuration();
00829
00830
00831
00832 if( EQUIV(config.x1, 0) && EQUIV(config.y1, 0) &&
00833 EQUIV(config.x2, 100) && EQUIV(config.y2, 0) &&
00834 EQUIV(config.x3, 100) && EQUIV(config.y3, 100) &&
00835 EQUIV(config.x4, 0) && EQUIV(config.y4, 100))
00836 {
00837 read_frame(frame,
00838 0,
00839 start_position,
00840 frame_rate,
00841 get_use_opengl());
00842 return 1;
00843 }
00844
00845
00846 int use_opengl = get_use_opengl() &&
00847 (config.mode == AffineEngine::PERSPECTIVE ||
00848 config.mode == AffineEngine::SHEER);
00849 read_frame(frame,
00850 0,
00851 start_position,
00852 frame_rate,
00853 use_opengl);
00854
00855 if(!engine) engine = new AffineEngine(get_project_smp() + 1,
00856 get_project_smp() + 1);
00857
00858 if(use_opengl)
00859 return run_opengl();
00860
00861
00862
00863 this->input = frame;
00864 this->output = frame;
00865
00866 int w = frame->get_w();
00867 int h = frame->get_h();
00868 int color_model = frame->get_color_model();
00869
00870 if(temp &&
00871 config.mode == AffineEngine::STRETCH &&
00872 (temp->get_w() != w * AFFINE_OVERSAMPLE ||
00873 temp->get_h() != h * AFFINE_OVERSAMPLE))
00874 {
00875 delete temp;
00876 temp = 0;
00877 }
00878 else
00879 if(temp &&
00880 (config.mode == AffineEngine::PERSPECTIVE ||
00881 config.mode == AffineEngine::SHEER) &&
00882 (temp->get_w() != w ||
00883 temp->get_h() != h))
00884 {
00885 delete temp;
00886 temp = 0;
00887 }
00888
00889 if(config.mode == AffineEngine::STRETCH)
00890 {
00891 if(!temp)
00892 {
00893 temp = new VFrame(0,
00894 w * AFFINE_OVERSAMPLE,
00895 h * AFFINE_OVERSAMPLE,
00896 color_model);
00897 }
00898 temp->clear_frame();
00899 }
00900
00901 if(config.mode == AffineEngine::PERSPECTIVE ||
00902 config.mode == AffineEngine::SHEER)
00903 {
00904 if(frame->get_rows()[0] == frame->get_rows()[0])
00905 {
00906 if(!temp)
00907 {
00908 temp = new VFrame(0,
00909 w,
00910 h,
00911 color_model);
00912 }
00913 temp->copy_from(input);
00914 input = temp;
00915 }
00916 output->clear_frame();
00917 }
00918
00919
00920 engine->process(output,
00921 input,
00922 temp,
00923 config.mode,
00924 config.x1,
00925 config.y1,
00926 config.x2,
00927 config.y2,
00928 config.x3,
00929 config.y3,
00930 config.x4,
00931 config.y4,
00932 config.forward);
00933
00934
00935
00936
00937
00938
00939 if(config.mode == AffineEngine::STRETCH)
00940 {
00941 #define RESAMPLE(type, components, chroma_offset) \
00942 { \
00943 for(int i = 0; i < h; i++) \
00944 { \
00945 type *out_row = (type*)output->get_rows()[i]; \
00946 type *in_row1 = (type*)temp->get_rows()[i * AFFINE_OVERSAMPLE]; \
00947 type *in_row2 = (type*)temp->get_rows()[i * AFFINE_OVERSAMPLE + 1]; \
00948 for(int j = 0; j < w; j++) \
00949 { \
00950 out_row[0] = (in_row1[0] + \
00951 in_row1[components] + \
00952 in_row2[0] + \
00953 in_row2[components]) / \
00954 AFFINE_OVERSAMPLE / \
00955 AFFINE_OVERSAMPLE; \
00956 out_row[1] = ((in_row1[1] + \
00957 in_row1[components + 1] + \
00958 in_row2[1] + \
00959 in_row2[components + 1]) - \
00960 chroma_offset * \
00961 AFFINE_OVERSAMPLE * \
00962 AFFINE_OVERSAMPLE) / \
00963 AFFINE_OVERSAMPLE / \
00964 AFFINE_OVERSAMPLE + \
00965 chroma_offset; \
00966 out_row[2] = ((in_row1[2] + \
00967 in_row1[components + 2] + \
00968 in_row2[2] + \
00969 in_row2[components + 2]) - \
00970 chroma_offset * \
00971 AFFINE_OVERSAMPLE * \
00972 AFFINE_OVERSAMPLE) / \
00973 AFFINE_OVERSAMPLE / \
00974 AFFINE_OVERSAMPLE + \
00975 chroma_offset; \
00976 if(components == 4) \
00977 { \
00978 out_row[3] = (in_row1[3] + \
00979 in_row1[components + 3] + \
00980 in_row2[3] + \
00981 in_row2[components + 3]) / \
00982 AFFINE_OVERSAMPLE / \
00983 AFFINE_OVERSAMPLE; \
00984 } \
00985 out_row += components; \
00986 in_row1 += components * AFFINE_OVERSAMPLE; \
00987 in_row2 += components * AFFINE_OVERSAMPLE; \
00988 } \
00989 } \
00990 }
00991
00992 switch(frame->get_color_model())
00993 {
00994 case BC_RGB_FLOAT:
00995 RESAMPLE(float, 3, 0)
00996 break;
00997 case BC_RGB888:
00998 RESAMPLE(unsigned char, 3, 0)
00999 break;
01000 case BC_RGBA_FLOAT:
01001 RESAMPLE(float, 4, 0)
01002 break;
01003 case BC_RGBA8888:
01004 RESAMPLE(unsigned char, 4, 0)
01005 break;
01006 case BC_YUV888:
01007 RESAMPLE(unsigned char, 3, 0x80)
01008 break;
01009 case BC_YUVA8888:
01010 RESAMPLE(unsigned char, 4, 0x80)
01011 break;
01012 case BC_RGB161616:
01013 RESAMPLE(uint16_t, 3, 0)
01014 break;
01015 case BC_RGBA16161616:
01016 RESAMPLE(uint16_t, 4, 0)
01017 break;
01018 case BC_YUV161616:
01019 RESAMPLE(uint16_t, 3, 0x8000)
01020 break;
01021 case BC_YUVA16161616:
01022 RESAMPLE(uint16_t, 4, 0x8000)
01023 break;
01024 }
01025 }
01026
01027 return 1;
01028 }
01029
01030
01031 int PerspectiveMain::handle_opengl()
01032 {
01033 #ifdef HAVE_GL
01034 engine->set_opengl(1);
01035 engine->process(get_output(),
01036 get_output(),
01037 get_output(),
01038 config.mode,
01039 config.x1,
01040 config.y1,
01041 config.x2,
01042 config.y2,
01043 config.x3,
01044 config.y3,
01045 config.x4,
01046 config.y4,
01047 config.forward);
01048 engine->set_opengl(0);
01049 return 0;
01050 #endif
01051 }
01052
01053
01054
01055
01056
01057