Fawkes API  Fawkes Development Version
yuv_viewer_gui.cpp
1 
2 /***************************************************************************
3  * yuv_viewer.cpp - YUV viewer gui
4  *
5  * Created: Sat Mar 22 16:34:02 2009
6  * Copyright 2009 Christof Rath <c.rath@student.tugraz.at>
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "yuv_viewer_gui.h"
24 
25 #include <fvutils/color/colorspaces.h>
26 #include <fvutils/draw/drawer.h>
27 
28 #include <cmath>
29 #include <cstring>
30 #include <iomanip>
31 #include <sstream>
32 
33 #define M_2xPI (2*M_PI)
34 using namespace fawkes;
35 using namespace firevision;
36 
37 /** @class YuvViewerGtkWindow "yuv_viewer_gui.h"
38  * Tool to show the YUV color space
39  *
40  * @author Christof Rath
41  */
42 
43 /** Constructor.
44  * @param cobject C base object
45  * @param builder Gtk builder
46  */
48  const Glib::RefPtr<Gtk::Builder> builder)
49  : Gtk::Window(cobject)
50 {
51  builder->get_widget("yuv_vp", __yuv_vp);
52  builder->get_widget("cur_vp", __cur_vp);
53  builder->get_widget("seg_vp", __seg_vp);
54  builder->get_widget("y_scale", __y_scale);
55  builder->get_widget("u_value", __u_value);
56  builder->get_widget("v_value", __v_value);
57  builder->get_widget("y_res", __y_res);
58  builder->get_widget("u_res", __u_res);
59  builder->get_widget("v_res", __v_res);
60 
61  __yuv_widget = Gtk::manage(new ImageWidget(256, 256));
62  __cur_widget = Gtk::manage(new ImageWidget( 60, 40));
63  __seg_widget = Gtk::manage(new ImageWidget(256, 256));
64 
65  __y_scale->signal_value_changed().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_y_value_changed));
66  __y_res->signal_value_changed().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_y_res_changed));
67  __u_res->signal_value_changed().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_uv_res_changed));
68  __v_res->signal_value_changed().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_uv_res_changed));
69 
70  __yuv_vp->signal_button_press_event().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_click_on_yuv));
71  __yuv_vp->signal_motion_notify_event().connect(sigc::mem_fun(*this, &YuvViewerGtkWindow::on_mouse_over_yuv));
72  __yuv_vp->add(*__yuv_widget);
73  __cur_vp->add(*__cur_widget);
74  __seg_vp->add(*__seg_widget);
75 
76 
77  memset(__cur_buffer + 60 * 40, 128, 60 * 40);
78  memset(__seg_buffer, 128, 256 * 256);
79  on_y_value_changed();
80  on_uv_res_changed();
81  calc_seg();
82  show_all_children();
83 }
84 
85 /** Destructor. */
87 {
88 }
89 
90 /** Signal hander that gets called after a click on the YUV pane
91  * @param event provides the x/y-coordinate
92  * @return true
93  */
94 bool
95 YuvViewerGtkWindow::on_click_on_yuv(GdkEventButton *event)
96 {
97  GdkEventMotion mot;
98  mot.x = event->x;
99  mot.y = event->y;
100  return on_mouse_over_yuv(&mot);
101 }
102 
103 /** Signal hander that gets called during a movement on the YUV pane (if the left button is pressed)
104  * @param event provides the x/y-coordinate
105  * @return true
106  */
107 bool
108 YuvViewerGtkWindow::on_mouse_over_yuv(GdkEventMotion *event)
109 {
110  unsigned int u = std::max(0, std::min(255, (int)event->x));
111  unsigned int v = 255 - std::max(0, std::min(255, (int)event->y));
112 
113  __u_value->set_text(convert_float2str(u, 0));
114  __v_value->set_text(convert_float2str(v, 0));
115  memset(__cur_buffer + 60 * 40, u, 60 * 20);
116  memset(__cur_buffer + 60 * 60, v, 60 * 20);
117  __cur_widget->show(YUV422_PLANAR, __cur_buffer);
118 
119  return true;
120 }
121 
122 /** Signal handler called when the Y value changes (HSlider) */
123 void
124 YuvViewerGtkWindow::on_y_value_changed()
125 {
126  unsigned int y = round(__y_scale->get_value());
127  memset(__yuv_buffer, y, 256 * 256);
128  memset(__cur_buffer, y, 60 * 40);
129 
130  Drawer d;
131  d.set_buffer(__yuv_buffer, 256, 256);
132  d.set_color(YUV_t::black());
133  d.draw_line(127, 127, 0, 64);
134  d.draw_line(127, 127, 64, 0);
135 
136  d.draw_line(128, 127, 192, 0);
137  d.draw_line(128, 127, 255, 64);
138 
139  d.draw_line(128, 128, 192, 255);
140  d.draw_line(128, 128, 255, 192);
141 
142  d.draw_line(127, 128, 0, 192);
143  d.draw_line(127, 128, 64, 255);
144 
145  __yuv_widget->show(YUV422_PLANAR, __yuv_buffer);
146  __cur_widget->show(YUV422_PLANAR, __cur_buffer);
147 }
148 
149 
150 void
151 YuvViewerGtkWindow::on_y_res_changed()
152 {
153  unsigned int r = round(__y_res->get_value());
154 
155  if (r == 0) {
156  __y_scale->set_value(127);
157  __y_scale->set_range(127, 128);
158  }
159  else {
160  __y_scale->set_range(0, 255);
161  __y_scale->set_increments(255.f / (pow(2, r) - 1), 0);
162  }
163 }
164 
165 void
166 YuvViewerGtkWindow::on_uv_res_changed()
167 {
168  unsigned char *yuv_u = __yuv_buffer + 256 * 256;
169  unsigned char *yuv_v = yuv_u + 256 * 256 / 2;
170  unsigned int u_div = 256 / (int)pow(2, __u_res->get_value());
171  unsigned int v_div = 256 / (int)pow(2, __v_res->get_value());
172 
173  for (unsigned int v = 0; v < 256; ++v) {
174  memset((yuv_v + v * 128), ((255 - v) / v_div) * v_div, 128);
175 
176  for (unsigned int u = 0; u < 128; ++u) {
177  yuv_u[v * 128 + u] = (u * 2 / u_div) * u_div;
178  }
179  }
180 
181  on_y_value_changed();
182 }
183 
184 /**
185  * Converts a float value to a Glib::ustring (locale dependent)
186  * @param f The float value
187  * @param width The precision width
188  * @return the formatted string
189  */
190 Glib::ustring
191 YuvViewerGtkWindow::convert_float2str(float f, unsigned int width)
192 {
193 #if GLIBMM_MAJOR_VERSION > 2 || ( GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION >= 16 )
194  return Glib::ustring::format(std::fixed, std::setprecision(width), f);
195 #else
196  std::ostringstream ss;
197  ss << std::fixed << std::setprecision(width);
198  ss << f;
199 
200  return Glib::locale_to_utf8(ss.str());
201 #endif
202 }
203 
204 /** Calculates the segmented window */
205 void
206 YuvViewerGtkWindow::calc_seg()
207 {
208  YUV_t c;
209  unsigned char *seg_u = __seg_buffer + 256 * 256;
210  unsigned char *seg_v = seg_u + 256 * 256 / 2;
211 
212  float a1 = atan2f(64, 128);
213  float a2 = atan2f(128, 64);
214  float a3 = atan2f(128, -64);
215  float a4 = atan2f(64, -128);
216  float a5 = atan2f(-64, -128) + M_2xPI;
217  float a6 = atan2f(-128, -64) + M_2xPI;
218  float a7 = atan2f(-128, 64) + M_2xPI;
219  float a8 = atan2f(-64, 128) + M_2xPI;
220 
221  for (int u = 0; u < 256; ++u) {
222  float du = u - 128;
223 
224  for (int v = 255; v >= 0; --v) {
225  float dv = v - 128;
226 
227  if (!du) {
228  if (dv > 0) YUV_t::red();
229  else c = YUV_t::gray();
230  }
231  else {
232  float a = atan2f(dv, du);
233  if (a < 0) a += M_2xPI;
234 
235  if (a >= a1 && a < a2) c = YUV_t::magenta();
236  else if (a >= a2 && a < a3) c = YUV_t::red();
237  else if (a >= a3 && a < a4) c = YUV_t::orange();
238  else if (a >= a4 && a < a5) c = YUV_t::yellow();
239  else if (a >= a5 && a < a6) c = YUV_t::green();
240  else if (a >= a6 && a < a7) c = YUV_t::gray();
241  else if (a >= a7 && a < a8) c = YUV_t::cyan();
242  else c = YUV_t::blue();
243  }
244 
245  unsigned int addr = ((255 - v) * 256 + u) / 2;
246  seg_u[addr] = c.U;
247  seg_v[addr] = c.V;
248  }
249  }
250 
251  __seg_widget->show(YUV422_PLANAR, __seg_buffer);
252 }
unsigned char V
V component.
Definition: yuv.h:62
This class is an image container to display fawkes cameras (or image buffers) inside a Gtk::Container...
Definition: image_widget.h:45
Fawkes library namespace.
virtual ~YuvViewerGtkWindow()
Destructor.
Draw to an image.
Definition: drawer.h:34
void draw_line(unsigned int x_start, unsigned int y_start, unsigned int x_end, unsigned int y_end)
Draw line.
Definition: drawer.cpp:381
YuvViewerGtkWindow(BaseObjectType *cobject, const Glib::RefPtr< Gtk::Builder > builder)
Constructor.
void set_buffer(unsigned char *buffer, unsigned int width, unsigned int height)
Set the buffer to draw to.
Definition: drawer.cpp:62
virtual bool show(colorspace_t colorspace, unsigned char *buffer, unsigned int width=0, unsigned int height=0)
Show image from given colorspace.
unsigned char U
U component.
Definition: yuv.h:61
YUV pixel.
Definition: yuv.h:59
void set_color(unsigned char y, unsigned char u, unsigned char v)
Set drawing color.
Definition: drawer.cpp:77