Visual Servoing Platform version 3.5.0
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/vpImageConvert.h>
64#include <visp3/core/vpImageTools.h>
65#include <visp3/core/vpMath.h>
66
67#ifndef DOXYGEN_SHOULD_SKIP_THIS
68
69#include <gtk/gtk.h>
70#include <gdk/gdk.h>
71#include <gdk/gdkrgb.h>
72
73class vpDisplayGTK::Impl
74{
75public:
76 Impl()
77 : m_widget(NULL), m_background(NULL), m_gc(NULL), m_blue(), m_red(), m_yellow(), m_green(), m_cyan(), m_orange(),
78 m_white(), m_black(), m_gdkcolor(), m_lightBlue(), m_darkBlue(), m_lightRed(), m_darkRed(), m_lightGreen(), m_darkGreen(),
79 m_purple(), m_lightGray(), m_gray(), m_darkGray(), m_colormap(NULL), m_font(NULL), m_vectgtk(NULL), m_col(NULL)
80 {
81
82 }
83
84 ~Impl() {}
85
86 void init(unsigned int win_width, unsigned int win_height, int win_x, int win_y, const std::string &title)
87 {
88 gint width = static_cast<gint>(win_width);
89 gint height = static_cast<gint>(win_height);
90
91 /* Initialisation of the gdk et gdk_rgb library */
92 int *argc = NULL;
93 char **argv;
94
95 gtk_init(argc, &argv);
96
97 /* Create the window*/
98 m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
99
100 gtk_widget_add_events(m_widget, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
101
102 gtk_window_set_default_size(GTK_WINDOW(m_widget), width, height);
103
104 gtk_window_move(GTK_WINDOW(m_widget), win_x, win_y);
105
106 gtk_widget_show(m_widget);
107
108 gdk_rgb_init();
109
110 /* Create background pixmap */
111 m_background = gdk_pixmap_new(m_widget->window, width, height, -1);
112
113 /* Create graphic context */
114 m_gc = gdk_gc_new(m_widget->window);
115
116 /* get the colormap */
117 m_colormap = gdk_window_get_colormap(m_widget->window);
118
119 m_col = new GdkColor *[vpColor::id_unknown]; // id_unknown = number of predefined colors
120
121 /* Create color */
122 gdk_color_parse("light blue", &m_lightBlue);
123 gdk_colormap_alloc_color(m_colormap, &m_lightBlue, FALSE, TRUE);
124 m_col[vpColor::id_lightBlue] = &m_lightBlue;
125
126 gdk_color_parse("blue", &m_blue);
127 gdk_colormap_alloc_color(m_colormap, &m_blue, FALSE, TRUE);
128 m_col[vpColor::id_blue] = &m_blue;
129
130 gdk_color_parse("dark blue", &m_darkBlue);
131 gdk_colormap_alloc_color(m_colormap, &m_darkBlue, FALSE, TRUE);
132 m_col[vpColor::id_darkBlue] = &m_darkBlue;
133
134 gdk_color_parse("#FF8C8C", &m_lightRed);
135 gdk_colormap_alloc_color(m_colormap, &m_lightRed, FALSE, TRUE);
136 m_col[vpColor::id_lightRed] = &m_lightRed;
137
138 gdk_color_parse("red", &m_red);
139 gdk_colormap_alloc_color(m_colormap, &m_red, FALSE, TRUE);
140 m_col[vpColor::id_red] = &m_red;
141
142 gdk_color_parse("dark red", &m_darkRed);
143 gdk_colormap_alloc_color(m_colormap, &m_darkRed, FALSE, TRUE);
144 m_col[vpColor::id_darkRed] = &m_darkRed;
145
146 gdk_color_parse("light green", &m_lightGreen);
147 gdk_colormap_alloc_color(m_colormap, &m_lightGreen, FALSE, TRUE);
148 m_col[vpColor::id_lightGreen] = &m_lightGreen;
149
150 gdk_color_parse("green", &m_green);
151 gdk_colormap_alloc_color(m_colormap, &m_green, FALSE, TRUE);
152 m_col[vpColor::id_green] = &m_green;
153
154 gdk_color_parse("dark green", &m_darkGreen);
155 gdk_colormap_alloc_color(m_colormap, &m_darkGreen, FALSE, TRUE);
156 m_col[vpColor::id_darkGreen] = &m_darkGreen;
157
158 gdk_color_parse("yellow", &m_yellow);
159 gdk_colormap_alloc_color(m_colormap, &m_yellow, FALSE, TRUE);
160 m_col[vpColor::id_yellow] = &m_yellow;
161
162 gdk_color_parse("cyan", &m_cyan);
163 gdk_colormap_alloc_color(m_colormap, &m_cyan, FALSE, TRUE);
164 m_col[vpColor::id_cyan] = &m_cyan;
165
166 gdk_color_parse("orange", &m_orange);
167 gdk_colormap_alloc_color(m_colormap, &m_orange, FALSE, TRUE);
168 m_col[vpColor::id_orange] = &m_orange;
169
170 gdk_color_parse("purple", &m_purple);
171 gdk_colormap_alloc_color(m_colormap, &m_purple, FALSE, TRUE);
172 m_col[vpColor::id_purple] = &m_purple;
173
174 gdk_color_parse("white", &m_white);
175 gdk_colormap_alloc_color(m_colormap, &m_white, FALSE, TRUE);
176 m_col[vpColor::id_white] = &m_white;
177
178 gdk_color_parse("black", &m_black);
179 gdk_colormap_alloc_color(m_colormap, &m_black, FALSE, TRUE);
180 m_col[vpColor::id_black] = &m_black;
181
182 gdk_color_parse("#C0C0C0", &m_lightGray);
183 gdk_colormap_alloc_color(m_colormap, &m_lightGray, FALSE, TRUE);
184 m_col[vpColor::id_lightGray] = &m_lightGray;
185
186 gdk_color_parse("#808080", &m_gray);
187 gdk_colormap_alloc_color(m_colormap, &m_gray, FALSE, TRUE);
188 m_col[vpColor::id_gray] = &m_gray;
189
190 gdk_color_parse("#404040", &m_darkGray);
191 gdk_colormap_alloc_color(m_colormap, &m_darkGray, FALSE, TRUE);
192 m_col[vpColor::id_darkGray] = &m_darkGray;
193
194 // Try to load a default font
195 m_font = gdk_font_load("-*-times-medium-r-normal-*-16-*-*-*-*-*-*-*");
196 if (m_font == NULL)
197 m_font = gdk_font_load("-*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*");
198 if (m_font == NULL)
199 m_font = gdk_font_load("-*-courier 10 pitch-medium-r-normal-*-16-*-*-*-*-*-*-*");
200
201 if (!title.empty())
202 gdk_window_set_title(m_widget->window, title.c_str());
203 }
204
205 void setFont(const std::string &fontname)
206 {
207 m_font = gdk_font_load((const gchar *)fontname.c_str());
208 }
209
210 void setTitle(const std::string &title)
211 {
212 gdk_window_set_title(m_widget->window, title.c_str());
213 }
214
215 void setWindowPosition(int win_x, int win_y)
216 {
217 gtk_window_move(GTK_WINDOW(m_widget), win_x, win_y);
218 }
219
220 void displayImage(const vpImage<unsigned char> &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_gray_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, I.bitmap, width);
225 } else {
227 I.subsample(scale, scale, sampled);
228 gdk_draw_gray_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, sampled.bitmap, width);
229 }
230
231 /* Le pixmap background devient le fond de la zone de dessin */
232 gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
233 }
234
235 void displayImage(const vpImage<vpRGBa> &I, unsigned int scale, gint width, gint height)
236 {
237 if (scale == 1) {
238 /* Copie de l'image dans le pixmap fond */
239 gdk_draw_rgb_32_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, (unsigned char *)I.bitmap, 4 * width);
240 } else {
241 vpImage<vpRGBa> sampled;
242 I.subsample(scale, scale, sampled);
243 gdk_draw_rgb_32_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, (unsigned char *)sampled.bitmap, 4 * width);
244 }
245
246 /* Le pixmap background devient le fond de la zone de dessin */
247 gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
248 }
249
250 void displayImageROI(const vpImage<unsigned char> &I, gint j_min, gint i_min, gint width, gint height)
251 {
252 gdk_draw_gray_image(m_background, m_gc, j_min, i_min,
253 width, height, GDK_RGB_DITHER_NONE, I.bitmap, width);
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 displayImageROI(const vpImage<vpRGBa> &I, gint j_min, gint i_min, gint width, gint height)
259 {
260 gdk_draw_rgb_32_image(m_background, m_gc, j_min, i_min, width, height, GDK_RGB_DITHER_NONE,
261 (unsigned char *)I.bitmap, width * 4);
262
263 /* Le pixmap background devient le fond de la zone de dessin */
264 gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
265 }
266
267 void closeDisplay()
268 {
269 if (m_col != NULL) {
270 delete[] m_col;
271 m_col = NULL;
272 }
273
274 if (m_widget != NULL) {
275 gdk_window_hide(m_widget->window);
276 gdk_window_destroy(m_widget->window);
277 gtk_widget_destroy(m_widget);
278 m_widget = NULL;
279 }
280 }
281
282 void flushDisplay()
283 {
284 gdk_window_clear(m_widget->window);
285 gdk_flush();
286 }
287
288 void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color, unsigned int scale)
289 {
290 if (color.id < vpColor::id_unknown)
291 gdk_gc_set_foreground(m_gc, m_col[color.id]);
292 else {
293 m_gdkcolor.red = 256 * color.R;
294 m_gdkcolor.green = 256 * color.G;
295 m_gdkcolor.blue = 256 * color.B;
296 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
297 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
298 }
299 if (m_font != NULL)
300 gdk_draw_string(m_background, m_font, m_gc, vpMath::round(ip.get_u() / scale),
301 vpMath::round(ip.get_v() / scale), (const gchar *)text);
302 else
303 std::cout << "Cannot draw string: no font is selected" << std::endl;
304 }
305
306 void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
307 unsigned int thickness, unsigned int scale)
308 {
309 if (color.id < vpColor::id_unknown)
310 gdk_gc_set_foreground(m_gc, m_col[color.id]);
311 else {
312 m_gdkcolor.red = 256 * color.R;
313 m_gdkcolor.green = 256 * color.G;
314 m_gdkcolor.blue = 256 * color.B;
315 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
316 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
317 }
318
319 gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
320
321 if (fill == false)
322 gdk_draw_arc(m_background, m_gc, FALSE, vpMath::round((center.get_u() - radius) / scale),
323 vpMath::round((center.get_v() - radius) / scale), static_cast<gint>(2. * radius / scale),
324 static_cast<gint>(2. * radius / scale), 23040, 23040); /* 23040 = 360*64 */
325 else
326 gdk_draw_arc(m_background, m_gc, TRUE, vpMath::round((center.get_u() - radius) / scale),
327 vpMath::round((center.get_v() - radius) / scale), static_cast<gint>(2. * radius / scale),
328 static_cast<gint>(2. * radius / scale), 23040, 23040); /* 23040 = 360*64 */
329 }
330
331 void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness, unsigned int scale)
332 {
333 if (color.id < vpColor::id_unknown)
334 gdk_gc_set_foreground(m_gc, m_col[color.id]);
335 else {
336 m_gdkcolor.red = 256 * color.R;
337 m_gdkcolor.green = 256 * color.G;
338 m_gdkcolor.blue = 256 * color.B;
339 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
340 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
341 }
342
343 gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
344 gdk_draw_line(m_background, m_gc, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
345 vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
346 gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
347 }
348
349 void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness, unsigned int scale)
350 {
351 if (color.id < vpColor::id_unknown)
352 gdk_gc_set_foreground(m_gc, m_col[color.id]);
353 else {
354 m_gdkcolor.red = 256 * color.R;
355 m_gdkcolor.green = 256 * color.G;
356 m_gdkcolor.blue = 256 * color.B;
357 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
358 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
359 }
360
361 gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
362 gdk_draw_line(m_background, m_gc, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
363 vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
364 }
365
366 void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness, unsigned int scale)
367 {
368 if (color.id < vpColor::id_unknown)
369 gdk_gc_set_foreground(m_gc, m_col[color.id]);
370 else {
371 m_gdkcolor.red = 256 * color.R;
372 m_gdkcolor.green = 256 * color.G;
373 m_gdkcolor.blue = 256 * color.B;
374 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
375 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
376 }
377
378 if (thickness == 1) {
379 gdk_draw_point(m_background, m_gc, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale));
380 } else {
381 gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(ip.get_u() / scale),
382 vpMath::round(ip.get_v() / scale), static_cast<gint>(thickness), static_cast<gint>(thickness));
383 }
384 }
385
386 void displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
387 bool fill, unsigned int thickness, unsigned int scale)
388 {
389 if (color.id < vpColor::id_unknown)
390 gdk_gc_set_foreground(m_gc, m_col[color.id]);
391 else {
392 m_gdkcolor.red = 256 * color.R;
393 m_gdkcolor.green = 256 * color.G;
394 m_gdkcolor.blue = 256 * color.B;
395 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
396 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
397 }
398 gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
399
400 if (fill == false)
401 gdk_draw_rectangle(m_background, m_gc, FALSE, vpMath::round(topLeft.get_u() / scale),
402 vpMath::round(topLeft.get_v() / scale), static_cast<gint>(w / scale), static_cast<gint>(h / scale));
403 else
404 gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(topLeft.get_u() / scale),
405 vpMath::round(topLeft.get_v() / scale), static_cast<gint>(w / scale), static_cast<gint>(h / scale));
406
407 if (thickness > 1)
408 gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
409 }
410
411 bool getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale, const GdkEventType &event_type)
412 {
413 bool ret = false;
414 do {
415 GdkEvent *ev = NULL;
416 while ((ev = gdk_event_get())) {
417 if (ev->any.window == m_widget->window && ev->type == event_type) {
418 double u = ((GdkEventButton *)ev)->x;
419 double v = ((GdkEventButton *)ev)->y;
420 ip.set_u(u * scale);
421 ip.set_v(v * scale);
422
423 switch (static_cast<int>(((GdkEventButton *)ev)->button)) {
424 case 1:
425 button = vpMouseButton::button1;
426 break;
427 case 2:
428 button = vpMouseButton::button2;
429 break;
430 case 3:
431 button = vpMouseButton::button3;
432 break;
433 }
434 ret = true;
435 }
436 gdk_event_free(ev);
437 }
438 if (blocking) {
439 flushDisplay();
440 vpTime::wait(100);
441 }
442
443 } while (ret == false && blocking == true);
444 return ret;
445 }
446
447 void getImage(vpImage<vpRGBa> &I, gint width, gint height)
448 {
449 GdkImage *ImageGtk;
450 ImageGtk = gdk_image_get(m_background, 0, 0, width, height);
451
452 I.resize(height, width);
453 guint32 pixel;
454
455 guchar OctetRouge, OctetVert, OctetBleu, mask;
456 mask = 0x000000FF;
457
458 for (gint y = 0; y < height; y++) {
459 for (gint x = 0; x < width; x++) {
460 pixel = gdk_image_get_pixel(ImageGtk, x, y);
461 OctetBleu = static_cast<guchar>(pixel) & mask;
462 OctetVert = static_cast<guchar>(pixel >> 8) & mask;
463 OctetRouge = static_cast<guchar>(pixel >> 16) & mask;
464 I[y][x].R = OctetRouge;
465 I[y][x].G = OctetVert;
466 I[y][x].B = OctetBleu;
467 I[y][x].A = vpRGBa::alpha_default; // default opacity
468 }
469 }
470 }
471
472 unsigned int getScreenDepth()
473 {
474 return static_cast<unsigned int>(gdk_window_get_visual(m_widget->window)->depth);
475 }
476
477 bool getKeyboardEvent(std::string &key, bool blocking)
478 {
479 bool ret = false;
480 int cpt = 0;
481 do {
482 GdkEvent *ev = NULL;
483 while ((ev = gdk_event_get()) != NULL) {
484 cpt++;
485 // printf("event %d type %d on window %p My window %p\n",
486 // cpt, ev->type, ev->any.window, widget->window);
487
488 if (ev->any.window == m_widget->window && ev->type == GDK_KEY_PRESS) {
489 // std::cout << "Key val: \"" << gdk_keyval_name (ev->key.keyval)
490 // /*ev->key.string*/ << "\"" << std::endl;
491 key = gdk_keyval_name(ev->key.keyval);
492 ret = true;
493 // printf("Key press detection\n");
494 }
495 gdk_event_free(ev);
496 }
497 if (blocking) {
498 flushDisplay();
499 vpTime::wait(100);
500 }
501 } while (ret == false && blocking == true);
502 return ret;
503 }
504
505 bool getPointerMotionEvent(vpImagePoint &ip, unsigned int scale)
506 {
507 bool ret = false;
508 GdkEvent *ev = NULL;
509 if ((ev = gdk_event_get())) {
510 if (ev->any.window == m_widget->window && ev->type == GDK_MOTION_NOTIFY) {
511 double u = ((GdkEventMotion *)ev)->x;
512 double v = ((GdkEventMotion *)ev)->y;
513 ip.set_u(u * scale);
514 ip.set_v(v * scale);
515
516 ret = true;
517 }
518 gdk_event_free(ev);
519 }
520 return ret;
521 }
522
523 void getPointerPosition(vpImagePoint &ip, unsigned int scale)
524 {
525 gint u, v;
526 gdk_window_get_pointer(m_widget->window, &u, &v, NULL);
527 ip.set_u(static_cast<double>(u) * scale);
528 ip.set_v(static_cast<double>(v) * scale);
529 }
530
531 void getScreenSize(bool is_init, unsigned int &w, unsigned int &h)
532 {
533 if (!is_init) {
534 int *argc = NULL;
535 char **argv;
536
537 gtk_init(argc, &argv);
538
539 GtkWidget *widget_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
540 gtk_window_set_default_size(GTK_WINDOW(widget_), 100, 100);
541 gtk_widget_show(widget_);
542
543 GdkScreen *screen_ = gdk_window_get_screen(widget_->window);
544 w = static_cast<unsigned int>(gdk_screen_get_width(screen_));
545 h = static_cast<unsigned int>(gdk_screen_get_height(screen_));
546 gtk_widget_destroy(widget_);
547 } else {
548 GdkScreen *screen_ = gdk_window_get_screen(m_widget->window);
549 w = static_cast<unsigned int>(gdk_screen_get_width(screen_));
550 h = static_cast<unsigned int>(gdk_screen_get_height(screen_));
551 }
552 }
553
554private:
555 GtkWidget *m_widget;
556 GdkPixmap *m_background;
557 GdkGC *m_gc;
558 GdkColor m_blue, m_red, m_yellow, m_green, m_cyan, m_orange, m_white, m_black, m_gdkcolor;
559 GdkColor m_lightBlue, m_darkBlue, m_lightRed, m_darkRed, m_lightGreen, m_darkGreen, m_purple;
560 GdkColor m_lightGray, m_gray, m_darkGray;
561 GdkColormap *m_colormap;
562
563 GdkFont *m_font;
564 guchar *m_vectgtk;
565 GdkColor **m_col;
566};
567
568#endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
569
592 : vpDisplay(), m_impl(new Impl())
593{
594 setScale(scaleType, I.getWidth(), I.getHeight());
595 init(I);
596}
597
621vpDisplayGTK::vpDisplayGTK(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title, vpScaleType scaleType)
622 : vpDisplay(), m_impl(new Impl())
623{
624 setScale(scaleType, I.getWidth(), I.getHeight());
625 init(I, win_x, win_y, win_title);
626}
627
648 : vpDisplay(), m_impl(new Impl())
649{
650 setScale(scaleType, I.getWidth(), I.getHeight());
651 init(I);
652}
653
675vpDisplayGTK::vpDisplayGTK(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title, vpScaleType scaleType)
676 : vpDisplay(), m_impl(new Impl())
677{
678 setScale(scaleType, I.getWidth(), I.getHeight());
679 init(I, win_x, win_y, win_title);
680}
681
704vpDisplayGTK::vpDisplayGTK(int win_x, int win_y, const std::string &win_title)
705 : vpDisplay(), m_impl(new Impl())
706{
707 m_windowXPosition = win_x;
708 m_windowYPosition = win_y;
709 m_title = win_title;
710}
711
732 : vpDisplay(), m_impl(new Impl())
733{
734}
735
740{
741 closeDisplay();
742 delete m_impl;
743}
744
753void vpDisplayGTK::init(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title)
754{
755 if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
756 throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
757 }
758
759 if (win_x != -1)
760 m_windowXPosition = win_x;
761 if (win_y != -1)
762 m_windowYPosition = win_y;
763
764 if (!win_title.empty())
765 m_title = win_title;
766
769
770 I.display = this;
772}
773
783void vpDisplayGTK::init(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title)
784{
785 if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
786 throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
787 }
788
789 if (win_x != -1)
790 m_windowXPosition = win_x;
791 if (win_y != -1)
792 m_windowYPosition = win_y;
793
794 if (!win_title.empty())
795 m_title = win_title;
796
799
800 I.display = this;
802}
803
812void vpDisplayGTK::init(unsigned int win_width, unsigned int win_height, int win_x, int win_y, const std::string &win_title)
813{
814 setScale(m_scaleType, win_width, win_height);
815
816 m_width = win_width / m_scale;
817 m_height = win_height / m_scale;
818
819 if (win_x != -1)
820 m_windowXPosition = win_x;
821 if (win_y != -1)
822 m_windowYPosition = win_y;
823
824 m_title = win_title;
825
827
829}
830
843void vpDisplayGTK::setFont(const std::string &fontname)
844{
845 m_impl->setFont(fontname);
846}
847
852void vpDisplayGTK::setTitle(const std::string &title)
853{
855 m_title = title;
856 if (!title.empty()) {
857 m_impl->setTitle(title);
858 }
859 } else {
860 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
861 }
862}
863
873void vpDisplayGTK::setWindowPosition(int win_x, int win_y)
874{
876 m_impl->setWindowPosition(win_x, win_y);
877 } else {
878 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
879 }
880}
881
894{
896 m_impl->displayImage(I, m_scale, static_cast<gint>(m_width), static_cast<gint>(m_height));
897 } else {
898 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
899 }
900}
901
920 unsigned int h)
921{
924 vpImageTools::crop(I, iP.get_i(), iP.get_j(), h, w, Itemp, m_scale, m_scale);
925
926 /* Copie de l'image dans le pixmap fond */
927 int i_min = (std::max)(static_cast<int>(ceil(iP.get_i() / m_scale)), 0);
928 int j_min = (std::max)(static_cast<int>(ceil(iP.get_j() / m_scale)), 0);
929
930 m_impl->displayImageROI(Itemp, static_cast<gint>(j_min), static_cast<gint>(i_min),
931 static_cast<gint>(Itemp.getWidth()), static_cast<gint>(Itemp.getHeight()));
932 } else {
933 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
934 }
935}
936
949{
951 m_impl->displayImage(I, m_scale, static_cast<gint>(m_width), static_cast<gint>(m_height));
952 } else {
953 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
954 }
955}
956
974void vpDisplayGTK::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w,
975 unsigned int h)
976{
978 vpImage<vpRGBa> Itemp;
979 vpImageTools::crop(I, iP.get_i(), iP.get_j(), h, w, Itemp, m_scale, m_scale);
980
981 /* Copie de l'image dans le pixmap fond */
982 int i_min = (std::max)(static_cast<int>(ceil(iP.get_i() / m_scale)), 0);
983 int j_min = (std::max)(static_cast<int>(ceil(iP.get_j() / m_scale)), 0);
984
985 m_impl->displayImageROI(Itemp, static_cast<gint>(j_min), static_cast<gint>(i_min),
986 static_cast<gint>(Itemp.getWidth()), static_cast<gint>(Itemp.getHeight()));
987 } else {
988 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
989 }
990}
991
997void vpDisplayGTK::displayImage(const unsigned char * /* I */) { vpTRACE(" not implemented "); }
998
1005{
1007 m_impl->closeDisplay();
1008
1010 }
1011}
1012
1018{
1020 m_impl->flushDisplay();
1021 } else {
1022 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1023 }
1024}
1025
1030void vpDisplayGTK::flushDisplayROI(const vpImagePoint & /*iP*/, const unsigned int /*width*/,
1031 const unsigned int /*height*/)
1032{
1034 m_impl->flushDisplay();
1035 } else {
1036 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1037 }
1038}
1039
1043void vpDisplayGTK::clearDisplay(const vpColor & /* color */) { vpTRACE("Not implemented"); }
1044
1052void vpDisplayGTK::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
1053 unsigned int h, unsigned int thickness)
1054{
1056 double a = ip2.get_i() - ip1.get_i();
1057 double b = ip2.get_j() - ip1.get_j();
1058 double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
1059
1060 if ((std::fabs(a) > std::numeric_limits<double>::epsilon()) &&
1061 (std::fabs(b) > std::numeric_limits<double>::epsilon())) {
1062 a /= lg;
1063 b /= lg;
1064
1065 vpImagePoint ip3;
1066 ip3.set_i(ip2.get_i() - w * a);
1067 ip3.set_j(ip2.get_j() - w * b);
1068
1069 vpImagePoint ip4;
1070 ip4.set_i(ip3.get_i() - b * h);
1071 ip4.set_j(ip3.get_j() + a * h);
1072
1073 if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1074 displayLine(ip2, ip4, color, thickness);
1075
1076 ip4.set_i(ip3.get_i() + b * h);
1077 ip4.set_j(ip3.get_j() - a * h);
1078
1079 if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1080 displayLine(ip2, ip4, color, thickness);
1081
1082 displayLine(ip1, ip2, color, thickness);
1083 }
1084 } else {
1085 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1086 }
1087}
1088
1100void vpDisplayGTK::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
1101{
1103 m_impl->displayCharString(ip, text, color, m_scale);
1104 } else {
1105 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1106 }
1107}
1117void vpDisplayGTK::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
1118 unsigned int thickness)
1119{
1121 if (thickness == 1)
1122 thickness = 0;
1123
1124 m_impl->displayCircle(center, radius, color, fill, thickness, m_scale);
1125 } else {
1126 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1127 }
1128}
1136void vpDisplayGTK::displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness)
1137{
1139 double i = ip.get_i();
1140 double j = ip.get_j();
1141 vpImagePoint ip1, ip2;
1142
1143 ip1.set_i(i - size / 2);
1144 ip1.set_j(j);
1145 ip2.set_i(i + size / 2);
1146 ip2.set_j(j);
1147 displayLine(ip1, ip2, color, thickness);
1148
1149 ip1.set_i(i);
1150 ip1.set_j(j - size / 2);
1151 ip2.set_i(i);
1152 ip2.set_j(j + size / 2);
1153
1154 displayLine(ip1, ip2, color, thickness);
1155 }
1156
1157 else {
1158 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1159 }
1160}
1167void vpDisplayGTK::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1168 unsigned int thickness)
1169{
1170
1172 if (thickness == 1)
1173 thickness = 0;
1174
1175 m_impl->displayDotLine(ip1, ip2, color, thickness, m_scale);
1176 } else {
1177 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1178 }
1179}
1180
1187void vpDisplayGTK::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1188 unsigned int thickness)
1189{
1191 if (thickness == 1)
1192 thickness = 0;
1193
1194 m_impl->displayLine(ip1, ip2, color, thickness, m_scale);
1195 } else {
1196 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1197 }
1198}
1199
1206void vpDisplayGTK::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
1207{
1209 m_impl->displayPoint(ip, color, thickness, m_scale);
1210 } else {
1211 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1212 }
1213}
1214
1228void vpDisplayGTK::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
1229 bool fill, unsigned int thickness)
1230{
1232 if (thickness == 1)
1233 thickness = 0;
1234
1235 m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1236 } else {
1237 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1238 }
1239}
1240
1253void vpDisplayGTK::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
1254 bool fill, unsigned int thickness)
1255{
1257 if (thickness == 1)
1258 thickness = 0;
1259
1260 unsigned int w = static_cast<unsigned int>(vpMath::round(bottomRight.get_u() - topLeft.get_u()));
1261 unsigned int h = static_cast<unsigned int>(vpMath::round(bottomRight.get_v() - topLeft.get_v()));
1262
1263 m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1264 } else {
1265 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1266 }
1267}
1268
1281void 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 } else {
1292 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1293 }
1294}
1295
1311bool vpDisplayGTK::getClick(bool blocking)
1312{
1313 bool ret = false;
1314
1316 vpImagePoint ip;
1318 ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1319 } else {
1320 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1321 }
1322 return ret;
1323}
1324
1341bool vpDisplayGTK::getClick(vpImagePoint &ip, bool blocking)
1342{
1343 bool ret = false;
1344
1347 ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1348 } else {
1349 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1350 }
1351 return ret;
1352}
1353
1374{
1375 bool ret = false;
1376
1378 ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1379 } else {
1380 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1381 }
1382 return ret;
1383}
1384
1409{
1410 bool ret = false;
1411
1413 ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_RELEASE);
1414 } else {
1415 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1416 }
1417 return ret;
1418}
1419
1420/*
1421 \brief gets the displayed image (including the overlay plane)
1422 and returns an RGBa image
1423*/
1425{
1426 // should certainly be optimized.
1428 m_impl->getImage(I, static_cast<gint>(m_width), static_cast<gint>(m_height));
1429 } else {
1430 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1431 }
1432}
1433
1440{
1441 unsigned int depth = m_impl->getScreenDepth();
1442
1443 return (depth);
1444}
1445
1462{
1463 bool ret = false;
1464
1466 std::string key;
1467 ret = m_impl->getKeyboardEvent(key, blocking);
1468 } else {
1469 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1470 }
1471 return ret;
1472}
1473
1493bool vpDisplayGTK::getKeyboardEvent(std::string &key, bool blocking)
1494{
1495 bool ret = false;
1496
1498 ret = m_impl->getKeyboardEvent(key, blocking);
1499 } else {
1500 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1501 }
1502 return ret;
1503}
1504
1518{
1519 bool ret = false;
1520
1522 ret = m_impl->getPointerMotionEvent(ip, m_scale);
1523 } else {
1524 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1525 }
1526 return ret;
1527}
1528
1540{
1542 m_impl->getPointerPosition(ip, m_scale);
1543 } else {
1544 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1545 }
1546
1547 return true;
1548}
1549
1554void vpDisplayGTK::getScreenSize(unsigned int &w, unsigned int &h)
1555{
1556 w = h = 0;
1557
1558 m_impl->getScreenSize(m_displayHasBeenInitialized, w, h);
1559}
1560
1565{
1566 unsigned int width, height;
1567 getScreenSize(width, height);
1568 return width;
1569}
1570
1575{
1576 unsigned int width, height;
1577 getScreenSize(width, height);
1578 return height;
1579}
1580
1581#elif !defined(VISP_BUILD_SHARED_LIBS)
1582// Work arround to avoid warning: libvisp_core.a(vpDisplayGTK.cpp.o) has no
1583// symbols
1584void dummy_vpDisplayGTK(){};
1585#endif
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:158
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 emited by the vpDisplay class and its derivates.
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
void setFont(const std::string &fontname)
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="")
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height)
virtual ~vpDisplayGTK()
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height)
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
bool getClick(bool blocking=true)
bool getKeyboardEvent(bool blocking=true)
bool getPointerMotionEvent(vpImagePoint &ip)
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)
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true)
void getScreenSize(unsigned int &screen_width, unsigned int &screen_height)
void getImage(vpImage< vpRGBa > &I)
get the window pixmap and put it in vpRGBa image
void clearDisplay(const vpColor &color=vpColor::white)
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
unsigned int getScreenDepth()
get the window depth (8,16,24,32)
unsigned int getScreenWidth()
void setTitle(const std::string &win_title)
bool getPointerPosition(vpImagePoint &ip)
unsigned int getScreenHeight()
void setWindowPosition(int win_x, int win_y)
void displayImage(const vpImage< vpRGBa > &I)
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)
void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:178
unsigned int m_height
Definition: vpDisplay.h:216
vpScaleType m_scaleType
Definition: vpDisplay.h:219
unsigned int m_width
Definition: vpDisplay.h:215
int m_windowXPosition
display position
Definition: vpDisplay.h:212
std::string m_title
Definition: vpDisplay.h:217
int m_windowYPosition
display position
Definition: vpDisplay.h:214
unsigned int m_scale
Definition: vpDisplay.h:218
bool m_displayHasBeenInitialized
display has been initialized
Definition: vpDisplay.h:210
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Definition: vpDisplay.cpp:259
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
void set_j(double jj)
Definition: vpImagePoint.h:177
double get_j() const
Definition: vpImagePoint.h:214
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
void set_i(double ii)
Definition: vpImagePoint.h:166
double get_u() const
Definition: vpImagePoint.h:262
void set_u(double u)
Definition: vpImagePoint.h:225
void set_v(double v)
Definition: vpImagePoint.h:236
double get_i() const
Definition: vpImagePoint.h:203
double get_v() const
Definition: vpImagePoint.h:273
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:305
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:1220
unsigned int getWidth() const
Definition: vpImage.h:246
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:800
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
unsigned int getHeight() const
Definition: vpImage.h:188
vpDisplay * display
Definition: vpImage.h:144
static double sqr(double x)
Definition: vpMath.h:116
static int round(double x)
Definition: vpMath.h:247
unsigned char B
Blue component.
Definition: vpRGBa.h:150
unsigned char R
Red component.
Definition: vpRGBa.h:148
unsigned char G
Green component.
Definition: vpRGBa.h:149
@ alpha_default
Definition: vpRGBa.h:69
Defines a rectangle in the plane.
Definition: vpRect.h:80
double getWidth() const
Definition: vpRect.h:228
vpImagePoint getTopLeft() const
Definition: vpRect.h:200
double getRight() const
Definition: vpRect.h:180
#define vpTRACE
Definition: vpDebug.h:416
VISP_EXPORT int wait(double t0, double t)