Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * yuv_viewer.cpp - YUV viewer gui 00004 * 00005 * Created: Sat Mar 22 16:34:02 2009 00006 * Copyright 2009 Christof Rath <c.rath@student.tugraz.at> 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL file in the doc directory. 00021 */ 00022 00023 #include "yuv_viewer_gui.h" 00024 00025 #include <fvutils/color/colorspaces.h> 00026 #include <fvutils/draw/drawer.h> 00027 00028 #include <cmath> 00029 #include <cstring> 00030 #include <iomanip> 00031 #include <sstream> 00032 00033 #define M_2xPI (2*M_PI) 00034 using namespace fawkes; 00035 using namespace firevision; 00036 00037 /** @class YuvViewerGtkWindow "yuv_viewer_gui.h" 00038 * Tool to show the YUV color space 00039 * 00040 * @author Christof Rath 00041 */ 00042 00043 /** Constructor. 00044 * @param cobject C base object 00045 * @param ref_xml Glade XML 00046 */ 00047 YuvViewerGtkWindow::YuvViewerGtkWindow(BaseObjectType* cobject, 00048 const Glib::RefPtr<Gnome::Glade::Xml> ref_xml) 00049 : Gtk::Window(cobject) 00050 { 00051 ref_xml->get_widget("yuv_vp", __yuv_vp); 00052 ref_xml->get_widget("cur_vp", __cur_vp); 00053 ref_xml->get_widget("seg_vp", __seg_vp); 00054 ref_xml->get_widget("y_scale", __y_scale); 00055 ref_xml->get_widget("u_value", __u_value); 00056 ref_xml->get_widget("v_value", __v_value); 00057 ref_xml->get_widget("y_res", __y_res); 00058 ref_xml->get_widget("u_res", __u_res); 00059 ref_xml->get_widget("v_res", __v_res); 00060 00061 __yuv_widget = Gtk::manage(new ImageWidget(256, 256)); 00062 __cur_widget = Gtk::manage(new ImageWidget( 60, 40)); 00063 __seg_widget = Gtk::manage(new ImageWidget(256, 256)); 00064 00065 __y_scale->signal_value_changed().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_y_value_changed)); 00066 __y_res->signal_value_changed().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_y_res_changed)); 00067 __u_res->signal_value_changed().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_uv_res_changed)); 00068 __v_res->signal_value_changed().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_uv_res_changed)); 00069 00070 __yuv_vp->signal_button_press_event().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_click_on_yuv)); 00071 __yuv_vp->signal_motion_notify_event().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_mouse_over_yuv)); 00072 __yuv_vp->add(*__yuv_widget); 00073 __cur_vp->add(*__cur_widget); 00074 __seg_vp->add(*__seg_widget); 00075 00076 00077 memset(__cur_buffer + 60 * 40, 128, 60 * 40); 00078 memset(__seg_buffer, 128, 256 * 256); 00079 on_y_value_changed(); 00080 on_uv_res_changed(); 00081 calc_seg(); 00082 show_all_children(); 00083 } 00084 00085 /** Destructor. */ 00086 YuvViewerGtkWindow::~YuvViewerGtkWindow() 00087 { 00088 } 00089 00090 /** Signal hander that gets called after a click on the YUV pane 00091 * @param event provides the x/y-coordinate 00092 * @return true 00093 */ 00094 bool 00095 YuvViewerGtkWindow::on_click_on_yuv(GdkEventButton *event) 00096 { 00097 GdkEventMotion mot; 00098 mot.x = event->x; 00099 mot.y = event->y; 00100 return on_mouse_over_yuv(&mot); 00101 } 00102 00103 /** Signal hander that gets called during a movement on the YUV pane (if the left button is pressed) 00104 * @param event provides the x/y-coordinate 00105 * @return true 00106 */ 00107 bool 00108 YuvViewerGtkWindow::on_mouse_over_yuv(GdkEventMotion *event) 00109 { 00110 unsigned int u = std::max(0, std::min(255, (int)event->x)); 00111 unsigned int v = 255 - std::max(0, std::min(255, (int)event->y)); 00112 00113 __u_value->set_text(convert_float2str(u, 0)); 00114 __v_value->set_text(convert_float2str(v, 0)); 00115 memset(__cur_buffer + 60 * 40, u, 60 * 20); 00116 memset(__cur_buffer + 60 * 60, v, 60 * 20); 00117 __cur_widget->show(YUV422_PLANAR, __cur_buffer); 00118 00119 return true; 00120 } 00121 00122 /** Signal handler called when the Y value changes (HSlider) */ 00123 void 00124 YuvViewerGtkWindow::on_y_value_changed() 00125 { 00126 unsigned int y = round(__y_scale->get_value()); 00127 memset(__yuv_buffer, y, 256 * 256); 00128 memset(__cur_buffer, y, 60 * 40); 00129 00130 Drawer d; 00131 d.set_buffer(__yuv_buffer, 256, 256); 00132 d.set_color(YUV_t::black()); 00133 d.draw_line(127, 127, 0, 64); 00134 d.draw_line(127, 127, 64, 0); 00135 00136 d.draw_line(128, 127, 192, 0); 00137 d.draw_line(128, 127, 255, 64); 00138 00139 d.draw_line(128, 128, 192, 255); 00140 d.draw_line(128, 128, 255, 192); 00141 00142 d.draw_line(127, 128, 0, 192); 00143 d.draw_line(127, 128, 64, 255); 00144 00145 __yuv_widget->show(YUV422_PLANAR, __yuv_buffer); 00146 __cur_widget->show(YUV422_PLANAR, __cur_buffer); 00147 } 00148 00149 00150 void 00151 YuvViewerGtkWindow::on_y_res_changed() 00152 { 00153 unsigned int r = round(__y_res->get_value()); 00154 00155 if (r == 0) { 00156 __y_scale->set_value(127); 00157 __y_scale->set_range(127, 128); 00158 } 00159 else { 00160 __y_scale->set_range(0, 255); 00161 __y_scale->set_increments(255.f / (pow(2, r) - 1), 0); 00162 } 00163 } 00164 00165 void 00166 YuvViewerGtkWindow::on_uv_res_changed() 00167 { 00168 unsigned char *yuv_u = __yuv_buffer + 256 * 256; 00169 unsigned char *yuv_v = yuv_u + 256 * 256 / 2; 00170 unsigned int u_div = 256 / (int)pow(2, __u_res->get_value()); 00171 unsigned int v_div = 256 / (int)pow(2, __v_res->get_value()); 00172 00173 for (unsigned int v = 0; v < 256; ++v) { 00174 memset((yuv_v + v * 128), ((255 - v) / v_div) * v_div, 128); 00175 00176 for (unsigned int u = 0; u < 128; ++u) { 00177 yuv_u[v * 128 + u] = (u * 2 / u_div) * u_div; 00178 } 00179 } 00180 00181 on_y_value_changed(); 00182 } 00183 00184 /** 00185 * Converts a float value to a Glib::ustring (locale dependent) 00186 * @param f The float value 00187 * @param width The precision width 00188 * @return the formatted string 00189 */ 00190 Glib::ustring 00191 YuvViewerGtkWindow::convert_float2str(float f, unsigned int width) 00192 { 00193 #if GLIBMM_MAJOR_VERSION > 2 || ( GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION >= 16 ) 00194 return Glib::ustring::format(std::fixed, std::setprecision(width), f); 00195 #else 00196 std::ostringstream ss; 00197 ss << std::fixed << std::setprecision(width); 00198 ss << f; 00199 00200 return Glib::locale_to_utf8(ss.str()); 00201 #endif 00202 } 00203 00204 /** Calculates the segmented window */ 00205 void 00206 YuvViewerGtkWindow::calc_seg() 00207 { 00208 YUV_t c; 00209 unsigned char *seg_u = __seg_buffer + 256 * 256; 00210 unsigned char *seg_v = seg_u + 256 * 256 / 2; 00211 00212 float a1 = atan2f(64, 128); 00213 float a2 = atan2f(128, 64); 00214 float a3 = atan2f(128, -64); 00215 float a4 = atan2f(64, -128); 00216 float a5 = atan2f(-64, -128) + M_2xPI; 00217 float a6 = atan2f(-128, -64) + M_2xPI; 00218 float a7 = atan2f(-128, 64) + M_2xPI; 00219 float a8 = atan2f(-64, 128) + M_2xPI; 00220 00221 for (int u = 0; u < 256; ++u) { 00222 float du = u - 128; 00223 00224 for (int v = 255; v >= 0; --v) { 00225 float dv = v - 128; 00226 00227 if (!du) { 00228 if (dv > 0) YUV_t::red(); 00229 else c = YUV_t::gray(); 00230 } 00231 else { 00232 float a = atan2f(dv, du); 00233 if (a < 0) a += M_2xPI; 00234 00235 if (a >= a1 && a < a2) c = YUV_t::magenta(); 00236 else if (a >= a2 && a < a3) c = YUV_t::red(); 00237 else if (a >= a3 && a < a4) c = YUV_t::orange(); 00238 else if (a >= a4 && a < a5) c = YUV_t::yellow(); 00239 else if (a >= a5 && a < a6) c = YUV_t::green(); 00240 else if (a >= a6 && a < a7) c = YUV_t::gray(); 00241 else if (a >= a7 && a < a8) c = YUV_t::cyan(); 00242 else c = YUV_t::blue(); 00243 } 00244 00245 unsigned int addr = ((255 - v) * 256 + u) / 2; 00246 seg_u[addr] = c.U; 00247 seg_v[addr] = c.V; 00248 } 00249 } 00250 00251 __seg_widget->show(YUV422_PLANAR, __seg_buffer); 00252 }