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
22 #include "bcdisplayinfo.h"
24 #include "bcsignals.h"
37 REGISTER_PLUGIN(LensMain)
42 LensConfig::LensConfig()
44 for(int i = 0; i < FOV_CHANNELS; i++)
48 mode = LensConfig::SHRINK;
54 int LensConfig::equivalent(LensConfig &that)
56 for(int i = 0; i < FOV_CHANNELS; i++)
57 if(!EQUIV(fov[i], that.fov[i])) return 0;
58 return EQUIV(aspect, that.aspect) &&
59 EQUIV(radius, that.radius) &&
60 EQUIV(center_x, that.center_x) &&
61 EQUIV(center_y, that.center_y) &&
63 draw_guides == that.draw_guides;
66 void LensConfig::copy_from(LensConfig &that)
68 for(int i = 0; i < FOV_CHANNELS; i++)
73 center_x = that.center_x;
74 center_y = that.center_y;
75 draw_guides = that.draw_guides;
78 void LensConfig::interpolate(LensConfig &prev,
82 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);
87 for(int i = 0; i < FOV_CHANNELS; i++)
88 fov[i] = prev.fov[i] * prev_scale + next.fov[i] * next_scale;
89 aspect = prev.aspect * prev_scale + next.aspect * next_scale;
90 radius = prev.radius * prev_scale + next.radius * next_scale;
91 center_x = prev.center_x * prev_scale + next.center_x * next_scale;
92 center_y = prev.center_y * prev_scale + next.center_y * next_scale;
94 draw_guides = prev.draw_guides;
99 void LensConfig::boundaries()
101 CLAMP(center_x, 0.0, 99.0);
102 CLAMP(center_y, 0.0, 99.0);
103 for(int i = 0; i < FOV_CHANNELS; i++)
104 CLAMP(fov[i], 0.0, 1.0);
105 CLAMP(aspect, 0.3, 3.0);
106 CLAMP(radius, 0.3, 3.0);
112 LensSlider::LensSlider(LensMain *client,
120 : BC_FSlider(x, y, 0, 200, 200, min, max, *output)
123 this->client = client;
124 this->output = output;
129 int LensSlider::handle_event()
131 float prev_output = *output;
132 *output = get_value();
133 text->update(*output);
135 float difference = *output - prev_output;
140 for(int i = 0; i < FOV_CHANNELS; i++)
142 if(output == &client->config.fov[i])
151 for(int i = 0; i < FOV_CHANNELS; i++)
153 if(output != &client->config.fov[i])
155 client->config.fov[i] += difference;
156 client->config.boundaries();
157 gui->fov_slider[i]->update(client->config.fov[i]);
158 gui->fov_text[i]->update(client->config.fov[i]);
164 client->send_configure_change();
170 LensText::LensText(LensMain *client,
176 : BC_TextBox(x, y, 100, 1, *output)
179 this->client = client;
180 this->output = output;
181 this->slider = slider;
184 int LensText::handle_event()
186 float prev_output = *output;
187 *output = atof(get_text());
188 slider->update(*output);
190 float difference = *output - prev_output;
195 for(int i = 0; i < FOV_CHANNELS; i++)
197 if(output == &client->config.fov[i])
206 for(int i = 0; i < FOV_CHANNELS; i++)
208 if(output != &client->config.fov[i])
210 client->config.fov[i] += difference;
211 client->config.boundaries();
212 gui->fov_slider[i]->update(client->config.fov[i]);
213 gui->fov_text[i]->update(client->config.fov[i]);
219 client->send_configure_change();
225 LensToggle::LensToggle(LensMain *client,
230 : BC_CheckBox(x, y, *output, text)
232 this->output = output;
233 this->client = client;
236 int LensToggle::handle_event()
238 *output = get_value();
239 client->send_configure_change();
252 LensMode::LensMode(LensMain *plugin,
262 this->plugin = plugin;
266 int LensMode::handle_event()
268 plugin->config.mode = from_text(get_text());
269 plugin->send_configure_change();
274 void LensMode::create_objects()
276 add_item(new BC_MenuItem(to_text(LensConfig::SHRINK)));
277 add_item(new BC_MenuItem(to_text(LensConfig::STRETCH)));
278 add_item(new BC_MenuItem(to_text(LensConfig::RECTILINEAR_STRETCH)));
279 add_item(new BC_MenuItem(to_text(LensConfig::RECTILINEAR_SHRINK)));
280 update(plugin->config.mode);
283 void LensMode::update(int mode)
285 char string[BCTEXTLEN];
286 sprintf(string, "%s", to_text(mode));
290 int LensMode::calculate_w(LensGUI *gui)
293 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(LensConfig::STRETCH)));
294 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(LensConfig::SHRINK)));
295 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(LensConfig::RECTILINEAR_STRETCH)));
296 result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(LensConfig::RECTILINEAR_SHRINK)));
300 int LensMode::from_text(char *text)
302 if(!strcmp(text, _("Sphere Stretch"))) return LensConfig::STRETCH;
304 if(!strcmp(text, _("Sphere Shrink"))) return LensConfig::SHRINK;
306 if(!strcmp(text, _("Rectilinear Stretch"))) return LensConfig::RECTILINEAR_STRETCH;
308 if(!strcmp(text, _("Rectilinear Shrink"))) return LensConfig::RECTILINEAR_SHRINK;
309 return LensConfig::STRETCH;
312 const char* LensMode::to_text(int mode)
316 case LensConfig::STRETCH:
317 return _("Sphere Stretch");
319 case LensConfig::SHRINK:
320 return _("Sphere Shrink");
322 case LensConfig::RECTILINEAR_STRETCH:
323 return _("Rectilinear Stretch");
325 case LensConfig::RECTILINEAR_SHRINK:
326 return _("Rectilinear Shrink");
336 // LensPresets::LensPresets(LensMain *plugin,
347 // this->plugin = plugin;
351 // int LensPresets::handle_event()
356 // void LensPresets::create_objects()
358 // // Remove existing items
359 // int total = total_items();
360 // for(int i = 0; i < total; i++)
365 // // Create current items
366 // plugin->load_presets();
367 // for(int i = 0; i < plugin->presets.total; i++)
369 // add_item(new BC_MenuItem(plugin->presets.values[i]->title));
373 // if(plugin->current_preset >= 0 &&
374 // plugin->current_preset < plugin->presets.total)
376 // set_text(plugin->presets.values[plugin->current_preset]->title);
384 // int LensPresets::from_text(LensMain *plugin, char *text)
388 // char* LensPresets::to_text(LensMain *plugin, int preset)
392 // void LensPresets::update(int preset)
401 // LensSavePreset::LensSavePreset(LensMain *plugin,
405 // : BC_GenericButton(x, y, "Save Preset")
407 // this->plugin = plugin;
411 // int LensSavePreset::handle_event()
421 // LensDeletePreset::LensDeletePreset(LensMain *plugin,
425 // : BC_GenericButton(x, y, "Delete Preset")
429 // int LensDeletePreset::handle_event()
439 // LensPresetText::LensPresetText(LensMain *plugin,
444 // : BC_TextBox(x, y, w, 1, "")
446 // this->plugin = plugin;
450 // int LensPresetText::handle_event()
466 LensGUI::LensGUI(LensMain *client)
467 : PluginClientWindow(client,
474 this->client = client;
482 void LensGUI::create_objects()
490 for(int i = 0; i < FOV_CHANNELS; i++)
494 case 0: add_tool(title = new BC_Title(x, y, _("R Field of View:"))); break;
495 case 1: add_tool(title = new BC_Title(x, y, _("G Field of View:"))); break;
496 case 2: add_tool(title = new BC_Title(x, y, _("B Field of View:"))); break;
497 case 3: add_tool(title = new BC_Title(x, y, _("A Field of View:"))); break;
500 y += title->get_h() + 5;
501 add_tool(fov_slider[i] = new LensSlider(client,
504 &client->config.fov[i],
509 x1 = x + fov_slider[i]->get_w() + 5;
510 add_tool(fov_text[i] = new LensText(client,
513 &client->config.fov[i],
516 fov_slider[i]->text = fov_text[i];
517 y += fov_text[i]->get_h() + 5;
520 add_tool(toggle = new LensToggle(client,
525 y += toggle->get_h() + 10;
528 add_tool(bar = new BC_Bar(x, y, get_w() - x * 2));
529 y += bar->get_h() + 5;
531 add_tool(title = new BC_Title(x, y, _("Aspect Ratio:")));
532 y += title->get_h() + 5;
533 add_tool(aspect_slider = new LensSlider(client,
536 &client->config.aspect,
541 x1 = x + aspect_slider->get_w() + 5;
542 add_tool(aspect_text = new LensText(client,
545 &client->config.aspect,
548 aspect_slider->text = aspect_text;
549 y += aspect_text->get_h() + 5;
552 add_tool(title = new BC_Title(x, y, _("Radius:")));
553 y += title->get_h() + 5;
554 add_tool(radius_slider = new LensSlider(client,
557 &client->config.radius,
562 x1 = x + radius_slider->get_w() + 5;
563 add_tool(radius_text = new LensText(client,
566 &client->config.radius,
569 radius_slider->text = radius_text;
570 y += radius_text->get_h() + 5;
573 add_tool(title = new BC_Title(x, y, _("Center X:")));
574 y += title->get_h() + 5;
575 add_tool(centerx_slider = new LensSlider(client,
578 &client->config.center_x,
583 x1 = x + centerx_slider->get_w() + 5;
584 add_tool(centerx_text = new LensText(client,
587 &client->config.center_x,
590 centerx_slider->text = centerx_text;
591 centerx_slider->set_precision(1.0);
592 y += centerx_text->get_h() + 5;
595 add_tool(title = new BC_Title(x, y, _("Center Y:")));
596 y += title->get_h() + 5;
597 add_tool(centery_slider = new LensSlider(client,
600 &client->config.center_y,
605 x1 = x + centery_slider->get_w() + 5;
606 add_tool(centery_text = new LensText(client,
609 &client->config.center_y,
612 centery_slider->text = centery_text;
613 centery_slider->set_precision(1.0);
614 y += centery_text->get_h() + 10;
616 add_tool(bar = new BC_Bar(x, y, get_w() - x * 2));
617 y += bar->get_h() + 5;
620 // add_tool(reverse = new LensToggle(client,
621 // &client->config.reverse,
625 // y += reverse->get_h() + 5;
627 add_tool(draw_guides = new LensToggle(client,
628 &client->config.draw_guides,
632 y += draw_guides->get_h() + 5;
635 add_tool(title = new BC_Title(x, y, _("Mode:")));
636 add_tool(mode = new LensMode(client,
638 x + title->get_w() + 5,
640 mode->create_objects();
641 y += mode->get_h() + 5;
644 // add_tool(title = new BC_Title(x, y, _("Preset:")));
645 // add_tool(presets = new LensPresets(client,
647 // x + title->get_w() + 5,
649 // get_w() - x - title->get_w() - 50));
650 // presets->create_objects();
651 // y += presets->get_h() + 5;
653 // add_tool(save_preset = new LensSavePreset(client,
657 // add_tool(preset_text = new LensPresetText(client,
659 // x + save_preset->get_w() + 5,
661 // get_w() - x - save_preset->get_w() - 10));
662 // y += preset_text->get_h() + 5;
663 // add_tool(delete_preset = new LensDeletePreset(client,
678 LensMain::LensMain(PluginServer *server)
679 : PluginVClient(server)
687 LensMain::~LensMain()
691 presets.remove_all_objects();
694 NEW_WINDOW_MACRO(LensMain, LensGUI)
695 LOAD_CONFIGURATION_MACRO(LensMain, LensConfig)
696 int LensMain::is_realtime() { return 1; }
697 const char* LensMain::plugin_title() { return _("Lens"); }
699 void LensMain::update_gui()
703 if(load_configuration())
705 ((LensGUI*)thread->window)->lock_window("LensMain::update_gui");
706 for(int i = 0; i < FOV_CHANNELS; i++)
708 ((LensGUI*)thread->window)->fov_slider[i]->update(config.fov[i]);
709 ((LensGUI*)thread->window)->fov_text[i]->update(config.fov[i]);
711 ((LensGUI*)thread->window)->aspect_slider->update(config.aspect);
712 ((LensGUI*)thread->window)->aspect_text->update(config.aspect);
713 ((LensGUI*)thread->window)->radius_slider->update(config.radius);
714 ((LensGUI*)thread->window)->radius_text->update(config.radius);
715 ((LensGUI*)thread->window)->centerx_slider->update(config.center_x);
716 ((LensGUI*)thread->window)->centerx_text->update(config.center_x);
717 ((LensGUI*)thread->window)->centery_slider->update(config.center_y);
718 ((LensGUI*)thread->window)->centery_text->update(config.center_y);
719 ((LensGUI*)thread->window)->mode->update(config.mode);
720 ((LensGUI*)thread->window)->draw_guides->update(config.draw_guides);
721 ((LensGUI*)thread->window)->unlock_window();
726 //void LensMain::save_presets()
728 // char path[BCTEXTLEN], string[BCTEXTLEN];
729 // sprintf(path, "%s/lenspresets.rc", File::get_config_path());
730 // BC_Hash *defaults = new BC_Hash(path);
733 // defaults->update("TOTAL_PRESETS", presets.total);
734 // for(int i = 0; i < presets.total; i++)
736 // LensPreset *preset = presets.values[i];
737 // sprintf(string, "TITLE_%d", i);
738 // defaults->update(string, preset->title);
740 // for(int j = 0; j < FOV_CHANNELS; j++)
742 // sprintf(string, "FOCAL_LENGTH_%d_%d", i, j);
743 // defaults->update(string, preset->fov[j]);
746 // sprintf(string, "ASPECT_%d", i);
747 // defaults->update(string, preset->aspect);
748 // sprintf(string, "RADIUS_%d", i);
749 // defaults->update(string, preset->radius);
750 // sprintf(string, "MODE_%d", i);
751 // defaults->update(string, preset->mode);
759 void LensMain::save_data(KeyFrame *keyframe)
762 char string[BCTEXTLEN];
766 // cause data to be stored directly in text
767 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
768 output.tag.set_title("LENS");
769 for(int i = 0; i < FOV_CHANNELS; i++)
771 sprintf(string, "FOCAL_LENGTH%d", i);
772 output.tag.set_property(string, config.fov[i]);
774 output.tag.set_property("ASPECT", config.aspect);
775 output.tag.set_property("RADIUS", config.radius);
776 output.tag.set_property("MODE", config.mode);
777 output.tag.set_property("CENTER_X", config.center_x);
778 output.tag.set_property("CENTER_Y", config.center_y);
779 output.tag.set_property("DRAW_GUIDES", config.draw_guides);
781 output.tag.set_title("/LENS");
783 output.append_newline();
784 output.terminate_string();
789 void LensMain::read_data(KeyFrame *keyframe)
792 char string[BCTEXTLEN];
795 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
801 result = input.read_tag();
805 if(input.tag.title_is("LENS"))
807 for(int i = 0; i < FOV_CHANNELS; i++)
809 sprintf(string, "FOCAL_LENGTH%d", i);
810 config.fov[i] = input.tag.get_property(string, config.fov[i]);
812 config.aspect = input.tag.get_property("ASPECT", config.aspect);
813 config.radius = input.tag.get_property("RADIUS", config.radius);
814 config.mode = input.tag.get_property("MODE", config.mode);
815 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
816 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
817 config.draw_guides = input.tag.get_property("DRAW_GUIDES", config.draw_guides);
825 int LensMain::process_buffer(VFrame *frame,
826 int64_t start_position,
830 load_configuration();
838 input = new_temp(frame->get_w(), frame->get_h(), frame->get_color_model());
855 if(!engine) engine = new LensEngine(this);
856 engine->process_packages();
857 if(config.draw_guides)
862 #define DRAW_GUIDES(components, type, max) \
864 type **rows = (type**)get_output()->get_rows(); \
865 if( (center_x >= 0 && center_x < w) || (center_y >= 0 && center_y < h) ) { \
866 type *hrow = rows[center_y] + components * (center_x - CENTER_W / 2); \
867 for(int i = center_x - CENTER_W / 2; i <= center_x + CENTER_W / 2; i++) \
869 if(i >= 0 && i < w) { \
870 hrow[0] = max - hrow[0]; \
871 hrow[1] = max - hrow[1]; \
872 hrow[2] = max - hrow[2]; \
873 hrow += components; \
877 for(int i = center_y - CENTER_W / 2; i <= center_y + CENTER_W / 2; i++) \
879 if(i >= 0 && i < h) { \
880 type *vrow = rows[i] + center_x * components; \
881 vrow[0] = max - vrow[0]; \
882 vrow[1] = max - vrow[1]; \
883 vrow[2] = max - vrow[2]; \
889 int w = get_output()->get_w();
890 int h = get_output()->get_h();
891 int center_x = (int)(config.center_x * w / 100);
892 int center_y = (int)(config.center_y * h / 100);
893 switch(get_output()->get_color_model())
896 DRAW_GUIDES(3, float, 1.0)
899 DRAW_GUIDES(4, float, 1.0)
902 DRAW_GUIDES(3, unsigned char, 0xff)
905 DRAW_GUIDES(4, unsigned char, 0xff)
908 DRAW_GUIDES(3, unsigned char, 0xff)
911 DRAW_GUIDES(4, unsigned char, 0xff)
922 int LensMain::handle_opengl()
925 static const char *shrink_frag =
926 "uniform sampler2D tex;\n"
927 "uniform vec2 texture_extents;\n"
928 "uniform vec2 image_extents;\n"
929 "uniform vec2 aspect;\n"
930 "uniform vec2 center_coord;\n"
931 "uniform vec4 border_color;\n"
933 "uniform vec4 max_z;\n"
936 " vec2 outcoord = gl_TexCoord[0].st * texture_extents;\n"
937 " vec2 coord_diff = outcoord - center_coord;\n"
938 " if(coord_diff.x == 0.0 && coord_diff.y == 0.0)\n"
940 " gl_FragColor = texture2D(tex, outcoord);\n"
944 " float z = sqrt(coord_diff.x * coord_diff.x +\n"
945 " coord_diff.y * coord_diff.y);\n"
946 " float a2 = atan(coord_diff.y, coord_diff.x);\n"
947 " vec4 a1 = asin(vec4(z, z, z, z) / r);\n"
948 " vec4 z_in = a1 * max_z * 2.0 / 3.14159;\n"
951 " in_x = z_in * cos(a2) * aspect.x + center_coord.x;\n"
952 " in_y = z_in * sin(a2) * aspect.y + center_coord.y;\n"
953 " if(z > r.r || in_x.r < 0.0 || in_x.r >= image_extents.x || in_y.r < 0.0 || in_y.r >= image_extents.y)\n"
954 " gl_FragColor.r = border_color.r;\n"
956 " gl_FragColor.r = texture2D(tex, vec2(in_x.r, in_y.r) / texture_extents).r;\n"
957 " if(z > r.g || in_x.g < 0.0 || in_x.g >= image_extents.x || in_y.g < 0.0 || in_y.g >= image_extents.y)\n"
958 " gl_FragColor.g = border_color.g;\n"
960 " gl_FragColor.g = texture2D(tex, vec2(in_x.g, in_y.g) / texture_extents).g;\n"
961 " if(z > r.b || in_x.b < 0.0 || in_x.b >= image_extents.x || in_y.b < 0.0 || in_y.b >= image_extents.y)\n"
962 " gl_FragColor.b = border_color.b;\n"
964 " gl_FragColor.b = texture2D(tex, vec2(in_x.b, in_y.b) / texture_extents).b;\n"
965 " if(z > r.a || in_x.a < 0.0 || in_x.a >= image_extents.x || in_y.a < 0.0 || in_y.a >= image_extents.y)\n"
966 " gl_FragColor.a = border_color.a;\n"
968 " gl_FragColor.a = texture2D(tex, vec2(in_x.a, in_y.a) / texture_extents).a;\n"
972 static const char *stretch_frag =
973 "uniform sampler2D tex;\n"
974 "uniform vec2 texture_extents;\n"
975 "uniform vec2 image_extents;\n"
976 "uniform vec2 aspect;\n"
977 "uniform vec2 center_coord;\n"
978 "uniform vec4 border_color;\n"
982 " vec2 outcoord = gl_TexCoord[0].st * texture_extents;\n"
983 " vec2 coord_diff = outcoord - center_coord;\n"
984 " float z = sqrt(coord_diff.x * coord_diff.x +\n"
985 " coord_diff.y * coord_diff.y);\n"
986 " vec4 a1 = (vec4(z, z, z, z) / (3.14159 * r / 2.0)) * (3.14159 / 2.0);\n"
987 " vec4 z_in = r * sin(a1);\n"
989 " if(coord_diff.x == 0.0)\n"
991 " if(coord_diff.y < 0.0)\n"
992 " a2 = 3.0 * 3.14159 / 2.0;\n"
994 " a2 = 3.14159 / 2.0;\n"
997 " a2 = atan(coord_diff.y, coord_diff.x);\n"
1000 " in_x = z_in * cos(a2) * aspect.x + center_coord.x;\n"
1001 " in_y = z_in * sin(a2) * aspect.y + center_coord.y;\n"
1002 " if(in_x.r < 0.0 || in_x.r >= image_extents.x || in_y.r < 0.0 || in_y.r >= image_extents.y)\n"
1003 " gl_FragColor.r = border_color.r;\n"
1005 " gl_FragColor.r = texture2D(tex, vec2(in_x.r, in_y.r) / texture_extents).r;\n"
1006 " if(in_x.g < 0.0 || in_x.g >= image_extents.x || in_y.g < 0.0 || in_y.g >= image_extents.y)\n"
1007 " gl_FragColor.g = border_color.g;\n"
1009 " gl_FragColor.g = texture2D(tex, vec2(in_x.g, in_y.g) / texture_extents).g;\n"
1010 " if(in_x.b < 0.0 || in_x.b >= image_extents.x || in_y.b < 0.0 || in_y.b >= image_extents.y)\n"
1011 " gl_FragColor.b = border_color.b;\n"
1013 " gl_FragColor.b = texture2D(tex, vec2(in_x.b, in_y.b) / texture_extents).b;\n"
1014 " if(in_x.a < 0.0 || in_x.a >= image_extents.x || in_y.a < 0.0 || in_y.a >= image_extents.y)\n"
1015 " gl_FragColor.a = border_color.a;\n"
1017 " gl_FragColor.a = texture2D(tex, vec2(in_x.a, in_y.a) / texture_extents).a;\n"
1021 static const char *rectilinear_stretch_frag =
1022 "uniform sampler2D tex;\n"
1023 "uniform vec2 texture_extents;\n"
1024 "uniform vec2 image_extents;\n"
1025 "uniform vec2 aspect;\n"
1026 "uniform vec2 center_coord;\n"
1027 "uniform vec4 border_color;\n"
1029 "uniform float radius;\n"
1032 " vec2 outcoord = gl_TexCoord[0].st * texture_extents;\n"
1033 " vec2 coord_diff = outcoord - center_coord;\n"
1034 " float z = sqrt(coord_diff.x * coord_diff.x +\n"
1035 " coord_diff.y * coord_diff.y);\n"
1036 " vec4 radius1 = (vec4(z, z, z, z) / r) * 2.0 * radius;\n"
1037 " vec4 z_in = r * atan(radius1) / (3.14159 / 2.0);\n"
1040 " if(coord_diff.x == 0.0)\n"
1042 " if(coord_diff.y < 0.0)\n"
1043 " angle = 3.0 * 3.14159 / 2.0;\n"
1045 " angle = 3.14159 / 2.0;\n"
1048 " angle = atan(coord_diff.y, coord_diff.x);\n"
1052 " in_x = z_in * cos(angle) * aspect.x + center_coord.x;\n"
1053 " in_y = z_in * sin(angle) * aspect.y + center_coord.y;\n"
1054 " if(in_x.r < 0.0 || in_x.r >= image_extents.x || in_y.r < 0.0 || in_y.r >= image_extents.y)\n"
1055 " gl_FragColor.r = border_color.r;\n"
1057 " gl_FragColor.r = texture2D(tex, vec2(in_x.r, in_y.r) / texture_extents).r;\n"
1058 " if(in_x.g < 0.0 || in_x.g >= image_extents.x || in_y.g < 0.0 || in_y.g >= image_extents.y)\n"
1059 " gl_FragColor.g = border_color.g;\n"
1061 " gl_FragColor.g = texture2D(tex, vec2(in_x.g, in_y.g) / texture_extents).g;\n"
1062 " if(in_x.b < 0.0 || in_x.b >= image_extents.x || in_y.b < 0.0 || in_y.b >= image_extents.y)\n"
1063 " gl_FragColor.b = border_color.b;\n"
1065 " gl_FragColor.b = texture2D(tex, vec2(in_x.b, in_y.b) / texture_extents).b;\n"
1066 " if(in_x.a < 0.0 || in_x.a >= image_extents.x || in_y.a < 0.0 || in_y.a >= image_extents.y)\n"
1067 " gl_FragColor.a = border_color.a;\n"
1069 " gl_FragColor.a = texture2D(tex, vec2(in_x.a, in_y.a) / texture_extents).a;\n"
1072 static const char *rectilinear_shrink_frag =
1073 "uniform sampler2D tex;\n"
1074 "uniform vec2 texture_extents;\n"
1075 "uniform vec2 image_extents;\n"
1076 "uniform vec2 aspect;\n"
1077 "uniform vec2 center_coord;\n"
1078 "uniform vec4 border_color;\n"
1080 "uniform float radius;\n"
1083 " vec2 outcoord = gl_TexCoord[0].st * texture_extents;\n"
1084 " vec2 coord_diff = outcoord - center_coord;\n"
1085 " float z = sqrt(coord_diff.x * coord_diff.x +\n"
1086 " coord_diff.y * coord_diff.y);\n"
1087 " vec4 radius1 = (vec4(z, z, z, z) / r) * 2.0 * radius;\n"
1088 " vec4 z_in = r * atan(radius1) / (3.14159 / 2.0);\n"
1091 " if(coord_diff.x == 0.0)\n"
1093 " if(coord_diff.y < 0.0)\n"
1094 " angle = 3.0 * 3.14159 / 2.0;\n"
1096 " angle = 3.14159 / 2.0;\n"
1099 " angle = atan(coord_diff.y, coord_diff.x);\n"
1103 " in_x = z_in * cos(angle) * aspect.x + center_coord.x;\n"
1104 " in_y = z_in * sin(angle) * aspect.y + center_coord.y;\n"
1105 " if(in_x.r < 0.0 || in_x.r >= image_extents.x || in_y.r < 0.0 || in_y.r >= image_extents.y)\n"
1106 " gl_FragColor.r = border_color.r;\n"
1108 " gl_FragColor.r = texture2D(tex, vec2(in_x.r, in_y.r) / texture_extents).r;\n"
1109 " if(in_x.g < 0.0 || in_x.g >= image_extents.x || in_y.g < 0.0 || in_y.g >= image_extents.y)\n"
1110 " gl_FragColor.g = border_color.g;\n"
1112 " gl_FragColor.g = texture2D(tex, vec2(in_x.g, in_y.g) / texture_extents).g;\n"
1113 " if(in_x.b < 0.0 || in_x.b >= image_extents.x || in_y.b < 0.0 || in_y.b >= image_extents.y)\n"
1114 " gl_FragColor.b = border_color.b;\n"
1116 " gl_FragColor.b = texture2D(tex, vec2(in_x.b, in_y.b) / texture_extents).b;\n"
1117 " if(in_x.a < 0.0 || in_x.a >= image_extents.x || in_y.a < 0.0 || in_y.a >= image_extents.y)\n"
1118 " gl_FragColor.a = border_color.a;\n"
1120 " gl_FragColor.a = texture2D(tex, vec2(in_x.a, in_y.a) / texture_extents).a;\n"
1123 get_output()->to_texture();
1124 get_output()->enable_opengl();
1125 unsigned int frag_shader = 0;
1129 case LensConfig::SHRINK:
1130 frag_shader = VFrame::make_shader(0, shrink_frag, 0);
1132 case LensConfig::STRETCH:
1133 frag_shader = VFrame::make_shader(0, stretch_frag, 0);
1135 case LensConfig::RECTILINEAR_STRETCH:
1136 frag_shader = VFrame::make_shader(0, rectilinear_stretch_frag, 0);
1138 case LensConfig::RECTILINEAR_SHRINK:
1139 frag_shader = VFrame::make_shader(0, rectilinear_shrink_frag, 0);
1145 float border_color[] = { 0, 0, 0, 0 };
1146 if(BC_CModels::is_yuv(get_output()->get_color_model()))
1148 border_color[1] = 0.5;
1149 border_color[2] = 0.5;
1152 double x_factor = config.aspect;
1153 double y_factor = 1.0 / config.aspect;
1154 if(x_factor < 1) x_factor = 1;
1155 if(y_factor < 1) y_factor = 1;
1157 glUseProgram(frag_shader);
1158 glUniform1i(glGetUniformLocation(frag_shader, "tex"), 0);
1159 glUniform2f(glGetUniformLocation(frag_shader, "aspect"),
1162 glUniform2f(glGetUniformLocation(frag_shader, "center_coord"),
1163 (GLfloat)get_input()->get_w() * config.center_x / 100.0,
1164 (GLfloat)get_input()->get_h() * config.center_y / 100.0);
1165 glUniform2f(glGetUniformLocation(frag_shader, "texture_extents"),
1166 (GLfloat)get_input()->get_texture_w(),
1167 (GLfloat)get_input()->get_texture_h());
1168 glUniform2f(glGetUniformLocation(frag_shader, "image_extents"),
1169 (GLfloat)get_input()->get_w(),
1170 (GLfloat)get_input()->get_h());
1172 int width = get_output()->get_w();
1173 int height = get_output()->get_h();
1174 float *fov = config.fov;
1179 case LensConfig::SHRINK:
1180 dim = MAX(width, height) * config.radius;
1181 max_z = dim * sqrt(2.0) / 2;
1182 glUniform4fv(glGetUniformLocation(frag_shader, "border_color"),
1184 (GLfloat*)border_color);
1185 glUniform4f(glGetUniformLocation(frag_shader, "max_z"),
1190 glUniform4f(glGetUniformLocation(frag_shader, "r"),
1191 (max_z / fov[0]) * 2 / M_PI,
1192 (max_z / fov[1]) * 2 / M_PI,
1193 (max_z / fov[2]) * 2 / M_PI,
1194 (max_z / fov[3]) * 2 / M_PI);
1197 case LensConfig::STRETCH:
1198 dim = MAX(width, height) * config.radius;
1199 max_z = dim * sqrt(2.0) / 2;
1200 glUniform4f(glGetUniformLocation(frag_shader, "r"),
1201 max_z / M_PI / (fov[0] / 2.0),
1202 max_z / M_PI / (fov[1] / 2.0),
1203 max_z / M_PI / (fov[2] / 2.0),
1204 max_z / M_PI / (fov[3] / 2.0));
1207 case LensConfig::RECTILINEAR_STRETCH:
1208 max_z = sqrt(SQR(width) + SQR(height)) / 2;
1209 glUniform4f(glGetUniformLocation(frag_shader, "r"),
1210 max_z / M_PI / (fov[0] / 2.0),
1211 max_z / M_PI / (fov[1] / 2.0),
1212 max_z / M_PI / (fov[2] / 2.0),
1213 max_z / M_PI / (fov[3] / 2.0));
1214 glUniform1f(glGetUniformLocation(frag_shader, "radius"),
1218 case LensConfig::RECTILINEAR_SHRINK:
1219 max_z = sqrt(SQR(width) + SQR(height)) / 2;
1220 glUniform4f(glGetUniformLocation(frag_shader, "r"),
1221 max_z / M_PI / (fov[0] / 2.0),
1222 max_z / M_PI / (fov[1] / 2.0),
1223 max_z / M_PI / (fov[2] / 2.0),
1224 max_z / M_PI / (fov[3] / 2.0));
1225 glUniform1f(glGetUniformLocation(frag_shader, "radius"),
1231 get_output()->init_screen();
1232 get_output()->bind_texture(0);
1233 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
1234 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
1235 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
1236 get_output()->draw_texture();
1240 if(config.draw_guides)
1242 int w = get_output()->get_w();
1243 int h = get_output()->get_h();
1244 int center_x = (int)(config.center_x * w / 100);
1245 int center_y = (int)(config.center_y * h / 100);
1247 glDisable(GL_TEXTURE_2D);
1248 glColor4f(0.0, 0.0, 0.0, 1.0);
1250 glVertex3f(center_x, -h + center_y - CENTER_H / 2, 0.0);
1251 glVertex3f(center_x, -h + center_y + CENTER_H / 2, 0.0);
1254 glVertex3f(center_x - CENTER_W / 2, -h + center_y, 0.0);
1255 glVertex3f(center_x + CENTER_W / 2, -h + center_y, 0.0);
1257 glColor4f(1.0, 1.0, 1.0, 1.0);
1259 glVertex3f(center_x - 1, -h + center_y - CENTER_H / 2 - 1, 0.0);
1260 glVertex3f(center_x - 1, -h + center_y + CENTER_H / 2 - 1, 0.0);
1263 glVertex3f(center_x - CENTER_W / 2 - 1, -h + center_y - 1, 0.0);
1264 glVertex3f(center_x + CENTER_W / 2 - 1, -h + center_y - 1, 0.0);
1267 get_output()->set_opengl_state(VFrame::SCREEN);
1281 LensPackage::LensPackage()
1288 LensUnit::LensUnit(LensEngine *engine, LensMain *plugin)
1289 : LoadClient(engine)
1291 this->plugin = plugin;
1294 LensUnit::~LensUnit()
1298 void LensUnit::process_shrink(LensPackage *pkg)
1301 float *fov = plugin->config.fov;
1302 float aspect = plugin->config.aspect;
1303 int row1 = pkg->row1;
1304 int row2 = pkg->row2;
1305 int width = plugin->get_input()->get_w();
1306 int height = plugin->get_input()->get_h();
1307 double x_factor = aspect;
1308 double y_factor = 1.0 / aspect;
1309 if(x_factor < 1) x_factor = 1;
1310 if(y_factor < 1) y_factor = 1;
1311 double dim = MAX(width, height) * plugin->config.radius;
1312 double max_z[FOV_CHANNELS];
1313 double center_x = width * plugin->config.center_x / 100.0;
1314 double center_y = height * plugin->config.center_y / 100.0;
1315 double r[FOV_CHANNELS];
1317 // max_z[0] = sqrt(SQR(width) + SQR(height)) / 2 / fov[0];
1318 // max_z[1] = sqrt(SQR(width) + SQR(height)) / 2 / fov[1];
1319 // max_z[2] = sqrt(SQR(width) + SQR(height)) / 2 / fov[2];
1320 // max_z[3] = sqrt(SQR(width) + SQR(height)) / 2 / fov[3];
1321 max_z[0] = dim * sqrt(2.0) / 2 / fov[0];
1322 max_z[1] = dim * sqrt(2.0) / 2 / fov[1];
1323 max_z[2] = dim * sqrt(2.0) / 2 / fov[2];
1324 max_z[3] = dim * sqrt(2.0) / 2 / fov[3];
1325 r[0] = max_z[0] * 2 / M_PI;
1326 r[1] = max_z[1] * 2 / M_PI;
1327 r[2] = max_z[2] * 2 / M_PI;
1328 r[3] = max_z[3] * 2 / M_PI;
1330 #define DO_LENS_SHRINK(type, components, chroma) \
1332 type **in_rows = (type**)plugin->get_temp()->get_rows(); \
1333 type **out_rows = (type**)plugin->get_input()->get_rows(); \
1334 type black[4] = { 0, chroma, chroma, 0 }; \
1336 for(int y = row1; y < row2; y++) \
1338 type *out_row = out_rows[y]; \
1339 type *in_row = in_rows[y]; \
1340 double y_diff = y - center_y; \
1342 for(int x = 0; x < width; x++) \
1344 double x_diff = x - center_x; \
1345 if(!x_diff && !y_diff) \
1347 type *in_pixel = in_row + x * components; \
1348 for(int c = 0; c < components; c++) \
1350 *out_row++ = *in_pixel++; \
1355 double z = sqrt(x_diff * x_diff + y_diff * y_diff); \
1356 double a2 = atan(y_diff / x_diff); \
1357 if(x_diff < 0.0) a2 += M_PI; \
1359 for(int i = 0; i < components; i++) \
1363 *out_row++ = black[i]; \
1367 double a1 = asin(z / r[i]); \
1368 double z_in = a1 * max_z[i] * 2 / M_PI; \
1370 float x_in = z_in * cos(a2) * x_factor + center_x; \
1371 float y_in = z_in * sin(a2) * y_factor + center_y; \
1373 if(x_in < 0.0 || x_in >= width - 1 || \
1374 y_in < 0.0 || y_in >= height - 1) \
1376 *out_row++ = black[i]; \
1380 float y1_fraction = y_in - floor(y_in); \
1381 float y2_fraction = 1.0 - y1_fraction; \
1382 float x1_fraction = x_in - floor(x_in); \
1383 float x2_fraction = 1.0 - x1_fraction; \
1384 type *in_pixel1 = in_rows[(int)y_in] + (int)x_in * components; \
1385 type *in_pixel2 = in_rows[(int)y_in + 1] + (int)x_in * components; \
1386 *out_row++ = (type)(in_pixel1[i] * x2_fraction * y2_fraction + \
1387 in_pixel2[i] * x2_fraction * y1_fraction + \
1388 in_pixel1[i + components] * x1_fraction * y2_fraction + \
1389 in_pixel2[i + components] * x1_fraction * y1_fraction); \
1396 type *out_pixel = out_rows[(int)center_y] + (int)center_x * components; \
1397 type *in_pixel = in_rows[(int)center_y] + (int)center_x * components; \
1398 for(int c = 0; c < components; c++) \
1400 *out_pixel++ = *in_pixel++; \
1405 switch(plugin->get_input()->get_color_model())
1408 DO_LENS_SHRINK(unsigned char, 3, 0x0);
1411 DO_LENS_SHRINK(unsigned char, 4, 0x0);
1414 DO_LENS_SHRINK(float, 3, 0.0);
1417 DO_LENS_SHRINK(float, 4, 0.0);
1420 DO_LENS_SHRINK(unsigned char, 3, 0x80);
1423 DO_LENS_SHRINK(unsigned char, 4, 0x80);
1428 void LensUnit::process_stretch(LensPackage *pkg)
1430 float *fov = plugin->config.fov;
1431 float aspect = plugin->config.aspect;
1432 int row1 = pkg->row1;
1433 int row2 = pkg->row2;
1434 double x_factor = aspect;
1435 double y_factor = 1.0 / aspect;
1436 if(x_factor < 1) x_factor = 1;
1437 if(y_factor < 1) y_factor = 1;
1438 int width = plugin->get_input()->get_w();
1439 int height = plugin->get_input()->get_h();
1440 double dim = MAX(width, height) * plugin->config.radius;
1441 double max_z = dim * sqrt(2.0) / 2;
1442 double center_x = width * plugin->config.center_x / 100.0;
1443 double center_y = height * plugin->config.center_y / 100.0;
1444 double r[FOV_CHANNELS];
1446 r[0] = max_z / M_PI / (fov[0] / 2.0);
1447 r[1] = max_z / M_PI / (fov[1] / 2.0);
1448 r[2] = max_z / M_PI / (fov[2] / 2.0);
1449 r[3] = max_z / M_PI / (fov[3] / 2.0);
1451 #define DO_LENS_STRETCH(type, components, chroma) \
1453 type **in_rows = (type**)plugin->get_temp()->get_rows(); \
1454 type **out_rows = (type**)plugin->get_input()->get_rows(); \
1455 type black[4] = { 0, chroma, chroma, 0 }; \
1457 for(int y = row1; y < row2; y++) \
1459 type *out_row = out_rows[y]; \
1460 double y_diff = y - center_y; \
1462 for(int x = 0; x < width; x++) \
1464 double x_diff = (x - center_x); \
1465 double z = sqrt(x_diff * x_diff + \
1471 a2 = 3 * M_PI / 2; \
1477 a2 = atan(y_diff / x_diff); \
1479 if(x_diff < 0.0) a2 += M_PI; \
1481 for(int i = 0; i < components; i++) \
1483 double a1 = (z / (M_PI * r[i] / 2)) * (M_PI / 2); \
1484 double z_in = r[i] * sin(a1); \
1486 double x_in = z_in * cos(a2) * x_factor + center_x; \
1487 double y_in = z_in * sin(a2) * y_factor + center_y; \
1489 if(x_in < 0.0 || x_in >= width - 1 || \
1490 y_in < 0.0 || y_in >= height - 1) \
1492 *out_row++ = black[i]; \
1496 float y1_fraction = y_in - floor(y_in); \
1497 float y2_fraction = 1.0 - y1_fraction; \
1498 float x1_fraction = x_in - floor(x_in); \
1499 float x2_fraction = 1.0 - x1_fraction; \
1500 type *in_pixel1 = in_rows[(int)y_in] + (int)x_in * components; \
1501 type *in_pixel2 = in_rows[(int)y_in + 1] + (int)x_in * components; \
1502 *out_row++ = (type)(in_pixel1[i] * x2_fraction * y2_fraction + \
1503 in_pixel2[i] * x2_fraction * y1_fraction + \
1504 in_pixel1[i + components] * x1_fraction * y2_fraction + \
1505 in_pixel2[i + components] * x1_fraction * y1_fraction); \
1511 type *out_pixel = out_rows[(int)center_y] + (int)center_x * components; \
1512 type *in_pixel = in_rows[(int)center_y] + (int)center_x * components; \
1513 for(int c = 0; c < components; c++) \
1515 *out_pixel++ = *in_pixel++; \
1520 switch(plugin->get_input()->get_color_model())
1523 DO_LENS_STRETCH(unsigned char, 3, 0x0);
1526 DO_LENS_STRETCH(unsigned char, 4, 0x0);
1529 DO_LENS_STRETCH(float, 3, 0.0);
1532 DO_LENS_STRETCH(float, 4, 0.0);
1535 DO_LENS_STRETCH(unsigned char, 3, 0x80);
1538 DO_LENS_STRETCH(unsigned char, 4, 0x80);
1543 void LensUnit::process_rectilinear_stretch(LensPackage *pkg)
1545 float *fov = plugin->config.fov;
1546 float aspect = plugin->config.aspect;
1547 int row1 = pkg->row1;
1548 int row2 = pkg->row2;
1549 double x_factor = aspect;
1550 double y_factor = 1.0 / aspect;
1551 if(x_factor < 1) x_factor = 1;
1552 if(y_factor < 1) y_factor = 1;
1553 int width = plugin->get_input()->get_w();
1554 int height = plugin->get_input()->get_h();
1555 // double dim = MAX(width, height) * plugin->config.radius;
1556 // double max_z = dim * sqrt(2.0) / 2;
1557 double max_z = sqrt(SQR(width) + SQR(height)) / 2;
1558 double center_x = width * plugin->config.center_x / 100.0;
1559 double center_y = height * plugin->config.center_y / 100.0;
1560 double r[FOV_CHANNELS];
1562 r[0] = max_z / M_PI / (fov[0] / 2.0);
1563 r[1] = max_z / M_PI / (fov[1] / 2.0);
1564 r[2] = max_z / M_PI / (fov[2] / 2.0);
1565 r[3] = max_z / M_PI / (fov[3] / 2.0);
1567 #define DO_LENS_RECTILINEAR_STRETCH(type, components, chroma) \
1569 type **in_rows = (type**)plugin->get_temp()->get_rows(); \
1570 type **out_rows = (type**)plugin->get_input()->get_rows(); \
1571 type black[4] = { 0, chroma, chroma, 0 }; \
1573 for(int y = row1; y < row2; y++) \
1575 type *out_row = out_rows[y]; \
1576 double y_diff = y - center_y; \
1578 for(int x = 0; x < width; x++) \
1580 double x_diff = (x - center_x); \
1581 /* Compute magnitude */ \
1582 double z = sqrt(x_diff * x_diff + \
1584 /* Compute angle */ \
1589 angle = 3 * M_PI / 2; \
1595 angle = atan(y_diff / x_diff); \
1597 if(x_diff < 0.0) angle += M_PI; \
1599 for(int i = 0; i < components; i++) \
1601 /* Compute new radius */ \
1602 double radius1 = (z / r[i]) * 2 * plugin->config.radius; \
1603 double z_in = r[i] * atan(radius1) / (M_PI / 2); \
1605 double x_in = z_in * cos(angle) * x_factor + center_x; \
1606 double y_in = z_in * sin(angle) * y_factor + center_y; \
1608 if(x_in < 0.0 || x_in >= width - 1 || \
1609 y_in < 0.0 || y_in >= height - 1) \
1611 *out_row++ = black[i]; \
1615 float y1_fraction = y_in - floor(y_in); \
1616 float y2_fraction = 1.0 - y1_fraction; \
1617 float x1_fraction = x_in - floor(x_in); \
1618 float x2_fraction = 1.0 - x1_fraction; \
1619 type *in_pixel1 = in_rows[(int)y_in] + (int)x_in * components; \
1620 type *in_pixel2 = in_rows[(int)y_in + 1] + (int)x_in * components; \
1621 *out_row++ = (type)(in_pixel1[i] * x2_fraction * y2_fraction + \
1622 in_pixel2[i] * x2_fraction * y1_fraction + \
1623 in_pixel1[i + components] * x1_fraction * y2_fraction + \
1624 in_pixel2[i + components] * x1_fraction * y1_fraction); \
1630 type *out_pixel = out_rows[(int)center_y] + (int)center_x * components; \
1631 type *in_pixel = in_rows[(int)center_y] + (int)center_x * components; \
1632 for(int c = 0; c < components; c++) \
1634 *out_pixel++ = *in_pixel++; \
1639 switch(plugin->get_input()->get_color_model())
1642 DO_LENS_RECTILINEAR_STRETCH(unsigned char, 3, 0x0);
1645 DO_LENS_RECTILINEAR_STRETCH(unsigned char, 4, 0x0);
1648 DO_LENS_RECTILINEAR_STRETCH(float, 3, 0.0);
1651 DO_LENS_RECTILINEAR_STRETCH(float, 4, 0.0);
1654 DO_LENS_RECTILINEAR_STRETCH(unsigned char, 3, 0x80);
1657 DO_LENS_RECTILINEAR_STRETCH(unsigned char, 4, 0x80);
1662 void LensUnit::process_rectilinear_shrink(LensPackage *pkg)
1664 float *fov = plugin->config.fov;
1665 float aspect = plugin->config.aspect;
1666 int row1 = pkg->row1;
1667 int row2 = pkg->row2;
1668 double x_factor = aspect;
1669 double y_factor = 1.0 / aspect;
1670 if(x_factor < 1) x_factor = 1;
1671 if(y_factor < 1) y_factor = 1;
1672 int width = plugin->get_input()->get_w();
1673 int height = plugin->get_input()->get_h();
1674 double max_z = MAX(width, height) / 2 * plugin->config.radius;
1675 double center_x = width * plugin->config.center_x / 100.0;
1676 double center_y = height * plugin->config.center_y / 100.0;
1677 double r[FOV_CHANNELS];
1679 r[0] = max_z / fov[0];
1680 r[1] = max_z / fov[1];
1681 r[2] = max_z / fov[2];
1682 r[3] = max_z / fov[3];
1684 #define DO_LENS_RECTILINEAR_SHRINK(type, components, chroma) \
1686 type **in_rows = (type**)plugin->get_temp()->get_rows(); \
1687 type **out_rows = (type**)plugin->get_input()->get_rows(); \
1688 type black[4] = { 0, chroma, chroma, 0 }; \
1690 for(int y = row1; y < row2; y++) \
1692 type *out_row = out_rows[y]; \
1693 double y_diff = y - center_y; \
1695 for(int x = 0; x < width; x++) \
1697 double x_diff = (x - center_x); \
1698 /* Compute magnitude */ \
1699 double z = sqrt(x_diff * x_diff + \
1701 /* Compute angle */ \
1706 angle = 3 * M_PI / 2; \
1712 angle = atan(y_diff / x_diff); \
1714 if(x_diff < 0.0) angle += M_PI; \
1716 for(int i = 0; i < components; i++) \
1718 /* Compute new radius */ \
1719 double radius1 = z / r[i]; \
1720 double z_in = r[i] * tan(radius1) / (M_PI / 2); \
1722 double x_in = z_in * cos(angle) * x_factor + center_x; \
1723 double y_in = z_in * sin(angle) * y_factor + center_y; \
1725 if(x_in < 0.0 || x_in >= width - 1 || \
1726 y_in < 0.0 || y_in >= height - 1) \
1728 *out_row++ = black[i]; \
1732 float y1_fraction = y_in - floor(y_in); \
1733 float y2_fraction = 1.0 - y1_fraction; \
1734 float x1_fraction = x_in - floor(x_in); \
1735 float x2_fraction = 1.0 - x1_fraction; \
1736 type *in_pixel1 = in_rows[(int)y_in] + (int)x_in * components; \
1737 type *in_pixel2 = in_rows[(int)y_in + 1] + (int)x_in * components; \
1738 *out_row++ = (type)(in_pixel1[i] * x2_fraction * y2_fraction + \
1739 in_pixel2[i] * x2_fraction * y1_fraction + \
1740 in_pixel1[i + components] * x1_fraction * y2_fraction + \
1741 in_pixel2[i + components] * x1_fraction * y1_fraction); \
1747 type *out_pixel = out_rows[(int)center_y] + (int)center_x * components; \
1748 type *in_pixel = in_rows[(int)center_y] + (int)center_x * components; \
1749 for(int c = 0; c < components; c++) \
1751 *out_pixel++ = *in_pixel++; \
1756 switch(plugin->get_input()->get_color_model())
1759 DO_LENS_RECTILINEAR_SHRINK(unsigned char, 3, 0x0);
1762 DO_LENS_RECTILINEAR_SHRINK(unsigned char, 4, 0x0);
1765 DO_LENS_RECTILINEAR_SHRINK(float, 3, 0.0);
1768 DO_LENS_RECTILINEAR_SHRINK(float, 4, 0.0);
1771 DO_LENS_RECTILINEAR_SHRINK(unsigned char, 3, 0x80);
1774 DO_LENS_RECTILINEAR_SHRINK(unsigned char, 4, 0x80);
1779 void LensUnit::process_package(LoadPackage *package)
1781 LensPackage *pkg = (LensPackage*)package;
1783 switch(plugin->config.mode)
1785 case LensConfig::SHRINK:
1786 process_shrink(pkg);
1788 case LensConfig::STRETCH:
1789 process_stretch(pkg);
1791 case LensConfig::RECTILINEAR_STRETCH:
1792 process_rectilinear_stretch(pkg);
1794 case LensConfig::RECTILINEAR_SHRINK :
1795 process_rectilinear_shrink(pkg);
1804 LensEngine::LensEngine(LensMain *plugin)
1805 : LoadServer(plugin->PluginClient::smp + 1, plugin->PluginClient::smp + 1)
1806 // : LoadServer(1, 1)
1808 this->plugin = plugin;
1811 LensEngine::~LensEngine()
1815 void LensEngine::init_packages()
1817 for(int i = 0; i < LoadServer::get_total_packages(); i++)
1819 LensPackage *package = (LensPackage*)LoadServer::get_package(i);
1820 package->row1 = plugin->get_input()->get_h() * i / LoadServer::get_total_packages();
1821 package->row2 = plugin->get_input()->get_h() * (i + 1) / LoadServer::get_total_packages();
1825 LoadClient* LensEngine::new_client()
1827 return new LensUnit(this, plugin);
1830 LoadPackage* LensEngine::new_package()
1832 return new LensPackage;