Visual Servoing Platform  version 3.6.1 under development (2024-04-24)
vpDisplayGTK.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5  *
6  * This software 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.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Image display.
33  *
34  * Authors:
35  * Christophe Collewet
36  *
37 *****************************************************************************/
38 
44 #include <visp3/core/vpConfig.h>
45 
46 #if (defined(VISP_HAVE_GTK))
47 
48 #include <cmath> // std::fabs
49 #include <iostream>
50 #include <limits> // numeric_limits
51 #include <stdio.h>
52 #include <stdlib.h>
53 
54 // Display stuff
55 #include <visp3/core/vpDisplay.h>
56 #include <visp3/gui/vpDisplayGTK.h>
57 
58 // debug / exception
59 #include <visp3/core/vpDebug.h>
60 #include <visp3/core/vpDisplayException.h>
61 #include <visp3/core/vpImageConvert.h>
62 #include <visp3/core/vpImageTools.h>
63 #include <visp3/core/vpMath.h>
64 
65 #ifndef DOXYGEN_SHOULD_SKIP_THIS
66 
67 #include <gdk/gdk.h>
68 #include <gdk/gdkrgb.h>
69 #include <gtk/gtk.h>
70 
71 class vpDisplayGTK::Impl
72 {
73 public:
74  Impl()
75  : m_widget(nullptr), m_background(nullptr), m_gc(nullptr), m_blue(), m_red(), m_yellow(), m_green(), m_cyan(), m_orange(),
76  m_white(), m_black(), m_gdkcolor(), m_lightBlue(), m_darkBlue(), m_lightRed(), m_darkRed(), m_lightGreen(),
77  m_darkGreen(), m_purple(), m_lightGray(), m_gray(), m_darkGray(), m_colormap(nullptr), m_font(nullptr), m_vectgtk(nullptr),
78  m_col(nullptr)
79  { }
80 
81  ~Impl() { }
82 
83  void init(unsigned int win_width, unsigned int win_height, int win_x, int win_y, const std::string &title)
84  {
85  gint width = static_cast<gint>(win_width);
86  gint height = static_cast<gint>(win_height);
87 
88  /* Initialisation of the gdk et gdk_rgb library */
89  int *argc = nullptr;
90  char **argv;
91 
92  gtk_init(argc, &argv);
93 
94  /* Create the window*/
95  m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
96 
97  gtk_widget_add_events(m_widget, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
98 
99  gtk_window_set_default_size(GTK_WINDOW(m_widget), width, height);
100 
101  gtk_window_move(GTK_WINDOW(m_widget), win_x, win_y);
102 
103  gtk_widget_show(m_widget);
104 
105  gdk_rgb_init();
106 
107  /* Create background pixmap */
108  m_background = gdk_pixmap_new(m_widget->window, width, height, -1);
109 
110  /* Create graphic context */
111  m_gc = gdk_gc_new(m_widget->window);
112 
113  /* get the colormap */
114  m_colormap = gdk_window_get_colormap(m_widget->window);
115 
116  m_col = new GdkColor *[vpColor::id_unknown]; // id_unknown = number of predefined colors
117 
118  /* Create color */
119  gdk_color_parse("light blue", &m_lightBlue);
120  gdk_colormap_alloc_color(m_colormap, &m_lightBlue, FALSE, TRUE);
121  m_col[vpColor::id_lightBlue] = &m_lightBlue;
122 
123  gdk_color_parse("blue", &m_blue);
124  gdk_colormap_alloc_color(m_colormap, &m_blue, FALSE, TRUE);
125  m_col[vpColor::id_blue] = &m_blue;
126 
127  gdk_color_parse("dark blue", &m_darkBlue);
128  gdk_colormap_alloc_color(m_colormap, &m_darkBlue, FALSE, TRUE);
129  m_col[vpColor::id_darkBlue] = &m_darkBlue;
130 
131  gdk_color_parse("#FF8C8C", &m_lightRed);
132  gdk_colormap_alloc_color(m_colormap, &m_lightRed, FALSE, TRUE);
133  m_col[vpColor::id_lightRed] = &m_lightRed;
134 
135  gdk_color_parse("red", &m_red);
136  gdk_colormap_alloc_color(m_colormap, &m_red, FALSE, TRUE);
137  m_col[vpColor::id_red] = &m_red;
138 
139  gdk_color_parse("dark red", &m_darkRed);
140  gdk_colormap_alloc_color(m_colormap, &m_darkRed, FALSE, TRUE);
141  m_col[vpColor::id_darkRed] = &m_darkRed;
142 
143  gdk_color_parse("light green", &m_lightGreen);
144  gdk_colormap_alloc_color(m_colormap, &m_lightGreen, FALSE, TRUE);
145  m_col[vpColor::id_lightGreen] = &m_lightGreen;
146 
147  gdk_color_parse("green", &m_green);
148  gdk_colormap_alloc_color(m_colormap, &m_green, FALSE, TRUE);
149  m_col[vpColor::id_green] = &m_green;
150 
151  gdk_color_parse("dark green", &m_darkGreen);
152  gdk_colormap_alloc_color(m_colormap, &m_darkGreen, FALSE, TRUE);
153  m_col[vpColor::id_darkGreen] = &m_darkGreen;
154 
155  gdk_color_parse("yellow", &m_yellow);
156  gdk_colormap_alloc_color(m_colormap, &m_yellow, FALSE, TRUE);
157  m_col[vpColor::id_yellow] = &m_yellow;
158 
159  gdk_color_parse("cyan", &m_cyan);
160  gdk_colormap_alloc_color(m_colormap, &m_cyan, FALSE, TRUE);
161  m_col[vpColor::id_cyan] = &m_cyan;
162 
163  gdk_color_parse("orange", &m_orange);
164  gdk_colormap_alloc_color(m_colormap, &m_orange, FALSE, TRUE);
165  m_col[vpColor::id_orange] = &m_orange;
166 
167  gdk_color_parse("purple", &m_purple);
168  gdk_colormap_alloc_color(m_colormap, &m_purple, FALSE, TRUE);
169  m_col[vpColor::id_purple] = &m_purple;
170 
171  gdk_color_parse("white", &m_white);
172  gdk_colormap_alloc_color(m_colormap, &m_white, FALSE, TRUE);
173  m_col[vpColor::id_white] = &m_white;
174 
175  gdk_color_parse("black", &m_black);
176  gdk_colormap_alloc_color(m_colormap, &m_black, FALSE, TRUE);
177  m_col[vpColor::id_black] = &m_black;
178 
179  gdk_color_parse("#C0C0C0", &m_lightGray);
180  gdk_colormap_alloc_color(m_colormap, &m_lightGray, FALSE, TRUE);
181  m_col[vpColor::id_lightGray] = &m_lightGray;
182 
183  gdk_color_parse("#808080", &m_gray);
184  gdk_colormap_alloc_color(m_colormap, &m_gray, FALSE, TRUE);
185  m_col[vpColor::id_gray] = &m_gray;
186 
187  gdk_color_parse("#404040", &m_darkGray);
188  gdk_colormap_alloc_color(m_colormap, &m_darkGray, FALSE, TRUE);
189  m_col[vpColor::id_darkGray] = &m_darkGray;
190 
191  // Try to load a default font
192  m_font = gdk_font_load("-*-times-medium-r-normal-*-16-*-*-*-*-*-*-*");
193  if (m_font == nullptr)
194  m_font = gdk_font_load("-*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*");
195  if (m_font == nullptr)
196  m_font = gdk_font_load("-*-courier 10 pitch-medium-r-normal-*-16-*-*-*-*-*-*-*");
197 
198  if (!title.empty())
199  gdk_window_set_title(m_widget->window, title.c_str());
200  }
201 
202  void setFont(const std::string &fontname) { m_font = gdk_font_load((const gchar *)fontname.c_str()); }
203 
204  void setTitle(const std::string &title) { gdk_window_set_title(m_widget->window, title.c_str()); }
205 
206  void setWindowPosition(int win_x, int win_y) { gtk_window_move(GTK_WINDOW(m_widget), win_x, win_y); }
207 
208  void displayImage(const vpImage<unsigned char> &I, unsigned int scale, gint width, gint height)
209  {
210  if (scale == 1) {
211  /* Copie de l'image dans le pixmap fond */
212  gdk_draw_gray_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, I.bitmap, width);
213  }
214  else {
215  vpImage<unsigned char> sampled;
216  I.subsample(scale, scale, sampled);
217  gdk_draw_gray_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, sampled.bitmap, width);
218  }
219 
220  /* Le pixmap background devient le fond de la zone de dessin */
221  gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
222  }
223 
224  void displayImage(const vpImage<vpRGBa> &I, unsigned int scale, gint width, gint height)
225  {
226  if (scale == 1) {
227  /* Copie de l'image dans le pixmap fond */
228  gdk_draw_rgb_32_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, (unsigned char *)I.bitmap,
229  4 * width);
230  }
231  else {
232  vpImage<vpRGBa> sampled;
233  I.subsample(scale, scale, sampled);
234  gdk_draw_rgb_32_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE,
235  (unsigned char *)sampled.bitmap, 4 * width);
236  }
237 
238  /* Le pixmap background devient le fond de la zone de dessin */
239  gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
240  }
241 
242  void displayImageROI(const vpImage<unsigned char> &I, gint j_min, gint i_min, gint width, gint height)
243  {
244  gdk_draw_gray_image(m_background, m_gc, j_min, i_min, width, height, GDK_RGB_DITHER_NONE, I.bitmap, width);
245  /* Le pixmap background devient le fond de la zone de dessin */
246  gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
247  }
248 
249  void displayImageROI(const vpImage<vpRGBa> &I, gint j_min, gint i_min, gint width, gint height)
250  {
251  gdk_draw_rgb_32_image(m_background, m_gc, j_min, i_min, width, height, GDK_RGB_DITHER_NONE,
252  (unsigned char *)I.bitmap, width * 4);
253 
254  /* Le pixmap background devient le fond de la zone de dessin */
255  gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
256  }
257 
258  void closeDisplay()
259  {
260  if (m_col != nullptr) {
261  delete[] m_col;
262  m_col = nullptr;
263  }
264 
265  if (m_widget != nullptr) {
266  gdk_window_hide(m_widget->window);
267  gdk_window_destroy(m_widget->window);
268  gtk_widget_destroy(m_widget);
269  m_widget = nullptr;
270  }
271  }
272 
273  void flushDisplay()
274  {
275  gdk_window_clear(m_widget->window);
276  gdk_flush();
277  }
278 
279  void displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color, unsigned int scale)
280  {
281  if (color.id < vpColor::id_unknown)
282  gdk_gc_set_foreground(m_gc, m_col[color.id]);
283  else {
284  m_gdkcolor.red = 256 * color.R;
285  m_gdkcolor.green = 256 * color.G;
286  m_gdkcolor.blue = 256 * color.B;
287  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
288  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
289  }
290  if (m_font != nullptr)
291  gdk_draw_string(m_background, m_font, m_gc, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale),
292  (const gchar *)text.c_str());
293  else
294  std::cout << "Cannot draw string: no font is selected" << std::endl;
295  }
296 
297  void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
298  unsigned int thickness, unsigned int scale)
299  {
300  if (color.id < vpColor::id_unknown)
301  gdk_gc_set_foreground(m_gc, m_col[color.id]);
302  else {
303  m_gdkcolor.red = 256 * color.R;
304  m_gdkcolor.green = 256 * color.G;
305  m_gdkcolor.blue = 256 * color.B;
306  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
307  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
308  }
309 
310  gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
311 
312  if (fill == false)
313  gdk_draw_arc(m_background, m_gc, FALSE, vpMath::round((center.get_u() - radius) / scale),
314  vpMath::round((center.get_v() - radius) / scale), static_cast<gint>(2. * radius / scale),
315  static_cast<gint>(2. * radius / scale), 23040, 23040); /* 23040 = 360*64 */
316  else
317  gdk_draw_arc(m_background, m_gc, TRUE, vpMath::round((center.get_u() - radius) / scale),
318  vpMath::round((center.get_v() - radius) / scale), static_cast<gint>(2. * radius / scale),
319  static_cast<gint>(2. * radius / scale), 23040, 23040); /* 23040 = 360*64 */
320  }
321 
322  void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
323  unsigned int scale)
324  {
325  if (color.id < vpColor::id_unknown)
326  gdk_gc_set_foreground(m_gc, m_col[color.id]);
327  else {
328  m_gdkcolor.red = 256 * color.R;
329  m_gdkcolor.green = 256 * color.G;
330  m_gdkcolor.blue = 256 * color.B;
331  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
332  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
333  }
334 
335  gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
336  gdk_draw_line(m_background, m_gc, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
337  vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
338  gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
339  }
340 
341  void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
342  unsigned int scale)
343  {
344  if (color.id < vpColor::id_unknown)
345  gdk_gc_set_foreground(m_gc, m_col[color.id]);
346  else {
347  m_gdkcolor.red = 256 * color.R;
348  m_gdkcolor.green = 256 * color.G;
349  m_gdkcolor.blue = 256 * color.B;
350  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
351  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
352  }
353 
354  gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
355  gdk_draw_line(m_background, m_gc, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
356  vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
357  }
358 
359  void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness, unsigned int scale)
360  {
361  if (color.id < vpColor::id_unknown)
362  gdk_gc_set_foreground(m_gc, m_col[color.id]);
363  else {
364  m_gdkcolor.red = 256 * color.R;
365  m_gdkcolor.green = 256 * color.G;
366  m_gdkcolor.blue = 256 * color.B;
367  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
368  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
369  }
370 
371  if (thickness == 1) {
372  gdk_draw_point(m_background, m_gc, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale));
373  }
374  else {
375  gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale),
376  static_cast<gint>(thickness), static_cast<gint>(thickness));
377  }
378  }
379 
380  void displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color, bool fill,
381  unsigned int thickness, unsigned int scale)
382  {
383  if (color.id < vpColor::id_unknown)
384  gdk_gc_set_foreground(m_gc, m_col[color.id]);
385  else {
386  m_gdkcolor.red = 256 * color.R;
387  m_gdkcolor.green = 256 * color.G;
388  m_gdkcolor.blue = 256 * color.B;
389  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
390  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
391  }
392  gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
393 
394  if (fill == false)
395  gdk_draw_rectangle(m_background, m_gc, FALSE, vpMath::round(topLeft.get_u() / scale),
396  vpMath::round(topLeft.get_v() / scale), static_cast<gint>(w / scale),
397  static_cast<gint>(h / scale));
398  else
399  gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(topLeft.get_u() / scale),
400  vpMath::round(topLeft.get_v() / scale), static_cast<gint>(w / scale),
401  static_cast<gint>(h / scale));
402 
403  if (thickness > 1)
404  gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
405  }
406 
407  bool getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale,
408  const GdkEventType &event_type)
409  {
410  bool ret = false;
411  do {
412  GdkEvent *ev = nullptr;
413  while ((ev = gdk_event_get())) {
414  if (ev->any.window == m_widget->window && ev->type == event_type) {
415  double u = ((GdkEventButton *)ev)->x;
416  double v = ((GdkEventButton *)ev)->y;
417  ip.set_u(u * scale);
418  ip.set_v(v * scale);
419 
420  switch (static_cast<int>(((GdkEventButton *)ev)->button)) {
421  case 1:
422  button = vpMouseButton::button1;
423  break;
424  case 2:
425  button = vpMouseButton::button2;
426  break;
427  case 3:
428  button = vpMouseButton::button3;
429  break;
430  }
431  ret = true;
432  }
433  gdk_event_free(ev);
434  }
435  if (blocking) {
436  flushDisplay();
437  vpTime::wait(100);
438  }
439 
440  } while (ret == false && blocking == true);
441  return ret;
442  }
443 
444  void getImage(vpImage<vpRGBa> &I, gint width, gint height)
445  {
446  GdkImage *ImageGtk;
447  ImageGtk = gdk_image_get(m_background, 0, 0, width, height);
448 
449  I.resize(height, width);
450  guint32 pixel;
451 
452  guchar OctetRouge, OctetVert, OctetBleu, mask;
453  mask = 0x000000FF;
454 
455  for (gint y = 0; y < height; ++y) {
456  for (gint x = 0; x < width; ++x) {
457  pixel = gdk_image_get_pixel(ImageGtk, x, y);
458  OctetBleu = static_cast<guchar>(pixel) & mask;
459  OctetVert = static_cast<guchar>(pixel >> 8) & mask;
460  OctetRouge = static_cast<guchar>(pixel >> 16) & mask;
461  I[y][x].R = OctetRouge;
462  I[y][x].G = OctetVert;
463  I[y][x].B = OctetBleu;
464  I[y][x].A = vpRGBa::alpha_default; // default opacity
465  }
466  }
467  }
468 
469  unsigned int getScreenDepth() { return static_cast<unsigned int>(gdk_window_get_visual(m_widget->window)->depth); }
470 
471  bool getKeyboardEvent(std::string &key, bool blocking)
472  {
473  bool ret = false;
474  int cpt = 0;
475  do {
476  GdkEvent *ev = nullptr;
477  while ((ev = gdk_event_get()) != nullptr) {
478  cpt++;
479 
480  if (ev->any.window == m_widget->window && ev->type == GDK_KEY_PRESS) {
481  key = gdk_keyval_name(ev->key.keyval);
482  ret = true;
483  }
484  gdk_event_free(ev);
485  }
486  if (blocking) {
487  flushDisplay();
488  vpTime::wait(100);
489  }
490  } while (ret == false && blocking == true);
491  return ret;
492  }
493 
494  bool getPointerMotionEvent(vpImagePoint &ip, unsigned int scale)
495  {
496  bool ret = false;
497  GdkEvent *ev = nullptr;
498  if ((ev = gdk_event_get())) {
499  if (ev->any.window == m_widget->window && ev->type == GDK_MOTION_NOTIFY) {
500  double u = ((GdkEventMotion *)ev)->x;
501  double v = ((GdkEventMotion *)ev)->y;
502  ip.set_u(u * scale);
503  ip.set_v(v * scale);
504 
505  ret = true;
506  }
507  gdk_event_free(ev);
508  }
509  return ret;
510  }
511 
512  void getPointerPosition(vpImagePoint &ip, unsigned int scale)
513  {
514  gint u, v;
515  gdk_window_get_pointer(m_widget->window, &u, &v, nullptr);
516  ip.set_u(static_cast<double>(u) * scale);
517  ip.set_v(static_cast<double>(v) * scale);
518  }
519 
520  void getScreenSize(bool is_init, unsigned int &w, unsigned int &h)
521  {
522  if (!is_init) {
523  int *argc = nullptr;
524  char **argv;
525 
526  gtk_init(argc, &argv);
527 
528  GtkWidget *widget_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
529  gtk_window_set_default_size(GTK_WINDOW(widget_), 100, 100);
530  gtk_widget_show(widget_);
531 
532  GdkScreen *screen_ = gdk_window_get_screen(widget_->window);
533  w = static_cast<unsigned int>(gdk_screen_get_width(screen_));
534  h = static_cast<unsigned int>(gdk_screen_get_height(screen_));
535  gtk_widget_destroy(widget_);
536  }
537  else {
538  GdkScreen *screen_ = gdk_window_get_screen(m_widget->window);
539  w = static_cast<unsigned int>(gdk_screen_get_width(screen_));
540  h = static_cast<unsigned int>(gdk_screen_get_height(screen_));
541  }
542  }
543 
544 private:
545  GtkWidget *m_widget;
546  GdkPixmap *m_background;
547  GdkGC *m_gc;
548  GdkColor m_blue, m_red, m_yellow, m_green, m_cyan, m_orange, m_white, m_black, m_gdkcolor;
549  GdkColor m_lightBlue, m_darkBlue, m_lightRed, m_darkRed, m_lightGreen, m_darkGreen, m_purple;
550  GdkColor m_lightGray, m_gray, m_darkGray;
551  GdkColormap *m_colormap;
552 
553  GdkFont *m_font;
554  guchar *m_vectgtk;
555  GdkColor **m_col;
556 };
557 
558 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
559 
582 {
583  setScale(scaleType, I.getWidth(), I.getHeight());
584  init(I);
585 }
586 
610 vpDisplayGTK::vpDisplayGTK(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title,
611  vpScaleType scaleType)
612  : vpDisplay(), m_impl(new Impl())
613 {
614  setScale(scaleType, I.getWidth(), I.getHeight());
615  init(I, win_x, win_y, win_title);
616 }
617 
637 vpDisplayGTK::vpDisplayGTK(vpImage<vpRGBa> &I, vpScaleType scaleType) : vpDisplay(), m_impl(new Impl())
638 {
639  setScale(scaleType, I.getWidth(), I.getHeight());
640  init(I);
641 }
642 
664 vpDisplayGTK::vpDisplayGTK(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title,
665  vpScaleType scaleType)
666  : vpDisplay(), m_impl(new Impl())
667 {
668  setScale(scaleType, I.getWidth(), I.getHeight());
669  init(I, win_x, win_y, win_title);
670 }
671 
694 vpDisplayGTK::vpDisplayGTK(int win_x, int win_y, const std::string &win_title) : vpDisplay(), m_impl(new Impl())
695 {
696  m_windowXPosition = win_x;
697  m_windowYPosition = win_y;
698  m_title = win_title;
699 }
700 
720 vpDisplayGTK::vpDisplayGTK() : vpDisplay(), m_impl(new Impl()) { }
721 
726 {
727  closeDisplay();
728  delete m_impl;
729 }
730 
739 void vpDisplayGTK::init(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title)
740 {
741  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
742  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
743  }
744 
745  if (win_x != -1)
746  m_windowXPosition = win_x;
747  if (win_y != -1)
748  m_windowYPosition = win_y;
749 
750  if (!win_title.empty())
751  m_title = win_title;
752 
755 
756  I.display = this;
758 }
759 
769 void vpDisplayGTK::init(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title)
770 {
771  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
772  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
773  }
774 
775  if (win_x != -1)
776  m_windowXPosition = win_x;
777  if (win_y != -1)
778  m_windowYPosition = win_y;
779 
780  if (!win_title.empty())
781  m_title = win_title;
782 
785 
786  I.display = this;
788 }
789 
798 void vpDisplayGTK::init(unsigned int win_width, unsigned int win_height, int win_x, int win_y,
799  const std::string &win_title)
800 {
801  setScale(m_scaleType, win_width, win_height);
802 
803  m_width = win_width / m_scale;
804  m_height = win_height / m_scale;
805 
806  if (win_x != -1)
807  m_windowXPosition = win_x;
808  if (win_y != -1)
809  m_windowYPosition = win_y;
810 
811  m_title = win_title;
812 
814 
816 }
817 
830 void vpDisplayGTK::setFont(const std::string &fontname) { m_impl->setFont(fontname); }
831 
836 void vpDisplayGTK::setTitle(const std::string &title)
837 {
839  m_title = title;
840  if (!title.empty()) {
841  m_impl->setTitle(title);
842  }
843  }
844  else {
845  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
846  }
847 }
848 
858 void vpDisplayGTK::setWindowPosition(int win_x, int win_y)
859 {
861  m_impl->setWindowPosition(win_x, win_y);
862  }
863  else {
864  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
865  }
866 }
867 
880 {
882  m_impl->displayImage(I, m_scale, static_cast<gint>(m_width), static_cast<gint>(m_height));
883  }
884  else {
885  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
886  }
887 }
888 
906 void vpDisplayGTK::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w,
907  unsigned int h)
908 {
911  vpImageTools::crop(I, iP.get_i(), iP.get_j(), h, w, Itemp, m_scale, m_scale);
912 
913  /* Copie de l'image dans le pixmap fond */
914  int i_min = std::max<int>(static_cast<int>(ceil(iP.get_i() / m_scale)), 0);
915  int j_min = std::max<int>(static_cast<int>(ceil(iP.get_j() / m_scale)), 0);
916 
917  m_impl->displayImageROI(Itemp, static_cast<gint>(j_min), static_cast<gint>(i_min),
918  static_cast<gint>(Itemp.getWidth()), static_cast<gint>(Itemp.getHeight()));
919  }
920  else {
921  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
922  }
923 }
924 
937 {
939  m_impl->displayImage(I, m_scale, static_cast<gint>(m_width), static_cast<gint>(m_height));
940  }
941  else {
942  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
943  }
944 }
945 
963 void vpDisplayGTK::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h)
964 {
966  vpImage<vpRGBa> Itemp;
967  vpImageTools::crop(I, iP.get_i(), iP.get_j(), h, w, Itemp, m_scale, m_scale);
968 
969  /* Copie de l'image dans le pixmap fond */
970  int i_min = std::max<int>(static_cast<int>(ceil(iP.get_i() / m_scale)), 0);
971  int j_min = std::max<int>(static_cast<int>(ceil(iP.get_j() / m_scale)), 0);
972 
973  m_impl->displayImageROI(Itemp, static_cast<gint>(j_min), static_cast<gint>(i_min),
974  static_cast<gint>(Itemp.getWidth()), static_cast<gint>(Itemp.getHeight()));
975  }
976  else {
977  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
978  }
979 }
980 
986 void vpDisplayGTK::displayImage(const unsigned char * /* I */) { vpTRACE(" not implemented "); }
987 
994 {
996  m_impl->closeDisplay();
997 
999  }
1000 }
1001 
1007 {
1009  m_impl->flushDisplay();
1010  }
1011  else {
1012  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1013  }
1014 }
1015 
1020 void vpDisplayGTK::flushDisplayROI(const vpImagePoint & /*iP*/, const unsigned int /*width*/,
1021  const unsigned int /*height*/)
1022 {
1024  m_impl->flushDisplay();
1025  }
1026  else {
1027  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1028  }
1029 }
1030 
1034 void vpDisplayGTK::clearDisplay(const vpColor & /* color */) { vpTRACE("Not implemented"); }
1035 
1043 void vpDisplayGTK::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
1044  unsigned int h, unsigned int thickness)
1045 {
1047  double a = ip2.get_i() - ip1.get_i();
1048  double b = ip2.get_j() - ip1.get_j();
1049  double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
1050 
1051  if ((std::fabs(a) > std::numeric_limits<double>::epsilon()) &&
1052  (std::fabs(b) > std::numeric_limits<double>::epsilon())) {
1053  a /= lg;
1054  b /= lg;
1055 
1056  vpImagePoint ip3;
1057  ip3.set_i(ip2.get_i() - w * a);
1058  ip3.set_j(ip2.get_j() - w * b);
1059 
1060  vpImagePoint ip4;
1061  ip4.set_i(ip3.get_i() - b * h);
1062  ip4.set_j(ip3.get_j() + a * h);
1063 
1064  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1065  displayLine(ip2, ip4, color, thickness);
1066 
1067  ip4.set_i(ip3.get_i() + b * h);
1068  ip4.set_j(ip3.get_j() - a * h);
1069 
1070  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1071  displayLine(ip2, ip4, color, thickness);
1072 
1073  displayLine(ip1, ip2, color, thickness);
1074  }
1075  }
1076  else {
1077  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1078  }
1079 }
1080 
1092 void vpDisplayGTK::displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color)
1093 {
1095  m_impl->displayText(ip, text, color, m_scale);
1096  }
1097  else {
1098  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1099  }
1100 }
1101 
1111 void vpDisplayGTK::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
1112  unsigned int thickness)
1113 {
1115  if (thickness == 1)
1116  thickness = 0;
1117 
1118  m_impl->displayCircle(center, radius, color, fill, thickness, m_scale);
1119  }
1120  else {
1121  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1122  }
1123 }
1131 void vpDisplayGTK::displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness)
1132 {
1134  double i = ip.get_i();
1135  double j = ip.get_j();
1136  vpImagePoint ip1, ip2;
1137 
1138  ip1.set_i(i - size / 2);
1139  ip1.set_j(j);
1140  ip2.set_i(i + size / 2);
1141  ip2.set_j(j);
1142  displayLine(ip1, ip2, color, thickness);
1143 
1144  ip1.set_i(i);
1145  ip1.set_j(j - size / 2);
1146  ip2.set_i(i);
1147  ip2.set_j(j + size / 2);
1148 
1149  displayLine(ip1, ip2, color, thickness);
1150  }
1151 
1152  else {
1153  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1154  }
1155 }
1162 void vpDisplayGTK::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1163  unsigned int thickness)
1164 {
1165 
1167  if (thickness == 1)
1168  thickness = 0;
1169 
1170  m_impl->displayDotLine(ip1, ip2, color, thickness, m_scale);
1171  }
1172  else {
1173  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1174  }
1175 }
1176 
1183 void vpDisplayGTK::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1184  unsigned int thickness)
1185 {
1187  if (thickness == 1)
1188  thickness = 0;
1189 
1190  m_impl->displayLine(ip1, ip2, color, thickness, m_scale);
1191  }
1192  else {
1193  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1194  }
1195 }
1196 
1203 void vpDisplayGTK::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
1204 {
1206  m_impl->displayPoint(ip, color, thickness, m_scale);
1207  }
1208  else {
1209  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1210  }
1211 }
1212 
1226 void vpDisplayGTK::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
1227  bool fill, unsigned int thickness)
1228 {
1230  if (thickness == 1)
1231  thickness = 0;
1232 
1233  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1234  }
1235  else {
1236  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1237  }
1238 }
1239 
1252 void vpDisplayGTK::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
1253  bool fill, unsigned int thickness)
1254 {
1256  if (thickness == 1)
1257  thickness = 0;
1258 
1259  unsigned int w = static_cast<unsigned int>(vpMath::round(bottomRight.get_u() - topLeft.get_u()));
1260  unsigned int h = static_cast<unsigned int>(vpMath::round(bottomRight.get_v() - topLeft.get_v()));
1261 
1262  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1263  }
1264  else {
1265  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1266  }
1267 }
1268 
1281 void vpDisplayGTK::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
1282 {
1284  if (thickness == 1)
1285  thickness = 0;
1286 
1287  vpImagePoint topLeft = rectangle.getTopLeft();
1288  unsigned int w = static_cast<unsigned int>(vpMath::round(rectangle.getWidth()));
1289  unsigned int h = static_cast<unsigned int>(vpMath::round(rectangle.getRight()));
1290  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1291  }
1292  else {
1293  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1294  }
1295 }
1296 
1312 bool vpDisplayGTK::getClick(bool blocking)
1313 {
1314  bool ret = false;
1315 
1317  vpImagePoint ip;
1319  ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1320  }
1321  else {
1322  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1323  }
1324  return ret;
1325 }
1326 
1343 bool vpDisplayGTK::getClick(vpImagePoint &ip, bool blocking)
1344 {
1345  bool ret = false;
1346 
1349  ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1350  }
1351  else {
1352  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1353  }
1354  return ret;
1355 }
1356 
1377 {
1378  bool ret = false;
1379 
1381  ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1382  }
1383  else {
1384  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1385  }
1386  return ret;
1387 }
1388 
1413 {
1414  bool ret = false;
1415 
1417  ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_RELEASE);
1418  }
1419  else {
1420  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1421  }
1422  return ret;
1423 }
1424 
1425 /*
1426  \brief gets the displayed image (including the overlay plane)
1427  and returns an RGBa image
1428 */
1430 {
1431  // should certainly be optimized.
1433  m_impl->getImage(I, static_cast<gint>(m_width), static_cast<gint>(m_height));
1434  }
1435  else {
1436  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1437  }
1438 }
1439 
1446 {
1447  unsigned int depth = m_impl->getScreenDepth();
1448 
1449  return (depth);
1450 }
1451 
1468 {
1469  bool ret = false;
1470 
1472  std::string key;
1473  ret = m_impl->getKeyboardEvent(key, blocking);
1474  }
1475  else {
1476  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1477  }
1478  return ret;
1479 }
1480 
1500 bool vpDisplayGTK::getKeyboardEvent(std::string &key, bool blocking)
1501 {
1502  bool ret = false;
1503 
1505  ret = m_impl->getKeyboardEvent(key, blocking);
1506  }
1507  else {
1508  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1509  }
1510  return ret;
1511 }
1512 
1526 {
1527  bool ret = false;
1528 
1530  ret = m_impl->getPointerMotionEvent(ip, m_scale);
1531  }
1532  else {
1533  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1534  }
1535  return ret;
1536 }
1537 
1549 {
1551  m_impl->getPointerPosition(ip, m_scale);
1552  }
1553  else {
1554  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1555  }
1556 
1557  return true;
1558 }
1559 
1564 void vpDisplayGTK::getScreenSize(unsigned int &w, unsigned int &h)
1565 {
1566  w = h = 0;
1567 
1568  m_impl->getScreenSize(m_displayHasBeenInitialized, w, h);
1569 }
1570 
1575 {
1576  unsigned int width, height;
1577  getScreenSize(width, height);
1578  return width;
1579 }
1580 
1585 {
1586  unsigned int width, height;
1587  getScreenSize(width, height);
1588  return height;
1589 }
1590 
1591 #elif !defined(VISP_BUILD_SHARED_LIBS)
1592 // Work around to avoid warning: libvisp_core.a(vpDisplayGTK.cpp.o) has no symbols
1593 void dummy_vpDisplayGTK() { };
1594 #endif
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:152
vpColorIdentifier id
Definition: vpColor.h:200
@ id_lightBlue
Definition: vpColor.h:178
@ id_yellow
Definition: vpColor.h:184
@ id_darkGray
Definition: vpColor.h:164
@ id_green
Definition: vpColor.h:174
@ id_darkRed
Definition: vpColor.h:170
@ id_lightGray
Definition: vpColor.h:160
@ id_red
Definition: vpColor.h:168
@ id_lightRed
Definition: vpColor.h:166
@ id_white
Definition: vpColor.h:158
@ id_black
Definition: vpColor.h:156
@ id_blue
Definition: vpColor.h:180
@ id_darkGreen
Definition: vpColor.h:176
@ id_gray
Definition: vpColor.h:162
@ id_lightGreen
Definition: vpColor.h:172
@ id_purple
Definition: vpColor.h:190
@ id_orange
Definition: vpColor.h:188
@ id_cyan
Definition: vpColor.h:186
@ id_darkBlue
Definition: vpColor.h:182
@ id_unknown
Definition: vpColor.h:193
Error that can be emitted by the vpDisplay class and its derivatives.
@ notInitializedError
Display not initialized.
bool getClick(bool blocking=true) vp_override
virtual ~vpDisplayGTK() vp_override
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1) vp_override
void clearDisplay(const vpColor &color=vpColor::white) vp_override
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1) vp_override
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) vp_override
void setWindowPosition(int win_x, int win_y) vp_override
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) vp_override
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1) vp_override
void flushDisplay() vp_override
void setTitle(const std::string &win_title) vp_override
bool getKeyboardEvent(bool blocking=true) vp_override
void closeDisplay() vp_override
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height) vp_override
void displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1) vp_override
void displayImage(const vpImage< vpRGBa > &I) vp_override
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height) vp_override
void setFont(const std::string &fontname) vp_override
bool getPointerPosition(vpImagePoint &ip) vp_override
unsigned int getScreenDepth()
get the window depth (8,16,24,32)
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="") vp_override
bool getPointerMotionEvent(vpImagePoint &ip) vp_override
void displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color=vpColor::green) vp_override
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true) vp_override
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1) vp_override
void getImage(vpImage< vpRGBa > &I) vp_override
Get the window pixmap and put it in vpRGBa image.
unsigned int getScreenHeight() vp_override
unsigned int getScreenWidth() vp_override
void getScreenSize(unsigned int &screen_width, unsigned int &screen_height) vp_override
Class that defines generic functionalities for display.
Definition: vpDisplay.h:173
unsigned int m_height
Definition: vpDisplay.h:212
vpScaleType m_scaleType
Definition: vpDisplay.h:215
unsigned int m_width
Definition: vpDisplay.h:211
int m_windowXPosition
display position
Definition: vpDisplay.h:208
std::string m_title
Definition: vpDisplay.h:213
int m_windowYPosition
display position
Definition: vpDisplay.h:210
unsigned int m_scale
Definition: vpDisplay.h:214
bool m_displayHasBeenInitialized
display has been initialized
Definition: vpDisplay.h:206
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Definition: vpDisplay.cpp:256
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
void set_j(double jj)
Definition: vpImagePoint.h:304
double get_j() const
Definition: vpImagePoint.h:125
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
void set_i(double ii)
Definition: vpImagePoint.h:293
double get_u() const
Definition: vpImagePoint.h:136
void set_u(double u)
Definition: vpImagePoint.h:330
void set_v(double v)
Definition: vpImagePoint.h:341
double get_i() const
Definition: vpImagePoint.h:114
double get_v() const
Definition: vpImagePoint.h:147
static void crop(const vpImage< Type > &I, double roi_top, double roi_left, unsigned int roi_height, unsigned int roi_width, vpImage< Type > &crop, unsigned int v_scale=1, unsigned int h_scale=1)
Definition: vpImageTools.h:312
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:1638
unsigned int getWidth() const
Definition: vpImage.h:245
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:783
Type * bitmap
points toward the bitmap
Definition: vpImage.h:139
unsigned int getHeight() const
Definition: vpImage.h:184
vpDisplay * display
Definition: vpImage.h:140
static double sqr(double x)
Definition: vpMath.h:201
static int round(double x)
Definition: vpMath.h:403
unsigned char B
Blue component.
Definition: vpRGBa.h:139
unsigned char R
Red component.
Definition: vpRGBa.h:137
unsigned char G
Green component.
Definition: vpRGBa.h:138
@ alpha_default
Definition: vpRGBa.h:63
Defines a rectangle in the plane.
Definition: vpRect.h:76
double getWidth() const
Definition: vpRect.h:224
vpImagePoint getTopLeft() const
Definition: vpRect.h:196
double getRight() const
Definition: vpRect.h:176
#define vpTRACE
Definition: vpDebug.h:405
VISP_EXPORT int wait(double t0, double t)