Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
vpDisplayGTK.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See https://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * Image display.
33 *
34 * Authors:
35 * Christophe Collewet
36 *
37*****************************************************************************/
38
44#include <visp3/core/vpConfig.h>
45
46#if (defined(VISP_HAVE_GTK))
47
48#include <cmath> // std::fabs
49#include <iostream>
50#include <limits> // numeric_limits
51#include <stdio.h>
52#include <stdlib.h>
53
54// Display stuff
55#include <visp3/core/vpDisplay.h>
56#include <visp3/gui/vpDisplayGTK.h>
57
58// debug / exception
59#include <visp3/core/vpDebug.h>
60#include <visp3/core/vpDisplayException.h>
61#include <visp3/core/vpImageConvert.h>
62#include <visp3/core/vpImageTools.h>
63#include <visp3/core/vpMath.h>
64
65#ifndef DOXYGEN_SHOULD_SKIP_THIS
66
67#include <gdk/gdk.h>
68#include <gdk/gdkrgb.h>
69#include <gtk/gtk.h>
70
71class vpDisplayGTK::Impl
72{
73public:
74 Impl()
75 : m_widget(NULL), m_background(NULL), m_gc(NULL), m_blue(), m_red(), m_yellow(), m_green(), m_cyan(), m_orange(),
76 m_white(), m_black(), m_gdkcolor(), m_lightBlue(), m_darkBlue(), m_lightRed(), m_darkRed(), m_lightGreen(),
77 m_darkGreen(), m_purple(), m_lightGray(), m_gray(), m_darkGray(), m_colormap(NULL), m_font(NULL), m_vectgtk(NULL),
78 m_col(NULL)
79 {
80 }
81
82 ~Impl() {}
83
84 void init(unsigned int win_width, unsigned int win_height, int win_x, int win_y, const std::string &title)
85 {
86 gint width = static_cast<gint>(win_width);
87 gint height = static_cast<gint>(win_height);
88
89 /* Initialisation of the gdk et gdk_rgb library */
90 int *argc = NULL;
91 char **argv;
92
93 gtk_init(argc, &argv);
94
95 /* Create the window*/
96 m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
97
98 gtk_widget_add_events(m_widget, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK);
99
100 gtk_window_set_default_size(GTK_WINDOW(m_widget), width, height);
101
102 gtk_window_move(GTK_WINDOW(m_widget), win_x, win_y);
103
104 gtk_widget_show(m_widget);
105
106 gdk_rgb_init();
107
108 /* Create background pixmap */
109 m_background = gdk_pixmap_new(m_widget->window, width, height, -1);
110
111 /* Create graphic context */
112 m_gc = gdk_gc_new(m_widget->window);
113
114 /* get the colormap */
115 m_colormap = gdk_window_get_colormap(m_widget->window);
116
117 m_col = new GdkColor *[vpColor::id_unknown]; // id_unknown = number of predefined colors
118
119 /* Create color */
120 gdk_color_parse("light blue", &m_lightBlue);
121 gdk_colormap_alloc_color(m_colormap, &m_lightBlue, FALSE, TRUE);
122 m_col[vpColor::id_lightBlue] = &m_lightBlue;
123
124 gdk_color_parse("blue", &m_blue);
125 gdk_colormap_alloc_color(m_colormap, &m_blue, FALSE, TRUE);
126 m_col[vpColor::id_blue] = &m_blue;
127
128 gdk_color_parse("dark blue", &m_darkBlue);
129 gdk_colormap_alloc_color(m_colormap, &m_darkBlue, FALSE, TRUE);
130 m_col[vpColor::id_darkBlue] = &m_darkBlue;
131
132 gdk_color_parse("#FF8C8C", &m_lightRed);
133 gdk_colormap_alloc_color(m_colormap, &m_lightRed, FALSE, TRUE);
134 m_col[vpColor::id_lightRed] = &m_lightRed;
135
136 gdk_color_parse("red", &m_red);
137 gdk_colormap_alloc_color(m_colormap, &m_red, FALSE, TRUE);
138 m_col[vpColor::id_red] = &m_red;
139
140 gdk_color_parse("dark red", &m_darkRed);
141 gdk_colormap_alloc_color(m_colormap, &m_darkRed, FALSE, TRUE);
142 m_col[vpColor::id_darkRed] = &m_darkRed;
143
144 gdk_color_parse("light green", &m_lightGreen);
145 gdk_colormap_alloc_color(m_colormap, &m_lightGreen, FALSE, TRUE);
146 m_col[vpColor::id_lightGreen] = &m_lightGreen;
147
148 gdk_color_parse("green", &m_green);
149 gdk_colormap_alloc_color(m_colormap, &m_green, FALSE, TRUE);
150 m_col[vpColor::id_green] = &m_green;
151
152 gdk_color_parse("dark green", &m_darkGreen);
153 gdk_colormap_alloc_color(m_colormap, &m_darkGreen, FALSE, TRUE);
154 m_col[vpColor::id_darkGreen] = &m_darkGreen;
155
156 gdk_color_parse("yellow", &m_yellow);
157 gdk_colormap_alloc_color(m_colormap, &m_yellow, FALSE, TRUE);
158 m_col[vpColor::id_yellow] = &m_yellow;
159
160 gdk_color_parse("cyan", &m_cyan);
161 gdk_colormap_alloc_color(m_colormap, &m_cyan, FALSE, TRUE);
162 m_col[vpColor::id_cyan] = &m_cyan;
163
164 gdk_color_parse("orange", &m_orange);
165 gdk_colormap_alloc_color(m_colormap, &m_orange, FALSE, TRUE);
166 m_col[vpColor::id_orange] = &m_orange;
167
168 gdk_color_parse("purple", &m_purple);
169 gdk_colormap_alloc_color(m_colormap, &m_purple, FALSE, TRUE);
170 m_col[vpColor::id_purple] = &m_purple;
171
172 gdk_color_parse("white", &m_white);
173 gdk_colormap_alloc_color(m_colormap, &m_white, FALSE, TRUE);
174 m_col[vpColor::id_white] = &m_white;
175
176 gdk_color_parse("black", &m_black);
177 gdk_colormap_alloc_color(m_colormap, &m_black, FALSE, TRUE);
178 m_col[vpColor::id_black] = &m_black;
179
180 gdk_color_parse("#C0C0C0", &m_lightGray);
181 gdk_colormap_alloc_color(m_colormap, &m_lightGray, FALSE, TRUE);
182 m_col[vpColor::id_lightGray] = &m_lightGray;
183
184 gdk_color_parse("#808080", &m_gray);
185 gdk_colormap_alloc_color(m_colormap, &m_gray, FALSE, TRUE);
186 m_col[vpColor::id_gray] = &m_gray;
187
188 gdk_color_parse("#404040", &m_darkGray);
189 gdk_colormap_alloc_color(m_colormap, &m_darkGray, FALSE, TRUE);
190 m_col[vpColor::id_darkGray] = &m_darkGray;
191
192 // Try to load a default font
193 m_font = gdk_font_load("-*-times-medium-r-normal-*-16-*-*-*-*-*-*-*");
194 if (m_font == NULL)
195 m_font = gdk_font_load("-*-courier-bold-r-normal-*-*-140-*-*-*-*-*-*");
196 if (m_font == NULL)
197 m_font = gdk_font_load("-*-courier 10 pitch-medium-r-normal-*-16-*-*-*-*-*-*-*");
198
199 if (!title.empty())
200 gdk_window_set_title(m_widget->window, title.c_str());
201 }
202
203 void setFont(const std::string &fontname) { m_font = gdk_font_load((const gchar *)fontname.c_str()); }
204
205 void setTitle(const std::string &title) { gdk_window_set_title(m_widget->window, title.c_str()); }
206
207 void setWindowPosition(int win_x, int win_y) { gtk_window_move(GTK_WINDOW(m_widget), win_x, win_y); }
208
209 void displayImage(const vpImage<unsigned char> &I, unsigned int scale, gint width, gint height)
210 {
211 if (scale == 1) {
212 /* Copie de l'image dans le pixmap fond */
213 gdk_draw_gray_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, I.bitmap, width);
214 } else {
216 I.subsample(scale, scale, sampled);
217 gdk_draw_gray_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, sampled.bitmap, width);
218 }
219
220 /* Le pixmap background devient le fond de la zone de dessin */
221 gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
222 }
223
224 void displayImage(const vpImage<vpRGBa> &I, unsigned int scale, gint width, gint height)
225 {
226 if (scale == 1) {
227 /* Copie de l'image dans le pixmap fond */
228 gdk_draw_rgb_32_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, (unsigned char *)I.bitmap,
229 4 * width);
230 } else {
231 vpImage<vpRGBa> sampled;
232 I.subsample(scale, scale, sampled);
233 gdk_draw_rgb_32_image(m_background, m_gc, 0, 0, width, height, GDK_RGB_DITHER_NONE,
234 (unsigned char *)sampled.bitmap, 4 * width);
235 }
236
237 /* Le pixmap background devient le fond de la zone de dessin */
238 gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
239 }
240
241 void displayImageROI(const vpImage<unsigned char> &I, gint j_min, gint i_min, gint width, gint height)
242 {
243 gdk_draw_gray_image(m_background, m_gc, j_min, i_min, width, height, GDK_RGB_DITHER_NONE, I.bitmap, width);
244 /* Le pixmap background devient le fond de la zone de dessin */
245 gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
246 }
247
248 void displayImageROI(const vpImage<vpRGBa> &I, gint j_min, gint i_min, gint width, gint height)
249 {
250 gdk_draw_rgb_32_image(m_background, m_gc, j_min, i_min, width, height, GDK_RGB_DITHER_NONE,
251 (unsigned char *)I.bitmap, width * 4);
252
253 /* Le pixmap background devient le fond de la zone de dessin */
254 gdk_window_set_back_pixmap(m_widget->window, m_background, FALSE);
255 }
256
257 void closeDisplay()
258 {
259 if (m_col != NULL) {
260 delete[] m_col;
261 m_col = NULL;
262 }
263
264 if (m_widget != NULL) {
265 gdk_window_hide(m_widget->window);
266 gdk_window_destroy(m_widget->window);
267 gtk_widget_destroy(m_widget);
268 m_widget = NULL;
269 }
270 }
271
272 void flushDisplay()
273 {
274 gdk_window_clear(m_widget->window);
275 gdk_flush();
276 }
277
278 void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color, unsigned int scale)
279 {
280 if (color.id < vpColor::id_unknown)
281 gdk_gc_set_foreground(m_gc, m_col[color.id]);
282 else {
283 m_gdkcolor.red = 256 * color.R;
284 m_gdkcolor.green = 256 * color.G;
285 m_gdkcolor.blue = 256 * color.B;
286 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
287 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
288 }
289 if (m_font != NULL)
290 gdk_draw_string(m_background, m_font, m_gc, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale),
291 (const gchar *)text);
292 else
293 std::cout << "Cannot draw string: no font is selected" << std::endl;
294 }
295
296 void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
297 unsigned int thickness, unsigned int scale)
298 {
299 if (color.id < vpColor::id_unknown)
300 gdk_gc_set_foreground(m_gc, m_col[color.id]);
301 else {
302 m_gdkcolor.red = 256 * color.R;
303 m_gdkcolor.green = 256 * color.G;
304 m_gdkcolor.blue = 256 * color.B;
305 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
306 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
307 }
308
309 gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
310
311 if (fill == false)
312 gdk_draw_arc(m_background, m_gc, FALSE, vpMath::round((center.get_u() - radius) / scale),
313 vpMath::round((center.get_v() - radius) / scale), static_cast<gint>(2. * radius / scale),
314 static_cast<gint>(2. * radius / scale), 23040, 23040); /* 23040 = 360*64 */
315 else
316 gdk_draw_arc(m_background, m_gc, TRUE, vpMath::round((center.get_u() - radius) / scale),
317 vpMath::round((center.get_v() - radius) / scale), static_cast<gint>(2. * radius / scale),
318 static_cast<gint>(2. * radius / scale), 23040, 23040); /* 23040 = 360*64 */
319 }
320
321 void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
322 unsigned int scale)
323 {
324 if (color.id < vpColor::id_unknown)
325 gdk_gc_set_foreground(m_gc, m_col[color.id]);
326 else {
327 m_gdkcolor.red = 256 * color.R;
328 m_gdkcolor.green = 256 * color.G;
329 m_gdkcolor.blue = 256 * color.B;
330 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
331 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
332 }
333
334 gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
335 gdk_draw_line(m_background, m_gc, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
336 vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
337 gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
338 }
339
340 void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
341 unsigned int scale)
342 {
343 if (color.id < vpColor::id_unknown)
344 gdk_gc_set_foreground(m_gc, m_col[color.id]);
345 else {
346 m_gdkcolor.red = 256 * color.R;
347 m_gdkcolor.green = 256 * color.G;
348 m_gdkcolor.blue = 256 * color.B;
349 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
350 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
351 }
352
353 gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
354 gdk_draw_line(m_background, m_gc, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
355 vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
356 }
357
358 void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness, unsigned int scale)
359 {
360 if (color.id < vpColor::id_unknown)
361 gdk_gc_set_foreground(m_gc, m_col[color.id]);
362 else {
363 m_gdkcolor.red = 256 * color.R;
364 m_gdkcolor.green = 256 * color.G;
365 m_gdkcolor.blue = 256 * color.B;
366 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
367 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
368 }
369
370 if (thickness == 1) {
371 gdk_draw_point(m_background, m_gc, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale));
372 } else {
373 gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale),
374 static_cast<gint>(thickness), static_cast<gint>(thickness));
375 }
376 }
377
378 void displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color, bool fill,
379 unsigned int thickness, unsigned int scale)
380 {
381 if (color.id < vpColor::id_unknown)
382 gdk_gc_set_foreground(m_gc, m_col[color.id]);
383 else {
384 m_gdkcolor.red = 256 * color.R;
385 m_gdkcolor.green = 256 * color.G;
386 m_gdkcolor.blue = 256 * color.B;
387 gdk_colormap_alloc_color(m_colormap, &m_gdkcolor, FALSE, TRUE);
388 gdk_gc_set_foreground(m_gc, &m_gdkcolor);
389 }
390 gdk_gc_set_line_attributes(m_gc, static_cast<gint>(thickness), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
391
392 if (fill == false)
393 gdk_draw_rectangle(m_background, m_gc, FALSE, vpMath::round(topLeft.get_u() / scale),
394 vpMath::round(topLeft.get_v() / scale), static_cast<gint>(w / scale),
395 static_cast<gint>(h / scale));
396 else
397 gdk_draw_rectangle(m_background, m_gc, TRUE, vpMath::round(topLeft.get_u() / scale),
398 vpMath::round(topLeft.get_v() / scale), static_cast<gint>(w / scale),
399 static_cast<gint>(h / scale));
400
401 if (thickness > 1)
402 gdk_gc_set_line_attributes(m_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
403 }
404
405 bool getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale,
406 const GdkEventType &event_type)
407 {
408 bool ret = false;
409 do {
410 GdkEvent *ev = NULL;
411 while ((ev = gdk_event_get())) {
412 if (ev->any.window == m_widget->window && ev->type == event_type) {
413 double u = ((GdkEventButton *)ev)->x;
414 double v = ((GdkEventButton *)ev)->y;
415 ip.set_u(u * scale);
416 ip.set_v(v * scale);
417
418 switch (static_cast<int>(((GdkEventButton *)ev)->button)) {
419 case 1:
420 button = vpMouseButton::button1;
421 break;
422 case 2:
423 button = vpMouseButton::button2;
424 break;
425 case 3:
426 button = vpMouseButton::button3;
427 break;
428 }
429 ret = true;
430 }
431 gdk_event_free(ev);
432 }
433 if (blocking) {
434 flushDisplay();
435 vpTime::wait(100);
436 }
437
438 } while (ret == false && blocking == true);
439 return ret;
440 }
441
442 void getImage(vpImage<vpRGBa> &I, gint width, gint height)
443 {
444 GdkImage *ImageGtk;
445 ImageGtk = gdk_image_get(m_background, 0, 0, width, height);
446
447 I.resize(height, width);
448 guint32 pixel;
449
450 guchar OctetRouge, OctetVert, OctetBleu, mask;
451 mask = 0x000000FF;
452
453 for (gint y = 0; y < height; y++) {
454 for (gint x = 0; x < width; x++) {
455 pixel = gdk_image_get_pixel(ImageGtk, x, y);
456 OctetBleu = static_cast<guchar>(pixel) & mask;
457 OctetVert = static_cast<guchar>(pixel >> 8) & mask;
458 OctetRouge = static_cast<guchar>(pixel >> 16) & mask;
459 I[y][x].R = OctetRouge;
460 I[y][x].G = OctetVert;
461 I[y][x].B = OctetBleu;
462 I[y][x].A = vpRGBa::alpha_default; // default opacity
463 }
464 }
465 }
466
467 unsigned int getScreenDepth() { return static_cast<unsigned int>(gdk_window_get_visual(m_widget->window)->depth); }
468
469 bool getKeyboardEvent(std::string &key, bool blocking)
470 {
471 bool ret = false;
472 int cpt = 0;
473 do {
474 GdkEvent *ev = NULL;
475 while ((ev = gdk_event_get()) != NULL) {
476 cpt++;
477
478 if (ev->any.window == m_widget->window && ev->type == GDK_KEY_PRESS) {
479 key = gdk_keyval_name(ev->key.keyval);
480 ret = true;
481 }
482 gdk_event_free(ev);
483 }
484 if (blocking) {
485 flushDisplay();
486 vpTime::wait(100);
487 }
488 } while (ret == false && blocking == true);
489 return ret;
490 }
491
492 bool getPointerMotionEvent(vpImagePoint &ip, unsigned int scale)
493 {
494 bool ret = false;
495 GdkEvent *ev = NULL;
496 if ((ev = gdk_event_get())) {
497 if (ev->any.window == m_widget->window && ev->type == GDK_MOTION_NOTIFY) {
498 double u = ((GdkEventMotion *)ev)->x;
499 double v = ((GdkEventMotion *)ev)->y;
500 ip.set_u(u * scale);
501 ip.set_v(v * scale);
502
503 ret = true;
504 }
505 gdk_event_free(ev);
506 }
507 return ret;
508 }
509
510 void getPointerPosition(vpImagePoint &ip, unsigned int scale)
511 {
512 gint u, v;
513 gdk_window_get_pointer(m_widget->window, &u, &v, NULL);
514 ip.set_u(static_cast<double>(u) * scale);
515 ip.set_v(static_cast<double>(v) * scale);
516 }
517
518 void getScreenSize(bool is_init, unsigned int &w, unsigned int &h)
519 {
520 if (!is_init) {
521 int *argc = NULL;
522 char **argv;
523
524 gtk_init(argc, &argv);
525
526 GtkWidget *widget_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
527 gtk_window_set_default_size(GTK_WINDOW(widget_), 100, 100);
528 gtk_widget_show(widget_);
529
530 GdkScreen *screen_ = gdk_window_get_screen(widget_->window);
531 w = static_cast<unsigned int>(gdk_screen_get_width(screen_));
532 h = static_cast<unsigned int>(gdk_screen_get_height(screen_));
533 gtk_widget_destroy(widget_);
534 } else {
535 GdkScreen *screen_ = gdk_window_get_screen(m_widget->window);
536 w = static_cast<unsigned int>(gdk_screen_get_width(screen_));
537 h = static_cast<unsigned int>(gdk_screen_get_height(screen_));
538 }
539 }
540
541private:
542 GtkWidget *m_widget;
543 GdkPixmap *m_background;
544 GdkGC *m_gc;
545 GdkColor m_blue, m_red, m_yellow, m_green, m_cyan, m_orange, m_white, m_black, m_gdkcolor;
546 GdkColor m_lightBlue, m_darkBlue, m_lightRed, m_darkRed, m_lightGreen, m_darkGreen, m_purple;
547 GdkColor m_lightGray, m_gray, m_darkGray;
548 GdkColormap *m_colormap;
549
550 GdkFont *m_font;
551 guchar *m_vectgtk;
552 GdkColor **m_col;
553};
554
555#endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
556
579{
580 setScale(scaleType, I.getWidth(), I.getHeight());
581 init(I);
582}
583
607vpDisplayGTK::vpDisplayGTK(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title,
608 vpScaleType scaleType)
609 : vpDisplay(), m_impl(new Impl())
610{
611 setScale(scaleType, I.getWidth(), I.getHeight());
612 init(I, win_x, win_y, win_title);
613}
614
635{
636 setScale(scaleType, I.getWidth(), I.getHeight());
637 init(I);
638}
639
661vpDisplayGTK::vpDisplayGTK(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title,
662 vpScaleType scaleType)
663 : vpDisplay(), m_impl(new Impl())
664{
665 setScale(scaleType, I.getWidth(), I.getHeight());
666 init(I, win_x, win_y, win_title);
667}
668
691vpDisplayGTK::vpDisplayGTK(int win_x, int win_y, const std::string &win_title) : vpDisplay(), m_impl(new Impl())
692{
693 m_windowXPosition = win_x;
694 m_windowYPosition = win_y;
695 m_title = win_title;
696}
697
717vpDisplayGTK::vpDisplayGTK() : vpDisplay(), m_impl(new Impl()) {}
718
723{
724 closeDisplay();
725 delete m_impl;
726}
727
736void vpDisplayGTK::init(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title)
737{
738 if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
739 throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
740 }
741
742 if (win_x != -1)
743 m_windowXPosition = win_x;
744 if (win_y != -1)
745 m_windowYPosition = win_y;
746
747 if (!win_title.empty())
748 m_title = win_title;
749
752
753 I.display = this;
755}
756
766void vpDisplayGTK::init(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title)
767{
768 if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
769 throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
770 }
771
772 if (win_x != -1)
773 m_windowXPosition = win_x;
774 if (win_y != -1)
775 m_windowYPosition = win_y;
776
777 if (!win_title.empty())
778 m_title = win_title;
779
782
783 I.display = this;
785}
786
795void vpDisplayGTK::init(unsigned int win_width, unsigned int win_height, int win_x, int win_y,
796 const std::string &win_title)
797{
798 setScale(m_scaleType, win_width, win_height);
799
800 m_width = win_width / m_scale;
801 m_height = win_height / m_scale;
802
803 if (win_x != -1)
804 m_windowXPosition = win_x;
805 if (win_y != -1)
806 m_windowYPosition = win_y;
807
808 m_title = win_title;
809
811
813}
814
827void vpDisplayGTK::setFont(const std::string &fontname) { m_impl->setFont(fontname); }
828
833void vpDisplayGTK::setTitle(const std::string &title)
834{
836 m_title = title;
837 if (!title.empty()) {
838 m_impl->setTitle(title);
839 }
840 } else {
841 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
842 }
843}
844
854void vpDisplayGTK::setWindowPosition(int win_x, int win_y)
855{
857 m_impl->setWindowPosition(win_x, win_y);
858 } else {
859 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
860 }
861}
862
875{
877 m_impl->displayImage(I, m_scale, static_cast<gint>(m_width), static_cast<gint>(m_height));
878 } else {
879 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
880 }
881}
882
901 unsigned int h)
902{
905 vpImageTools::crop(I, iP.get_i(), iP.get_j(), h, w, Itemp, m_scale, m_scale);
906
907 /* Copie de l'image dans le pixmap fond */
908 int i_min = (std::max)(static_cast<int>(ceil(iP.get_i() / m_scale)), 0);
909 int j_min = (std::max)(static_cast<int>(ceil(iP.get_j() / m_scale)), 0);
910
911 m_impl->displayImageROI(Itemp, static_cast<gint>(j_min), static_cast<gint>(i_min),
912 static_cast<gint>(Itemp.getWidth()), static_cast<gint>(Itemp.getHeight()));
913 } else {
914 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
915 }
916}
917
930{
932 m_impl->displayImage(I, m_scale, static_cast<gint>(m_width), static_cast<gint>(m_height));
933 } else {
934 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
935 }
936}
937
955void vpDisplayGTK::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h)
956{
958 vpImage<vpRGBa> Itemp;
959 vpImageTools::crop(I, iP.get_i(), iP.get_j(), h, w, Itemp, m_scale, m_scale);
960
961 /* Copie de l'image dans le pixmap fond */
962 int i_min = (std::max)(static_cast<int>(ceil(iP.get_i() / m_scale)), 0);
963 int j_min = (std::max)(static_cast<int>(ceil(iP.get_j() / m_scale)), 0);
964
965 m_impl->displayImageROI(Itemp, static_cast<gint>(j_min), static_cast<gint>(i_min),
966 static_cast<gint>(Itemp.getWidth()), static_cast<gint>(Itemp.getHeight()));
967 } else {
968 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
969 }
970}
971
977void vpDisplayGTK::displayImage(const unsigned char * /* I */) { vpTRACE(" not implemented "); }
978
985{
987 m_impl->closeDisplay();
988
990 }
991}
992
998{
1000 m_impl->flushDisplay();
1001 } else {
1002 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1003 }
1004}
1005
1010void vpDisplayGTK::flushDisplayROI(const vpImagePoint & /*iP*/, const unsigned int /*width*/,
1011 const unsigned int /*height*/)
1012{
1014 m_impl->flushDisplay();
1015 } else {
1016 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1017 }
1018}
1019
1023void vpDisplayGTK::clearDisplay(const vpColor & /* color */) { vpTRACE("Not implemented"); }
1024
1032void vpDisplayGTK::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
1033 unsigned int h, unsigned int thickness)
1034{
1036 double a = ip2.get_i() - ip1.get_i();
1037 double b = ip2.get_j() - ip1.get_j();
1038 double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
1039
1040 if ((std::fabs(a) > std::numeric_limits<double>::epsilon()) &&
1041 (std::fabs(b) > std::numeric_limits<double>::epsilon())) {
1042 a /= lg;
1043 b /= lg;
1044
1045 vpImagePoint ip3;
1046 ip3.set_i(ip2.get_i() - w * a);
1047 ip3.set_j(ip2.get_j() - w * b);
1048
1049 vpImagePoint ip4;
1050 ip4.set_i(ip3.get_i() - b * h);
1051 ip4.set_j(ip3.get_j() + a * h);
1052
1053 if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1054 displayLine(ip2, ip4, color, thickness);
1055
1056 ip4.set_i(ip3.get_i() + b * h);
1057 ip4.set_j(ip3.get_j() - a * h);
1058
1059 if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1060 displayLine(ip2, ip4, color, thickness);
1061
1062 displayLine(ip1, ip2, color, thickness);
1063 }
1064 } else {
1065 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1066 }
1067}
1068
1080void vpDisplayGTK::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
1081{
1083 m_impl->displayCharString(ip, text, color, m_scale);
1084 } else {
1085 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1086 }
1087}
1097void vpDisplayGTK::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
1098 unsigned int thickness)
1099{
1101 if (thickness == 1)
1102 thickness = 0;
1103
1104 m_impl->displayCircle(center, radius, color, fill, thickness, m_scale);
1105 } else {
1106 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1107 }
1108}
1116void vpDisplayGTK::displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness)
1117{
1119 double i = ip.get_i();
1120 double j = ip.get_j();
1121 vpImagePoint ip1, ip2;
1122
1123 ip1.set_i(i - size / 2);
1124 ip1.set_j(j);
1125 ip2.set_i(i + size / 2);
1126 ip2.set_j(j);
1127 displayLine(ip1, ip2, color, thickness);
1128
1129 ip1.set_i(i);
1130 ip1.set_j(j - size / 2);
1131 ip2.set_i(i);
1132 ip2.set_j(j + size / 2);
1133
1134 displayLine(ip1, ip2, color, thickness);
1135 }
1136
1137 else {
1138 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1139 }
1140}
1147void vpDisplayGTK::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1148 unsigned int thickness)
1149{
1150
1152 if (thickness == 1)
1153 thickness = 0;
1154
1155 m_impl->displayDotLine(ip1, ip2, color, thickness, m_scale);
1156 } else {
1157 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1158 }
1159}
1160
1167void vpDisplayGTK::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1168 unsigned int thickness)
1169{
1171 if (thickness == 1)
1172 thickness = 0;
1173
1174 m_impl->displayLine(ip1, ip2, color, thickness, m_scale);
1175 } else {
1176 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1177 }
1178}
1179
1186void vpDisplayGTK::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
1187{
1189 m_impl->displayPoint(ip, color, thickness, m_scale);
1190 } else {
1191 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1192 }
1193}
1194
1208void vpDisplayGTK::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
1209 bool fill, unsigned int thickness)
1210{
1212 if (thickness == 1)
1213 thickness = 0;
1214
1215 m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1216 } else {
1217 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1218 }
1219}
1220
1233void vpDisplayGTK::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
1234 bool fill, unsigned int thickness)
1235{
1237 if (thickness == 1)
1238 thickness = 0;
1239
1240 unsigned int w = static_cast<unsigned int>(vpMath::round(bottomRight.get_u() - topLeft.get_u()));
1241 unsigned int h = static_cast<unsigned int>(vpMath::round(bottomRight.get_v() - topLeft.get_v()));
1242
1243 m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1244 } else {
1245 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1246 }
1247}
1248
1261void vpDisplayGTK::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
1262{
1264 if (thickness == 1)
1265 thickness = 0;
1266
1267 vpImagePoint topLeft = rectangle.getTopLeft();
1268 unsigned int w = static_cast<unsigned int>(vpMath::round(rectangle.getWidth()));
1269 unsigned int h = static_cast<unsigned int>(vpMath::round(rectangle.getRight()));
1270 m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
1271 } else {
1272 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1273 }
1274}
1275
1291bool vpDisplayGTK::getClick(bool blocking)
1292{
1293 bool ret = false;
1294
1296 vpImagePoint ip;
1298 ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1299 } else {
1300 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1301 }
1302 return ret;
1303}
1304
1321bool vpDisplayGTK::getClick(vpImagePoint &ip, bool blocking)
1322{
1323 bool ret = false;
1324
1327 ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1328 } else {
1329 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1330 }
1331 return ret;
1332}
1333
1354{
1355 bool ret = false;
1356
1358 ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_PRESS);
1359 } else {
1360 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1361 }
1362 return ret;
1363}
1364
1389{
1390 bool ret = false;
1391
1393 ret = m_impl->getClick(ip, button, blocking, m_scale, GDK_BUTTON_RELEASE);
1394 } else {
1395 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1396 }
1397 return ret;
1398}
1399
1400/*
1401 \brief gets the displayed image (including the overlay plane)
1402 and returns an RGBa image
1403*/
1405{
1406 // should certainly be optimized.
1408 m_impl->getImage(I, static_cast<gint>(m_width), static_cast<gint>(m_height));
1409 } else {
1410 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1411 }
1412}
1413
1420{
1421 unsigned int depth = m_impl->getScreenDepth();
1422
1423 return (depth);
1424}
1425
1442{
1443 bool ret = false;
1444
1446 std::string key;
1447 ret = m_impl->getKeyboardEvent(key, blocking);
1448 } else {
1449 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1450 }
1451 return ret;
1452}
1453
1473bool vpDisplayGTK::getKeyboardEvent(std::string &key, bool blocking)
1474{
1475 bool ret = false;
1476
1478 ret = m_impl->getKeyboardEvent(key, blocking);
1479 } else {
1480 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1481 }
1482 return ret;
1483}
1484
1498{
1499 bool ret = false;
1500
1502 ret = m_impl->getPointerMotionEvent(ip, m_scale);
1503 } else {
1504 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1505 }
1506 return ret;
1507}
1508
1520{
1522 m_impl->getPointerPosition(ip, m_scale);
1523 } else {
1524 throw(vpDisplayException(vpDisplayException::notInitializedError, "GTK not initialized"));
1525 }
1526
1527 return true;
1528}
1529
1534void vpDisplayGTK::getScreenSize(unsigned int &w, unsigned int &h)
1535{
1536 w = h = 0;
1537
1538 m_impl->getScreenSize(m_displayHasBeenInitialized, w, h);
1539}
1540
1545{
1546 unsigned int width, height;
1547 getScreenSize(width, height);
1548 return width;
1549}
1550
1555{
1556 unsigned int width, height;
1557 getScreenSize(width, height);
1558 return height;
1559}
1560
1561#elif !defined(VISP_BUILD_SHARED_LIBS)
1562// Work around to avoid warning: libvisp_core.a(vpDisplayGTK.cpp.o) has no
1563// symbols
1564void dummy_vpDisplayGTK(){};
1565#endif
Class to define RGB colors available for display functionalities.
Definition vpColor.h:152
vpColorIdentifier id
Definition vpColor.h:200
@ id_lightBlue
Definition vpColor.h:178
@ id_yellow
Definition vpColor.h:184
@ id_darkGray
Definition vpColor.h:164
@ id_green
Definition vpColor.h:174
@ id_darkRed
Definition vpColor.h:170
@ id_lightGray
Definition vpColor.h:160
@ id_red
Definition vpColor.h:168
@ id_lightRed
Definition vpColor.h:166
@ id_white
Definition vpColor.h:158
@ id_black
Definition vpColor.h:156
@ id_blue
Definition vpColor.h:180
@ id_darkGreen
Definition vpColor.h:176
@ id_gray
Definition vpColor.h:162
@ id_lightGreen
Definition vpColor.h:172
@ id_purple
Definition vpColor.h:190
@ id_orange
Definition vpColor.h:188
@ id_cyan
Definition vpColor.h:186
@ id_darkBlue
Definition vpColor.h:182
@ id_unknown
Definition vpColor.h:193
Error that can be emitted by the vpDisplay class and its derivatives.
@ notInitializedError
Display not initialized.
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 functionalities for display.
Definition vpDisplay.h:173
unsigned int m_height
Definition vpDisplay.h:212
vpScaleType m_scaleType
Definition vpDisplay.h:215
unsigned int m_width
Definition vpDisplay.h:211
int m_windowXPosition
display position
Definition vpDisplay.h:208
std::string m_title
Definition vpDisplay.h:213
int m_windowYPosition
display position
Definition vpDisplay.h:210
unsigned int m_scale
Definition vpDisplay.h:214
bool m_displayHasBeenInitialized
display has been initialized
Definition vpDisplay.h:206
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void set_j(double jj)
double get_j() const
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
void set_i(double ii)
double get_u() const
void set_u(double u)
void set_v(double v)
double get_i() const
double get_v() const
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 of the vpImage class member functions.
Definition vpImage.h:135
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition vpImage.h:1466
unsigned int getWidth() const
Definition vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:795
Type * bitmap
points toward the bitmap
Definition vpImage.h:139
unsigned int getHeight() const
Definition vpImage.h:184
vpDisplay * display
Definition vpImage.h:140
static double sqr(double x)
Definition vpMath.h:124
static int round(double x)
Definition vpMath.h:323
unsigned char B
Blue component.
Definition vpRGBa.h:140
unsigned char R
Red component.
Definition vpRGBa.h:138
unsigned char G
Green component.
Definition vpRGBa.h:139
@ alpha_default
Definition vpRGBa.h:63
Defines a rectangle in the plane.
Definition vpRect.h:76
double getWidth() const
Definition vpRect.h:224
vpImagePoint getTopLeft() const
Definition vpRect.h:196
double getRight() const
Definition vpRect.h:176
#define vpTRACE
Definition vpDebug.h:411
VISP_EXPORT int wait(double t0, double t)