Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
vpDisplayGTK.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Image display.
32  */
33 
39 #include <visp3/core/vpConfig.h>
40 
41 #if (defined(VISP_HAVE_GTK))
42 
43 #include <cmath> // std::fabs
44 #include <iostream>
45 #include <limits> // numeric_limits
46 #include <stdio.h>
47 #include <stdlib.h>
48 
49 // Display stuff
50 #include <visp3/core/vpDisplay.h>
51 #include <visp3/gui/vpDisplayGTK.h>
52 
53 // debug / exception
54 #include <visp3/core/vpDisplayException.h>
55 #include <visp3/core/vpImageConvert.h>
56 #include <visp3/core/vpImageTools.h>
57 #include <visp3/core/vpMath.h>
58 
59 #ifndef DOXYGEN_SHOULD_SKIP_THIS
60 
61 #include <gdk/gdk.h>
62 #include <gdk/gdkrgb.h>
63 #include <gtk/gtk.h>
64 
66 
67 class vpDisplayGTK::Impl
68 {
69 public:
70  Impl()
71  : m_widget(nullptr), m_background(nullptr), m_gc(nullptr), m_blue(), m_red(), m_yellow(), m_green(), m_cyan(), m_orange(),
72  m_white(), m_black(), m_gdkcolor(), m_lightBlue(), m_darkBlue(), m_lightRed(), m_darkRed(), m_lightGreen(),
73  m_darkGreen(), m_purple(), m_lightGray(), m_gray(), m_darkGray(), m_colormap(nullptr), m_font(nullptr), m_vectgtk(nullptr),
74  m_col(nullptr)
75  { }
76 
77  ~Impl() { }
78 
79  void init(unsigned int win_width, unsigned int win_height, int win_x, int win_y, const std::string &title)
80  {
81  gint width = static_cast<gint>(win_width);
82  gint height = static_cast<gint>(win_height);
83 
84  /* Initialisation of the gdk et gdk_rgb library */
85  int *argc = nullptr;
86  char **argv;
87 
88  gtk_init(argc, &argv);
89 
90  /* Create the window*/
91  m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
92 
93  gtk_widget_add_events(m_widget, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
94 
95  gtk_window_set_default_size(GTK_WINDOW(m_widget), width, height);
96 
97  gtk_window_move(GTK_WINDOW(m_widget), win_x, win_y);
98 
99  gtk_widget_show(m_widget);
100 
101  gdk_rgb_init();
102 
103  /* Create background pixmap */
104  m_background = gdk_pixmap_new(m_widget->window, width, height, -1);
105 
106  /* Create graphic context */
107  m_gc = gdk_gc_new(m_widget->window);
108 
109  /* get the colormap */
110  m_colormap = gdk_window_get_colormap(m_widget->window);
111 
112  m_col = new GdkColor *[vpColor::id_unknown]; // id_unknown = number of predefined colors
113 
114  /* Create color */
115  gdk_color_parse("light blue", &m_lightBlue);
116  gdk_colormap_alloc_color(m_colormap, &m_lightBlue, FALSE, TRUE);
117  m_col[vpColor::id_lightBlue] = &m_lightBlue;
118 
119  gdk_color_parse("blue", &m_blue);
120  gdk_colormap_alloc_color(m_colormap, &m_blue, FALSE, TRUE);
121  m_col[vpColor::id_blue] = &m_blue;
122 
123  gdk_color_parse("dark blue", &m_darkBlue);
124  gdk_colormap_alloc_color(m_colormap, &m_darkBlue, FALSE, TRUE);
125  m_col[vpColor::id_darkBlue] = &m_darkBlue;
126 
127  gdk_color_parse("#FF8C8C", &m_lightRed);
128  gdk_colormap_alloc_color(m_colormap, &m_lightRed, FALSE, TRUE);
129  m_col[vpColor::id_lightRed] = &m_lightRed;
130 
131  gdk_color_parse("red", &m_red);
132  gdk_colormap_alloc_color(m_colormap, &m_red, FALSE, TRUE);
133  m_col[vpColor::id_red] = &m_red;
134 
135  gdk_color_parse("dark red", &m_darkRed);
136  gdk_colormap_alloc_color(m_colormap, &m_darkRed, FALSE, TRUE);
137  m_col[vpColor::id_darkRed] = &m_darkRed;
138 
139  gdk_color_parse("light green", &m_lightGreen);
140  gdk_colormap_alloc_color(m_colormap, &m_lightGreen, FALSE, TRUE);
141  m_col[vpColor::id_lightGreen] = &m_lightGreen;
142 
143  gdk_color_parse("green", &m_green);
144  gdk_colormap_alloc_color(m_colormap, &m_green, FALSE, TRUE);
145  m_col[vpColor::id_green] = &m_green;
146 
147  gdk_color_parse("dark green", &m_darkGreen);
148  gdk_colormap_alloc_color(m_colormap, &m_darkGreen, FALSE, TRUE);
149  m_col[vpColor::id_darkGreen] = &m_darkGreen;
150 
151  gdk_color_parse("yellow", &m_yellow);
152  gdk_colormap_alloc_color(m_colormap, &m_yellow, FALSE, TRUE);
153  m_col[vpColor::id_yellow] = &m_yellow;
154 
155  gdk_color_parse("cyan", &m_cyan);
156  gdk_colormap_alloc_color(m_colormap, &m_cyan, FALSE, TRUE);
157  m_col[vpColor::id_cyan] = &m_cyan;
158 
159  gdk_color_parse("orange", &m_orange);
160  gdk_colormap_alloc_color(m_colormap, &m_orange, FALSE, TRUE);
161  m_col[vpColor::id_orange] = &m_orange;
162 
163  gdk_color_parse("purple", &m_purple);
164  gdk_colormap_alloc_color(m_colormap, &m_purple, FALSE, TRUE);
165  m_col[vpColor::id_purple] = &m_purple;
166 
167  gdk_color_parse("white", &m_white);
168  gdk_colormap_alloc_color(m_colormap, &m_white, FALSE, TRUE);
169  m_col[vpColor::id_white] = &m_white;
170 
171  gdk_color_parse("black", &m_black);
172  gdk_colormap_alloc_color(m_colormap, &m_black, FALSE, TRUE);
173  m_col[vpColor::id_black] = &m_black;
174 
175  gdk_color_parse("#C0C0C0", &m_lightGray);
176  gdk_colormap_alloc_color(m_colormap, &m_lightGray, FALSE, TRUE);
177  m_col[vpColor::id_lightGray] = &m_lightGray;
178 
179  gdk_color_parse("#808080", &m_gray);
180  gdk_colormap_alloc_color(m_colormap, &m_gray, FALSE, TRUE);
181  m_col[vpColor::id_gray] = &m_gray;
182 
183  gdk_color_parse("#404040", &m_darkGray);
184  gdk_colormap_alloc_color(m_colormap, &m_darkGray, FALSE, TRUE);
185  m_col[vpColor::id_darkGray] = &m_darkGray;
186 
187  // Try to load a default font
188  m_font = gdk_font_load("-*-times-medium-r-normal-*-16-*-*-*-*-*-*-*");
189  if (m_font == nullptr)
190  m_font = gdk_font_load("-*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*");
191  if (m_font == nullptr)
192  m_font = gdk_font_load("-*-courier 10 pitch-medium-r-normal-*-16-*-*-*-*-*-*-*");
193 
194  if (!title.empty())
195  gdk_window_set_title(m_widget->window, title.c_str());
196  }
197 
198  void setFont(const std::string &fontname) { m_font = gdk_font_load((const gchar *)fontname.c_str()); }
199 
200  void setTitle(const std::string &title) { gdk_window_set_title(m_widget->window, title.c_str()); }
201 
202  void setWindowPosition(int win_x, int win_y) { gtk_window_move(GTK_WINDOW(m_widget), win_x, win_y); }
203 
204  void displayImage(const vpImage<unsigned char> &I, unsigned int scale, gint width, gint height)
205  {
206  if (scale == 1) {
207  /* Copie de l'image dans le pixmap fond */
208  gdk_draw_gray_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, I.bitmap, width);
209  }
210  else {
211  vpImage<unsigned char> sampled;
212  I.subsample(scale, scale, sampled);
213  gdk_draw_gray_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, sampled.bitmap, width);
214  }
215 
216  /* Le pixmap background devient le fond de la zone de dessin */
217  gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
218  }
219 
220  void displayImage(const vpImage<vpRGBa> &I, unsigned int scale, gint width, gint height)
221  {
222  if (scale == 1) {
223  /* Copie de l'image dans le pixmap fond */
224  gdk_draw_rgb_32_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, (unsigned char *)I.bitmap,
225  4 * width);
226  }
227  else {
228  vpImage<vpRGBa> sampled;
229  I.subsample(scale, scale, sampled);
230  gdk_draw_rgb_32_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE,
231  (unsigned char *)sampled.bitmap, 4 * width);
232  }
233 
234  /* Le pixmap background devient le fond de la zone de dessin */
235  gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
236  }
237 
238  void displayImageROI(const vpImage<unsigned char> &I, gint j_min, gint i_min, gint width, gint height)
239  {
240  gdk_draw_gray_image(m_background, m_gc, j_min, i_min, width, height, GDK_RGB_DITHER_NONE, I.bitmap, width);
241  /* Le pixmap background devient le fond de la zone de dessin */
242  gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
243  }
244 
245  void displayImageROI(const vpImage<vpRGBa> &I, gint j_min, gint i_min, gint width, gint height)
246  {
247  gdk_draw_rgb_32_image(m_background, m_gc, j_min, i_min, width, height, GDK_RGB_DITHER_NONE,
248  (unsigned char *)I.bitmap, width * 4);
249 
250  /* Le pixmap background devient le fond de la zone de dessin */
251  gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
252  }
253 
254  void closeDisplay()
255  {
256  if (m_col != nullptr) {
257  delete[] m_col;
258  m_col = nullptr;
259  }
260 
261  if (m_widget != nullptr) {
262  gdk_window_hide(m_widget->window);
263  gdk_window_destroy(m_widget->window);
264  gtk_widget_destroy(m_widget);
265  m_widget = nullptr;
266  }
267  }
268 
269  void flushDisplay()
270  {
271  gdk_window_clear(m_widget->window);
272  gdk_flush();
273  }
274 
275  void displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color, unsigned int scale)
276  {
277  if (color.id < vpColor::id_unknown)
278  gdk_gc_set_foreground(m_gc, m_col[color.id]);
279  else {
280  m_gdkcolor.red = 256 * color.R;
281  m_gdkcolor.green = 256 * color.G;
282  m_gdkcolor.blue = 256 * color.B;
283  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
284  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
285  }
286  if (m_font != nullptr)
287  gdk_draw_string(m_background, m_font, m_gc, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale),
288  (const gchar *)text.c_str());
289  else
290  std::cout << "Cannot draw string: no font is selected" << std::endl;
291  }
292 
293  void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
294  unsigned int thickness, unsigned int scale)
295  {
296  if (color.id < vpColor::id_unknown)
297  gdk_gc_set_foreground(m_gc, m_col[color.id]);
298  else {
299  m_gdkcolor.red = 256 * color.R;
300  m_gdkcolor.green = 256 * color.G;
301  m_gdkcolor.blue = 256 * color.B;
302  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
303  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
304  }
305 
306  gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
307 
308  if (fill == false)
309  gdk_draw_arc(m_background, m_gc, FALSE, vpMath::round((center.get_u() - radius) / scale),
310  vpMath::round((center.get_v() - radius) / scale), static_cast<gint>(2. * radius / scale),
311  static_cast<gint>(2. * radius / scale), 23040, 23040); /* 23040 = 360*64 */
312  else
313  gdk_draw_arc(m_background, m_gc, TRUE, 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  }
317 
318  void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
319  unsigned int scale)
320  {
321  if (color.id < vpColor::id_unknown)
322  gdk_gc_set_foreground(m_gc, m_col[color.id]);
323  else {
324  m_gdkcolor.red = 256 * color.R;
325  m_gdkcolor.green = 256 * color.G;
326  m_gdkcolor.blue = 256 * color.B;
327  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
328  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
329  }
330 
331  gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
332  gdk_draw_line(m_background, m_gc, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
333  vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
334  gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
335  }
336 
337  void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
338  unsigned int scale)
339  {
340  if (color.id < vpColor::id_unknown)
341  gdk_gc_set_foreground(m_gc, m_col[color.id]);
342  else {
343  m_gdkcolor.red = 256 * color.R;
344  m_gdkcolor.green = 256 * color.G;
345  m_gdkcolor.blue = 256 * color.B;
346  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
347  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
348  }
349 
350  gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
351  gdk_draw_line(m_background, m_gc, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
352  vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
353  }
354 
355  void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness, unsigned int scale)
356  {
357  if (color.id < vpColor::id_unknown)
358  gdk_gc_set_foreground(m_gc, m_col[color.id]);
359  else {
360  m_gdkcolor.red = 256 * color.R;
361  m_gdkcolor.green = 256 * color.G;
362  m_gdkcolor.blue = 256 * color.B;
363  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
364  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
365  }
366 
367  if (thickness == 1) {
368  gdk_draw_point(m_background, m_gc, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale));
369  }
370  else {
371  gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale),
372  static_cast<gint>(thickness), static_cast<gint>(thickness));
373  }
374  }
375 
376  void displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color, bool fill,
377  unsigned int thickness, unsigned int scale)
378  {
379  if (color.id < vpColor::id_unknown)
380  gdk_gc_set_foreground(m_gc, m_col[color.id]);
381  else {
382  m_gdkcolor.red = 256 * color.R;
383  m_gdkcolor.green = 256 * color.G;
384  m_gdkcolor.blue = 256 * color.B;
385  gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
386  gdk_gc_set_foreground(m_gc, &m_gdkcolor);
387  }
388  gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
389 
390  if (fill == false)
391  gdk_draw_rectangle(m_background, m_gc, FALSE, vpMath::round(topLeft.get_u() / scale),
392  vpMath::round(topLeft.get_v() / scale), static_cast<gint>(w / scale),
393  static_cast<gint>(h / scale));
394  else
395  gdk_draw_rectangle(m_background, m_gc, TRUE, 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 
399  if (thickness > 1)
400  gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
401  }
402 
403  bool getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale,
404  const GdkEventType &event_type)
405  {
406  bool ret = false;
407  do {
408  GdkEvent *ev = nullptr;
409  while ((ev = gdk_event_get())) {
410  if (ev->any.window == m_widget->window && ev->type == event_type) {
411  double u = ((GdkEventButton *)ev)->x;
412  double v = ((GdkEventButton *)ev)->y;
413  ip.set_u(u * scale);
414  ip.set_v(v * scale);
415 
416  switch (static_cast<int>(((GdkEventButton *)ev)->button)) {
417  case 1:
418  button = vpMouseButton::button1;
419  break;
420  case 2:
421  button = vpMouseButton::button2;
422  break;
423  case 3:
424  button = vpMouseButton::button3;
425  break;
426  }
427  ret = true;
428  }
429  gdk_event_free(ev);
430  }
431  if (blocking) {
432  flushDisplay();
433  vpTime::wait(100);
434  }
435 
436  } while (ret == false && blocking == true);
437  return ret;
438  }
439 
440  void getImage(vpImage<vpRGBa> &I, gint width, gint height)
441  {
442  GdkImage *ImageGtk;
443  ImageGtk = gdk_image_get(m_background, 0, 0, width, height);
444 
445  I.resize(height, width);
446  guint32 pixel;
447 
448  guchar OctetRouge, OctetVert, OctetBleu, mask;
449  mask = 0x000000FF;
450 
451  for (gint y = 0; y < height; ++y) {
452  for (gint x = 0; x < width; ++x) {
453  pixel = gdk_image_get_pixel(ImageGtk, x, y);
454  OctetBleu = static_cast<guchar>(pixel) & mask;
455  OctetVert = static_cast<guchar>(pixel >> 8) & mask;
456  OctetRouge = static_cast<guchar>(pixel >> 16) & mask;
457  I[y][x].R = OctetRouge;
458  I[y][x].G = OctetVert;
459  I[y][x].B = OctetBleu;
460  I[y][x].A = vpRGBa::alpha_default; // default opacity
461  }
462  }
463  }
464 
465  unsigned int getScreenDepth() { return static_cast<unsigned int>(gdk_window_get_visual(m_widget->window)->depth); }
466 
467  bool getKeyboardEvent(std::string &key, bool blocking)
468  {
469  bool ret = false;
470  int cpt = 0;
471  do {
472  GdkEvent *ev = nullptr;
473  while ((ev = gdk_event_get()) != nullptr) {
474  cpt++;
475 
476  if (ev->any.window == m_widget->window && ev->type == GDK_KEY_PRESS) {
477  key = gdk_keyval_name(ev->key.keyval);
478  ret = true;
479  }
480  gdk_event_free(ev);
481  }
482  if (blocking) {
483  flushDisplay();
484  vpTime::wait(100);
485  }
486  } while (ret == false && blocking == true);
487  return ret;
488  }
489 
490  bool getPointerMotionEvent(vpImagePoint &ip, unsigned int scale)
491  {
492  bool ret = false;
493  GdkEvent *ev = nullptr;
494  if ((ev = gdk_event_get())) {
495  if (ev->any.window == m_widget->window && ev->type == GDK_MOTION_NOTIFY) {
496  double u = ((GdkEventMotion *)ev)->x;
497  double v = ((GdkEventMotion *)ev)->y;
498  ip.set_u(u * scale);
499  ip.set_v(v * scale);
500 
501  ret = true;
502  }
503  gdk_event_free(ev);
504  }
505  return ret;
506  }
507 
508  void getPointerPosition(vpImagePoint &ip, unsigned int scale)
509  {
510  gint u, v;
511  gdk_window_get_pointer(m_widget->window, &u, &v, nullptr);
512  ip.set_u(static_cast<double>(u) * scale);
513  ip.set_v(static_cast<double>(v) * scale);
514  }
515 
516  void getScreenSize(bool is_init, unsigned int &w, unsigned int &h)
517  {
518  if (!is_init) {
519  int *argc = nullptr;
520  char **argv;
521 
522  gtk_init(argc, &argv);
523 
524  GtkWidget *widget_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
525  gtk_window_set_default_size(GTK_WINDOW(widget_), 100, 100);
526  gtk_widget_show(widget_);
527 
528  GdkScreen *screen_ = gdk_window_get_screen(widget_->window);
529  w = static_cast<unsigned int>(gdk_screen_get_width(screen_));
530  h = static_cast<unsigned int>(gdk_screen_get_height(screen_));
531  gtk_widget_destroy(widget_);
532  }
533  else {
534  GdkScreen *screen_ = gdk_window_get_screen(m_widget->window);
535  w = static_cast<unsigned int>(gdk_screen_get_width(screen_));
536  h = static_cast<unsigned int>(gdk_screen_get_height(screen_));
537  }
538  }
539 
540 private:
541  GtkWidget *m_widget;
542  GdkPixmap *m_background;
543  GdkGC *m_gc;
544  GdkColor m_blue, m_red, m_yellow, m_green, m_cyan, m_orange, m_white, m_black, m_gdkcolor;
545  GdkColor m_lightBlue, m_darkBlue, m_lightRed, m_darkRed, m_lightGreen, m_darkGreen, m_purple;
546  GdkColor m_lightGray, m_gray, m_darkGray;
547  GdkColormap *m_colormap;
548 
549  GdkFont *m_font;
550  guchar *m_vectgtk;
551  GdkColor **m_col;
552 };
553 
554 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
555 
578 {
579  setScale(scaleType, I.getWidth(), I.getHeight());
580  init(I);
581 }
582 
606 vpDisplayGTK::vpDisplayGTK(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title,
607  vpScaleType scaleType)
608  : vpDisplay(), m_impl(new Impl())
609 {
610  setScale(scaleType, I.getWidth(), I.getHeight());
611  init(I, win_x, win_y, win_title);
612 }
613 
633 vpDisplayGTK::vpDisplayGTK(vpImage<vpRGBa> &I, vpScaleType scaleType) : vpDisplay(), m_impl(new Impl())
634 {
635  setScale(scaleType, I.getWidth(), I.getHeight());
636  init(I);
637 }
638 
660 vpDisplayGTK::vpDisplayGTK(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title,
661  vpScaleType scaleType)
662  : vpDisplay(), m_impl(new Impl())
663 {
664  setScale(scaleType, I.getWidth(), I.getHeight());
665  init(I, win_x, win_y, win_title);
666 }
667 
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 
724 vpDisplayGTK::vpDisplayGTK() : vpDisplay(), m_impl(new Impl()) { }
725 
730 {
731  closeDisplay();
732  delete m_impl;
733 }
734 
743 void vpDisplayGTK::init(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title)
744 {
745  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
746  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
747  }
748 
749  if (win_x != -1)
750  m_windowXPosition = win_x;
751  if (win_y != -1)
752  m_windowYPosition = win_y;
753 
754  if (!win_title.empty())
755  m_title = win_title;
756 
759 
760  I.display = this;
762 }
763 
773 void vpDisplayGTK::init(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title)
774 {
775  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
776  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
777  }
778 
779  if (win_x != -1)
780  m_windowXPosition = win_x;
781  if (win_y != -1)
782  m_windowYPosition = win_y;
783 
784  if (!win_title.empty())
785  m_title = win_title;
786 
789 
790  I.display = this;
792 }
793 
802 void vpDisplayGTK::init(unsigned int win_width, unsigned int win_height, int win_x, int win_y,
803  const std::string &win_title)
804 {
805  setScale(m_scaleType, win_width, win_height);
806 
807  m_width = win_width / m_scale;
808  m_height = win_height / m_scale;
809 
810  if (win_x != -1)
811  m_windowXPosition = win_x;
812  if (win_y != -1)
813  m_windowYPosition = win_y;
814 
815  m_title = win_title;
816 
818 
820 }
821 
834 void vpDisplayGTK::setFont(const std::string &fontname) { m_impl->setFont(fontname); }
835 
840 void vpDisplayGTK::setTitle(const std::string &title)
841 {
843  m_title = title;
844  if (!title.empty()) {
845  m_impl->setTitle(title);
846  }
847  }
848  else {
849  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
850  }
851 }
852 
862 void vpDisplayGTK::setWindowPosition(int win_x, int win_y)
863 {
865  m_impl->setWindowPosition(win_x, win_y);
866  }
867  else {
868  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
869  }
870 }
871 
884 {
886  m_impl->displayImage(I, m_scale, static_cast<gint>(m_width), static_cast<gint>(m_height));
887  }
888  else {
889  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
890  }
891 }
892 
910 void vpDisplayGTK::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w,
911  unsigned int h)
912 {
915  vpImageTools::crop(I, iP.get_i(), iP.get_j(), h, w, Itemp, m_scale, m_scale);
916 
917  /* Copie de l'image dans le pixmap fond */
918  int i_min = std::max<int>(static_cast<int>(ceil(iP.get_i() / m_scale)), 0);
919  int j_min = std::max<int>(static_cast<int>(ceil(iP.get_j() / m_scale)), 0);
920 
921  m_impl->displayImageROI(Itemp, static_cast<gint>(j_min), static_cast<gint>(i_min),
922  static_cast<gint>(Itemp.getWidth()), static_cast<gint>(Itemp.getHeight()));
923  }
924  else {
925  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
926  }
927 }
928 
941 {
943  m_impl->displayImage(I, m_scale, static_cast<gint>(m_width), static_cast<gint>(m_height));
944  }
945  else {
946  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
947  }
948 }
949 
967 void vpDisplayGTK::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h)
968 {
970  vpImage<vpRGBa> Itemp;
971  vpImageTools::crop(I, iP.get_i(), iP.get_j(), h, w, Itemp, m_scale, m_scale);
972 
973  /* Copie de l'image dans le pixmap fond */
974  int i_min = std::max<int>(static_cast<int>(ceil(iP.get_i() / m_scale)), 0);
975  int j_min = std::max<int>(static_cast<int>(ceil(iP.get_j() / m_scale)), 0);
976 
977  m_impl->displayImageROI(Itemp, static_cast<gint>(j_min), static_cast<gint>(i_min),
978  static_cast<gint>(Itemp.getWidth()), static_cast<gint>(Itemp.getHeight()));
979  }
980  else {
981  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
982  }
983 }
984 
990 void vpDisplayGTK::displayImage(const unsigned char * /* I */)
991 {
992  // not implemented
993 }
994 
1001 {
1003  m_impl->closeDisplay();
1004 
1006  }
1007 }
1008 
1014 {
1016  m_impl->flushDisplay();
1017  }
1018  else {
1019  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1020  }
1021 }
1022 
1027 void vpDisplayGTK::flushDisplayROI(const vpImagePoint & /*iP*/, const unsigned int /*width*/,
1028  const unsigned int /*height*/)
1029 {
1031  m_impl->flushDisplay();
1032  }
1033  else {
1034  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1035  }
1036 }
1037 
1041 void vpDisplayGTK::clearDisplay(const vpColor & /* color */)
1042 {
1043  // Not implemented
1044 }
1045 
1053 void vpDisplayGTK::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
1054  unsigned int h, unsigned int thickness)
1055 {
1057  double a = ip2.get_i() - ip1.get_i();
1058  double b = ip2.get_j() - ip1.get_j();
1059  double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
1060 
1061  if ((std::fabs(a) > std::numeric_limits<double>::epsilon()) &&
1062  (std::fabs(b) > std::numeric_limits<double>::epsilon())) {
1063  a /= lg;
1064  b /= lg;
1065 
1066  vpImagePoint ip3;
1067  ip3.set_i(ip2.get_i() - w * a);
1068  ip3.set_j(ip2.get_j() - w * b);
1069 
1070  vpImagePoint ip4;
1071  ip4.set_i(ip3.get_i() - b * h);
1072  ip4.set_j(ip3.get_j() + a * h);
1073 
1074  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1075  displayLine(ip2, ip4, color, thickness);
1076 
1077  ip4.set_i(ip3.get_i() + b * h);
1078  ip4.set_j(ip3.get_j() - a * h);
1079 
1080  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1081  displayLine(ip2, ip4, color, thickness);
1082 
1083  displayLine(ip1, ip2, color, thickness);
1084  }
1085  }
1086  else {
1087  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1088  }
1089 }
1090 
1102 void vpDisplayGTK::displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color)
1103 {
1105  m_impl->displayText(ip, text, color, m_scale);
1106  }
1107  else {
1108  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1109  }
1110 }
1111 
1121 void vpDisplayGTK::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
1122  unsigned int thickness)
1123 {
1125  if (thickness == 1)
1126  thickness = 0;
1127 
1128  m_impl->displayCircle(center, radius, color, fill, thickness, m_scale);
1129  }
1130  else {
1131  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1132  }
1133 }
1141 void vpDisplayGTK::displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness)
1142 {
1144  double i = ip.get_i();
1145  double j = ip.get_j();
1146  vpImagePoint ip1, ip2;
1147 
1148  ip1.set_i(i - size / 2);
1149  ip1.set_j(j);
1150  ip2.set_i(i + size / 2);
1151  ip2.set_j(j);
1152  displayLine(ip1, ip2, color, thickness);
1153 
1154  ip1.set_i(i);
1155  ip1.set_j(j - size / 2);
1156  ip2.set_i(i);
1157  ip2.set_j(j + size / 2);
1158 
1159  displayLine(ip1, ip2, color, thickness);
1160  }
1161 
1162  else {
1163  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1164  }
1165 }
1172 void vpDisplayGTK::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1173  unsigned int thickness)
1174 {
1175 
1177  if (thickness == 1)
1178  thickness = 0;
1179 
1180  m_impl->displayDotLine(ip1, ip2, color, thickness, m_scale);
1181  }
1182  else {
1183  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1184  }
1185 }
1186 
1193 void vpDisplayGTK::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1194  unsigned int thickness)
1195 {
1197  if (thickness == 1)
1198  thickness = 0;
1199 
1200  m_impl->displayLine(ip1, ip2, color, thickness, m_scale);
1201  }
1202  else {
1203  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1204  }
1205 }
1206 
1213 void vpDisplayGTK::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
1214 {
1216  m_impl->displayPoint(ip, color, thickness, m_scale);
1217  }
1218  else {
1219  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1220  }
1221 }
1222 
1236 void vpDisplayGTK::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
1237  bool fill, unsigned int thickness)
1238 {
1240  if (thickness == 1)
1241  thickness = 0;
1242 
1243  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1244  }
1245  else {
1246  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1247  }
1248 }
1249 
1262 void vpDisplayGTK::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
1263  bool fill, unsigned int thickness)
1264 {
1266  if (thickness == 1)
1267  thickness = 0;
1268 
1269  unsigned int w = static_cast<unsigned int>(vpMath::round(bottomRight.get_u() - topLeft.get_u()));
1270  unsigned int h = static_cast<unsigned int>(vpMath::round(bottomRight.get_v() - topLeft.get_v()));
1271 
1272  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1273  }
1274  else {
1275  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1276  }
1277 }
1278 
1291 void vpDisplayGTK::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
1292 {
1294  if (thickness == 1)
1295  thickness = 0;
1296 
1297  vpImagePoint topLeft = rectangle.getTopLeft();
1298  unsigned int w = static_cast<unsigned int>(vpMath::round(rectangle.getWidth()));
1299  unsigned int h = static_cast<unsigned int>(vpMath::round(rectangle.getRight()));
1300  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1301  }
1302  else {
1303  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1304  }
1305 }
1306 
1322 bool vpDisplayGTK::getClick(bool blocking)
1323 {
1324  bool ret = false;
1325 
1327  vpImagePoint ip;
1329  ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1330  }
1331  else {
1332  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1333  }
1334  return ret;
1335 }
1336 
1353 bool vpDisplayGTK::getClick(vpImagePoint &ip, bool blocking)
1354 {
1355  bool ret = false;
1356 
1359  ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1360  }
1361  else {
1362  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1363  }
1364  return ret;
1365 }
1366 
1387 {
1388  bool ret = false;
1389 
1391  ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1392  }
1393  else {
1394  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1395  }
1396  return ret;
1397 }
1398 
1423 {
1424  bool ret = false;
1425 
1427  ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_RELEASE);
1428  }
1429  else {
1430  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1431  }
1432  return ret;
1433 }
1434 
1435 /*
1436  \brief gets the displayed image (including the overlay plane)
1437  and returns an RGBa image
1438 */
1440 {
1441  // should certainly be optimized.
1443  m_impl->getImage(I, static_cast<gint>(m_width), static_cast<gint>(m_height));
1444  }
1445  else {
1446  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1447  }
1448 }
1449 
1456 {
1457  unsigned int depth = m_impl->getScreenDepth();
1458 
1459  return (depth);
1460 }
1461 
1478 {
1479  bool ret = false;
1480 
1482  std::string key;
1483  ret = m_impl->getKeyboardEvent(key, blocking);
1484  }
1485  else {
1486  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1487  }
1488  return ret;
1489 }
1490 
1510 bool vpDisplayGTK::getKeyboardEvent(std::string &key, bool blocking)
1511 {
1512  bool ret = false;
1513 
1515  ret = m_impl->getKeyboardEvent(key, blocking);
1516  }
1517  else {
1518  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1519  }
1520  return ret;
1521 }
1522 
1536 {
1537  bool ret = false;
1538 
1540  ret = m_impl->getPointerMotionEvent(ip, m_scale);
1541  }
1542  else {
1543  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1544  }
1545  return ret;
1546 }
1547 
1559 {
1561  m_impl->getPointerPosition(ip, m_scale);
1562  }
1563  else {
1564  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1565  }
1566 
1567  return true;
1568 }
1569 
1574 void vpDisplayGTK::getScreenSize(unsigned int &w, unsigned int &h)
1575 {
1576  w = h = 0;
1577 
1578  m_impl->getScreenSize(m_displayHasBeenInitialized, w, h);
1579 }
1580 
1585 {
1586  unsigned int width, height;
1587  getScreenSize(width, height);
1588  return width;
1589 }
1590 
1595 {
1596  unsigned int width, height;
1597  getScreenSize(width, height);
1598  return height;
1599 }
1600 
1601 END_VISP_NAMESPACE
1602 
1603 #elif !defined(VISP_BUILD_SHARED_LIBS)
1604 // Work around to avoid warning: libvisp_gui.a(vpDisplayGTK.cpp.o) has no symbols
1605 void dummy_vpDisplayGTK() { };
1606 #endif
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:157
vpColorIdentifier id
Definition: vpColor.h:206
@ id_lightBlue
Definition: vpColor.h:184
@ id_yellow
Definition: vpColor.h:190
@ id_darkGray
Definition: vpColor.h:170
@ id_green
Definition: vpColor.h:180
@ id_darkRed
Definition: vpColor.h:176
@ id_lightGray
Definition: vpColor.h:166
@ id_red
Definition: vpColor.h:174
@ id_lightRed
Definition: vpColor.h:172
@ id_white
Definition: vpColor.h:164
@ id_black
Definition: vpColor.h:162
@ id_blue
Definition: vpColor.h:186
@ id_darkGreen
Definition: vpColor.h:182
@ id_gray
Definition: vpColor.h:168
@ id_lightGreen
Definition: vpColor.h:178
@ id_purple
Definition: vpColor.h:196
@ id_orange
Definition: vpColor.h:194
@ id_cyan
Definition: vpColor.h:192
@ id_darkBlue
Definition: vpColor.h:188
@ id_unknown
Definition: vpColor.h:199
Error that can be emitted by the vpDisplay class and its derivatives.
@ notInitializedError
Display not initialized.
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1) VP_OVERRIDE
virtual ~vpDisplayGTK() VP_OVERRIDE
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1) VP_OVERRIDE
void getScreenSize(unsigned int &screen_width, unsigned int &screen_height) VP_OVERRIDE
void getImage(vpImage< vpRGBa > &I) VP_OVERRIDE
Get the window pixmap and put it in vpRGBa image.
unsigned int getScreenWidth() VP_OVERRIDE
bool getClick(bool blocking=true) VP_OVERRIDE
unsigned int getScreenHeight() VP_OVERRIDE
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height) VP_OVERRIDE
void setFont(const std::string &fontname) VP_OVERRIDE
void displayImage(const vpImage< vpRGBa > &I) VP_OVERRIDE
void flushDisplay() VP_OVERRIDE
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
void setTitle(const std::string &win_title) 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
bool getPointerMotionEvent(vpImagePoint &ip) VP_OVERRIDE
void setWindowPosition(int win_x, int win_y) VP_OVERRIDE
unsigned int getScreenDepth()
get the window depth (8,16,24,32)
void closeDisplay() VP_OVERRIDE
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="") VP_OVERRIDE
bool getPointerPosition(vpImagePoint &ip) VP_OVERRIDE
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
bool getKeyboardEvent(bool blocking=true) VP_OVERRIDE
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true) VP_OVERRIDE
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) 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 displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color=vpColor::green) VP_OVERRIDE
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height) VP_OVERRIDE
Class that defines generic functionalities for display.
Definition: vpDisplay.h:178
unsigned int m_height
Definition: vpDisplay.h:930
vpScaleType m_scaleType
Definition: vpDisplay.h:933
unsigned int m_width
Definition: vpDisplay.h:929
int m_windowXPosition
display position
Definition: vpDisplay.h:926
std::string m_title
Definition: vpDisplay.h:931
int m_windowYPosition
display position
Definition: vpDisplay.h:928
unsigned int m_scale
Definition: vpDisplay.h:932
bool m_displayHasBeenInitialized
display has been initialized
Definition: vpDisplay.h:924
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Definition: vpDisplay.cpp:262
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:309
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:298
double get_u() const
Definition: vpImagePoint.h:136
void set_u(double u)
Definition: vpImagePoint.h:335
void set_v(double v)
Definition: vpImagePoint.h:346
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:315
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:749
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:538
Type * bitmap
points toward the bitmap
Definition: vpImage.h:135
unsigned int getHeight() const
Definition: vpImage.h:181
vpDisplay * display
Definition: vpImage.h:136
static double sqr(double x)
Definition: vpMath.h:203
static int round(double x)
Definition: vpMath.h:409
unsigned char B
Blue component.
Definition: vpRGBa.h:169
unsigned char R
Red component.
Definition: vpRGBa.h:167
unsigned char G
Green component.
Definition: vpRGBa.h:168
@ alpha_default
Definition: vpRGBa.h:67
Defines a rectangle in the plane.
Definition: vpRect.h:79
double getWidth() const
Definition: vpRect.h:227
vpImagePoint getTopLeft() const
Definition: vpRect.h:199
double getRight() const
Definition: vpRect.h:179
VISP_EXPORT int wait(double t0, double t)