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  */
47 YuvViewerGtkWindow::YuvViewerGtkWindow(BaseObjectType * cobject,
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(
66  sigc::mem_fun(*this, &YuvViewerGtkWindow::on_y_value_changed));
67  y_res_->signal_value_changed().connect(
68  sigc::mem_fun(*this, &YuvViewerGtkWindow::on_y_res_changed));
69  u_res_->signal_value_changed().connect(
70  sigc::mem_fun(*this, &YuvViewerGtkWindow::on_uv_res_changed));
71  v_res_->signal_value_changed().connect(
72  sigc::mem_fun(*this, &YuvViewerGtkWindow::on_uv_res_changed));
73 
74  yuv_vp_->signal_button_press_event().connect(
75  sigc::mem_fun(*this, &YuvViewerGtkWindow::on_click_on_yuv));
76  yuv_vp_->signal_motion_notify_event().connect(
77  sigc::mem_fun(*this, &YuvViewerGtkWindow::on_mouse_over_yuv));
78  yuv_vp_->add(*yuv_widget_);
79  cur_vp_->add(*cur_widget_);
80  seg_vp_->add(*seg_widget_);
81 
82  memset(cur_buffer_ + 60 * 40, 128, 60 * 40);
83  memset(seg_buffer_, 128, 256 * 256);
84  on_y_value_changed();
85  on_uv_res_changed();
86  calc_seg();
87  show_all_children();
88 }
89 
90 /** Destructor. */
92 {
93 }
94 
95 /** Signal hander that gets called after a click on the YUV pane
96  * @param event provides the x/y-coordinate
97  * @return true
98  */
99 bool
100 YuvViewerGtkWindow::on_click_on_yuv(GdkEventButton *event)
101 {
102  GdkEventMotion mot;
103  mot.x = event->x;
104  mot.y = event->y;
105  return on_mouse_over_yuv(&mot);
106 }
107 
108 /** Signal hander that gets called during a movement on the YUV pane (if the left button is pressed)
109  * @param event provides the x/y-coordinate
110  * @return true
111  */
112 bool
113 YuvViewerGtkWindow::on_mouse_over_yuv(GdkEventMotion *event)
114 {
115  unsigned int u = std::max(0, std::min(255, (int)event->x));
116  unsigned int v = 255 - std::max(0, std::min(255, (int)event->y));
117 
118  u_value_->set_text(convert_float2str(u, 0));
119  v_value_->set_text(convert_float2str(v, 0));
120  memset(cur_buffer_ + 60 * 40, u, 60 * 20);
121  memset(cur_buffer_ + 60 * 60, v, 60 * 20);
122  cur_widget_->show(YUV422_PLANAR, cur_buffer_);
123 
124  return true;
125 }
126 
127 /** Signal handler called when the Y value changes (HSlider) */
128 void
129 YuvViewerGtkWindow::on_y_value_changed()
130 {
131  unsigned int y = round(y_scale_->get_value());
132  memset(yuv_buffer_, y, 256 * 256);
133  memset(cur_buffer_, y, 60 * 40);
134 
135  Drawer d;
136  d.set_buffer(yuv_buffer_, 256, 256);
137  d.set_color(YUV_t::black());
138  d.draw_line(127, 127, 0, 64);
139  d.draw_line(127, 127, 64, 0);
140 
141  d.draw_line(128, 127, 192, 0);
142  d.draw_line(128, 127, 255, 64);
143 
144  d.draw_line(128, 128, 192, 255);
145  d.draw_line(128, 128, 255, 192);
146 
147  d.draw_line(127, 128, 0, 192);
148  d.draw_line(127, 128, 64, 255);
149 
150  yuv_widget_->show(YUV422_PLANAR, yuv_buffer_);
151  cur_widget_->show(YUV422_PLANAR, cur_buffer_);
152 }
153 
154 void
155 YuvViewerGtkWindow::on_y_res_changed()
156 {
157  unsigned int r = round(y_res_->get_value());
158 
159  if (r == 0) {
160  y_scale_->set_value(127);
161  y_scale_->set_range(127, 128);
162  } else {
163  y_scale_->set_range(0, 255);
164  y_scale_->set_increments(255.f / (pow(2, r) - 1), 0);
165  }
166 }
167 
168 void
169 YuvViewerGtkWindow::on_uv_res_changed()
170 {
171  unsigned char *yuv_u = yuv_buffer_ + 256 * 256;
172  unsigned char *yuv_v = yuv_u + 256 * 256 / 2;
173  unsigned int u_div = 256 / (int)pow(2, u_res_->get_value());
174  unsigned int v_div = 256 / (int)pow(2, v_res_->get_value());
175 
176  for (unsigned int v = 0; v < 256; ++v) {
177  memset((yuv_v + v * 128), ((255 - v) / v_div) * v_div, 128);
178 
179  for (unsigned int u = 0; u < 128; ++u) {
180  yuv_u[v * 128 + u] = (u * 2 / u_div) * u_div;
181  }
182  }
183 
184  on_y_value_changed();
185 }
186 
187 /**
188  * Converts a float value to a Glib::ustring (locale dependent)
189  * @param f The float value
190  * @param width The precision width
191  * @return the formatted string
192  */
193 Glib::ustring
194 YuvViewerGtkWindow::convert_float2str(float f, unsigned int width)
195 {
196 #if GLIBMM_MAJOR_VERSION > 2 || (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION >= 16)
197  return Glib::ustring::format(std::fixed, std::setprecision(width), f);
198 #else
199  std::ostringstream ss;
200  ss << std::fixed << std::setprecision(width);
201  ss << f;
202 
203  return Glib::locale_to_utf8(ss.str());
204 #endif
205 }
206 
207 /** Calculates the segmented window */
208 void
209 YuvViewerGtkWindow::calc_seg()
210 {
211  YUV_t c;
212  unsigned char *seg_u = seg_buffer_ + 256 * 256;
213  unsigned char *seg_v = seg_u + 256 * 256 / 2;
214 
215  float a1 = atan2f(64, 128);
216  float a2 = atan2f(128, 64);
217  float a3 = atan2f(128, -64);
218  float a4 = atan2f(64, -128);
219  float a5 = atan2f(-64, -128) + M_2xPI;
220  float a6 = atan2f(-128, -64) + M_2xPI;
221  float a7 = atan2f(-128, 64) + M_2xPI;
222  float a8 = atan2f(-64, 128) + M_2xPI;
223 
224  for (int u = 0; u < 256; ++u) {
225  float du = u - 128;
226 
227  for (int v = 255; v >= 0; --v) {
228  float dv = v - 128;
229 
230  if (!du) {
231  if (dv > 0)
232  YUV_t::red();
233  else
234  c = YUV_t::gray();
235  } else {
236  float a = atan2f(dv, du);
237  if (a < 0)
238  a += M_2xPI;
239 
240  if (a >= a1 && a < a2)
241  c = YUV_t::magenta();
242  else if (a >= a2 && a < a3)
243  c = YUV_t::red();
244  else if (a >= a3 && a < a4)
245  c = YUV_t::orange();
246  else if (a >= a4 && a < a5)
247  c = YUV_t::yellow();
248  else if (a >= a5 && a < a6)
249  c = YUV_t::green();
250  else if (a >= a6 && a < a7)
251  c = YUV_t::gray();
252  else if (a >= a7 && a < a8)
253  c = YUV_t::cyan();
254  else
255  c = YUV_t::blue();
256  }
257 
258  unsigned int addr = ((255 - v) * 256 + u) / 2;
259  seg_u[addr] = c.U;
260  seg_v[addr] = c.V;
261  }
262  }
263 
264  seg_widget_->show(YUV422_PLANAR, seg_buffer_);
265 }
unsigned char V
V component.
Definition: yuv.h:61
This class is an image container to display fawkes cameras (or image buffers) inside a Gtk::Container...
Definition: image_widget.h:42
Fawkes library namespace.
virtual ~YuvViewerGtkWindow()
Destructor.
Draw to an image.
Definition: drawer.h:31
void draw_line(unsigned int x_start, unsigned int y_start, unsigned int x_end, unsigned int y_end)
Draw line.
Definition: drawer.cpp:363
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:58
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:60
YUV pixel.
Definition: yuv.h:57
void set_color(unsigned char y, unsigned char u, unsigned char v)
Set drawing color.
Definition: drawer.cpp:71