Visual Servoing Platform  version 3.3.0 under development (2020-02-17)
vpDisplayGTK.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 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 http://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  * Eric Marchand
37  * Fabien Spindler
38  *
39  *****************************************************************************/
40 
46 #include <visp3/core/vpConfig.h>
47 
48 #if (defined(VISP_HAVE_GTK))
49 
50 #include <cmath> // std::fabs
51 #include <iostream>
52 #include <limits> // numeric_limits
53 #include <stdio.h>
54 #include <stdlib.h>
55 
56 // Display stuff
57 #include <visp3/core/vpDisplay.h>
58 #include <visp3/gui/vpDisplayGTK.h>
59 
60 // debug / exception
61 #include <visp3/core/vpDebug.h>
62 #include <visp3/core/vpDisplayException.h>
63 #include <visp3/core/vpImageTools.h>
64 #include <visp3/core/vpMath.h>
65 
88  : widget(NULL), m_background(NULL), m_gc(NULL), blue(), red(), yellow(), green(), cyan(), orange(), white(), black(),
89  gdkcolor(), lightBlue(), darkBlue(), lightRed(), darkRed(), lightGreen(), darkGreen(), purple(), lightGray(),
90  gray(), darkGray(), colormap(NULL), font(NULL), vectgtk(NULL), col(NULL), ncol(0), nrow(0)
91 {
92  setScale(scaleType, I.getWidth(), I.getHeight());
93  init(I);
94 }
95 
119 vpDisplayGTK::vpDisplayGTK(vpImage<unsigned char> &I, int x, int y, const std::string &title, vpScaleType scaleType)
120  : widget(NULL), m_background(NULL), m_gc(NULL), blue(), red(), yellow(), green(), cyan(), orange(), white(), black(),
121  gdkcolor(), lightBlue(), darkBlue(), lightRed(), darkRed(), lightGreen(), darkGreen(), purple(), lightGray(),
122  gray(), darkGray(), colormap(NULL), font(NULL), vectgtk(NULL), col(NULL), ncol(0), nrow(0)
123 {
124  setScale(scaleType, I.getWidth(), I.getHeight());
125  init(I, x, y, title);
126 }
127 
148  : widget(NULL), m_background(NULL), m_gc(NULL), blue(), red(), yellow(), green(), cyan(), orange(), white(), black(),
149  gdkcolor(), lightBlue(), darkBlue(), lightRed(), darkRed(), lightGreen(), darkGreen(), purple(), lightGray(),
150  gray(), darkGray(), colormap(NULL), font(NULL), vectgtk(NULL), col(NULL), ncol(0), nrow(0)
151 {
152  setScale(scaleType, I.getWidth(), I.getHeight());
153  init(I);
154 }
155 
177 vpDisplayGTK::vpDisplayGTK(vpImage<vpRGBa> &I, int x, int y, const std::string &title, vpScaleType scaleType)
178  : widget(NULL), m_background(NULL), m_gc(NULL), blue(), red(), yellow(), green(), cyan(), orange(), white(), black(),
179  gdkcolor(), lightBlue(), darkBlue(), lightRed(), darkRed(), lightGreen(), darkGreen(), purple(), lightGray(),
180  gray(), darkGray(), colormap(NULL), font(NULL), vectgtk(NULL), col(NULL), ncol(0), nrow(0)
181 {
182  setScale(scaleType, I.getWidth(), I.getHeight());
183  init(I, x, y, title);
184 }
185 
208 vpDisplayGTK::vpDisplayGTK(int x, int y, const std::string &title)
209  : widget(NULL), m_background(NULL), m_gc(NULL), blue(), red(), yellow(), green(), cyan(), orange(), white(), black(),
210  gdkcolor(), lightBlue(), darkBlue(), lightRed(), darkRed(), lightGreen(), darkGreen(), purple(), lightGray(),
211  gray(), darkGray(), colormap(NULL), font(NULL), vectgtk(NULL), col(NULL), ncol(0), nrow(0)
212 {
213  m_windowXPosition = x;
214  m_windowYPosition = y;
215  m_title = title;
216 }
217 
238  : vpDisplay(), widget(NULL), m_background(NULL), m_gc(NULL), blue(), red(), yellow(), green(), cyan(), orange(),
239  white(), black(), gdkcolor(), lightBlue(), darkBlue(), lightRed(), darkRed(), lightGreen(), darkGreen(), purple(),
240  lightGray(), gray(), darkGray(), colormap(NULL), font(NULL), vectgtk(NULL), col(NULL), ncol(0), nrow(0)
241 
242 {
243 }
244 
249 
258 void vpDisplayGTK::init(vpImage<unsigned char> &I, int x, int y, const std::string &title)
259 {
260  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
261  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
262  }
263 
264  if (x != -1)
265  m_windowXPosition = x;
266  if (y != -1)
267  m_windowYPosition = y;
268 
269  if (!title.empty())
270  m_title = title;
271 
274 
275  I.display = this;
277 }
278 
288 void vpDisplayGTK::init(vpImage<vpRGBa> &I, int x, int y, const std::string &title)
289 {
290  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
291  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
292  }
293 
294  if (x != -1)
295  m_windowXPosition = x;
296  if (y != -1)
297  m_windowYPosition = y;
298 
299  if (!title.empty())
300  m_title = title;
301 
304 
305  I.display = this;
307 }
316 void vpDisplayGTK::init(unsigned int w, unsigned int h, int x, int y, const std::string &title)
317 {
318  /* Initialisation of thegdk et gdk_rgb library */
319  int *argc = NULL;
320  char **argv;
321 
322  gtk_init(argc, &argv);
323 
324  setScale(m_scaleType, w, h);
325 
326  m_width = w / m_scale;
327  m_height = h / m_scale;
328 
329  /* Create the window*/
330  widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
331 
332  gtk_widget_add_events(widget, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
333 
334  gtk_window_set_default_size(GTK_WINDOW(widget), (gint)m_width, (gint)m_height);
335 
336  if (x != -1)
337  m_windowXPosition = x;
338  if (y != -1)
339  m_windowYPosition = y;
340 
341  gtk_window_move(GTK_WINDOW(widget), m_windowXPosition, m_windowYPosition);
342 
343  gtk_widget_show(widget);
344 
345  gdk_rgb_init();
346 
347  /* Create background pixmap */
348  m_background = gdk_pixmap_new(widget->window, (gint)m_width, (gint)m_height, -1);
349 
350  /* Create graphic context */
351  m_gc = gdk_gc_new(widget->window);
352 
353  /* get the colormap */
354  colormap = gdk_window_get_colormap(widget->window);
355 
356  col = new GdkColor *[vpColor::id_unknown]; // id_unknown = number of predefined colors
357 
358  /* Create color */
359  gdk_color_parse("light blue", &lightBlue);
360  gdk_colormap_alloc_color(colormap, &lightBlue, FALSE, TRUE);
361  col[vpColor::id_lightBlue] = &lightBlue;
362 
363  gdk_color_parse("blue", &blue);
364  gdk_colormap_alloc_color(colormap, &blue, FALSE, TRUE);
365  col[vpColor::id_blue] = &blue;
366 
367  gdk_color_parse("dark blue", &darkBlue);
368  gdk_colormap_alloc_color(colormap, &darkBlue, FALSE, TRUE);
369  col[vpColor::id_darkBlue] = &darkBlue;
370 
371  gdk_color_parse("#FF8C8C", &lightRed);
372  gdk_colormap_alloc_color(colormap, &lightRed, FALSE, TRUE);
373  col[vpColor::id_lightRed] = &lightRed;
374 
375  gdk_color_parse("red", &red);
376  gdk_colormap_alloc_color(colormap, &red, FALSE, TRUE);
377  col[vpColor::id_red] = &red;
378 
379  gdk_color_parse("dark red", &darkRed);
380  gdk_colormap_alloc_color(colormap, &darkRed, FALSE, TRUE);
381  col[vpColor::id_darkRed] = &darkRed;
382 
383  gdk_color_parse("light green", &lightGreen);
384  gdk_colormap_alloc_color(colormap, &lightGreen, FALSE, TRUE);
385  col[vpColor::id_lightGreen] = &lightGreen;
386 
387  gdk_color_parse("green", &green);
388  gdk_colormap_alloc_color(colormap, &green, FALSE, TRUE);
389  col[vpColor::id_green] = &green;
390 
391  gdk_color_parse("dark green", &darkGreen);
392  gdk_colormap_alloc_color(colormap, &darkGreen, FALSE, TRUE);
393  col[vpColor::id_darkGreen] = &darkGreen;
394 
395  gdk_color_parse("yellow", &yellow);
396  gdk_colormap_alloc_color(colormap, &yellow, FALSE, TRUE);
397  col[vpColor::id_yellow] = &yellow;
398 
399  gdk_color_parse("cyan", &cyan);
400  gdk_colormap_alloc_color(colormap, &cyan, FALSE, TRUE);
401  col[vpColor::id_cyan] = &cyan;
402 
403  gdk_color_parse("orange", &orange);
404  gdk_colormap_alloc_color(colormap, &orange, FALSE, TRUE);
405  col[vpColor::id_orange] = &orange;
406 
407  gdk_color_parse("purple", &purple);
408  gdk_colormap_alloc_color(colormap, &purple, FALSE, TRUE);
409  col[vpColor::id_purple] = &purple;
410 
411  gdk_color_parse("white", &white);
412  gdk_colormap_alloc_color(colormap, &white, FALSE, TRUE);
413  col[vpColor::id_white] = &white;
414 
415  gdk_color_parse("black", &black);
416  gdk_colormap_alloc_color(colormap, &black, FALSE, TRUE);
417  col[vpColor::id_black] = &black;
418 
419  gdk_color_parse("#C0C0C0", &lightGray);
420  gdk_colormap_alloc_color(colormap, &lightGray, FALSE, TRUE);
421  col[vpColor::id_lightGray] = &lightGray;
422 
423  gdk_color_parse("#808080", &gray);
424  gdk_colormap_alloc_color(colormap, &gray, FALSE, TRUE);
425  col[vpColor::id_gray] = &gray;
426 
427  gdk_color_parse("#404040", &darkGray);
428  gdk_colormap_alloc_color(colormap, &darkGray, FALSE, TRUE);
429  col[vpColor::id_darkGray] = &darkGray;
430 
431  // Try to load a default font
432  font = gdk_font_load("-*-times-medium-r-normal-*-16-*-*-*-*-*-*-*");
433  if (font == NULL)
434  font = gdk_font_load("-*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*");
435  if (font == NULL)
436  font = gdk_font_load("-*-courier 10 pitch-medium-r-normal-*-16-*-*-*-*-*-*-*");
437 
438  m_title = title;
439  if (!title.empty())
440  gdk_window_set_title(widget->window, m_title.c_str());
441 
443 }
444 
459 void vpDisplayGTK::setFont(const std::string &fontname) { font = gdk_font_load((const gchar *)fontname.c_str()); }
460 
465 void vpDisplayGTK::setTitle(const std::string &title)
466 {
468  m_title = title;
469  if (!title.empty())
470  gdk_window_set_title(widget->window, m_title.c_str());
471  } else {
472  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
473  }
474 }
475 
485 void vpDisplayGTK::setWindowPosition(int winx, int winy)
486 {
487 
489  gtk_window_move(GTK_WINDOW(widget), winx, winy);
490  } else {
491  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
492  }
493 }
494 
507 {
508 
510  if (m_scale == 1) {
511  /* Copie de l'image dans le pixmap fond */
512  gdk_draw_gray_image(m_background, m_gc, 0, 0, (gint)m_width, (gint)m_height, GDK_RGB_DITHER_NONE, I.bitmap,
513  (gint)m_width);
514  } else {
515  vpImage<unsigned char> sampled;
516  I.subsample(m_scale, m_scale, sampled);
517  gdk_draw_gray_image(m_background, m_gc, 0, 0, (gint)m_width, (gint)m_height, GDK_RGB_DITHER_NONE, sampled.bitmap,
518  (gint)m_width);
519  }
520 
521  /* Le pixmap background devient le fond de la zone de dessin */
522  gdk_window_set_back_pixmap(widget->window, m_background, FALSE);
523  } else {
524  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
525  }
526 }
527 
545 void vpDisplayGTK::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w,
546  unsigned int h)
547 {
550  vpImageTools::crop(I, iP.get_i(), iP.get_j(), h, w, Itemp, m_scale, m_scale);
551 
552  /* Copie de l'image dans le pixmap fond */
553  int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
554  int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
555 
556  gdk_draw_gray_image(m_background, m_gc, (gint)j_min, (gint)i_min, (gint)Itemp.getWidth(), (gint)Itemp.getHeight(),
557  GDK_RGB_DITHER_NONE, Itemp.bitmap, (gint)Itemp.getWidth());
558 
559  /* Le pixmap background devient le fond de la zone de dessin */
560  gdk_window_set_back_pixmap(widget->window, m_background, FALSE);
561  } else {
562  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
563  }
564 }
565 
578 {
579 
581  if (m_scale == 1) {
582  /* Copie de l'image dans le pixmap fond */
583  gdk_draw_rgb_32_image(m_background, m_gc, 0, 0, (gint)m_width, (gint)m_height, GDK_RGB_DITHER_NONE,
584  (unsigned char *)I.bitmap, (gint)(4 * m_width));
585  } else {
586  vpImage<vpRGBa> sampled;
587  I.subsample(m_scale, m_scale, sampled);
588  gdk_draw_rgb_32_image(m_background, m_gc, 0, 0, (gint)m_width, (gint)m_height, GDK_RGB_DITHER_NONE,
589  (unsigned char *)sampled.bitmap, (gint)(4 * m_width));
590  }
591  /* Permet de fermer la fenetre si besoin (cas des sequences d'images) */
592  // while (g_main_iteration(FALSE));
593 
594  /* Le pixmap background devient le fond de la zone de dessin */
595  gdk_window_set_back_pixmap(widget->window, m_background, FALSE);
596  } else {
597  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
598  }
599 }
600 
618 void vpDisplayGTK::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w,
619  unsigned int h)
620 {
622  vpImage<vpRGBa> Itemp;
623  vpImageTools::crop(I, iP.get_i(), iP.get_j(), h, w, Itemp, m_scale, m_scale);
624 
625  /* Copie de l'image dans le pixmap fond */
626  int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
627  int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
628 
629  gdk_draw_rgb_32_image(m_background, m_gc, (gint)j_min, (gint)i_min, (gint)Itemp.getWidth(), (gint)Itemp.getHeight(),
630  GDK_RGB_DITHER_NONE, (unsigned char *)Itemp.bitmap, (gint)Itemp.getWidth() * 4);
631 
632  /* Le pixmap background devient le fond de la zone de dessin */
633  gdk_window_set_back_pixmap(widget->window, m_background, FALSE);
634  } else {
635  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
636  }
637 }
638 
644 void vpDisplayGTK::displayImage(const unsigned char * /* I */) { vpTRACE(" not implemented "); }
645 
652 {
653  if (col != NULL) {
654  delete[] col;
655  col = NULL;
656  }
657 
658  if (widget != NULL) {
659  gdk_window_hide(widget->window);
660  gdk_window_destroy(widget->window);
661  gtk_widget_destroy(widget);
662  widget = NULL;
663  }
665 }
666 
672 {
674  gdk_window_clear(widget->window);
675  gdk_flush();
676  } else {
677  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
678  }
679 }
680 
685 void vpDisplayGTK::flushDisplayROI(const vpImagePoint & /*iP*/, const unsigned int /*width*/,
686  const unsigned int /*height*/)
687 {
689  gdk_window_clear(widget->window);
690  gdk_flush();
691  } else {
692  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
693  }
694 }
695 
699 void vpDisplayGTK::clearDisplay(const vpColor & /* color */) { vpTRACE("Not implemented"); }
700 
708 void vpDisplayGTK::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
709  unsigned int h, unsigned int thickness)
710 {
712  double a = ip2.get_i() - ip1.get_i();
713  double b = ip2.get_j() - ip1.get_j();
714  double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
715 
716  // if ((a==0)&&(b==0))
717  if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
718  (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
719  // DisplayCrossLarge(i1,j1,3,col) ;
720  } else {
721  a /= lg;
722  b /= lg;
723 
724  vpImagePoint ip3;
725  ip3.set_i(ip2.get_i() - w * a);
726  ip3.set_j(ip2.get_j() - w * b);
727 
728  vpImagePoint ip4;
729  ip4.set_i(ip3.get_i() - b * h);
730  ip4.set_j(ip3.get_j() + a * h);
731 
732  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
733  displayLine(ip2, ip4, color, thickness);
734 
735  ip4.set_i(ip3.get_i() + b * h);
736  ip4.set_j(ip3.get_j() - a * h);
737 
738  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
739  displayLine(ip2, ip4, color, thickness);
740 
741  displayLine(ip1, ip2, color, thickness);
742  }
743  } else {
744  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
745  }
746 }
747 
759 void vpDisplayGTK::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
760 {
762  if (color.id < vpColor::id_unknown)
763  gdk_gc_set_foreground(m_gc, col[color.id]);
764  else {
765  gdkcolor.red = 256 * color.R;
766  gdkcolor.green = 256 * color.G;
767  gdkcolor.blue = 256 * color.B;
768  gdk_colormap_alloc_color(colormap, &gdkcolor, FALSE, TRUE);
769  gdk_gc_set_foreground(m_gc, &gdkcolor);
770  }
771  if (font != NULL)
772  gdk_draw_string(m_background, font, m_gc, vpMath::round(ip.get_u() / m_scale),
773  vpMath::round(ip.get_v() / m_scale), (const gchar *)text);
774  else
775  std::cout << "Cannot draw string: no font is selected" << std::endl;
776  } else {
777  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
778  }
779 }
789 void vpDisplayGTK::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
790  unsigned int thickness)
791 {
793  if (thickness == 1)
794  thickness = 0;
795 
796  if (color.id < vpColor::id_unknown)
797  gdk_gc_set_foreground(m_gc, col[color.id]);
798  else {
799  gdkcolor.red = 256 * color.R;
800  gdkcolor.green = 256 * color.G;
801  gdkcolor.blue = 256 * color.B;
802  gdk_colormap_alloc_color(colormap, &gdkcolor, FALSE, TRUE);
803  gdk_gc_set_foreground(m_gc, &gdkcolor);
804  }
805 
806  gdk_gc_set_line_attributes(m_gc, (gint)thickness, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
807 
808  if (fill == false)
809  gdk_draw_arc(m_background, m_gc, FALSE, vpMath::round((center.get_u() - radius) / m_scale),
810  vpMath::round((center.get_v() - radius) / m_scale), (gint)(2. * radius / m_scale),
811  (gint)(2. * radius / m_scale), 23040, 23040); /* 23040 = 360*64 */
812  else
813  gdk_draw_arc(m_background, m_gc, TRUE, vpMath::round((center.get_u() - radius) / m_scale),
814  vpMath::round((center.get_v() - radius) / m_scale), (gint)(2. * radius / m_scale),
815  (gint)(2. * radius / m_scale), 23040, 23040); /* 23040 = 360*64 */
816  } else {
817  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
818  }
819 }
827 void vpDisplayGTK::displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness)
828 {
830  double i = ip.get_i();
831  double j = ip.get_j();
832  vpImagePoint ip1, ip2;
833 
834  ip1.set_i(i - size / 2);
835  ip1.set_j(j);
836  ip2.set_i(i + size / 2);
837  ip2.set_j(j);
838  displayLine(ip1, ip2, color, thickness);
839 
840  ip1.set_i(i);
841  ip1.set_j(j - size / 2);
842  ip2.set_i(i);
843  ip2.set_j(j + size / 2);
844 
845  displayLine(ip1, ip2, color, thickness);
846  }
847 
848  else {
849  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
850  }
851 }
858 void vpDisplayGTK::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
859  unsigned int thickness)
860 {
861 
863  if (thickness == 1)
864  thickness = 0;
865 
866  if (color.id < vpColor::id_unknown)
867  gdk_gc_set_foreground(m_gc, col[color.id]);
868  else {
869  gdkcolor.red = 256 * color.R;
870  gdkcolor.green = 256 * color.G;
871  gdkcolor.blue = 256 * color.B;
872  gdk_colormap_alloc_color(colormap, &gdkcolor, FALSE, TRUE);
873  gdk_gc_set_foreground(m_gc, &gdkcolor);
874  }
875 
876  gdk_gc_set_line_attributes(m_gc, (gint)thickness, GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
877  gdk_draw_line(m_background, m_gc, vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale),
879  gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
880  } else {
881  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
882  }
883 }
884 
891 void vpDisplayGTK::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
892  unsigned int thickness)
893 {
895  if (thickness == 1)
896  thickness = 0;
897 
898  if (color.id < vpColor::id_unknown)
899  gdk_gc_set_foreground(m_gc, col[color.id]);
900  else {
901  gdkcolor.red = 256 * color.R;
902  gdkcolor.green = 256 * color.G;
903  gdkcolor.blue = 256 * color.B;
904  gdk_colormap_alloc_color(colormap, &gdkcolor, FALSE, TRUE);
905  gdk_gc_set_foreground(m_gc, &gdkcolor);
906  }
907 
908  gdk_gc_set_line_attributes(m_gc, (gint)thickness, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
909  gdk_draw_line(m_background, m_gc, vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale),
911  } else {
912  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
913  }
914 }
915 
922 void vpDisplayGTK::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
923 {
925  if (color.id < vpColor::id_unknown)
926  gdk_gc_set_foreground(m_gc, col[color.id]);
927  else {
928  gdkcolor.red = 256 * color.R;
929  gdkcolor.green = 256 * color.G;
930  gdkcolor.blue = 256 * color.B;
931  gdk_colormap_alloc_color(colormap, &gdkcolor, FALSE, TRUE);
932  gdk_gc_set_foreground(m_gc, &gdkcolor);
933  }
934 
935  if (thickness == 1) {
936  gdk_draw_point(m_background, m_gc, vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale));
937  } else {
938  gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(ip.get_u() / m_scale),
939  vpMath::round(ip.get_v() / m_scale), thickness, thickness);
940  }
941  } else {
942  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
943  }
944 }
945 
959 void vpDisplayGTK::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
960  bool fill, unsigned int thickness)
961 {
963  if (thickness == 1)
964  thickness = 0;
965 
966  if (color.id < vpColor::id_unknown)
967  gdk_gc_set_foreground(m_gc, col[color.id]);
968  else {
969  gdkcolor.red = 256 * color.R;
970  gdkcolor.green = 256 * color.G;
971  gdkcolor.blue = 256 * color.B;
972  gdk_colormap_alloc_color(colormap, &gdkcolor, FALSE, TRUE);
973  gdk_gc_set_foreground(m_gc, &gdkcolor);
974  }
975  gdk_gc_set_line_attributes(m_gc, (gint)thickness, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
976 
977  if (fill == false)
978  gdk_draw_rectangle(m_background, m_gc, FALSE, vpMath::round(topLeft.get_u() / m_scale),
979  vpMath::round(topLeft.get_v() / m_scale), (gint)w / m_scale, (gint)h / m_scale);
980  else
981  gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(topLeft.get_u() / m_scale),
982  vpMath::round(topLeft.get_v() / m_scale), (gint)w / m_scale, (gint)h / m_scale);
983 
984  if (thickness > 1)
985  gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
986  } else {
987  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
988  }
989 }
990 
1003 void vpDisplayGTK::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
1004  bool fill, unsigned int thickness)
1005 {
1007  if (thickness == 1)
1008  thickness = 0;
1009 
1010  if (color.id < vpColor::id_unknown)
1011  gdk_gc_set_foreground(m_gc, col[color.id]);
1012  else {
1013  gdkcolor.red = 256 * color.R;
1014  gdkcolor.green = 256 * color.G;
1015  gdkcolor.blue = 256 * color.B;
1016  gdk_colormap_alloc_color(colormap, &gdkcolor, FALSE, TRUE);
1017  gdk_gc_set_foreground(m_gc, &gdkcolor);
1018  }
1019 
1020  gdk_gc_set_line_attributes(m_gc, (gint)thickness, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
1021 
1022  int w = vpMath::round(bottomRight.get_u() - topLeft.get_u());
1023  int h = vpMath::round(bottomRight.get_v() - topLeft.get_v());
1024 
1025  if (fill == false)
1026  gdk_draw_rectangle(m_background, m_gc, FALSE, vpMath::round(topLeft.get_u() / m_scale),
1027  vpMath::round(topLeft.get_v() / m_scale), w / m_scale, h / m_scale);
1028  else
1029  gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(topLeft.get_u() / m_scale),
1030  vpMath::round(topLeft.get_v() / m_scale), w / m_scale, h / m_scale);
1031 
1032  if (thickness > 1)
1033  gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
1034  } else {
1035  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1036  }
1037 }
1038 
1051 void vpDisplayGTK::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
1052 {
1054  if (color.id < vpColor::id_unknown)
1055  gdk_gc_set_foreground(m_gc, col[color.id]);
1056  else {
1057  gdkcolor.red = 256 * color.R;
1058  gdkcolor.green = 256 * color.G;
1059  gdkcolor.blue = 256 * color.B;
1060  gdk_colormap_alloc_color(colormap, &gdkcolor, FALSE, TRUE);
1061  gdk_gc_set_foreground(m_gc, &gdkcolor);
1062  }
1063 
1064  if (thickness == 1)
1065  thickness = 0;
1066 
1067  gdk_gc_set_line_attributes(m_gc, (gint)thickness, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
1068 
1069  if (fill == false)
1070  gdk_draw_rectangle(m_background, m_gc, FALSE, vpMath::round(rectangle.getLeft() / m_scale),
1071  vpMath::round(rectangle.getTop() / m_scale), vpMath::round(rectangle.getWidth() / m_scale),
1072  vpMath::round(rectangle.getHeight() / m_scale));
1073 
1074  else
1075  gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(rectangle.getLeft() / m_scale),
1076  vpMath::round(rectangle.getTop() / m_scale), vpMath::round(rectangle.getWidth() / m_scale),
1077  vpMath::round(rectangle.getHeight() / m_scale));
1078 
1079  if (thickness > 1)
1080  gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
1081  } else {
1082  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1083  }
1084 }
1085 
1101 bool vpDisplayGTK::getClick(bool blocking)
1102 {
1103  bool ret = false;
1104 
1106 
1107  // flushDisplay() ;
1108  // int cpt =0;
1109  do {
1110  GdkEvent *ev = NULL;
1111  while ((ev = gdk_event_get()) != NULL) {
1112  // cpt++;
1113  // printf("event %d type %d on window %p My window %p\n",
1114  // cpt, ev->type, ev->any.window, widget->window);
1115 
1116  if (ev->any.window == widget->window && ev->type == GDK_BUTTON_PRESS) {
1117  ret = true;
1118  // printf("Click detection\n");
1119  }
1120  gdk_event_free(ev);
1121  }
1122  if (blocking) {
1123  flushDisplay();
1124  vpTime::wait(100);
1125  }
1126  } while (ret == false && blocking == true);
1127  } else {
1128  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1129  }
1130  return ret;
1131 }
1132 
1149 bool vpDisplayGTK::getClick(vpImagePoint &ip, bool blocking)
1150 {
1151  bool ret = false;
1152 
1154 
1155  double u, v;
1156  do {
1157  GdkEvent *ev = NULL;
1158  while ((ev = gdk_event_get()) != NULL) {
1159  if (ev->any.window == widget->window && ev->type == GDK_BUTTON_PRESS) {
1160  u = ((GdkEventButton *)ev)->x;
1161  v = ((GdkEventButton *)ev)->y;
1162  ip.set_u(u * m_scale);
1163  ip.set_v(v * m_scale);
1164  ret = true;
1165  }
1166  gdk_event_free(ev);
1167  }
1168  if (blocking) {
1169  flushDisplay();
1170  vpTime::wait(100);
1171  }
1172  } while (ret == false && blocking == true);
1173  } else {
1174  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1175  }
1176  return ret;
1177 }
1178 
1199 {
1200  bool ret = false;
1201 
1203  double u, v;
1204  do {
1205  GdkEvent *ev = NULL;
1206  while ((ev = gdk_event_get())) {
1207  if (ev->any.window == widget->window && ev->type == GDK_BUTTON_PRESS) {
1208  u = ((GdkEventButton *)ev)->x;
1209  v = ((GdkEventButton *)ev)->y;
1210  ip.set_u(u * m_scale);
1211  ip.set_v(v * m_scale);
1212 
1213  switch ((int)((GdkEventButton *)ev)->button) {
1214  case 1:
1215  button = vpMouseButton::button1;
1216  break;
1217  case 2:
1218  button = vpMouseButton::button2;
1219  break;
1220  case 3:
1221  button = vpMouseButton::button3;
1222  break;
1223  }
1224  ret = true;
1225  }
1226  gdk_event_free(ev);
1227  }
1228  if (blocking) {
1229  flushDisplay();
1230  vpTime::wait(100);
1231  }
1232 
1233  } while (ret == false && blocking == true);
1234  } else {
1235  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1236  }
1237  return ret;
1238 }
1239 
1264 {
1265  bool ret = false;
1266 
1268 
1269  // flushDisplay() ;
1270  double u, v;
1271  do {
1272  GdkEvent *ev = NULL;
1273  while ((ev = gdk_event_get()) != NULL) {
1274  if (ev->any.window == widget->window && ev->type == GDK_BUTTON_RELEASE) {
1275  u = ((GdkEventButton *)ev)->x;
1276  v = ((GdkEventButton *)ev)->y;
1277  ip.set_u(u * m_scale);
1278  ip.set_v(v * m_scale);
1279 
1280  switch ((int)((GdkEventButton *)ev)->button) {
1281  case 1:
1282  button = vpMouseButton::button1;
1283  break;
1284  case 2:
1285  button = vpMouseButton::button2;
1286  break;
1287  case 3:
1288  button = vpMouseButton::button3;
1289  break;
1290  }
1291  ret = true;
1292  }
1293  gdk_event_free(ev);
1294  }
1295  if (blocking) {
1296  flushDisplay();
1297  vpTime::wait(100);
1298  }
1299 
1300  } while (ret == false && blocking == true);
1301  } else {
1302  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1303  }
1304  return ret;
1305 }
1306 
1307 /*
1308  \brief gets the displayed image (including the overlay plane)
1309  and returns an RGBa image
1310 */
1312 {
1313  // should certainly be optimized.
1315 
1316  GdkImage *ImageGtk;
1317  /*
1318  */
1319 
1320  ImageGtk = gdk_image_get(m_background, 0, 0, (gint)m_width, (gint)m_height);
1321 
1322  I.resize(m_height, m_width);
1323  guint32 pixel;
1324  gint x, y;
1325  guchar OctetRouge, OctetVert, OctetBleu, mask;
1326  mask = 0x000000FF;
1327 
1328  for (y = 0; y < (gint)m_height; y++) {
1329  for (x = 0; x < (gint)m_width; x++) {
1330  pixel = gdk_image_get_pixel(ImageGtk, x, y);
1331  OctetBleu = (guchar)pixel & mask;
1332  OctetVert = (guchar)(pixel >> 8) & mask;
1333  OctetRouge = (guchar)(pixel >> 16) & mask;
1334  I[y][x].R = OctetRouge;
1335  I[y][x].G = OctetVert;
1336  I[y][x].B = OctetBleu;
1337  I[y][x].A = vpRGBa::alpha_default; // default opacity
1338  }
1339  }
1340  } else {
1341  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1342  }
1343 }
1344 
1351 {
1352 
1353  unsigned int depth;
1354 
1355  depth = (unsigned int)gdk_window_get_visual(widget->window)->depth;
1356 
1357  return (depth);
1358 }
1359 
1376 {
1377  bool ret = false;
1378 
1380 
1381  int cpt = 0;
1382  do {
1383  GdkEvent *ev = NULL;
1384  while ((ev = gdk_event_get()) != NULL) {
1385  cpt++;
1386  // printf("event %d type %d on window %p My window %p\n",
1387  // cpt, ev->type, ev->any.window, widget->window);
1388 
1389  if (ev->any.window == widget->window && ev->type == GDK_KEY_PRESS) {
1390  ret = true;
1391  // printf("Key press detection\n");
1392  }
1393  gdk_event_free(ev);
1394  }
1395  if (blocking) {
1396  flushDisplay();
1397  vpTime::wait(100);
1398  }
1399  } while (ret == false && blocking == true);
1400  } else {
1401  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1402  }
1403  return ret;
1404 }
1405 
1425 bool vpDisplayGTK::getKeyboardEvent(std::string &key, bool blocking)
1426 {
1427  bool ret = false;
1428 
1430 
1431  int cpt = 0;
1432  do {
1433  GdkEvent *ev = NULL;
1434  while ((ev = gdk_event_get()) != NULL) {
1435  cpt++;
1436  // printf("event %d type %d on window %p My window %p\n",
1437  // cpt, ev->type, ev->any.window, widget->window);
1438 
1439  if (ev->any.window == widget->window && ev->type == GDK_KEY_PRESS) {
1440  // std::cout << "Key val: \"" << gdk_keyval_name (ev->key.keyval)
1441  // /*ev->key.string*/ << "\"" << std::endl;
1442  key = gdk_keyval_name(ev->key.keyval);
1443  ret = true;
1444  // printf("Key press detection\n");
1445  }
1446  gdk_event_free(ev);
1447  }
1448  if (blocking) {
1449  flushDisplay();
1450  vpTime::wait(100);
1451  }
1452  } while (ret == false && blocking == true);
1453  } else {
1454  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1455  }
1456  return ret;
1457 }
1458 
1472 {
1473  bool ret = false;
1474 
1476  GdkEvent *ev = NULL;
1477  if ((ev = gdk_event_get())) {
1478  if (ev->any.window == widget->window && ev->type == GDK_MOTION_NOTIFY) {
1479  double u = ((GdkEventMotion *)ev)->x;
1480  double v = ((GdkEventMotion *)ev)->y;
1481  ip.set_u(u * m_scale);
1482  ip.set_v(v * m_scale);
1483 
1484  ret = true;
1485  }
1486  gdk_event_free(ev);
1487  }
1488  } else {
1489  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1490  }
1491  return ret;
1492 }
1493 
1505 {
1507  int u, v;
1508  gdk_window_get_pointer(widget->window, &u, &v, NULL);
1509  ip.set_u(u * m_scale);
1510  ip.set_v(v * m_scale);
1511  } else {
1512  throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1513  }
1514 
1515  return true;
1516 }
1517 
1522 void vpDisplayGTK::getScreenSize(unsigned int &w, unsigned int &h)
1523 {
1524  w = h = 0;
1525 
1527  int *argc = NULL;
1528  char **argv;
1529 
1530  gtk_init(argc, &argv);
1531 
1532  GtkWidget *widget_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1533  gtk_window_set_default_size(GTK_WINDOW(widget_), 100, 100);
1534  gtk_widget_show(widget_);
1535 
1536  GdkScreen *screen_ = gdk_window_get_screen(widget_->window);
1537  w = (unsigned int)gdk_screen_get_width(screen_);
1538  h = (unsigned int)gdk_screen_get_height(screen_);
1539  gtk_widget_destroy(widget_);
1540  } else {
1541  GdkScreen *screen_ = gdk_window_get_screen(widget->window);
1542  w = (unsigned int)gdk_screen_get_width(screen_);
1543  h = (unsigned int)gdk_screen_get_height(screen_);
1544  }
1545 }
1546 
1551 {
1552  unsigned int width, height;
1553  getScreenSize(width, height);
1554  return width;
1555 }
1556 
1561 {
1562  unsigned int width, height;
1563  getScreenSize(width, height);
1564  return height;
1565 }
1566 
1567 #elif !defined(VISP_BUILD_SHARED_LIBS)
1568 // Work arround to avoid warning: libvisp_core.a(vpDisplayGTK.cpp.o) has no
1569 // symbols
1570 void dummy_vpDisplayGTK(){};
1571 #endif
unsigned int m_height
Definition: vpDisplay.h:210
vpDisplay * display
Definition: vpImage.h:142
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
double get_i() const
Definition: vpImagePoint.h:204
double getTop() const
Definition: vpRect.h:192
VISP_EXPORT int wait(double t0, double t)
Definition: vpTime.cpp:173
int m_windowYPosition
display position
Definition: vpDisplay.h:208
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:171
bool getClick(bool blocking=true)
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:879
unsigned char B
Blue component.
Definition: vpRGBa.h:150
Type * bitmap
points toward the bitmap
Definition: vpImage.h:141
void set_u(double u)
Definition: vpImagePoint.h:226
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:1299
Class to define colors available for display functionnalities.
Definition: vpColor.h:119
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height)
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true)
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
unsigned char G
Green component.
Definition: vpRGBa.h:149
bool m_displayHasBeenInitialized
display has been initialized
Definition: vpDisplay.h:204
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
vpColorIdentifier id
Definition: vpColor.h:168
double get_u() const
Definition: vpImagePoint.h:263
int m_windowXPosition
display position
Definition: vpDisplay.h:206
void flushDisplay()
double getWidth() const
Definition: vpRect.h:227
void set_i(double ii)
Definition: vpImagePoint.h:167
unsigned int m_scale
Definition: vpDisplay.h:212
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Definition: vpDisplay.cpp:259
#define vpTRACE
Definition: vpDebug.h:416
static double sqr(double x)
Definition: vpMath.h:114
virtual ~vpDisplayGTK()
double get_j() const
Definition: vpImagePoint.h:215
bool getPointerPosition(vpImagePoint &ip)
vpScaleType m_scaleType
Definition: vpDisplay.h:213
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
std::string m_title
Definition: vpDisplay.h:211
void displayImage(const vpImage< vpRGBa > &I)
unsigned int getScreenWidth()
bool getPointerMotionEvent(vpImagePoint &ip)
double getLeft() const
Definition: vpRect.h:173
void getScreenSize(unsigned int &width, unsigned int &height)
void setTitle(const std::string &title)
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
void getImage(vpImage< vpRGBa > &I)
get the window pixmap and put it in vpRGBa image
void closeDisplay()
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)
static int round(double x)
Definition: vpMath.h:241
void set_j(double jj)
Definition: vpImagePoint.h:178
void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)
Error that can be emited by the vpDisplay class and its derivates.
void set_v(double v)
Definition: vpImagePoint.h:237
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
unsigned int getHeight() const
Definition: vpImage.h:186
void setFont(const std::string &fontname)
unsigned int m_width
Definition: vpDisplay.h:209
void setWindowPosition(int winx, int winy)
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:296
unsigned char R
Red component.
Definition: vpRGBa.h:148
unsigned int getScreenDepth()
get the window depth (8,16,24,32)
double getHeight() const
Definition: vpRect.h:166
Defines a rectangle in the plane.
Definition: vpRect.h:78
unsigned int getScreenHeight()
void clearDisplay(const vpColor &color=vpColor::white)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
bool getKeyboardEvent(bool blocking=true)
unsigned int getWidth() const
Definition: vpImage.h:244
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height)
double get_v() const
Definition: vpImagePoint.h:274
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
Definition: vpImagePoint.h:285