X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;ds=sidebyside;f=cinelerra-5.1%2Fplugins%2Fperspective%2Fperspective.C;fp=cinelerra-5.1%2Fplugins%2Fperspective%2Fperspective.C;h=26a2e774ebc1eba55a4cc9f25e98151808450d64;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hp=0000000000000000000000000000000000000000;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/plugins/perspective/perspective.C b/cinelerra-5.1/plugins/perspective/perspective.C new file mode 100644 index 00000000..26a2e774 --- /dev/null +++ b/cinelerra-5.1/plugins/perspective/perspective.C @@ -0,0 +1,1029 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "affine.h" +#include "cursors.h" +#include "language.h" +#include "perspective.h" + + + + + + + +REGISTER_PLUGIN(PerspectiveMain) + + + +PerspectiveConfig::PerspectiveConfig() +{ + x1 = 0; + y1 = 0; + x2 = 100; + y2 = 0; + x3 = 100; + y3 = 100; + x4 = 0; + y4 = 100; + mode = AffineEngine::PERSPECTIVE; + window_w = 400; + window_h = 450; + current_point = 0; + forward = 1; +} + +int PerspectiveConfig::equivalent(PerspectiveConfig &that) +{ + return + EQUIV(x1, that.x1) && + EQUIV(y1, that.y1) && + EQUIV(x2, that.x2) && + EQUIV(y2, that.y2) && + EQUIV(x3, that.x3) && + EQUIV(y3, that.y3) && + EQUIV(x4, that.x4) && + EQUIV(y4, that.y4) && + mode == that.mode && + forward == that.forward; +} + +void PerspectiveConfig::copy_from(PerspectiveConfig &that) +{ + x1 = that.x1; + y1 = that.y1; + x2 = that.x2; + y2 = that.y2; + x3 = that.x3; + y3 = that.y3; + x4 = that.x4; + y4 = that.y4; + mode = that.mode; + window_w = that.window_w; + window_h = that.window_h; + current_point = that.current_point; + forward = that.forward; +} + +void PerspectiveConfig::interpolate(PerspectiveConfig &prev, + PerspectiveConfig &next, + int64_t prev_frame, + int64_t next_frame, + int64_t current_frame) +{ + double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame); + double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame); + this->x1 = prev.x1 * prev_scale + next.x1 * next_scale; + this->y1 = prev.y1 * prev_scale + next.y1 * next_scale; + this->x2 = prev.x2 * prev_scale + next.x2 * next_scale; + this->y2 = prev.y2 * prev_scale + next.y2 * next_scale; + this->x3 = prev.x3 * prev_scale + next.x3 * next_scale; + this->y3 = prev.y3 * prev_scale + next.y3 * next_scale; + this->x4 = prev.x4 * prev_scale + next.x4 * next_scale; + this->y4 = prev.y4 * prev_scale + next.y4 * next_scale; + mode = prev.mode; + forward = prev.forward; +} + + + + + + + + + + + + + +PerspectiveWindow::PerspectiveWindow(PerspectiveMain *plugin) + : PluginClientWindow(plugin, + plugin->config.window_w, + plugin->config.window_h, + plugin->config.window_w, + plugin->config.window_h, + 0) +{ +//printf("PerspectiveWindow::PerspectiveWindow 1 %d %d\n", plugin->config.window_w, plugin->config.window_h); + this->plugin = plugin; +} + +PerspectiveWindow::~PerspectiveWindow() +{ +} + +void PerspectiveWindow::create_objects() +{ + int x = 10, y = 10; + + add_subwindow(canvas = new PerspectiveCanvas(plugin, + x, + y, + get_w() - 20, + get_h() - 140)); + canvas->set_cursor(CROSS_CURSOR, 0, 0); + y += canvas->get_h() + 10; + add_subwindow(new BC_Title(x, y, _("Current X:"))); + x += 80; + this->x = new PerspectiveCoord(this, + plugin, + x, + y, + plugin->get_current_x(), + 1); + this->x->create_objects(); + x += 140; + add_subwindow(new BC_Title(x, y, _("Y:"))); + x += 20; + this->y = new PerspectiveCoord(this, + plugin, + x, + y, + plugin->get_current_y(), + 0); + this->y->create_objects(); + y += 30; + x = 10; + add_subwindow(new PerspectiveReset(plugin, x, y)); + x += 100; + add_subwindow(mode_perspective = new PerspectiveMode(plugin, + x, + y, + AffineEngine::PERSPECTIVE, + _("Perspective"))); + x += 120; + add_subwindow(mode_sheer = new PerspectiveMode(plugin, + x, + y, + AffineEngine::SHEER, + _("Sheer"))); + x = 110; + y += 30; + add_subwindow(mode_stretch = new PerspectiveMode(plugin, + x, + y, + AffineEngine::STRETCH, + _("Stretch"))); + update_canvas(); + y += 30; + x = 10; + add_subwindow(new BC_Title(x, y, _("Perspective direction:"))); + x += 170; + add_subwindow(forward = new PerspectiveDirection(plugin, + x, + y, + 1, + _("Forward"))); + x += 100; + add_subwindow(reverse = new PerspectiveDirection(plugin, + x, + y, + 0, + _("Reverse"))); + + show_window(); +} + + + +int PerspectiveWindow::resize_event(int w, int h) +{ + return 1; +} + +void PerspectiveWindow::update_canvas() +{ + canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h()); + int x1, y1, x2, y2, x3, y3, x4, y4; + calculate_canvas_coords(x1, y1, x2, y2, x3, y3, x4, y4); + +// printf("PerspectiveWindow::update_canvas %d,%d %d,%d %d,%d %d,%d\n", +// x1, +// y1, +// x2, +// y2, +// x3, +// y3, +// x4, +// y4); +// Draw divisions + canvas->set_color(WHITE); + +#define DIVISIONS 10 + for(int i = 0; i <= DIVISIONS; i++) + { +// latitude + canvas->draw_line( + x1 + (x4 - x1) * i / DIVISIONS, + y1 + (y4 - y1) * i / DIVISIONS, + x2 + (x3 - x2) * i / DIVISIONS, + y2 + (y3 - y2) * i / DIVISIONS); +// longitude + canvas->draw_line( + x1 + (x2 - x1) * i / DIVISIONS, + y1 + (y2 - y1) * i / DIVISIONS, + x4 + (x3 - x4) * i / DIVISIONS, + y4 + (y3 - y4) * i / DIVISIONS); + } + +// Corners +#define RADIUS 5 + if(plugin->config.current_point == 0) + canvas->draw_disc(x1 - RADIUS, y1 - RADIUS, RADIUS * 2, RADIUS * 2); + else + canvas->draw_circle(x1 - RADIUS, y1 - RADIUS, RADIUS * 2, RADIUS * 2); + + if(plugin->config.current_point == 1) + canvas->draw_disc(x2 - RADIUS, y2 - RADIUS, RADIUS * 2, RADIUS * 2); + else + canvas->draw_circle(x2 - RADIUS, y2 - RADIUS, RADIUS * 2, RADIUS * 2); + + if(plugin->config.current_point == 2) + canvas->draw_disc(x3 - RADIUS, y3 - RADIUS, RADIUS * 2, RADIUS * 2); + else + canvas->draw_circle(x3 - RADIUS, y3 - RADIUS, RADIUS * 2, RADIUS * 2); + + if(plugin->config.current_point == 3) + canvas->draw_disc(x4 - RADIUS, y4 - RADIUS, RADIUS * 2, RADIUS * 2); + else + canvas->draw_circle(x4 - RADIUS, y4 - RADIUS, RADIUS * 2, RADIUS * 2); + + canvas->flash(); +} + +void PerspectiveWindow::update_mode() +{ + mode_perspective->update(plugin->config.mode == AffineEngine::PERSPECTIVE); + mode_sheer->update(plugin->config.mode == AffineEngine::SHEER); + mode_stretch->update(plugin->config.mode == AffineEngine::STRETCH); + forward->update(plugin->config.forward); + reverse->update(!plugin->config.forward); +} + +void PerspectiveWindow::update_coord() +{ + x->update(plugin->get_current_x()); + y->update(plugin->get_current_y()); +} + +void PerspectiveWindow::calculate_canvas_coords(int &x1, + int &y1, + int &x2, + int &y2, + int &x3, + int &y3, + int &x4, + int &y4) +{ + int w = canvas->get_w() - 1; + int h = canvas->get_h() - 1; + if(plugin->config.mode == AffineEngine::PERSPECTIVE || + plugin->config.mode == AffineEngine::STRETCH) + { + x1 = (int)(plugin->config.x1 * w / 100); + y1 = (int)(plugin->config.y1 * h / 100); + x2 = (int)(plugin->config.x2 * w / 100); + y2 = (int)(plugin->config.y2 * h / 100); + x3 = (int)(plugin->config.x3 * w / 100); + y3 = (int)(plugin->config.y3 * h / 100); + x4 = (int)(plugin->config.x4 * w / 100); + y4 = (int)(plugin->config.y4 * h / 100); + } + else + { + x1 = (int)(plugin->config.x1 * w) / 100; + y1 = 0; + x2 = x1 + w; + y2 = 0; + x4 = (int)(plugin->config.x4 * w) / 100; + y4 = h; + x3 = x4 + w; + y3 = h; + } +} + + + + +PerspectiveCanvas::PerspectiveCanvas(PerspectiveMain *plugin, + int x, + int y, + int w, + int h) + : BC_SubWindow(x, y, w, h, BLACK) +{ + this->plugin = plugin; + state = PerspectiveCanvas::NONE; +} + + + + +int PerspectiveCanvas::button_press_event() +{ + if(is_event_win() && cursor_inside()) + { +// Set current point + int x1, y1, x2, y2, x3, y3, x4, y4; + int cursor_x = get_cursor_x(); + int cursor_y = get_cursor_y(); + ((PerspectiveWindow*)plugin->thread->window)->calculate_canvas_coords(x1, y1, x2, y2, x3, y3, x4, y4); + + float distance1 = DISTANCE(cursor_x, cursor_y, x1, y1); + float distance2 = DISTANCE(cursor_x, cursor_y, x2, y2); + float distance3 = DISTANCE(cursor_x, cursor_y, x3, y3); + float distance4 = DISTANCE(cursor_x, cursor_y, x4, y4); +// printf("PerspectiveCanvas::button_press_event %f %d %d %d %d\n", +// distance3, +// cursor_x, +// cursor_y, +// x3, +// y3); + float min = distance1; + plugin->config.current_point = 0; + if(distance2 < min) + { + min = distance2; + plugin->config.current_point = 1; + } + if(distance3 < min) + { + min = distance3; + plugin->config.current_point = 2; + } + if(distance4 < min) + { + min = distance4; + plugin->config.current_point = 3; + } + + if(plugin->config.mode == AffineEngine::SHEER) + { + if(plugin->config.current_point == 1) + plugin->config.current_point = 0; + else + if(plugin->config.current_point == 2) + plugin->config.current_point = 3; + } + start_cursor_x = cursor_x; + start_cursor_y = cursor_y; + + if(alt_down() || shift_down()) + { + if(alt_down()) + state = PerspectiveCanvas::DRAG_FULL; + else + state = PerspectiveCanvas::ZOOM; + +// Get starting positions + start_x1 = plugin->config.x1; + start_y1 = plugin->config.y1; + start_x2 = plugin->config.x2; + start_y2 = plugin->config.y2; + start_x3 = plugin->config.x3; + start_y3 = plugin->config.y3; + start_x4 = plugin->config.x4; + start_y4 = plugin->config.y4; + } + else + { + state = PerspectiveCanvas::DRAG; + +// Get starting positions + start_x1 = plugin->get_current_x(); + start_y1 = plugin->get_current_y(); + } + ((PerspectiveWindow*)plugin->thread->window)->update_coord(); + ((PerspectiveWindow*)plugin->thread->window)->update_canvas(); + return 1; + } + + return 0; +} + +int PerspectiveCanvas::button_release_event() +{ + if(state != PerspectiveCanvas::NONE) + { + state = PerspectiveCanvas::NONE; + return 1; + } + return 0; +} + +int PerspectiveCanvas::cursor_motion_event() +{ + if(state != PerspectiveCanvas::NONE) + { + int w = get_w() - 1; + int h = get_h() - 1; + if(state == PerspectiveCanvas::DRAG) + { + plugin->set_current_x((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x1); + plugin->set_current_y((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y1); + } + else + if(state == PerspectiveCanvas::DRAG_FULL) + { + plugin->config.x1 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x1); + plugin->config.y1 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y1); + plugin->config.x2 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x2); + plugin->config.y2 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y2); + plugin->config.x3 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x3); + plugin->config.y3 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y3); + plugin->config.x4 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x4); + plugin->config.y4 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y4); + } + else + if(state == PerspectiveCanvas::ZOOM) + { + float center_x = (start_x1 + + start_x2 + + start_x3 + + start_x4) / 4; + float center_y = (start_y1 + + start_y2 + + start_y3 + + start_y4) / 4; + float zoom = (float)(get_cursor_y() - start_cursor_y + 640) / 640; + plugin->config.x1 = center_x + (start_x1 - center_x) * zoom; + plugin->config.y1 = center_y + (start_y1 - center_y) * zoom; + plugin->config.x2 = center_x + (start_x2 - center_x) * zoom; + plugin->config.y2 = center_y + (start_y2 - center_y) * zoom; + plugin->config.x3 = center_x + (start_x3 - center_x) * zoom; + plugin->config.y3 = center_y + (start_y3 - center_y) * zoom; + plugin->config.x4 = center_x + (start_x4 - center_x) * zoom; + plugin->config.y4 = center_y + (start_y4 - center_y) * zoom; + } + ((PerspectiveWindow*)plugin->thread->window)->update_canvas(); + ((PerspectiveWindow*)plugin->thread->window)->update_coord(); + plugin->send_configure_change(); + return 1; + } + + return 0; +} + + + + + + +PerspectiveCoord::PerspectiveCoord(PerspectiveWindow *gui, + PerspectiveMain *plugin, + int x, + int y, + float value, + int is_x) + : BC_TumbleTextBox(gui, value, (float)-100, (float)200, x, y, 100) +{ + this->plugin = plugin; + this->is_x = is_x; +} + +int PerspectiveCoord::handle_event() +{ + if(is_x) + plugin->set_current_x(atof(get_text())); + else + plugin->set_current_y(atof(get_text())); + ((PerspectiveWindow*)plugin->thread->window)->update_canvas(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + +PerspectiveReset::PerspectiveReset(PerspectiveMain *plugin, + int x, + int y) + : BC_GenericButton(x, y, _("Reset")) +{ + this->plugin = plugin; +} +int PerspectiveReset::handle_event() +{ + plugin->config.x1 = 0; + plugin->config.y1 = 0; + plugin->config.x2 = 100; + plugin->config.y2 = 0; + plugin->config.x3 = 100; + plugin->config.y3 = 100; + plugin->config.x4 = 0; + plugin->config.y4 = 100; + ((PerspectiveWindow*)plugin->thread->window)->update_canvas(); + ((PerspectiveWindow*)plugin->thread->window)->update_coord(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + + + + +PerspectiveMode::PerspectiveMode(PerspectiveMain *plugin, + int x, + int y, + int value, + char *text) + : BC_Radial(x, y, plugin->config.mode == value, text) +{ + this->plugin = plugin; + this->value = value; +} +int PerspectiveMode::handle_event() +{ + plugin->config.mode = value; + ((PerspectiveWindow*)plugin->thread->window)->update_mode(); + ((PerspectiveWindow*)plugin->thread->window)->update_canvas(); + plugin->send_configure_change(); + return 1; +} + + + + +PerspectiveDirection::PerspectiveDirection(PerspectiveMain *plugin, + int x, + int y, + int value, + char *text) + : BC_Radial(x, y, plugin->config.forward == value, text) +{ + this->plugin = plugin; + this->value = value; +} +int PerspectiveDirection::handle_event() +{ + plugin->config.forward = value; + ((PerspectiveWindow*)plugin->thread->window)->update_mode(); + plugin->send_configure_change(); + return 1; +} + + + + + + + + + + + + +PerspectiveMain::PerspectiveMain(PluginServer *server) + : PluginVClient(server) +{ + + engine = 0; + temp = 0; +} + +PerspectiveMain::~PerspectiveMain() +{ + + if(engine) delete engine; + if(temp) delete temp; +} + +const char* PerspectiveMain::plugin_title() { return _("Perspective"); } +int PerspectiveMain::is_realtime() { return 1; } + + + +NEW_WINDOW_MACRO(PerspectiveMain, PerspectiveWindow) + +LOAD_CONFIGURATION_MACRO(PerspectiveMain, PerspectiveConfig) + + + +void PerspectiveMain::update_gui() +{ + if(thread) + { +//printf("PerspectiveMain::update_gui 1\n"); + thread->window->lock_window(); +//printf("PerspectiveMain::update_gui 2\n"); + load_configuration(); + ((PerspectiveWindow*)thread->window)->update_coord(); + ((PerspectiveWindow*)thread->window)->update_mode(); + ((PerspectiveWindow*)thread->window)->update_canvas(); + thread->window->unlock_window(); +//printf("PerspectiveMain::update_gui 3\n"); + } +} + + + + + +void PerspectiveMain::save_data(KeyFrame *keyframe) +{ + FileXML output; + +// cause data to be stored directly in text + output.set_shared_output(keyframe->get_data(), MESSAGESIZE); + output.tag.set_title("PERSPECTIVE"); + + output.tag.set_property("X1", config.x1); + output.tag.set_property("X2", config.x2); + output.tag.set_property("X3", config.x3); + output.tag.set_property("X4", config.x4); + output.tag.set_property("Y1", config.y1); + output.tag.set_property("Y2", config.y2); + output.tag.set_property("Y3", config.y3); + output.tag.set_property("Y4", config.y4); + + output.tag.set_property("MODE", config.mode); + output.tag.set_property("FORWARD", config.forward); + output.tag.set_property("WINDOW_W", config.window_w); + output.tag.set_property("WINDOW_H", config.window_h); + output.append_tag(); + output.tag.set_title("/PERSPECTIVE"); + output.append_tag(); + output.append_newline(); + output.terminate_string(); +} + +void PerspectiveMain::read_data(KeyFrame *keyframe) +{ + FileXML input; + + input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data())); + + int result = 0; + + while(!result) + { + result = input.read_tag(); + + if(!result) + { + if(input.tag.title_is("PERSPECTIVE")) + { + config.x1 = input.tag.get_property("X1", config.x1); + config.x2 = input.tag.get_property("X2", config.x2); + config.x3 = input.tag.get_property("X3", config.x3); + config.x4 = input.tag.get_property("X4", config.x4); + config.y1 = input.tag.get_property("Y1", config.y1); + config.y2 = input.tag.get_property("Y2", config.y2); + config.y3 = input.tag.get_property("Y3", config.y3); + config.y4 = input.tag.get_property("Y4", config.y4); + + config.mode = input.tag.get_property("MODE", config.mode); + config.forward = input.tag.get_property("FORWARD", config.forward); + config.window_w = input.tag.get_property("WINDOW_W", config.window_w); + config.window_h = input.tag.get_property("WINDOW_H", config.window_h); + } + } + } +} + +float PerspectiveMain::get_current_x() +{ + switch(config.current_point) + { + case 0: + return config.x1; + break; + case 1: + return config.x2; + break; + case 2: + return config.x3; + break; + case 3: + return config.x4; + break; + } + return 0; +} + +float PerspectiveMain::get_current_y() +{ + switch(config.current_point) + { + case 0: + return config.y1; + break; + case 1: + return config.y2; + break; + case 2: + return config.y3; + break; + case 3: + return config.y4; + break; + } + return 0; +} + +void PerspectiveMain::set_current_x(float value) +{ + switch(config.current_point) + { + case 0: + config.x1 = value; + break; + case 1: + config.x2 = value; + break; + case 2: + config.x3 = value; + break; + case 3: + config.x4 = value; + break; + } +} + +void PerspectiveMain::set_current_y(float value) +{ + switch(config.current_point) + { + case 0: + config.y1 = value; + break; + case 1: + config.y2 = value; + break; + case 2: + config.y3 = value; + break; + case 3: + config.y4 = value; + break; + } +} + + + +int PerspectiveMain::process_buffer(VFrame *frame, + int64_t start_position, + double frame_rate) +{ + /*int need_reconfigure =*/ load_configuration(); + +// Do nothing + if( EQUIV(config.x1, 0) && EQUIV(config.y1, 0) && + EQUIV(config.x2, 100) && EQUIV(config.y2, 0) && + EQUIV(config.x3, 100) && EQUIV(config.y3, 100) && + EQUIV(config.x4, 0) && EQUIV(config.y4, 100)) + { + read_frame(frame, + 0, + start_position, + frame_rate, + get_use_opengl()); + return 1; + } + +// Opengl does some funny business with stretching. + int use_opengl = get_use_opengl() && + (config.mode == AffineEngine::PERSPECTIVE || + config.mode == AffineEngine::SHEER); + read_frame(frame, + 0, + start_position, + frame_rate, + use_opengl); + + if(!engine) engine = new AffineEngine(get_project_smp() + 1, + get_project_smp() + 1); + + if(use_opengl) + return run_opengl(); + + + + this->input = frame; + this->output = frame; + + int w = frame->get_w(); + int h = frame->get_h(); + int color_model = frame->get_color_model(); + + if(temp && + config.mode == AffineEngine::STRETCH && + (temp->get_w() != w * AFFINE_OVERSAMPLE || + temp->get_h() != h * AFFINE_OVERSAMPLE)) + { + delete temp; + temp = 0; + } + else + if(temp && + (config.mode == AffineEngine::PERSPECTIVE || + config.mode == AffineEngine::SHEER) && + (temp->get_w() != w || + temp->get_h() != h)) + { + delete temp; + temp = 0; + } + + if(config.mode == AffineEngine::STRETCH) + { + if(!temp) + { + temp = new VFrame(0, + -1, + w * AFFINE_OVERSAMPLE, + h * AFFINE_OVERSAMPLE, + color_model, + -1); + } + temp->clear_frame(); + } + + if(config.mode == AffineEngine::PERSPECTIVE || + config.mode == AffineEngine::SHEER) + { + if(frame->get_rows()[0] == frame->get_rows()[0]) + { + if(!temp) + { + temp = new VFrame(0, + -1, + w, + h, + color_model, + -1); + } + temp->copy_from(input); + input = temp; + } + output->clear_frame(); + } + + + engine->process(output, + input, + temp, + config.mode, + config.x1, + config.y1, + config.x2, + config.y2, + config.x3, + config.y3, + config.x4, + config.y4, + config.forward); + + + + +// Resample + + if(config.mode == AffineEngine::STRETCH) + { +#define RESAMPLE(type, components, chroma_offset) \ +{ \ + for(int i = 0; i < h; i++) \ + { \ + type *out_row = (type*)output->get_rows()[i]; \ + type *in_row1 = (type*)temp->get_rows()[i * AFFINE_OVERSAMPLE]; \ + type *in_row2 = (type*)temp->get_rows()[i * AFFINE_OVERSAMPLE + 1]; \ + for(int j = 0; j < w; j++) \ + { \ + out_row[0] = (in_row1[0] + \ + in_row1[components] + \ + in_row2[0] + \ + in_row2[components]) / \ + AFFINE_OVERSAMPLE / \ + AFFINE_OVERSAMPLE; \ + out_row[1] = ((in_row1[1] + \ + in_row1[components + 1] + \ + in_row2[1] + \ + in_row2[components + 1]) - \ + chroma_offset * \ + AFFINE_OVERSAMPLE * \ + AFFINE_OVERSAMPLE) / \ + AFFINE_OVERSAMPLE / \ + AFFINE_OVERSAMPLE + \ + chroma_offset; \ + out_row[2] = ((in_row1[2] + \ + in_row1[components + 2] + \ + in_row2[2] + \ + in_row2[components + 2]) - \ + chroma_offset * \ + AFFINE_OVERSAMPLE * \ + AFFINE_OVERSAMPLE) / \ + AFFINE_OVERSAMPLE / \ + AFFINE_OVERSAMPLE + \ + chroma_offset; \ + if(components == 4) \ + { \ + out_row[3] = (in_row1[3] + \ + in_row1[components + 3] + \ + in_row2[3] + \ + in_row2[components + 3]) / \ + AFFINE_OVERSAMPLE / \ + AFFINE_OVERSAMPLE; \ + } \ + out_row += components; \ + in_row1 += components * AFFINE_OVERSAMPLE; \ + in_row2 += components * AFFINE_OVERSAMPLE; \ + } \ + } \ +} + + switch(frame->get_color_model()) + { + case BC_RGB_FLOAT: + RESAMPLE(float, 3, 0) + break; + case BC_RGB888: + RESAMPLE(unsigned char, 3, 0) + break; + case BC_RGBA_FLOAT: + RESAMPLE(float, 4, 0) + break; + case BC_RGBA8888: + RESAMPLE(unsigned char, 4, 0) + break; + case BC_YUV888: + RESAMPLE(unsigned char, 3, 0x80) + break; + case BC_YUVA8888: + RESAMPLE(unsigned char, 4, 0x80) + break; + case BC_RGB161616: + RESAMPLE(uint16_t, 3, 0) + break; + case BC_RGBA16161616: + RESAMPLE(uint16_t, 4, 0) + break; + case BC_YUV161616: + RESAMPLE(uint16_t, 3, 0x8000) + break; + case BC_YUVA16161616: + RESAMPLE(uint16_t, 4, 0x8000) + break; + } + } + + return 1; +} + + +int PerspectiveMain::handle_opengl() +{ +#ifdef HAVE_GL + engine->set_opengl(1); + engine->process(get_output(), + get_output(), + get_output(), + config.mode, + config.x1, + config.y1, + config.x2, + config.y2, + config.x3, + config.y3, + config.x4, + config.y4, + config.forward); + engine->set_opengl(0); + return 0; +#endif +} + + + + + +