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