yuv_viewer_gui.cpp

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 }

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1