Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
vpDisplayX.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Image display.
32  */
33 
39 #include <visp3/core/vpConfig.h>
40 #ifdef VISP_HAVE_X11
41 
42 #include <cmath> // std::fabs
43 #include <iostream>
44 #include <limits> // numeric_limits
45 #include <stdio.h>
46 #include <stdlib.h>
47 
48 // Display stuff
49 #include <visp3/core/vpDisplay.h>
50 #include <visp3/gui/vpDisplayX.h>
51 
52 // debug / exception
53 #include <visp3/core/vpDisplayException.h>
54 
55 // math
56 #include <visp3/core/vpMath.h>
57 
58 #ifndef DOXYGEN_SHOULD_SKIP_THIS
59 
60 #include <X11/Xlib.h>
61 #include <X11/Xutil.h>
62 
64 
65 // Work around to use this class with Eigen3
66 #ifdef Success
67 #undef Success // See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=253
68 #endif
69 
70 class vpDisplayX::Impl
71 {
72 public:
73  Impl()
74  : display(nullptr), window(), Ximage(nullptr), lut(), context(), screen(0), event(), pixmap(), x_color(nullptr),
75  screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
76  BShift(0)
77  { }
78 
79  ~Impl() { }
80 
81  void clearDisplay(const vpColor &color, unsigned int width, unsigned int height)
82  {
83  if (color.id < vpColor::id_unknown)
84  XSetWindowBackground(display, window, x_color[color.id]);
85  else {
86  xcolor.pad = 0;
87  xcolor.red = 256 * color.R;
88  xcolor.green = 256 * color.G;
89  xcolor.blue = 256 * color.B;
90  XAllocColor(display, lut, &xcolor);
91  XSetForeground(display, context, xcolor.pixel);
92  }
93 
94  XClearWindow(display, window);
95 
96  XFreePixmap(display, pixmap);
97  // Pixmap creation.
98  pixmap = XCreatePixmap(display, window, width, height, screen_depth);
99  }
100 
101  void closeDisplay()
102  {
103  if (ximage_data_init == true)
104  free(Ximage->data);
105 
106  Ximage->data = nullptr;
107  XDestroyImage(Ximage);
108 
109  XFreePixmap(display, pixmap);
110 
111  XFreeGC(display, context);
112  XDestroyWindow(display, window);
113  XCloseDisplay(display);
114 
115  if (x_color != nullptr) {
116  delete[] x_color;
117  x_color = nullptr;
118  }
119  }
120 
121  void displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color, unsigned int scale)
122  {
123  if (color.id < vpColor::id_unknown)
124  XSetForeground(display, context, x_color[color.id]);
125  else {
126  xcolor.pad = 0;
127  xcolor.red = 256 * color.R;
128  xcolor.green = 256 * color.G;
129  xcolor.blue = 256 * color.B;
130  XAllocColor(display, lut, &xcolor);
131  XSetForeground(display, context, xcolor.pixel);
132  }
133  XDrawString(display, pixmap, context, (int)(ip.get_u() / scale), (int)(ip.get_v() / scale), text.c_str(),
134  (int)text.size());
135  }
136 
137  void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
138  unsigned int thickness, unsigned int scale)
139  {
140  if (color.id < vpColor::id_unknown)
141  XSetForeground(display, context, x_color[color.id]);
142  else {
143  xcolor.pad = 0;
144  xcolor.red = 256 * color.R;
145  xcolor.green = 256 * color.G;
146  xcolor.blue = 256 * color.B;
147  XAllocColor(display, lut, &xcolor);
148  XSetForeground(display, context, xcolor.pixel);
149  }
150 
151  XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
152 
153  if (fill == false) {
154  XDrawArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / scale),
155  vpMath::round((center.get_v() - radius) / scale), radius * 2 / scale, radius * 2 / scale, 0,
156  23040); /* 23040 = 360*64 */
157  }
158  else {
159  XFillArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / scale),
160  vpMath::round((center.get_v() - radius) / scale), radius * 2 / scale, radius * 2 / scale, 0,
161  23040); /* 23040 = 360*64 */
162  }
163  }
164 
165  void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
166  unsigned int scale)
167  {
168  if (color.id < vpColor::id_unknown)
169  XSetForeground(display, context, x_color[color.id]);
170  else {
171  xcolor.pad = 0;
172  xcolor.red = 256 * color.R;
173  xcolor.green = 256 * color.G;
174  xcolor.blue = 256 * color.B;
175  XAllocColor(display, lut, &xcolor);
176  XSetForeground(display, context, xcolor.pixel);
177  }
178 
179  XSetLineAttributes(display, context, thickness, LineOnOffDash, CapButt, JoinBevel);
180 
181  XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
182  vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
183  }
184 
185  void displayImage(const vpImage<unsigned char> &I, unsigned int scale, unsigned int width, unsigned int height)
186  {
187  switch (screen_depth) {
188  case 8: {
189  // Correction de l'image de facon a liberer les niveaux de gris
190  // ROUGE, VERT, BLEU, JAUNE
191  unsigned char nivGrisMax = 255 - vpColor::id_unknown;
192  if (scale == 1) {
193  unsigned char *src_8 = (unsigned char *)I.bitmap;
194  unsigned char *dst_8 = (unsigned char *)Ximage->data;
195  unsigned int i = 0;
196  unsigned int size = width * height;
197 
198  while (i < size) {
199  unsigned char nivGris = src_8[i];
200  if (nivGris > nivGrisMax) {
201  dst_8[i] = 255;
202  }
203  else {
204  dst_8[i] = nivGris;
205  }
206  ++i;
207  }
208  }
209  else {
210  // Correction de l'image de facon a liberer les niveaux de gris
211  // ROUGE, VERT, BLEU, JAUNE
212  unsigned char *dst_8 = (unsigned char *)Ximage->data;
213  unsigned int k = 0;
214  for (unsigned int i = 0; i < height; i++) {
215  for (unsigned int j = 0; j < width; j++) {
216  unsigned char nivGris = I[i * scale][j * scale];
217  if (nivGris > nivGrisMax)
218  dst_8[k++] = 255;
219  else
220  dst_8[k++] = nivGris;
221  }
222  }
223  }
224 
225  // Affichage de l'image dans la Pixmap.
226  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
227  XSetWindowBackgroundPixmap(display, window, pixmap);
228  break;
229  }
230  case 16: {
231  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
232  if (scale == 1) {
233  for (unsigned int i = 0; i < height; i++) {
234  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
235  unsigned short *dst_16 = (unsigned short *)dst_8;
236  for (unsigned int j = 0; j < width; j++) {
237  *(dst_16 + j) = (unsigned short)colortable[I[i][j]];
238  }
239  }
240  }
241  else {
242  for (unsigned int i = 0; i < height; i++) {
243  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
244  unsigned short *dst_16 = (unsigned short *)dst_8;
245  for (unsigned int j = 0; j < width; j++) {
246  *(dst_16 + j) = (unsigned short)colortable[I[i * scale][j * scale]];
247  }
248  }
249  }
250 
251  // Affichage de l'image dans la Pixmap.
252  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
253  XSetWindowBackgroundPixmap(display, window, pixmap);
254  break;
255  }
256 
257  case 24:
258  default: {
259  unsigned char *dst_32 = (unsigned char *)Ximage->data;
260  if (scale == 1) {
261  unsigned int size_ = width * height;
262  unsigned char *bitmap = I.bitmap;
263  unsigned char *n = I.bitmap + size_;
264  // for (unsigned int i = 0; i < size; i++) // suppression de
265  // l'iterateur i
266  if (XImageByteOrder(display) == 1) {
267  // big endian
268  while (bitmap < n) {
269  unsigned char val = *(bitmap++);
270  *(dst_32++) = vpRGBa::alpha_default;
271  *(dst_32++) = val; // Red
272  *(dst_32++) = val; // Green
273  *(dst_32++) = val; // Blue
274  }
275  }
276  else {
277  // little endian
278  while (bitmap < n) {
279  unsigned char val = *(bitmap++);
280  *(dst_32++) = val; // Blue
281  *(dst_32++) = val; // Green
282  *(dst_32++) = val; // Red
283  *(dst_32++) = vpRGBa::alpha_default;
284  }
285  }
286  }
287  else {
288  if (XImageByteOrder(display) == 1) {
289  // big endian
290  for (unsigned int i = 0; i < height; i++) {
291  for (unsigned int j = 0; j < width; j++) {
292  unsigned char val = I[i * scale][j * scale];
293  *(dst_32++) = vpRGBa::alpha_default;
294  *(dst_32++) = val; // Red
295  *(dst_32++) = val; // Green
296  *(dst_32++) = val; // Blue
297  }
298  }
299  }
300  else {
301  // little endian
302  for (unsigned int i = 0; i < height; i++) {
303  for (unsigned int j = 0; j < width; j++) {
304  unsigned char val = I[i * scale][j * scale];
305  *(dst_32++) = val; // Blue
306  *(dst_32++) = val; // Green
307  *(dst_32++) = val; // Red
308  *(dst_32++) = vpRGBa::alpha_default;
309  }
310  }
311  }
312  }
313 
314  // Affichage de l'image dans la Pixmap.
315  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
316  XSetWindowBackgroundPixmap(display, window, pixmap);
317  break;
318  }
319  }
320  }
321 
322  void displayImage(const vpImage<vpRGBa> &I, unsigned int scale, unsigned int width, unsigned int height)
323  {
324  switch (screen_depth) {
325  case 16: {
326  vpRGBa *bitmap = I.bitmap;
327  unsigned int r, g, b;
328  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
329 
330  if (scale == 1) {
331  for (unsigned int i = 0; i < height; i++) {
332  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
333  unsigned short *dst_16 = (unsigned short *)dst_8;
334  for (unsigned int j = 0; j < width; j++) {
335  r = bitmap->R;
336  g = bitmap->G;
337  b = bitmap->B;
338  *(dst_16 + j) =
339  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
340  bitmap++;
341  }
342  }
343  }
344  else {
345  for (unsigned int i = 0; i < height; i++) {
346  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
347  unsigned short *dst_16 = (unsigned short *)dst_8;
348  for (unsigned int j = 0; j < width; j++) {
349  vpRGBa val = I[i * scale][j * scale];
350  r = val.R;
351  g = val.G;
352  b = val.B;
353  *(dst_16 + j) =
354  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
355  bitmap++;
356  }
357  }
358  }
359 
360  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
361  XSetWindowBackgroundPixmap(display, window, pixmap);
362 
363  break;
364  }
365  case 24:
366  case 32: {
367  /*
368  * 32-bit source, 24/32-bit destination
369  */
370  unsigned char *dst_32 = nullptr;
371  dst_32 = (unsigned char *)Ximage->data;
372  if (scale == 1) {
373  vpRGBa *bitmap = I.bitmap;
374  unsigned int sizeI = width * height;
375  if (XImageByteOrder(display) == 1) {
376  // big endian
377  for (unsigned int i = 0; i < sizeI; i++) {
378  *(dst_32++) = bitmap->A;
379  *(dst_32++) = bitmap->R;
380  *(dst_32++) = bitmap->G;
381  *(dst_32++) = bitmap->B;
382  bitmap++;
383  }
384  }
385  else {
386  // little endian
387  for (unsigned int i = 0; i < sizeI; i++) {
388  *(dst_32++) = bitmap->B;
389  *(dst_32++) = bitmap->G;
390  *(dst_32++) = bitmap->R;
391  *(dst_32++) = bitmap->A;
392  bitmap++;
393  }
394  }
395  }
396  else {
397  if (XImageByteOrder(display) == 1) {
398  // big endian
399  for (unsigned int i = 0; i < height; i++) {
400  for (unsigned int j = 0; j < width; j++) {
401  vpRGBa val = I[i * scale][j * scale];
402  *(dst_32++) = val.A;
403  *(dst_32++) = val.R;
404  *(dst_32++) = val.G;
405  *(dst_32++) = val.B;
406  }
407  }
408  }
409  else {
410  // little endian
411  for (unsigned int i = 0; i < height; i++) {
412  for (unsigned int j = 0; j < width; j++) {
413  vpRGBa val = I[i * scale][j * scale];
414  *(dst_32++) = val.B;
415  *(dst_32++) = val.G;
416  *(dst_32++) = val.R;
417  *(dst_32++) = val.A;
418  }
419  }
420  }
421  }
422 
423  // Affichage de l'image dans la Pixmap.
424  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
425  XSetWindowBackgroundPixmap(display, window, pixmap);
426  break;
427  }
428  default:
430  "Unsupported depth (%d bpp) for color display", screen_depth));
431  }
432  }
433 
434  void displayImage(const unsigned char *bitmap, unsigned int width, unsigned int height)
435  {
436  unsigned char *dst_32 = (unsigned char *)Ximage->data;
437  for (unsigned int i = 0; i < width * height; i++) {
438  *(dst_32++) = *bitmap; // red component.
439  *(dst_32++) = *bitmap; // green component.
440  *(dst_32++) = *bitmap; // blue component.
441  *(dst_32++) = *bitmap; // luminance component.
442  bitmap++;
443  }
444 
445  // Affichage de l'image dans la Pixmap.
446  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
447  XSetWindowBackgroundPixmap(display, window, pixmap);
448  }
449 
450  void displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w, unsigned int h,
451  unsigned int scale, unsigned int width, unsigned int height)
452  {
453  switch (screen_depth) {
454  case 8: {
455  // Correction de l'image de facon a liberer les niveaux de gris
456  // ROUGE, VERT, BLEU, JAUNE
457  unsigned char nivGrisMax = 255 - vpColor::id_unknown;
458  if (scale == 1) {
459  unsigned char *src_8 = (unsigned char *)I.bitmap;
460  unsigned char *dst_8 = (unsigned char *)Ximage->data;
461  unsigned int iwidth = I.getWidth();
462 
463  src_8 = src_8 + (int)(iP.get_i() * iwidth + iP.get_j());
464  dst_8 = dst_8 + (int)(iP.get_i() * width + iP.get_j());
465 
466  unsigned int i = 0;
467  while (i < h) {
468  unsigned int j = 0;
469  while (j < w) {
470  unsigned char nivGris = *(src_8 + j);
471  if (nivGris > nivGrisMax)
472  *(dst_8 + j) = 255;
473  else
474  *(dst_8 + j) = nivGris;
475  ++j;
476  }
477  src_8 = src_8 + iwidth;
478  dst_8 = dst_8 + width;
479  ++i;
480  }
481 
482  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
483  w, h);
484  }
485  else {
486  // Correction de l'image de facon a liberer les niveaux de gris
487  // ROUGE, VERT, BLEU, JAUNE
488  int i_min = std::max<int>((int)ceil(iP.get_i() / scale), 0);
489  int j_min = std::max<int>((int)ceil(iP.get_j() / scale), 0);
490  int i_max = std::min<int>((int)ceil((iP.get_i() + h) / scale), (int)height);
491  int j_max = std::min<int>((int)ceil((iP.get_j() + w) / scale), (int)width);
492 
493  unsigned int i_min_ = (unsigned int)i_min;
494  unsigned int i_max_ = (unsigned int)i_max;
495  unsigned int j_min_ = (unsigned int)j_min;
496  unsigned int j_max_ = (unsigned int)j_max;
497 
498  for (unsigned int i = i_min_; i < i_max_; i++) {
499  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * width;
500  for (unsigned int j = j_min_; j < j_max_; j++) {
501  unsigned char nivGris = I[i * scale][j * scale];
502  if (nivGris > nivGrisMax)
503  dst_8[j] = 255;
504  else
505  dst_8[j] = nivGris;
506  }
507  }
508  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
509  }
510 
511  // Affichage de l'image dans la Pixmap.
512  XSetWindowBackgroundPixmap(display, window, pixmap);
513  break;
514  }
515  case 16: {
516  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
517  if (scale == 1) {
518  for (unsigned int i = (unsigned int)iP.get_i(); i < (unsigned int)(iP.get_i() + h); i++) {
519  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
520  unsigned short *dst_16 = (unsigned short *)dst_8;
521  for (unsigned int j = (unsigned int)iP.get_j(); j < (unsigned int)(iP.get_j() + w); j++) {
522  *(dst_16 + j) = (unsigned short)colortable[I[i][j]];
523  }
524  }
525 
526  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
527  w, h);
528  }
529  else {
530  int i_min = std::max<int>((int)ceil(iP.get_i() / scale), 0);
531  int j_min = std::max<int>((int)ceil(iP.get_j() / scale), 0);
532  int i_max = std::min<int>((int)ceil((iP.get_i() + h) / scale), (int)height);
533  int j_max = std::min<int>((int)ceil((iP.get_j() + w) / scale), (int)width);
534 
535  unsigned int i_min_ = (unsigned int)i_min;
536  unsigned int i_max_ = (unsigned int)i_max;
537  unsigned int j_min_ = (unsigned int)j_min;
538  unsigned int j_max_ = (unsigned int)j_max;
539 
540  for (unsigned int i = i_min_; i < i_max_; i++) {
541  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
542  unsigned short *dst_16 = (unsigned short *)dst_8;
543  for (unsigned int j = j_min_; j < j_max_; j++) {
544  *(dst_16 + j) = (unsigned short)colortable[I[i * scale][j * scale]];
545  }
546  }
547 
548  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
549  }
550 
551  XSetWindowBackgroundPixmap(display, window, pixmap);
552  break;
553  }
554 
555  case 24:
556  default: {
557  if (scale == 1) {
558  unsigned int iwidth = I.getWidth();
559  unsigned char *src_8 = I.bitmap + (int)(iP.get_i() * iwidth + iP.get_j());
560  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(iP.get_i() * 4 * width + iP.get_j() * 4);
561 
562  if (XImageByteOrder(display) == 1) {
563  // big endian
564  unsigned int i = 0;
565  while (i < h) {
566  unsigned int j = 0;
567  while (j < w) {
568  unsigned char val = *(src_8 + j);
569  *(dst_32 + 4 * j) = vpRGBa::alpha_default;
570  *(dst_32 + 4 * j + 1) = val;
571  *(dst_32 + 4 * j + 2) = val;
572  *(dst_32 + 4 * j + 3) = val;
573  ++j;
574  }
575  src_8 = src_8 + iwidth;
576  dst_32 = dst_32 + 4 * width;
577  ++i;
578  }
579  }
580  else {
581  // little endian
582  unsigned int i = 0;
583  while (i < h) {
584  unsigned int j = 0;
585  while (j < w) {
586  unsigned char val = *(src_8 + j);
587  *(dst_32 + 4 * j) = val;
588  *(dst_32 + 4 * j + 1) = val;
589  *(dst_32 + 4 * j + 2) = val;
590  *(dst_32 + 4 * j + 3) = vpRGBa::alpha_default;
591  ++j;
592  }
593  src_8 = src_8 + iwidth;
594  dst_32 = dst_32 + 4 * width;
595  ++i;
596  }
597  }
598 
599  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
600  w, h);
601  }
602  else {
603  int i_min = std::max<int>((int)ceil(iP.get_i() / scale), 0);
604  int j_min = std::max<int>((int)ceil(iP.get_j() / scale), 0);
605  int i_max = std::min<int>((int)ceil((iP.get_i() + h) / scale), (int)height);
606  int j_max = std::min<int>((int)ceil((iP.get_j() + w) / scale), (int)width);
607 
608  unsigned int i_min_ = (unsigned int)i_min;
609  unsigned int i_max_ = (unsigned int)i_max;
610  unsigned int j_min_ = (unsigned int)j_min;
611  unsigned int j_max_ = (unsigned int)j_max;
612 
613  if (XImageByteOrder(display) == 1) {
614  // big endian
615  for (unsigned int i = i_min_; i < i_max_; i++) {
616  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
617  for (unsigned int j = j_min_; j < j_max_; j++) {
618  unsigned char val = I[i * scale][j * scale];
619  *(dst_32++) = vpRGBa::alpha_default;
620  *(dst_32++) = val;
621  *(dst_32++) = val;
622  *(dst_32++) = val;
623  }
624  }
625  }
626  else {
627  // little endian
628  for (unsigned int i = i_min_; i < i_max_; i++) {
629  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
630  for (unsigned int j = j_min_; j < j_max_; j++) {
631  unsigned char val = I[i * scale][j * scale];
632  *(dst_32++) = val;
633  *(dst_32++) = val;
634  *(dst_32++) = val;
635  *(dst_32++) = vpRGBa::alpha_default;
636  }
637  }
638  }
639 
640  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
641  }
642 
643  XSetWindowBackgroundPixmap(display, window, pixmap);
644  break;
645  }
646  }
647  }
648 
649  void displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h,
650  unsigned int scale, unsigned int width, unsigned int height)
651  {
652  switch (screen_depth) {
653  case 16: {
654  if (scale == 1) {
655  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
656  for (unsigned int i = (unsigned int)iP.get_i(); i < (unsigned int)(iP.get_i() + h); i++) {
657  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
658  unsigned short *dst_16 = (unsigned short *)dst_8;
659  for (unsigned int j = (unsigned int)iP.get_j(); j < (unsigned int)(iP.get_j() + w); j++) {
660  vpRGBa val = I[i][j];
661  unsigned int r = val.R;
662  unsigned int g = val.G;
663  unsigned int b = val.B;
664  *(dst_16 + j) =
665  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
666  }
667  }
668  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
669  w, h);
670  }
671  else {
672  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
673  int i_min = std::max<int>((int)ceil(iP.get_i() / scale), 0);
674  int j_min = std::max<int>((int)ceil(iP.get_j() / scale), 0);
675  int i_max = std::min<int>((int)ceil((iP.get_i() + h) / scale), (int)height);
676  int j_max = std::min<int>((int)ceil((iP.get_j() + w) / scale), (int)width);
677 
678  unsigned int i_min_ = (unsigned int)i_min;
679  unsigned int i_max_ = (unsigned int)i_max;
680  unsigned int j_min_ = (unsigned int)j_min;
681  unsigned int j_max_ = (unsigned int)j_max;
682 
683  for (unsigned int i = i_min_; i < i_max_; i++) {
684  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
685  unsigned short *dst_16 = (unsigned short *)dst_8;
686  for (unsigned int j = j_min_; j < j_max_; j++) {
687  vpRGBa val = I[i * scale][j * scale];
688  unsigned int r = val.R;
689  unsigned int g = val.G;
690  unsigned int b = val.B;
691  *(dst_16 + j) =
692  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
693  }
694  }
695  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
696  }
697 
698  XSetWindowBackgroundPixmap(display, window, pixmap);
699 
700  break;
701  }
702  case 24:
703  case 32: {
704  /*
705  * 32-bit source, 24/32-bit destination
706  */
707 
708  if (scale == 1) {
709  unsigned char *dst_32 = (unsigned char *)Ximage->data;
710  vpRGBa *src_32 = I.bitmap;
711 
712  unsigned int iwidth = I.getWidth();
713 
714  src_32 = src_32 + (int)(iP.get_i() * iwidth + iP.get_j());
715  dst_32 = dst_32 + (int)(iP.get_i() * 4 * width + iP.get_j() * 4);
716 
717  unsigned int i = 0;
718 
719  if (XImageByteOrder(display) == 1) {
720  // big endian
721  while (i < h) {
722  unsigned int j = 0;
723  while (j < w) {
724  *(dst_32 + 4 * j) = (src_32 + j)->A;
725  *(dst_32 + 4 * j + 1) = (src_32 + j)->R;
726  *(dst_32 + 4 * j + 2) = (src_32 + j)->G;
727  *(dst_32 + 4 * j + 3) = (src_32 + j)->B;
728 
729  ++j;
730  }
731  src_32 = src_32 + iwidth;
732  dst_32 = dst_32 + 4 * width;
733  ++i;
734  }
735 
736  }
737  else {
738  // little endian
739  while (i < h) {
740  unsigned int j = 0;
741  while (j < w) {
742  *(dst_32 + 4 * j) = (src_32 + j)->B;
743  *(dst_32 + 4 * j + 1) = (src_32 + j)->G;
744  *(dst_32 + 4 * j + 2) = (src_32 + j)->R;
745  *(dst_32 + 4 * j + 3) = (src_32 + j)->A;
746 
747  ++j;
748  }
749  src_32 = src_32 + iwidth;
750  dst_32 = dst_32 + 4 * width;
751  ++i;
752  }
753  }
754 
755  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
756  w, h);
757  }
758  else {
759  int i_min = std::max<int>((int)ceil(iP.get_i() / scale), 0);
760  int j_min = std::max<int>((int)ceil(iP.get_j() / scale), 0);
761  int i_max = std::min<int>((int)ceil((iP.get_i() + h) / scale), (int)height);
762  int j_max = std::min<int>((int)ceil((iP.get_j() + w) / scale), (int)width);
763 
764  unsigned int i_min_ = (unsigned int)i_min;
765  unsigned int i_max_ = (unsigned int)i_max;
766  unsigned int j_min_ = (unsigned int)j_min;
767  unsigned int j_max_ = (unsigned int)j_max;
768 
769  if (XImageByteOrder(display) == 1) {
770  // big endian
771  for (unsigned int i = i_min_; i < i_max_; i++) {
772  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
773  for (unsigned int j = j_min_; j < j_max_; j++) {
774  vpRGBa val = I[i * scale][j * scale];
775  *(dst_32++) = val.A;
776  *(dst_32++) = val.R;
777  *(dst_32++) = val.G;
778  *(dst_32++) = val.B;
779  }
780  }
781  }
782  else {
783  // little endian
784  for (unsigned int i = i_min_; i < i_max_; i++) {
785  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
786  for (unsigned int j = j_min_; j < j_max_; j++) {
787  vpRGBa val = I[i * scale][j * scale];
788  *(dst_32++) = val.B;
789  *(dst_32++) = val.G;
790  *(dst_32++) = val.R;
791  *(dst_32++) = val.A;
792  }
793  }
794  }
795  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
796  }
797 
798  XSetWindowBackgroundPixmap(display, window, pixmap);
799  break;
800  }
801  default:
803  "Unsupported depth (%d bpp) for color display", screen_depth));
804  }
805  }
806 
807  void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
808  unsigned int scale)
809  {
810  if (color.id < vpColor::id_unknown)
811  XSetForeground(display, context, x_color[color.id]);
812  else {
813  xcolor.pad = 0;
814  xcolor.red = 256 * color.R;
815  xcolor.green = 256 * color.G;
816  xcolor.blue = 256 * color.B;
817  XAllocColor(display, lut, &xcolor);
818  XSetForeground(display, context, xcolor.pixel);
819  }
820 
821  XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
822 
823  XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
824  vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
825  }
826 
827  void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness, unsigned int scale)
828  {
829  if (color.id < vpColor::id_unknown)
830  XSetForeground(display, context, x_color[color.id]);
831  else {
832  xcolor.pad = 0;
833  xcolor.red = 256 * color.R;
834  xcolor.green = 256 * color.G;
835  xcolor.blue = 256 * color.B;
836  XAllocColor(display, lut, &xcolor);
837  XSetForeground(display, context, xcolor.pixel);
838  }
839 
840  if (thickness == 1) {
841  XDrawPoint(display, pixmap, context, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale));
842  }
843  else {
844  XFillRectangle(display, pixmap, context, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale),
845  thickness, thickness);
846  }
847  }
848 
849  void displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color, bool fill,
850  unsigned int thickness, unsigned int scale)
851  {
852  if (color.id < vpColor::id_unknown)
853  XSetForeground(display, context, x_color[color.id]);
854  else {
855  xcolor.pad = 0;
856  xcolor.red = 256 * color.R;
857  xcolor.green = 256 * color.G;
858  xcolor.blue = 256 * color.B;
859  XAllocColor(display, lut, &xcolor);
860  XSetForeground(display, context, xcolor.pixel);
861  }
862  XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
863  if (fill == false) {
864  XDrawRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / scale),
865  vpMath::round(topLeft.get_v() / scale), w / scale, h / scale);
866  }
867  else {
868  XFillRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / scale),
869  vpMath::round(topLeft.get_v() / scale), w / scale, h / scale);
870  }
871  }
872 
873  void flushDisplay()
874  {
875  XClearWindow(display, window);
876  XFlush(display);
877  }
878 
879  void flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h, unsigned int scale)
880  {
881  XClearArea(display, window, (int)(iP.get_u() / scale), (int)(iP.get_v() / scale), w / scale, h / scale, 0);
882  XFlush(display);
883  }
884 
885  bool getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale)
886  {
887  bool ret = false;
888  Window rootwin, childwin;
889  int root_x, root_y, win_x, win_y;
890  unsigned int modifier;
891 
892  // Event testing
893  if (blocking) {
894  XCheckMaskEvent(display, ButtonPressMask, &event);
895  XCheckMaskEvent(display, ButtonReleaseMask, &event);
896  XMaskEvent(display, ButtonPressMask, &event);
897  ret = true;
898  }
899  else {
900  ret = XCheckMaskEvent(display, ButtonPressMask, &event);
901  }
902 
903  if (ret) {
904  // Get mouse position
905  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
906  ip.set_u((double)event.xbutton.x * scale);
907  ip.set_v((double)event.xbutton.y * scale);
908  switch (event.xbutton.button) {
909  case Button1:
910  button = vpMouseButton::button1;
911  break;
912  case Button2:
913  button = vpMouseButton::button2;
914  break;
915  case Button3:
916  button = vpMouseButton::button3;
917  break;
918  }
919  }
920  }
921 
922  return ret;
923  }
924 
925  bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale)
926  {
927  bool ret = false;
928  Window rootwin, childwin;
929  int root_x, root_y, win_x, win_y;
930  unsigned int modifier;
931 
932  // Event testing
933  if (blocking) {
934  XCheckMaskEvent(display, ButtonPressMask, &event);
935  XCheckMaskEvent(display, ButtonReleaseMask, &event);
936  XMaskEvent(display, ButtonReleaseMask, &event);
937  ret = true;
938  }
939  else {
940  ret = XCheckMaskEvent(display, ButtonReleaseMask, &event);
941  }
942 
943  if (ret) {
944  /* Recuperation de la coordonnee du pixel clique. */
945  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
946  ip.set_u((double)event.xbutton.x * scale);
947  ip.set_v((double)event.xbutton.y * scale);
948  switch (event.xbutton.button) {
949  case Button1:
950  button = vpMouseButton::button1;
951  break;
952  case Button2:
953  button = vpMouseButton::button2;
954  break;
955  case Button3:
956  button = vpMouseButton::button3;
957  break;
958  }
959  }
960  }
961 
962  return ret;
963  }
964 
965  void getImage(vpImage<vpRGBa> &I, unsigned int width, unsigned int height)
966  {
967  XImage *xi;
968 
969  XCopyArea(display, window, pixmap, context, 0, 0, width, height, 0, 0);
970 
971  xi = XGetImage(display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap);
972 
973  I.resize(height, width);
974 
975  unsigned char *src_32 = nullptr;
976  src_32 = (unsigned char *)xi->data;
977 
978  if (screen_depth == 16) {
979  for (unsigned int i = 0; i < I.getHeight(); i++) {
980  size_t i_ = i * width;
981  for (unsigned int j = 0; j < height; j++) {
982  size_t ij_ = i_ + j;
983  unsigned long pixel = XGetPixel(xi, (int)j, (int)i);
984  I.bitmap[ij_].R = (((pixel & RMask) << RShift) >> 8);
985  I.bitmap[ij_].G = (((pixel & GMask) << GShift) >> 8);
986  I.bitmap[ij_].B = (((pixel & BMask) << BShift) >> 8);
987  // On OSX the bottom/right corner (around the resizing icon) has
988  // alpha component with different values than 255. That's why we
989  // force alpha to vpRGBa::alpha_default
990  I.bitmap[ij_].A = vpRGBa::alpha_default;
991  }
992  }
993 
994  }
995  else {
996  if (XImageByteOrder(display) == 1) {
997  // big endian
998  for (unsigned int i = 0; i < width * height; i++) {
999  // On OSX the bottom/right corner (around the resizing icon) has
1000  // alpha component with different values than 255. That's why we
1001  // force alpha to vpRGBa::alpha_default
1002  I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4] ;
1003  I.bitmap[i].R = src_32[i * 4 + 1];
1004  I.bitmap[i].G = src_32[i * 4 + 2];
1005  I.bitmap[i].B = src_32[i * 4 + 3];
1006  }
1007  }
1008  else {
1009  // little endian
1010  for (unsigned int i = 0; i < width * height; i++) {
1011  I.bitmap[i].B = src_32[i * 4];
1012  I.bitmap[i].G = src_32[i * 4 + 1];
1013  I.bitmap[i].R = src_32[i * 4 + 2];
1014  // On OSX the bottom/right corner (around the resizing icon) has
1015  // alpha component with different values than 255. That's why we
1016  // force alpha to vpRGBa::alpha_default
1017  I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4 + 3];
1018  }
1019  }
1020  }
1021  XDestroyImage(xi);
1022  }
1023 
1024  bool getKeyboardEvent(bool blocking)
1025  {
1026  bool ret = false;
1027 
1028  // Event testing
1029  if (blocking) {
1030  XMaskEvent(display, KeyPressMask, &event);
1031  ret = true;
1032  }
1033  else {
1034  ret = XCheckMaskEvent(display, KeyPressMask, &event);
1035  }
1036 
1037  return ret;
1038  }
1039 
1040  bool getKeyboardEvent(std::string &key, bool blocking)
1041  {
1042  bool ret = false;
1043  KeySym keysym;
1044  // int count;
1045  XComposeStatus compose_status;
1046  char buffer;
1047 
1048  // Event testing
1049  if (blocking) {
1050  XMaskEvent(display, KeyPressMask, &event);
1051  /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
1052  key = buffer;
1053  ret = true;
1054  }
1055  else {
1056  ret = XCheckMaskEvent(display, KeyPressMask, &event);
1057  if (ret) {
1058  /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
1059  key = buffer;
1060  }
1061  }
1062 
1063  return ret;
1064  }
1065 
1069  int getMsb(unsigned int u32val)
1070  {
1071  int i;
1072 
1073  for (i = 31; i >= 0; --i) {
1074  if (u32val & 0x80000000L)
1075  break;
1076  u32val <<= 1;
1077  }
1078  return i;
1079  }
1080 
1081  bool getPointerMotionEvent(vpImagePoint &ip, unsigned int scale)
1082  {
1083  bool ret = false;
1084 
1085  Window rootwin, childwin;
1086  int root_x, root_y, win_x, win_y;
1087  unsigned int modifier;
1088  // Event testing
1089  ret = XCheckMaskEvent(display, PointerMotionMask, &event);
1090 
1091  if (ret) {
1092  // Get mouse position
1093  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
1094  ip.set_u((double)event.xbutton.x * scale);
1095  ip.set_v((double)event.xbutton.y * scale);
1096  }
1097  }
1098 
1099  return ret;
1100  }
1101 
1102  bool getPointerPosition(vpImagePoint &ip, unsigned int scale)
1103  {
1104  bool ret = false;
1105  Window rootwin, childwin;
1106  int root_x, root_y, win_x, win_y;
1107  unsigned int modifier;
1108  // Event testing
1109  ret = true;
1110 
1111  if (ret) {
1112  // Get mouse position
1113  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
1114  ip.set_u((double)win_x * scale);
1115  ip.set_v((double)win_y * scale);
1116  }
1117  }
1118 
1119  return ret;
1120  }
1121 
1122  unsigned int getScreenDepth()
1123  {
1124  Display *display_;
1125  int screen_;
1126  unsigned int depth;
1127 
1128  if ((display_ = XOpenDisplay(nullptr)) == nullptr) {
1129  throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
1130  XDisplayName(nullptr)));
1131  }
1132  screen_ = DefaultScreen(display_);
1133  depth = (unsigned int)DefaultDepth(display_, screen_);
1134 
1135  XCloseDisplay(display_);
1136 
1137  return (depth);
1138  }
1139 
1140  void getScreenSize(unsigned int &w, unsigned int &h)
1141  {
1142  Display *display_;
1143  int screen_;
1144 
1145  if ((display_ = XOpenDisplay(nullptr)) == nullptr) {
1146  throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
1147  XDisplayName(nullptr)));
1148  }
1149  screen_ = DefaultScreen(display_);
1150  w = (unsigned int)DisplayWidth(display_, screen_);
1151  h = (unsigned int)DisplayHeight(display_, screen_);
1152 
1153  XCloseDisplay(display_);
1154  }
1155 
1156  void init(unsigned int win_width, unsigned int win_height, int win_x, int win_y, const std::string &win_title)
1157  {
1158  if (x_color == nullptr) {
1159  // id_unknown = number of predefined colors
1160  x_color = new unsigned long[vpColor::id_unknown];
1161  }
1162  // setup X11
1163  XSizeHints hints;
1164 
1165  // Positionnement de la fenetre dans l'ecran.
1166  if ((win_x < 0) || (win_y < 0)) {
1167  hints.flags = 0;
1168  }
1169  else {
1170  hints.flags = USPosition;
1171  hints.x = win_x;
1172  hints.y = win_y;
1173  }
1174 
1175  if ((display = XOpenDisplay(nullptr)) == nullptr) {
1176  throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.", XDisplayName(nullptr)));
1177  }
1178 
1179  screen = DefaultScreen(display);
1180  lut = DefaultColormap(display, screen);
1181  screen_depth = (unsigned int)DefaultDepth(display, screen);
1182 
1183  if ((window = XCreateSimpleWindow(display, RootWindow(display, screen), win_x, win_y, win_width, win_height, 1,
1184  BlackPixel(display, screen), WhitePixel(display, screen))) == 0) {
1185  throw(vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create window."));
1186  }
1187 
1188  //
1189  // Create color table for 8 and 16 bits screen
1190  //
1191  if (screen_depth == 8) {
1192  lut = XCreateColormap(display, window, DefaultVisual(display, screen), AllocAll);
1193  xcolor.flags = DoRed | DoGreen | DoBlue;
1194 
1195  for (unsigned int i = 0; i < 256; i++) {
1196  xcolor.pixel = i;
1197  xcolor.red = 256 * i;
1198  xcolor.green = 256 * i;
1199  xcolor.blue = 256 * i;
1200  XStoreColor(display, lut, &xcolor);
1201  }
1202 
1203  XSetWindowColormap(display, window, lut);
1204  XInstallColormap(display, lut);
1205  }
1206 
1207  else if (screen_depth == 16) {
1208  for (unsigned int i = 0; i < 256; i++) {
1209  xcolor.pad = 0;
1210  xcolor.red = xcolor.green = xcolor.blue = 256 * i;
1211  if (XAllocColor(display, lut, &xcolor) == 0) {
1212  throw(vpDisplayException(vpDisplayException::colorAllocError, "Can't allocate 256 colors. Only %d allocated.", i));
1213  }
1214  colortable[i] = xcolor.pixel;
1215  }
1216 
1217  XSetWindowColormap(display, window, lut);
1218  XInstallColormap(display, lut);
1219 
1220  Visual *visual = DefaultVisual(display, screen);
1221  RMask = visual->red_mask;
1222  GMask = visual->green_mask;
1223  BMask = visual->blue_mask;
1224 
1225  RShift = 15 - getMsb(RMask); /* these are right-shifts */
1226  GShift = 15 - getMsb(GMask);
1227  BShift = 15 - getMsb(BMask);
1228  }
1229 
1230  vpColor pcolor; // predefined colors
1231 
1232  //
1233  // Create colors for overlay
1234  //
1235  switch (screen_depth) {
1236 
1237  case 8:
1238  // Color BLACK: default set to 0
1239 
1240  // Color WHITE: default set to 255
1241 
1242  // Color LIGHT GRAY.
1243  x_color[vpColor::id_lightGray] = 254;
1244  xcolor.pixel = x_color[vpColor::id_lightGray];
1245  xcolor.red = 256 * 192;
1246  xcolor.green = 256 * 192;
1247  xcolor.blue = 256 * 192;
1248  XStoreColor(display, lut, &xcolor);
1249 
1250  // Color GRAY.
1251  x_color[vpColor::id_gray] = 253;
1252  xcolor.pixel = x_color[vpColor::id_gray];
1253  xcolor.red = 256 * 128;
1254  xcolor.green = 256 * 128;
1255  xcolor.blue = 256 * 128;
1256  XStoreColor(display, lut, &xcolor);
1257 
1258  // Color DARK GRAY.
1259  x_color[vpColor::id_darkGray] = 252;
1260  xcolor.pixel = x_color[vpColor::id_darkGray];
1261  xcolor.red = 256 * 64;
1262  xcolor.green = 256 * 64;
1263  xcolor.blue = 256 * 64;
1264  XStoreColor(display, lut, &xcolor);
1265 
1266  // Color LIGHT RED.
1267  x_color[vpColor::id_lightRed] = 251;
1268  xcolor.pixel = x_color[vpColor::id_lightRed];
1269  xcolor.red = 256 * 255;
1270  xcolor.green = 256 * 140;
1271  xcolor.blue = 256 * 140;
1272  XStoreColor(display, lut, &xcolor);
1273 
1274  // Color RED.
1275  x_color[vpColor::id_red] = 250;
1276  xcolor.pixel = x_color[vpColor::id_red];
1277  xcolor.red = 256 * 255;
1278  xcolor.green = 0;
1279  xcolor.blue = 0;
1280  XStoreColor(display, lut, &xcolor);
1281 
1282  // Color DARK RED.
1283  x_color[vpColor::id_darkRed] = 249;
1284  xcolor.pixel = x_color[vpColor::id_darkRed];
1285  xcolor.red = 256 * 128;
1286  xcolor.green = 0;
1287  xcolor.blue = 0;
1288  XStoreColor(display, lut, &xcolor);
1289 
1290  // Color LIGHT GREEN.
1291  x_color[vpColor::id_lightGreen] = 248;
1292  xcolor.pixel = x_color[vpColor::id_lightGreen];
1293  xcolor.red = 256 * 140;
1294  xcolor.green = 256 * 255;
1295  xcolor.blue = 256 * 140;
1296  XStoreColor(display, lut, &xcolor);
1297 
1298  // Color GREEN.
1299  x_color[vpColor::id_green] = 247;
1300  xcolor.pixel = x_color[vpColor::id_green];
1301  xcolor.red = 0;
1302  xcolor.green = 256 * 255;
1303  xcolor.blue = 0;
1304  XStoreColor(display, lut, &xcolor);
1305 
1306  // Color DARK GREEN.
1307  x_color[vpColor::id_darkGreen] = 246;
1308  xcolor.pixel = x_color[vpColor::id_darkGreen];
1309  xcolor.red = 0;
1310  xcolor.green = 256 * 128;
1311  xcolor.blue = 0;
1312  XStoreColor(display, lut, &xcolor);
1313 
1314  // Color LIGHT BLUE.
1315  x_color[vpColor::id_lightBlue] = 245;
1316  xcolor.pixel = x_color[vpColor::id_lightBlue];
1317  xcolor.red = 256 * 140;
1318  xcolor.green = 256 * 140;
1319  xcolor.blue = 256 * 255;
1320  XStoreColor(display, lut, &xcolor);
1321 
1322  // Color BLUE.
1323  x_color[vpColor::id_blue] = 244;
1324  xcolor.pixel = x_color[vpColor::id_blue];
1325  xcolor.red = 0;
1326  xcolor.green = 0;
1327  xcolor.blue = 256 * 255;
1328  XStoreColor(display, lut, &xcolor);
1329 
1330  // Color DARK BLUE.
1331  x_color[vpColor::id_darkBlue] = 243;
1332  xcolor.pixel = x_color[vpColor::id_darkBlue];
1333  xcolor.red = 0;
1334  xcolor.green = 0;
1335  xcolor.blue = 256 * 128;
1336  XStoreColor(display, lut, &xcolor);
1337 
1338  // Color YELLOW.
1339  x_color[vpColor::id_yellow] = 242;
1340  xcolor.pixel = x_color[vpColor::id_yellow];
1341  xcolor.red = 256 * 255;
1342  xcolor.green = 256 * 255;
1343  xcolor.blue = 0;
1344  XStoreColor(display, lut, &xcolor);
1345 
1346  // Color ORANGE.
1347  x_color[vpColor::id_orange] = 241;
1348  xcolor.pixel = x_color[vpColor::id_orange];
1349  xcolor.red = 256 * 255;
1350  xcolor.green = 256 * 165;
1351  xcolor.blue = 0;
1352  XStoreColor(display, lut, &xcolor);
1353 
1354  // Color CYAN.
1355  x_color[vpColor::id_cyan] = 240;
1356  xcolor.pixel = x_color[vpColor::id_cyan];
1357  xcolor.red = 0;
1358  xcolor.green = 256 * 255;
1359  xcolor.blue = 256 * 255;
1360  XStoreColor(display, lut, &xcolor);
1361 
1362  // Color PURPLE.
1363  x_color[vpColor::id_purple] = 239;
1364  xcolor.pixel = x_color[vpColor::id_purple];
1365  xcolor.red = 256 * 128;
1366  xcolor.green = 0;
1367  xcolor.blue = 256 * 128;
1368  XStoreColor(display, lut, &xcolor);
1369 
1370  break;
1371 
1372  case 16:
1373  case 24:
1374  case 32: {
1375  xcolor.flags = DoRed | DoGreen | DoBlue;
1376 
1377  // Couleur BLACK.
1378  pcolor = vpColor::black;
1379  xcolor.pad = 0;
1380  xcolor.red = 256 * pcolor.R;
1381  xcolor.green = 256 * pcolor.G;
1382  xcolor.blue = 256 * pcolor.B;
1383  XAllocColor(display, lut, &xcolor);
1384  x_color[vpColor::id_black] = xcolor.pixel;
1385 
1386  // Color WHITE.
1387  pcolor = vpColor::white;
1388  xcolor.pad = 0;
1389  xcolor.red = 256 * pcolor.R;
1390  xcolor.green = 256 * pcolor.G;
1391  xcolor.blue = 256 * pcolor.B;
1392  XAllocColor(display, lut, &xcolor);
1393  x_color[vpColor::id_white] = xcolor.pixel;
1394 
1395  // Color LIGHT GRAY.
1396  pcolor = vpColor::lightGray;
1397  xcolor.pad = 0;
1398  xcolor.red = 256 * pcolor.R;
1399  xcolor.green = 256 * pcolor.G;
1400  xcolor.blue = 256 * pcolor.B;
1401  XAllocColor(display, lut, &xcolor);
1402  x_color[vpColor::id_lightGray] = xcolor.pixel;
1403 
1404  // Color GRAY.
1405  pcolor = vpColor::gray;
1406  xcolor.pad = 0;
1407  xcolor.red = 256 * pcolor.R;
1408  xcolor.green = 256 * pcolor.G;
1409  xcolor.blue = 256 * pcolor.B;
1410  XAllocColor(display, lut, &xcolor);
1411  x_color[vpColor::id_gray] = xcolor.pixel;
1412 
1413  // Color DARK GRAY.
1414  pcolor = vpColor::darkGray;
1415  xcolor.pad = 0;
1416  xcolor.red = 256 * pcolor.R;
1417  xcolor.green = 256 * pcolor.G;
1418  xcolor.blue = 256 * pcolor.B;
1419  XAllocColor(display, lut, &xcolor);
1420  x_color[vpColor::id_darkGray] = xcolor.pixel;
1421 
1422  // Color LIGHT RED.
1423  pcolor = vpColor::lightRed;
1424  xcolor.pad = 0;
1425  xcolor.red = 256 * pcolor.R;
1426  xcolor.green = 256 * pcolor.G;
1427  xcolor.blue = 256 * pcolor.B;
1428  XAllocColor(display, lut, &xcolor);
1429  x_color[vpColor::id_lightRed] = xcolor.pixel;
1430 
1431  // Color RED.
1432  pcolor = vpColor::red;
1433  xcolor.pad = 0;
1434  xcolor.red = 256 * pcolor.R;
1435  xcolor.green = 256 * pcolor.G;
1436  xcolor.blue = 256 * pcolor.B;
1437  XAllocColor(display, lut, &xcolor);
1438  x_color[vpColor::id_red] = xcolor.pixel;
1439 
1440  // Color DARK RED.
1441  pcolor = vpColor::darkRed;
1442  xcolor.pad = 0;
1443  xcolor.red = 256 * pcolor.R;
1444  xcolor.green = 256 * pcolor.G;
1445  xcolor.blue = 256 * pcolor.B;
1446  XAllocColor(display, lut, &xcolor);
1447  x_color[vpColor::id_darkRed] = xcolor.pixel;
1448 
1449  // Color LIGHT GREEN.
1450  pcolor = vpColor::lightGreen;
1451  xcolor.pad = 0;
1452  xcolor.red = 256 * pcolor.R;
1453  xcolor.green = 256 * pcolor.G;
1454  xcolor.blue = 256 * pcolor.B;
1455  XAllocColor(display, lut, &xcolor);
1456  x_color[vpColor::id_lightGreen] = xcolor.pixel;
1457 
1458  // Color GREEN.
1459  pcolor = vpColor::green;
1460  xcolor.pad = 0;
1461  xcolor.red = 256 * pcolor.R;
1462  xcolor.green = 256 * pcolor.G;
1463  xcolor.blue = 256 * pcolor.B;
1464  XAllocColor(display, lut, &xcolor);
1465  x_color[vpColor::id_green] = xcolor.pixel;
1466 
1467  // Color DARK GREEN.
1468  pcolor = vpColor::darkGreen;
1469  xcolor.pad = 0;
1470  xcolor.red = 256 * pcolor.R;
1471  xcolor.green = 256 * pcolor.G;
1472  xcolor.blue = 256 * pcolor.B;
1473  XAllocColor(display, lut, &xcolor);
1474  x_color[vpColor::id_darkGreen] = xcolor.pixel;
1475 
1476  // Color LIGHT BLUE.
1477  pcolor = vpColor::lightBlue;
1478  xcolor.pad = 0;
1479  xcolor.red = 256 * pcolor.R;
1480  xcolor.green = 256 * pcolor.G;
1481  xcolor.blue = 256 * pcolor.B;
1482  XAllocColor(display, lut, &xcolor);
1483  x_color[vpColor::id_lightBlue] = xcolor.pixel;
1484 
1485  // Color BLUE.
1486  pcolor = vpColor::blue;
1487  xcolor.pad = 0;
1488  xcolor.red = 256 * pcolor.R;
1489  xcolor.green = 256 * pcolor.G;
1490  xcolor.blue = 256 * pcolor.B;
1491  XAllocColor(display, lut, &xcolor);
1492  x_color[vpColor::id_blue] = xcolor.pixel;
1493 
1494  // Color DARK BLUE.
1495  pcolor = vpColor::darkBlue;
1496  xcolor.pad = 0;
1497  xcolor.red = 256 * pcolor.R;
1498  xcolor.green = 256 * pcolor.G;
1499  xcolor.blue = 256 * pcolor.B;
1500  XAllocColor(display, lut, &xcolor);
1501  x_color[vpColor::id_darkBlue] = xcolor.pixel;
1502 
1503  // Color YELLOW.
1504  pcolor = vpColor::yellow;
1505  xcolor.pad = 0;
1506  xcolor.red = 256 * pcolor.R;
1507  xcolor.green = 256 * pcolor.G;
1508  xcolor.blue = 256 * pcolor.B;
1509  XAllocColor(display, lut, &xcolor);
1510  x_color[vpColor::id_yellow] = xcolor.pixel;
1511 
1512  // Color ORANGE.
1513  pcolor = vpColor::orange;
1514  xcolor.pad = 0;
1515  xcolor.red = 256 * pcolor.R;
1516  xcolor.green = 256 * pcolor.G;
1517  xcolor.blue = 256 * pcolor.B;
1518  XAllocColor(display, lut, &xcolor);
1519  x_color[vpColor::id_orange] = xcolor.pixel;
1520 
1521  // Color CYAN.
1522  pcolor = vpColor::cyan;
1523  xcolor.pad = 0;
1524  xcolor.red = 256 * pcolor.R;
1525  xcolor.green = 256 * pcolor.G;
1526  xcolor.blue = 256 * pcolor.B;
1527  XAllocColor(display, lut, &xcolor);
1528  x_color[vpColor::id_cyan] = xcolor.pixel;
1529 
1530  // Color PURPLE.
1531  pcolor = vpColor::purple;
1532  xcolor.pad = 0;
1533  xcolor.red = 256 * pcolor.R;
1534  xcolor.green = 256 * pcolor.G;
1535  xcolor.blue = 256 * pcolor.B;
1536  XAllocColor(display, lut, &xcolor);
1537  x_color[vpColor::id_purple] = xcolor.pixel;
1538  break;
1539  }
1540  }
1541 
1542  XSetStandardProperties(display, window, win_title.c_str(), win_title.c_str(), None, 0, 0, &hints);
1543  XMapWindow(display, window);
1544  // Selection des evenements.
1545  XSelectInput(display, window,
1546  ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
1547  StructureNotifyMask | PointerMotionMask);
1548 
1549  /* Creation du contexte graphique */
1550  values.plane_mask = AllPlanes;
1551  values.fill_style = FillSolid;
1552  values.foreground = WhitePixel(display, screen);
1553  values.background = BlackPixel(display, screen);
1554  context = XCreateGC(display, window, GCPlaneMask | GCFillStyle | GCForeground | GCBackground, &values);
1555 
1556  if (context == nullptr) {
1557  throw(vpDisplayException(vpDisplayException::XWindowsError, "Can't create graphics context"));
1558  }
1559 
1560  // Pixmap creation.
1561  pixmap = XCreatePixmap(display, window, win_width, win_height, screen_depth);
1562 
1563  // Hangs when forward X11 is used to send the display to an other computer
1564  // do
1565  // XNextEvent ( display, &event );
1566  // while ( event.xany.type != Expose );
1567 
1568  {
1569  Ximage = XCreateImage(display, DefaultVisual(display, screen), screen_depth, ZPixmap, 0, nullptr, win_width,
1570  win_height, XBitmapPad(display), 0);
1571 
1572  Ximage->data = (char *)malloc(win_height * (unsigned int)Ximage->bytes_per_line);
1573  ximage_data_init = true;
1574  }
1575 
1576  XSync(display, true);
1577 
1578  XStoreName(display, window, win_title.c_str());
1579  }
1580 
1581  void setFont(const std::string &fontname)
1582  {
1583  try {
1584  Font stringfont;
1585  stringfont = XLoadFont(display, fontname.c_str()); //"-adobe-times-bold-r-normal--18*");
1586  XSetFont(display, context, stringfont);
1587  }
1588  catch (...) {
1590  }
1591  }
1592 
1593  void setTitle(const std::string &title) { XStoreName(display, window, title.c_str()); }
1594 
1595  void setWindowPosition(int win_x, int win_y) { XMoveWindow(display, window, win_x, win_y); }
1596 
1597 private:
1598  Display *display;
1599  Window window;
1600  XImage *Ximage;
1601  Colormap lut;
1602  GC context;
1603  int screen;
1604  XEvent event;
1605  Pixmap pixmap;
1606  unsigned long *x_color; // Array of predefined colors
1607  unsigned int screen_depth;
1608  unsigned short colortable[256];
1609  XColor xcolor;
1610  XGCValues values;
1611  bool ximage_data_init;
1612  unsigned int RMask, GMask, BMask;
1613  int RShift, GShift, BShift;
1614 };
1615 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
1616 
1637 {
1638  setScale(scaleType, I.getWidth(), I.getHeight());
1639 
1640  init(I);
1641 }
1642 
1664 vpDisplayX::vpDisplayX(vpImage<unsigned char> &I, int x, int y, const std::string &title, vpScaleType scaleType)
1665  : vpDisplay(), m_impl(new Impl())
1666 {
1667  setScale(scaleType, I.getWidth(), I.getHeight());
1668  init(I, x, y, title);
1669 }
1670 
1690 vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, vpScaleType scaleType) : vpDisplay(), m_impl(new Impl())
1691 {
1692  setScale(scaleType, I.getWidth(), I.getHeight());
1693  init(I);
1694 }
1695 
1717 vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, int x, int y, const std::string &title, vpScaleType scaleType)
1718  : vpDisplay(), m_impl(new Impl())
1719 {
1720  setScale(scaleType, I.getWidth(), I.getHeight());
1721  init(I, x, y, title);
1722 }
1723 
1749 vpDisplayX::vpDisplayX(int x, int y, const std::string &title) : vpDisplay(), m_impl(new Impl())
1750 {
1751  m_windowXPosition = x;
1752  m_windowYPosition = y;
1753 
1754  m_title = title;
1755 }
1756 
1780 vpDisplayX::vpDisplayX() : vpDisplay(), m_impl(new Impl()) { }
1781 
1786 {
1787  closeDisplay();
1788  delete m_impl;
1789 }
1790 
1798 void vpDisplayX::init(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title)
1799 {
1800  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
1801  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
1802  }
1803 
1804  if (win_x != -1)
1805  m_windowXPosition = win_x;
1806  if (win_y != -1)
1807  m_windowYPosition = win_y;
1808 
1809  if (!win_title.empty())
1810  m_title = win_title;
1811 
1814 
1815  I.display = this;
1817 }
1818 
1827 void vpDisplayX::init(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title)
1828 {
1829  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
1830  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
1831  }
1832 
1833  if (win_x != -1)
1834  m_windowXPosition = win_x;
1835  if (win_y != -1)
1836  m_windowYPosition = win_y;
1837 
1838  if (!win_title.empty())
1839  m_title = win_title;
1840 
1843 
1844  I.display = this;
1846 }
1847 
1855 void vpDisplayX::init(unsigned int win_width, unsigned int win_height, int win_x, int win_y,
1856  const std::string &win_title)
1857 {
1858  setScale(m_scaleType, win_width, win_height);
1859 
1860  m_width = win_width / m_scale;
1861  m_height = win_height / m_scale;
1862 
1863  if (win_x != -1)
1864  m_windowXPosition = win_x;
1865  if (win_y != -1)
1866  m_windowYPosition = win_y;
1867 
1868  m_title = win_title;
1869 
1871 
1873 }
1874 
1889 void vpDisplayX::setFont(const std::string &fontname)
1890 {
1892  if (!fontname.empty()) {
1893  m_impl->setFont(fontname);
1894  }
1895  }
1896  else {
1897  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1898  }
1899 }
1900 
1905 void vpDisplayX::setTitle(const std::string &title)
1906 {
1908  m_title = title;
1909  if (!title.empty())
1910  m_impl->setTitle(title);
1911  }
1912  else {
1913  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1914  }
1915 }
1916 
1926 void vpDisplayX::setWindowPosition(int win_x, int win_y)
1927 {
1929  m_impl->setWindowPosition(win_x, win_y);
1930  }
1931  else {
1932  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1933  }
1934 }
1935 
1948 {
1950  m_impl->displayImage(I, m_scale, m_width, m_height);
1951  }
1952  else {
1953  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1954  }
1955 }
1956 
1969 {
1971  m_impl->displayImage(I, m_scale, m_width, m_height);
1972  }
1973  else {
1974  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1975  }
1976 }
1977 
1989 void vpDisplayX::displayImage(const unsigned char *bitmap)
1990 {
1992  m_impl->displayImage(bitmap, m_width, m_height);
1993  }
1994  else {
1995  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1996  }
1997 }
1998 
2014 void vpDisplayX::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w,
2015  unsigned int h)
2016 {
2018  m_impl->displayImageROI(I, iP, w, h, m_scale, m_width, m_height);
2019  }
2020  else {
2021  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2022  }
2023 }
2024 
2040 void vpDisplayX::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h)
2041 {
2043  m_impl->displayImageROI(I, iP, w, h, m_scale, m_width, m_height);
2044  }
2045  else {
2046  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2047  }
2048 }
2049 
2058 {
2060  m_impl->closeDisplay();
2061 
2063  }
2064 }
2065 
2072 {
2074  m_impl->flushDisplay();
2075  }
2076  else {
2077  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2078  }
2079 }
2080 
2088 void vpDisplayX::flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h)
2089 {
2091  m_impl->flushDisplayROI(iP, w, h, m_scale);
2092  }
2093  else {
2094  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2095  }
2096 }
2097 
2103 {
2105  m_impl->clearDisplay(color, m_width, m_height);
2106  }
2107  else {
2108  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2109  }
2110 }
2111 
2119 void vpDisplayX::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
2120  unsigned int h, unsigned int thickness)
2121 {
2123  double a = ip2.get_i() - ip1.get_i();
2124  double b = ip2.get_j() - ip1.get_j();
2125  double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
2126 
2127  // if ( ( a==0 ) && ( b==0 ) )
2128  if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
2129  (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
2130  // DisplayCrossLarge(i1,j1,3,col) ;
2131  }
2132  else {
2133  a /= lg;
2134  b /= lg;
2135 
2136  vpImagePoint ip3;
2137  ip3.set_i(ip2.get_i() - w * a);
2138  ip3.set_j(ip2.get_j() - w * b);
2139 
2140  vpImagePoint ip4;
2141  ip4.set_i(ip3.get_i() - b * h);
2142  ip4.set_j(ip3.get_j() + a * h);
2143 
2144  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2145  displayLine(ip2, ip4, color, thickness);
2146 
2147  ip4.set_i(ip3.get_i() + b * h);
2148  ip4.set_j(ip3.get_j() - a * h);
2149 
2150  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2151  displayLine(ip2, ip4, color, thickness);
2152 
2153  displayLine(ip1, ip2, color, thickness);
2154  }
2155  }
2156  else {
2157  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2158  }
2159 }
2160 
2172 void vpDisplayX::displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color)
2173 {
2175  m_impl->displayText(ip, text, color, m_scale);
2176  }
2177  else {
2178  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2179  }
2180 }
2181 
2191 void vpDisplayX::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
2192  unsigned int thickness)
2193 {
2195  if (thickness == 1)
2196  thickness = 0;
2197  m_impl->displayCircle(center, radius, color, fill, thickness, m_scale);
2198  }
2199  else {
2200  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2201  }
2202 }
2203 
2211 void vpDisplayX::displayCross(const vpImagePoint &ip, unsigned int cross_size, const vpColor &color,
2212  unsigned int thickness)
2213 {
2215  double i = ip.get_i();
2216  double j = ip.get_j();
2217  vpImagePoint ip1, ip2;
2218 
2219  ip1.set_i(i - cross_size / 2);
2220  ip1.set_j(j);
2221  ip2.set_i(i + cross_size / 2);
2222  ip2.set_j(j);
2223  displayLine(ip1, ip2, color, thickness);
2224 
2225  ip1.set_i(i);
2226  ip1.set_j(j - cross_size / 2);
2227  ip2.set_i(i);
2228  ip2.set_j(j + cross_size / 2);
2229 
2230  displayLine(ip1, ip2, color, thickness);
2231  }
2232  else {
2233  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2234  }
2235 }
2242 void vpDisplayX::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2243  unsigned int thickness)
2244 {
2246  if (thickness == 1)
2247  thickness = 0;
2248 
2249  m_impl->displayDotLine(ip1, ip2, color, thickness, m_scale);
2250  }
2251  else {
2252  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2253  }
2254 }
2255 
2262 void vpDisplayX::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2263  unsigned int thickness)
2264 {
2266  if (thickness == 1)
2267  thickness = 0;
2268  m_impl->displayLine(ip1, ip2, color, thickness, m_scale);
2269  }
2270  else {
2271  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2272  }
2273 }
2274 
2281 void vpDisplayX::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
2282 {
2284  m_impl->displayPoint(ip, color, thickness, m_scale);
2285  }
2286  else {
2287  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2288  }
2289 }
2290 
2304 void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
2305  bool fill, unsigned int thickness)
2306 {
2308  if (thickness == 1)
2309  thickness = 0;
2310 
2311  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2312  }
2313  else {
2314  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2315  }
2316 }
2317 
2330 void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
2331  bool fill, unsigned int thickness)
2332 {
2334  if (thickness == 1)
2335  thickness = 0;
2336 
2337  unsigned int w = static_cast<unsigned int>(vpMath::round(bottomRight.get_u() - topLeft.get_u()));
2338  unsigned int h = static_cast<unsigned int>(vpMath::round(bottomRight.get_v() - topLeft.get_v()));
2339 
2340  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2341  }
2342  else {
2343  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2344  }
2345 }
2346 
2359 void vpDisplayX::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
2360 {
2362  if (thickness == 1)
2363  thickness = 0;
2364  vpImagePoint topLeft = rectangle.getTopLeft();
2365  unsigned int w = static_cast<unsigned int>(vpMath::round(rectangle.getWidth()));
2366  unsigned int h = static_cast<unsigned int>(vpMath::round(rectangle.getHeight()));
2367  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2368  }
2369  else {
2370  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2371  }
2372 }
2373 
2389 bool vpDisplayX::getClick(bool blocking)
2390 {
2391  bool ret = false;
2392 
2394  vpImagePoint ip;
2396  ret = m_impl->getClick(ip, button, blocking, m_scale);
2397  }
2398  else {
2399  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2400  }
2401  return ret;
2402 }
2403 
2419 bool vpDisplayX::getClick(vpImagePoint &ip, bool blocking)
2420 {
2421  bool ret = false;
2422 
2425  ret = m_impl->getClick(ip, button, blocking, m_scale);
2426  }
2427  else {
2428  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2429  }
2430  return ret;
2431 }
2432 
2453 {
2454  bool ret = false;
2455 
2457  ret = m_impl->getClick(ip, button, blocking, m_scale);
2458  }
2459  else {
2460  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2461  }
2462  return ret;
2463 }
2464 
2489 {
2490  bool ret = false;
2491 
2493  ret = m_impl->getClickUp(ip, button, blocking, m_scale);
2494  }
2495  else {
2496  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2497  }
2498  return ret;
2499 }
2500 
2501 /*
2502  Gets the displayed image (including the overlay plane)
2503  and returns an RGBa image. If a scale factor is set using setScale(), the
2504  size of the image is the size of the down scaled image.
2505 
2506  \param I : Image to get.
2507 */
2509 {
2511  m_impl->getImage(I, m_width, m_height);
2512  }
2513  else {
2514  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2515  }
2516 }
2517 
2521 unsigned int vpDisplayX::getScreenDepth() { return m_impl->getScreenDepth(); }
2522 
2527 void vpDisplayX::getScreenSize(unsigned int &w, unsigned int &h) { m_impl->getScreenSize(w, h); }
2528 
2533 {
2534  unsigned int width, height;
2535  getScreenSize(width, height);
2536  return width;
2537 }
2538 
2543 {
2544  unsigned int width, height;
2545  getScreenSize(width, height);
2546  return height;
2547 }
2548 
2569 bool vpDisplayX::getKeyboardEvent(bool blocking)
2570 {
2571  bool ret = false;
2572 
2574  ret = m_impl->getKeyboardEvent(blocking);
2575  }
2576  else {
2577  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2578  }
2579  return ret;
2580 }
2581 
2605 bool vpDisplayX::getKeyboardEvent(std::string &key, bool blocking)
2606 {
2607  bool ret = false;
2609  ret = m_impl->getKeyboardEvent(key, blocking);
2610  }
2611  else {
2612  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2613  }
2614  return ret;
2615 }
2629 {
2630 
2631  bool ret = false;
2633  ret = m_impl->getPointerMotionEvent(ip, m_scale);
2634  }
2635  else {
2636  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2637  }
2638  return ret;
2639 }
2640 
2652 {
2653  bool ret = false;
2655  ret = m_impl->getPointerPosition(ip, m_scale);
2656  }
2657  else {
2658  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2659  }
2660  return ret;
2661 }
2662 
2663 END_VISP_NAMESPACE
2664 
2665 #elif !defined(VISP_BUILD_SHARED_LIBS)
2666 // Work around to avoid warning: libvisp_gui.a(vpDisplayX.cpp.o) has no symbols
2667 void dummy_vpDisplayX() { };
2668 #endif
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:157
static const vpColor white
Definition: vpColor.h:212
vpColorIdentifier id
Definition: vpColor.h:206
static const vpColor red
Definition: vpColor.h:217
static const vpColor darkGray
Definition: vpColor.h:215
static const vpColor cyan
Definition: vpColor.h:226
static const vpColor orange
Definition: vpColor.h:227
static const vpColor darkRed
Definition: vpColor.h:218
static const vpColor blue
Definition: vpColor.h:223
static const vpColor lightGray
Definition: vpColor.h:213
static const vpColor lightBlue
Definition: vpColor.h:222
static const vpColor darkGreen
Definition: vpColor.h:221
static const vpColor darkBlue
Definition: vpColor.h:224
static const vpColor purple
Definition: vpColor.h:228
static const vpColor lightGreen
Definition: vpColor.h:219
static const vpColor yellow
Definition: vpColor.h:225
@ 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
static const vpColor lightRed
Definition: vpColor.h:216
static const vpColor black
Definition: vpColor.h:211
static const vpColor green
Definition: vpColor.h:220
static const vpColor gray
Definition: vpColor.h:214
Error that can be emitted by the vpDisplay class and its derivatives.
@ connexionError
Connection error.
@ colorAllocError
Color allocation error.
@ cannotOpenWindowError
Unable to open display window.
@ notInitializedError
Display not initialized.
@ XWindowsError
XWindow error.
@ depthNotSupportedError
Color depth not supported.
bool getPointerPosition(vpImagePoint &ip) VP_OVERRIDE
unsigned int getScreenDepth()
unsigned int getScreenWidth() 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
void setFont(const std::string &font) VP_OVERRIDE
unsigned int getScreenHeight() VP_OVERRIDE
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1) VP_OVERRIDE
virtual ~vpDisplayX() VP_OVERRIDE
void getImage(vpImage< vpRGBa > &I) VP_OVERRIDE
Get the window pixmap and put it in vpRGBa image.
void getScreenSize(unsigned int &width, unsigned int &height) VP_OVERRIDE
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true) VP_OVERRIDE
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1) VP_OVERRIDE
void flushDisplay() VP_OVERRIDE
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="") VP_OVERRIDE
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height) VP_OVERRIDE
bool getKeyboardEvent(bool blocking=true) VP_OVERRIDE
void clearDisplay(const vpColor &color=vpColor::white) VP_OVERRIDE
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
bool getClick(bool blocking=true) VP_OVERRIDE
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
void setWindowPosition(int win_x, int win_y) VP_OVERRIDE
bool getPointerMotionEvent(vpImagePoint &ip) VP_OVERRIDE
void displayImage(const vpImage< unsigned char > &I) VP_OVERRIDE
void displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color=vpColor::green) VP_OVERRIDE
void closeDisplay() VP_OVERRIDE
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height) VP_OVERRIDE
void setTitle(const std::string &title) VP_OVERRIDE
Class that defines generic functionalities for display.
Definition: vpDisplay.h:178
unsigned int m_height
Definition: vpDisplay.h:930
vpScaleType m_scaleType
Definition: vpDisplay.h:933
unsigned int m_width
Definition: vpDisplay.h:929
static void display(const vpImage< unsigned char > &I)
int m_windowXPosition
display position
Definition: vpDisplay.h:926
std::string m_title
Definition: vpDisplay.h:931
int m_windowYPosition
display position
Definition: vpDisplay.h:928
unsigned int m_scale
Definition: vpDisplay.h:932
bool m_displayHasBeenInitialized
display has been initialized
Definition: vpDisplay.h:924
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Definition: vpDisplay.cpp:262
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
void set_j(double jj)
Definition: vpImagePoint.h:309
double get_j() const
Definition: vpImagePoint.h:125
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
void set_i(double ii)
Definition: vpImagePoint.h:298
double get_u() const
Definition: vpImagePoint.h:136
void set_u(double u)
Definition: vpImagePoint.h:335
void set_v(double v)
Definition: vpImagePoint.h:346
double get_i() const
Definition: vpImagePoint.h:114
double get_v() const
Definition: vpImagePoint.h:147
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:538
Type * bitmap
points toward the bitmap
Definition: vpImage.h:135
unsigned int getHeight() const
Definition: vpImage.h:181
vpDisplay * display
Definition: vpImage.h:136
static double sqr(double x)
Definition: vpMath.h:203
static int round(double x)
Definition: vpMath.h:409
Definition: vpRGBa.h:65
unsigned char B
Blue component.
Definition: vpRGBa.h:169
unsigned char R
Red component.
Definition: vpRGBa.h:167
unsigned char G
Green component.
Definition: vpRGBa.h:168
@ alpha_default
Definition: vpRGBa.h:67
unsigned char A
Additionnal component.
Definition: vpRGBa.h:170
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 getHeight() const
Definition: vpRect.h:166