4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "perspective.h"
33 REGISTER_PLUGIN(PerspectiveMain)
37 PerspectiveConfig::PerspectiveConfig()
43 mode = AffineEngine::PERSPECTIVE;
44 smoothing = AffineEngine::AF_DEFAULT;
51 int PerspectiveConfig::equivalent(PerspectiveConfig &that)
63 smoothing == that.smoothing &&
64 forward == that.forward;
67 void PerspectiveConfig::copy_from(PerspectiveConfig &that)
69 x1 = that.x1; y1 = that.y1;
70 x2 = that.x2; y2 = that.y2;
71 x3 = that.x3; y3 = that.y3;
72 x4 = that.x4; y4 = that.y4;
74 smoothing = that.smoothing;
75 window_w = that.window_w;
76 window_h = that.window_h;
77 current_point = that.current_point;
78 forward = that.forward;
81 void PerspectiveConfig::interpolate(PerspectiveConfig &prev, PerspectiveConfig &next,
82 int64_t prev_frame, int64_t next_frame, int64_t current_frame)
84 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
85 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
86 this->x1 = prev.x1 * prev_scale + next.x1 * next_scale;
87 this->y1 = prev.y1 * prev_scale + next.y1 * next_scale;
88 this->x2 = prev.x2 * prev_scale + next.x2 * next_scale;
89 this->y2 = prev.y2 * prev_scale + next.y2 * next_scale;
90 this->x3 = prev.x3 * prev_scale + next.x3 * next_scale;
91 this->y3 = prev.y3 * prev_scale + next.y3 * next_scale;
92 this->x4 = prev.x4 * prev_scale + next.x4 * next_scale;
93 this->y4 = prev.y4 * prev_scale + next.y4 * next_scale;
95 smoothing = prev.smoothing;
96 forward = prev.forward;
100 PerspectiveWindow::PerspectiveWindow(PerspectiveMain *plugin)
101 : PluginClientWindow(plugin,
102 plugin->config.window_w, plugin->config.window_h,
103 plugin->config.window_w, plugin->config.window_h, 0)
105 //printf("PerspectiveWindow::PerspectiveWindow 1 %d %d\n", plugin->config.window_w, plugin->config.window_h);
106 this->plugin = plugin;
109 PerspectiveWindow::~PerspectiveWindow()
113 void PerspectiveWindow::create_objects()
117 add_subwindow(canvas = new PerspectiveCanvas(plugin,
118 x, y, get_w() - 20, get_h() - 140));
119 canvas->set_cursor(CROSS_CURSOR, 0, 0);
120 y += canvas->get_h() + 10;
121 add_subwindow(new BC_Title(x, y, _("Current X:")));
123 this->x = new PerspectiveCoord(this,
124 plugin, x, y, plugin->get_current_x(), 1);
125 this->x->create_objects();
127 add_subwindow(new BC_Title(x, y, _("Y:")));
129 this->y = new PerspectiveCoord(this,
130 plugin, x, y, plugin->get_current_y(), 0);
131 this->y->create_objects();
133 add_subwindow(mode_perspective = new PerspectiveMode(plugin,
134 x, y, AffineEngine::PERSPECTIVE, _("Perspective")));
136 add_subwindow(mode_sheer = new PerspectiveMode(plugin,
137 x, y, AffineEngine::SHEER, _("Sheer")));
139 add_subwindow(affine = new PerspectiveAffine(this, x, y));
140 affine->create_objects();
142 add_subwindow(mode_stretch = new PerspectiveMode(plugin,
143 x, y, AffineEngine::STRETCH, _("Stretch")));
145 add_subwindow(new PerspectiveReset(plugin, x, y));
148 add_subwindow(new BC_Title(x, y, _("Perspective direction:")));
150 add_subwindow(forward = new PerspectiveDirection(plugin,
151 x, y, 1, _("Forward")));
153 add_subwindow(reverse = new PerspectiveDirection(plugin,
154 x, y, 0, _("Reverse")));
161 int PerspectiveWindow::resize_event(int w, int h)
166 void PerspectiveWindow::update_canvas()
168 canvas->clear_box(0, 0, canvas->get_w(), canvas->get_h());
169 int x1, y1, x2, y2, x3, y3, x4, y4;
170 calculate_canvas_coords(x1, y1, x2, y2, x3, y3, x4, y4);
172 //printf("PerspectiveWindow::update_canvas %d,%d %d,%d %d,%d %d,%d\n",
173 // x1, y1, x2, y2, x3, y3, x4, y4);
175 canvas->set_color(WHITE);
178 for( int i=0; i<=DIVISIONS; ++i ) {
179 canvas->draw_line( // latitude
180 x1 + (x4 - x1) * i / DIVISIONS,
181 y1 + (y4 - y1) * i / DIVISIONS,
182 x2 + (x3 - x2) * i / DIVISIONS,
183 y2 + (y3 - y2) * i / DIVISIONS);
184 canvas->draw_line( // longitude
185 x1 + (x2 - x1) * i / DIVISIONS,
186 y1 + (y2 - y1) * i / DIVISIONS,
187 x4 + (x3 - x4) * i / DIVISIONS,
188 y4 + (y3 - y4) * i / DIVISIONS);
193 if(plugin->config.current_point == 0)
194 canvas->draw_disc(x1 - RADIUS, y1 - RADIUS, RADIUS * 2, RADIUS * 2);
196 canvas->draw_circle(x1 - RADIUS, y1 - RADIUS, RADIUS * 2, RADIUS * 2);
198 if(plugin->config.current_point == 1)
199 canvas->draw_disc(x2 - RADIUS, y2 - RADIUS, RADIUS * 2, RADIUS * 2);
201 canvas->draw_circle(x2 - RADIUS, y2 - RADIUS, RADIUS * 2, RADIUS * 2);
203 if(plugin->config.current_point == 2)
204 canvas->draw_disc(x3 - RADIUS, y3 - RADIUS, RADIUS * 2, RADIUS * 2);
206 canvas->draw_circle(x3 - RADIUS, y3 - RADIUS, RADIUS * 2, RADIUS * 2);
208 if(plugin->config.current_point == 3)
209 canvas->draw_disc(x4 - RADIUS, y4 - RADIUS, RADIUS * 2, RADIUS * 2);
211 canvas->draw_circle(x4 - RADIUS, y4 - RADIUS, RADIUS * 2, RADIUS * 2);
216 void PerspectiveWindow::update_mode()
218 mode_perspective->update(plugin->config.mode == AffineEngine::PERSPECTIVE);
219 mode_sheer->update(plugin->config.mode == AffineEngine::SHEER);
220 mode_stretch->update(plugin->config.mode == AffineEngine::STRETCH);
221 forward->update(plugin->config.forward);
222 reverse->update(!plugin->config.forward);
225 void PerspectiveWindow::update_coord()
227 x->update(plugin->get_current_x());
228 y->update(plugin->get_current_y());
231 void PerspectiveWindow::calculate_canvas_coords(
232 int &x1, int &y1, int &x2, int &y2,
233 int &x3, int &y3, int &x4, int &y4)
235 int w = canvas->get_w() - 1;
236 int h = canvas->get_h() - 1;
237 if( plugin->config.mode == AffineEngine::PERSPECTIVE ||
238 plugin->config.mode == AffineEngine::STRETCH ) {
239 x1 = (int)(plugin->config.x1 * w / 100);
240 y1 = (int)(plugin->config.y1 * h / 100);
241 x2 = (int)(plugin->config.x2 * w / 100);
242 y2 = (int)(plugin->config.y2 * h / 100);
243 x3 = (int)(plugin->config.x3 * w / 100);
244 y3 = (int)(plugin->config.y3 * h / 100);
245 x4 = (int)(plugin->config.x4 * w / 100);
246 y4 = (int)(plugin->config.y4 * h / 100);
249 x1 = (int)(plugin->config.x1 * w) / 100;
253 x4 = (int)(plugin->config.x4 * w) / 100;
261 PerspectiveCanvas::PerspectiveCanvas(PerspectiveMain *plugin,
262 int x, int y, int w, int h)
263 : BC_SubWindow(x, y, w, h, BLACK)
265 this->plugin = plugin;
266 state = PerspectiveCanvas::NONE;
270 int PerspectiveCanvas::button_press_event()
272 if( is_event_win() && cursor_inside() ) {
274 int x1, y1, x2, y2, x3, y3, x4, y4;
275 int cursor_x = get_cursor_x();
276 int cursor_y = get_cursor_y();
277 ((PerspectiveWindow*)plugin->thread->window)->calculate_canvas_coords(x1, y1, x2, y2, x3, y3, x4, y4);
279 float distance1 = DISTANCE(cursor_x, cursor_y, x1, y1);
280 float distance2 = DISTANCE(cursor_x, cursor_y, x2, y2);
281 float distance3 = DISTANCE(cursor_x, cursor_y, x3, y3);
282 float distance4 = DISTANCE(cursor_x, cursor_y, x4, y4);
283 // printf("PerspectiveCanvas::button_press_event %f %d %d %d %d\n",
289 float min = distance1;
290 plugin->config.current_point = 0;
291 if( distance2 < min ) {
293 plugin->config.current_point = 1;
295 if( distance3 < min ) {
297 plugin->config.current_point = 2;
299 if( distance4 < min ) {
301 plugin->config.current_point = 3;
304 if( plugin->config.mode == AffineEngine::SHEER ) {
305 if( plugin->config.current_point == 1 )
306 plugin->config.current_point = 0;
307 else if( plugin->config.current_point == 2 )
308 plugin->config.current_point = 3;
310 start_cursor_x = cursor_x;
311 start_cursor_y = cursor_y;
313 if( alt_down() || shift_down() ) {
315 PerspectiveCanvas::DRAG_FULL :
316 PerspectiveCanvas::ZOOM;
317 // Get starting positions
318 start_x1 = plugin->config.x1;
319 start_y1 = plugin->config.y1;
320 start_x2 = plugin->config.x2;
321 start_y2 = plugin->config.y2;
322 start_x3 = plugin->config.x3;
323 start_y3 = plugin->config.y3;
324 start_x4 = plugin->config.x4;
325 start_y4 = plugin->config.y4;
328 state = PerspectiveCanvas::DRAG;
329 // Get starting positions
330 start_x1 = plugin->get_current_x();
331 start_y1 = plugin->get_current_y();
333 ((PerspectiveWindow*)plugin->thread->window)->update_coord();
334 ((PerspectiveWindow*)plugin->thread->window)->update_canvas();
341 int PerspectiveCanvas::button_release_event()
343 if( state != PerspectiveCanvas::NONE ) {
344 state = PerspectiveCanvas::NONE;
350 int PerspectiveCanvas::cursor_motion_event()
352 if( state != PerspectiveCanvas::NONE ) {
355 if( state == PerspectiveCanvas::DRAG ) {
356 plugin->set_current_x((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x1);
357 plugin->set_current_y((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y1);
359 else if( state == PerspectiveCanvas::DRAG_FULL ) {
360 plugin->config.x1 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x1);
361 plugin->config.y1 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y1);
362 plugin->config.x2 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x2);
363 plugin->config.y2 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y2);
364 plugin->config.x3 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x3);
365 plugin->config.y3 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y3);
366 plugin->config.x4 = ((float)(get_cursor_x() - start_cursor_x) / w * 100 + start_x4);
367 plugin->config.y4 = ((float)(get_cursor_y() - start_cursor_y) / h * 100 + start_y4);
369 else if( state == PerspectiveCanvas::ZOOM ) {
370 float center_x = (start_x1 + start_x2 + start_x3 + start_x4) / 4;
371 float center_y = (start_y1 + start_y2 + start_y3 + start_y4) / 4;
372 float zoom = (float)(get_cursor_y() - start_cursor_y + 640) / 640;
373 plugin->config.x1 = center_x + (start_x1 - center_x) * zoom;
374 plugin->config.y1 = center_y + (start_y1 - center_y) * zoom;
375 plugin->config.x2 = center_x + (start_x2 - center_x) * zoom;
376 plugin->config.y2 = center_y + (start_y2 - center_y) * zoom;
377 plugin->config.x3 = center_x + (start_x3 - center_x) * zoom;
378 plugin->config.y3 = center_y + (start_y3 - center_y) * zoom;
379 plugin->config.x4 = center_x + (start_x4 - center_x) * zoom;
380 plugin->config.y4 = center_y + (start_y4 - center_y) * zoom;
382 ((PerspectiveWindow*)plugin->thread->window)->update_canvas();
383 ((PerspectiveWindow*)plugin->thread->window)->update_coord();
384 plugin->send_configure_change();
392 PerspectiveCoord::PerspectiveCoord(PerspectiveWindow *gui,
393 PerspectiveMain *plugin, int x, int y, float value, int is_x)
394 : BC_TumbleTextBox(gui, value, (float)-100, (float)200, x, y, 100)
396 this->plugin = plugin;
400 int PerspectiveCoord::handle_event()
402 float v = atof(get_text());
404 plugin->set_current_x(v);
406 plugin->set_current_y(v);
407 ((PerspectiveWindow*)plugin->thread->window)->update_canvas();
408 plugin->send_configure_change();
413 PerspectiveReset::PerspectiveReset(PerspectiveMain *plugin, int x, int y)
414 : BC_GenericButton(x, y, _("Reset"))
416 this->plugin = plugin;
418 int PerspectiveReset::handle_event()
420 plugin->config.x1 = 0; plugin->config.y1 = 0;
421 plugin->config.x2 = 100; plugin->config.y2 = 0;
422 plugin->config.x3 = 100; plugin->config.y3 = 100;
423 plugin->config.x4 = 0; plugin->config.y4 = 100;
424 ((PerspectiveWindow*)plugin->thread->window)->update_canvas();
425 ((PerspectiveWindow*)plugin->thread->window)->update_coord();
426 plugin->send_configure_change();
431 PerspectiveMode::PerspectiveMode(PerspectiveMain *plugin,
432 int x, int y, int value, char *text)
433 : BC_Radial(x, y, plugin->config.mode == value, text)
435 this->plugin = plugin;
438 int PerspectiveMode::handle_event()
440 plugin->config.mode = value;
441 ((PerspectiveWindow*)plugin->thread->window)->update_mode();
442 ((PerspectiveWindow*)plugin->thread->window)->update_canvas();
443 plugin->send_configure_change();
448 PerspectiveDirection::PerspectiveDirection(PerspectiveMain *plugin,
453 : BC_Radial(x, y, plugin->config.forward == value, text)
455 this->plugin = plugin;
458 int PerspectiveDirection::handle_event()
460 plugin->config.forward = value;
461 ((PerspectiveWindow*)plugin->thread->window)->update_mode();
462 plugin->send_configure_change();
467 int PerspectiveAffineItem::handle_event()
469 ((PerspectiveAffine *)get_popup_menu())->update(id);
473 PerspectiveAffine::PerspectiveAffine(PerspectiveWindow *gui, int x, int y)
474 : BC_PopupMenu(x, y, 100, "", 1)
477 affine_modes[AffineEngine::AF_DEFAULT] = _("default");
478 affine_modes[AffineEngine::AF_NEAREST] = _("Nearest");
479 affine_modes[AffineEngine::AF_LINEAR] = _("Linear");
480 affine_modes[AffineEngine::AF_CUBIC] = _("Cubic");
483 PerspectiveAffine::~PerspectiveAffine()
485 int id = total_items();
487 remove_item(get_item(id));
488 for( int id=0; id<n_modes; ++id )
489 delete affine_items[id];
491 void PerspectiveAffine::affine_item(int id)
493 affine_items[id] = new PerspectiveAffineItem(affine_modes[id], id);
494 add_item(affine_items[id]);
497 void PerspectiveAffine::create_objects()
499 affine_item(AffineEngine::AF_DEFAULT);
500 affine_item(AffineEngine::AF_NEAREST);
501 affine_item(AffineEngine::AF_LINEAR);
502 affine_item(AffineEngine::AF_CUBIC);
503 update(gui->plugin->config.smoothing, 0);
506 void PerspectiveAffine::update(int mode, int send)
508 if( this->mode == mode ) return;
510 set_text(affine_modes[mode]);
511 gui->plugin->config.smoothing = mode;
512 if( send ) gui->plugin->send_configure_change();
515 PerspectiveMain::PerspectiveMain(PluginServer *server)
516 : PluginVClient(server)
523 PerspectiveMain::~PerspectiveMain()
526 if(engine) delete engine;
527 if(temp) delete temp;
530 const char* PerspectiveMain::plugin_title() { return _("Perspective"); }
531 int PerspectiveMain::is_realtime() { return 1; }
534 NEW_WINDOW_MACRO(PerspectiveMain, PerspectiveWindow)
536 LOAD_CONFIGURATION_MACRO(PerspectiveMain, PerspectiveConfig)
538 void PerspectiveMain::update_gui()
540 if( !thread ) return;
541 //printf("PerspectiveMain::update_gui 1\n");
542 thread->window->lock_window();
543 PerspectiveWindow *gui = (PerspectiveWindow*)thread->window;
544 //printf("PerspectiveMain::update_gui 2\n");
545 load_configuration();
548 gui->update_canvas();
549 thread->window->unlock_window();
550 //printf("PerspectiveMain::update_gui 3\n");
557 void PerspectiveMain::save_data(KeyFrame *keyframe)
561 // cause data to be stored directly in text
562 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
563 output.tag.set_title("PERSPECTIVE");
565 output.tag.set_property("X1", config.x1);
566 output.tag.set_property("X2", config.x2);
567 output.tag.set_property("X3", config.x3);
568 output.tag.set_property("X4", config.x4);
569 output.tag.set_property("Y1", config.y1);
570 output.tag.set_property("Y2", config.y2);
571 output.tag.set_property("Y3", config.y3);
572 output.tag.set_property("Y4", config.y4);
574 output.tag.set_property("MODE", config.mode);
575 output.tag.set_property("SMOOTHING", config.smoothing);
576 output.tag.set_property("FORWARD", config.forward);
577 output.tag.set_property("WINDOW_W", config.window_w);
578 output.tag.set_property("WINDOW_H", config.window_h);
580 output.tag.set_title("/PERSPECTIVE");
582 output.append_newline();
583 output.terminate_string();
586 void PerspectiveMain::read_data(KeyFrame *keyframe)
589 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
592 while(!(result = input.read_tag()) ) {
593 if(input.tag.title_is("PERSPECTIVE")) {
594 config.x1 = input.tag.get_property("X1", config.x1);
595 config.x2 = input.tag.get_property("X2", config.x2);
596 config.x3 = input.tag.get_property("X3", config.x3);
597 config.x4 = input.tag.get_property("X4", config.x4);
598 config.y1 = input.tag.get_property("Y1", config.y1);
599 config.y2 = input.tag.get_property("Y2", config.y2);
600 config.y3 = input.tag.get_property("Y3", config.y3);
601 config.y4 = input.tag.get_property("Y4", config.y4);
603 config.mode = input.tag.get_property("MODE", config.mode);
604 config.smoothing = input.tag.get_property("SMOOTHING", config.smoothing);
605 config.forward = input.tag.get_property("FORWARD", config.forward);
606 config.window_w = input.tag.get_property("WINDOW_W", config.window_w);
607 config.window_h = input.tag.get_property("WINDOW_H", config.window_h);
612 float PerspectiveMain::get_current_x()
614 switch( config.current_point ) {
615 case 0: return config.x1;
616 case 1: return config.x2;
617 case 2: return config.x3;
618 case 3: return config.x4;
623 float PerspectiveMain::get_current_y()
625 switch( config.current_point ) {
626 case 0: return config.y1;
627 case 1: return config.y2;
628 case 2: return config.y3;
629 case 3: return config.y4;
634 void PerspectiveMain::set_current_x(float value)
636 switch( config.current_point ) {
637 case 0: config.x1 = value; break;
638 case 1: config.x2 = value; break;
639 case 2: config.x3 = value; break;
640 case 3: config.x4 = value; break;
644 void PerspectiveMain::set_current_y(float value)
646 switch( config.current_point ) {
647 case 0: config.y1 = value; break;
648 case 1: config.y2 = value; break;
649 case 2: config.y3 = value; break;
650 case 3: config.y4 = value; break;
654 int PerspectiveMain::process_buffer(VFrame *frame,
655 int64_t start_position, double frame_rate)
657 /*int need_reconfigure =*/ load_configuration();
658 int smoothing = config.smoothing;
659 // default smoothing uses opengl if possible
660 int use_opengl = smoothing != AffineEngine::AF_DEFAULT ? 0 :
661 // Opengl does some funny business with stretching.
662 config.mode == AffineEngine::PERSPECTIVE ||
663 config.mode == AffineEngine::SHEER ? get_use_opengl() : 0;
665 read_frame(frame, 0, start_position, frame_rate, use_opengl);
669 if( EQUIV(config.x1, 0) && EQUIV(config.y1, 0) &&
670 EQUIV(config.x2, 100) && EQUIV(config.y2, 0) &&
671 EQUIV(config.x3, 100) && EQUIV(config.y3, 100) &&
672 EQUIV(config.x4, 0) && EQUIV(config.y4, 100) )
676 int cpus = get_project_smp() + 1;
677 engine = new AffineEngine(cpus, cpus);
679 engine->set_interpolation(smoothing);
685 this->output = frame;
687 int w = frame->get_w(), need_w = w;
688 int h = frame->get_h(), need_h = h;
689 int color_model = frame->get_color_model();
690 switch( config.mode ) {
691 case AffineEngine::STRETCH:
692 need_w *= AFFINE_OVERSAMPLE;
693 need_h *= AFFINE_OVERSAMPLE;
694 case AffineEngine::SHEER:
695 case AffineEngine::PERSPECTIVE:
697 if( temp->get_w() != need_w || temp->get_h() != need_h ||
698 temp->get_color_model() != color_model ) {
699 delete temp; temp = 0;
703 temp = new VFrame(need_w, need_h, color_model);
706 switch( config.mode ) {
707 case AffineEngine::STRETCH:
710 case AffineEngine::PERSPECTIVE:
711 case AffineEngine::SHEER:
712 temp->copy_from(input);
714 output->clear_frame();
717 delete temp; temp = 0;
721 engine->process(output, input, temp, config.mode,
722 config.x1, config.y1, config.x2, config.y2,
723 config.x3, config.y3, config.x4, config.y4,
728 if( config.mode == AffineEngine::STRETCH ) {
730 #define RESAMPLE(tag, type, components, chroma_offset) \
732 int os = AFFINE_OVERSAMPLE, os2 = os*os; \
733 for( int i=0; i<h; ++i ) { \
734 type *out_row = (type*)output->get_rows()[i]; \
735 type *in_row1 = (type*)temp->get_rows()[i * os]; \
736 type *in_row2 = (type*)temp->get_rows()[i * os + 1]; \
737 for( int j=0; j<w; ++j ) { \
739 ( in_row1[0] + in_row1[components + 0] + \
740 in_row2[0] + in_row2[components + 0] ) / os2; \
742 ( in_row1[1] + in_row1[components + 1] + \
743 in_row2[1] + in_row2[components + 1] ) / os2; \
745 ( in_row1[2] + in_row1[components + 2] + \
746 in_row2[2] + in_row2[components + 2] ) / os2; \
747 if( components == 4 ) { \
749 ( in_row1[3] + in_row1[components + 3] + \
750 in_row2[3] + in_row2[components + 3] ) / os2; \
752 out_row += components; \
753 in_row1 += components * os; \
754 in_row2 += components * os; \
759 switch( frame->get_color_model() ) {
760 RESAMPLE( BC_RGB_FLOAT, float, 3, 0 );
761 RESAMPLE( BC_RGB888, unsigned char, 3, 0 );
762 RESAMPLE( BC_RGBA_FLOAT, float, 4, 0 );
763 RESAMPLE( BC_RGBA8888, unsigned char, 4, 0 );
764 RESAMPLE( BC_YUV888, unsigned char, 3, 0x80 );
765 RESAMPLE( BC_YUVA8888, unsigned char, 4, 0x80 );
766 RESAMPLE( BC_RGB161616, uint16_t, 3, 0 );
767 RESAMPLE( BC_RGBA16161616, uint16_t, 4, 0 );
768 RESAMPLE( BC_YUV161616, uint16_t, 3, 0x8000 );
769 RESAMPLE( BC_YUVA16161616, uint16_t, 4, 0x8000 );
777 int PerspectiveMain::handle_opengl()
780 engine->set_opengl(1);
781 engine->process(get_output(), get_output(), get_output(), config.mode,
782 config.x1, config.y1, config.x2, config.y2,
783 config.x3, config.y3, config.x4, config.y4,
785 engine->set_opengl(0);