Visual Servoing Platform  version 3.5.1 under development (2023-03-14)
vpDisplayX.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Image display.
33  *
34  * Authors:
35  * Fabien Spindler
36  * Anthony Saunier
37  *
38  *****************************************************************************/
39 
45 #include <visp3/core/vpConfig.h>
46 #ifdef VISP_HAVE_X11
47 
48 #include <cmath> // std::fabs
49 #include <iostream>
50 #include <limits> // numeric_limits
51 #include <stdio.h>
52 #include <stdlib.h>
53 
54 // Display stuff
55 #include <visp3/core/vpDisplay.h>
56 #include <visp3/gui/vpDisplayX.h>
57 
58 // debug / exception
59 #include <visp3/core/vpDebug.h>
60 #include <visp3/core/vpDisplayException.h>
61 
62 // math
63 #include <visp3/core/vpMath.h>
64 
65 #ifndef DOXYGEN_SHOULD_SKIP_THIS
66 
67 #include <X11/Xlib.h>
68 #include <X11/Xutil.h>
69 
70 // Work around to use this class with Eigen3
71 #ifdef Success
72 #undef Success // See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=253
73 #endif
74 
75 class vpDisplayX::Impl
76 {
77 public:
78  Impl()
79  : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
80  screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
81  BShift(0)
82  {
83  }
84 
85  ~Impl() {}
86 
87  void clearDisplay(const vpColor &color, unsigned int width, unsigned int height)
88  {
89  if (color.id < vpColor::id_unknown)
90  XSetWindowBackground(display, window, x_color[color.id]);
91  else {
92  xcolor.pad = 0;
93  xcolor.red = 256 * color.R;
94  xcolor.green = 256 * color.G;
95  xcolor.blue = 256 * color.B;
96  XAllocColor(display, lut, &xcolor);
97  XSetForeground(display, context, xcolor.pixel);
98  }
99 
100  XClearWindow(display, window);
101 
102  XFreePixmap(display, pixmap);
103  // Pixmap creation.
104  pixmap = XCreatePixmap(display, window, width, height, screen_depth);
105  }
106 
107  void closeDisplay()
108  {
109  if (ximage_data_init == true)
110  free(Ximage->data);
111 
112  Ximage->data = NULL;
113  XDestroyImage(Ximage);
114 
115  XFreePixmap(display, pixmap);
116 
117  XFreeGC(display, context);
118  XDestroyWindow(display, window);
119  XCloseDisplay(display);
120 
121  if (x_color != NULL) {
122  delete[] x_color;
123  x_color = NULL;
124  }
125  }
126 
127  void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color, unsigned int scale)
128  {
129  if (color.id < vpColor::id_unknown)
130  XSetForeground(display, context, x_color[color.id]);
131  else {
132  xcolor.pad = 0;
133  xcolor.red = 256 * color.R;
134  xcolor.green = 256 * color.G;
135  xcolor.blue = 256 * color.B;
136  XAllocColor(display, lut, &xcolor);
137  XSetForeground(display, context, xcolor.pixel);
138  }
139  XDrawString(display, pixmap, context, (int)(ip.get_u() / scale), (int)(ip.get_v() / scale), text,
140  (int)strlen(text));
141  }
142 
143  void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
144  unsigned int thickness, unsigned int scale)
145  {
146  if (color.id < vpColor::id_unknown)
147  XSetForeground(display, context, x_color[color.id]);
148  else {
149  xcolor.pad = 0;
150  xcolor.red = 256 * color.R;
151  xcolor.green = 256 * color.G;
152  xcolor.blue = 256 * color.B;
153  XAllocColor(display, lut, &xcolor);
154  XSetForeground(display, context, xcolor.pixel);
155  }
156 
157  XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
158 
159  if (fill == false) {
160  XDrawArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / scale),
161  vpMath::round((center.get_v() - radius) / scale), radius * 2 / scale, radius * 2 / scale, 0,
162  23040); /* 23040 = 360*64 */
163  } else {
164  XFillArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / scale),
165  vpMath::round((center.get_v() - radius) / scale), radius * 2 / scale, radius * 2 / scale, 0,
166  23040); /* 23040 = 360*64 */
167  }
168  }
169 
170  void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
171  unsigned int scale)
172  {
173  if (color.id < vpColor::id_unknown)
174  XSetForeground(display, context, x_color[color.id]);
175  else {
176  xcolor.pad = 0;
177  xcolor.red = 256 * color.R;
178  xcolor.green = 256 * color.G;
179  xcolor.blue = 256 * color.B;
180  XAllocColor(display, lut, &xcolor);
181  XSetForeground(display, context, xcolor.pixel);
182  }
183 
184  XSetLineAttributes(display, context, thickness, LineOnOffDash, CapButt, JoinBevel);
185 
186  XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
187  vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
188  }
189 
190  void displayImage(const vpImage<unsigned char> &I, unsigned int scale, unsigned int width, unsigned int height)
191  {
192  switch (screen_depth) {
193  case 8: {
194  // Correction de l'image de facon a liberer les niveaux de gris
195  // ROUGE, VERT, BLEU, JAUNE
196  unsigned char nivGrisMax = 255 - vpColor::id_unknown;
197  if (scale == 1) {
198  unsigned char *src_8 = (unsigned char *)I.bitmap;
199  unsigned char *dst_8 = (unsigned char *)Ximage->data;
200  unsigned int i = 0;
201  unsigned int size = width * height;
202 
203  while (i < size) {
204  unsigned char nivGris = src_8[i];
205  if (nivGris > nivGrisMax)
206  dst_8[i] = 255;
207  else
208  dst_8[i] = nivGris;
209  i++;
210  }
211  } else {
212  // Correction de l'image de facon a liberer les niveaux de gris
213  // ROUGE, VERT, BLEU, JAUNE
214  unsigned char *dst_8 = (unsigned char *)Ximage->data;
215  unsigned int k = 0;
216  for (unsigned int i = 0; i < height; i++) {
217  for (unsigned int j = 0; j < width; j++) {
218  unsigned char nivGris = I[i * scale][j * scale];
219  if (nivGris > nivGrisMax)
220  dst_8[k++] = 255;
221  else
222  dst_8[k++] = nivGris;
223  }
224  }
225  }
226 
227  // Affichage de l'image dans la Pixmap.
228  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
229  XSetWindowBackgroundPixmap(display, window, pixmap);
230  break;
231  }
232  case 16: {
233  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
234  if (scale == 1) {
235  for (unsigned int i = 0; i < height; i++) {
236  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
237  unsigned short *dst_16 = (unsigned short *)dst_8;
238  for (unsigned int j = 0; j < width; j++) {
239  *(dst_16 + j) = (unsigned short)colortable[I[i][j]];
240  }
241  }
242  } else {
243  for (unsigned int i = 0; i < height; i++) {
244  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
245  unsigned short *dst_16 = (unsigned short *)dst_8;
246  for (unsigned int j = 0; j < width; j++) {
247  *(dst_16 + j) = (unsigned short)colortable[I[i * scale][j * scale]];
248  }
249  }
250  }
251 
252  // Affichage de l'image dans la Pixmap.
253  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
254  XSetWindowBackgroundPixmap(display, window, pixmap);
255  break;
256  }
257 
258  case 24:
259  default: {
260  unsigned char *dst_32 = (unsigned char *)Ximage->data;
261  if (scale == 1) {
262  unsigned int size_ = width * height;
263  unsigned char *bitmap = I.bitmap;
264  unsigned char *n = I.bitmap + size_;
265  // for (unsigned int i = 0; i < size; i++) // suppression de
266  // l'iterateur i
267  if (XImageByteOrder(display) == 1) {
268  // big endian
269  while (bitmap < n) {
270  unsigned char val = *(bitmap++);
271  *(dst_32++) = vpRGBa::alpha_default;
272  *(dst_32++) = val; // Red
273  *(dst_32++) = val; // Green
274  *(dst_32++) = val; // Blue
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  } else {
287  if (XImageByteOrder(display) == 1) {
288  // big endian
289  for (unsigned int i = 0; i < height; i++) {
290  for (unsigned int j = 0; j < width; j++) {
291  unsigned char val = I[i * scale][j * scale];
292  *(dst_32++) = vpRGBa::alpha_default;
293  *(dst_32++) = val; // Red
294  *(dst_32++) = val; // Green
295  *(dst_32++) = val; // Blue
296  }
297  }
298  } else {
299  // little endian
300  for (unsigned int i = 0; i < height; i++) {
301  for (unsigned int j = 0; j < width; j++) {
302  unsigned char val = I[i * scale][j * scale];
303  *(dst_32++) = val; // Blue
304  *(dst_32++) = val; // Green
305  *(dst_32++) = val; // Red
306  *(dst_32++) = vpRGBa::alpha_default;
307  }
308  }
309  }
310  }
311 
312  // Affichage de l'image dans la Pixmap.
313  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
314  XSetWindowBackgroundPixmap(display, window, pixmap);
315  break;
316  }
317  }
318  }
319 
320  void displayImage(const vpImage<vpRGBa> &I, unsigned int scale, unsigned int width, unsigned int height)
321  {
322  switch (screen_depth) {
323  case 16: {
324  vpRGBa *bitmap = I.bitmap;
325  unsigned int r, g, b;
326  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
327 
328  if (scale == 1) {
329  for (unsigned int i = 0; i < height; i++) {
330  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
331  unsigned short *dst_16 = (unsigned short *)dst_8;
332  for (unsigned int j = 0; j < width; j++) {
333  r = bitmap->R;
334  g = bitmap->G;
335  b = bitmap->B;
336  *(dst_16 + j) =
337  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
338  bitmap++;
339  }
340  }
341  } else {
342  for (unsigned int i = 0; i < height; i++) {
343  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
344  unsigned short *dst_16 = (unsigned short *)dst_8;
345  for (unsigned int j = 0; j < width; j++) {
346  vpRGBa val = I[i * scale][j * scale];
347  r = val.R;
348  g = val.G;
349  b = val.B;
350  *(dst_16 + j) =
351  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
352  bitmap++;
353  }
354  }
355  }
356 
357  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
358  XSetWindowBackgroundPixmap(display, window, pixmap);
359 
360  break;
361  }
362  case 24:
363  case 32: {
364  /*
365  * 32-bit source, 24/32-bit destination
366  */
367  unsigned char *dst_32 = NULL;
368  dst_32 = (unsigned char *)Ximage->data;
369  if (scale == 1) {
370  vpRGBa *bitmap = I.bitmap;
371  unsigned int sizeI = width * height;
372  if (XImageByteOrder(display) == 1) {
373  // big endian
374  for (unsigned int i = 0; i < sizeI; i++) {
375  *(dst_32++) = bitmap->A;
376  *(dst_32++) = bitmap->R;
377  *(dst_32++) = bitmap->G;
378  *(dst_32++) = bitmap->B;
379  bitmap++;
380  }
381  } else {
382  // little endian
383  for (unsigned int i = 0; i < sizeI; i++) {
384  *(dst_32++) = bitmap->B;
385  *(dst_32++) = bitmap->G;
386  *(dst_32++) = bitmap->R;
387  *(dst_32++) = bitmap->A;
388  bitmap++;
389  }
390  }
391  } else {
392  if (XImageByteOrder(display) == 1) {
393  // big endian
394  for (unsigned int i = 0; i < height; i++) {
395  for (unsigned int j = 0; j < width; j++) {
396  vpRGBa val = I[i * scale][j * scale];
397  *(dst_32++) = val.A;
398  *(dst_32++) = val.R;
399  *(dst_32++) = val.G;
400  *(dst_32++) = val.B;
401  }
402  }
403  } else {
404  // little endian
405  for (unsigned int i = 0; i < height; i++) {
406  for (unsigned int j = 0; j < width; j++) {
407  vpRGBa val = I[i * scale][j * scale];
408  *(dst_32++) = val.B;
409  *(dst_32++) = val.G;
410  *(dst_32++) = val.R;
411  *(dst_32++) = val.A;
412  }
413  }
414  }
415  }
416 
417  // Affichage de l'image dans la Pixmap.
418  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
419  XSetWindowBackgroundPixmap(display, window, pixmap);
420  break;
421  }
422  default:
424  "Unsupported depth (%d bpp) for color display", screen_depth));
425  }
426  }
427 
428  void displayImage(const unsigned char *bitmap, unsigned int width, unsigned int height)
429  {
430  unsigned char *dst_32 = (unsigned char *)Ximage->data;
431  for (unsigned int i = 0; i < width * height; i++) {
432  *(dst_32++) = *bitmap; // red component.
433  *(dst_32++) = *bitmap; // green component.
434  *(dst_32++) = *bitmap; // blue component.
435  *(dst_32++) = *bitmap; // luminance component.
436  bitmap++;
437  }
438 
439  // Affichage de l'image dans la Pixmap.
440  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
441  XSetWindowBackgroundPixmap(display, window, pixmap);
442  }
443 
444  void displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w, unsigned int h,
445  unsigned int scale, unsigned int width, unsigned int height)
446  {
447  switch (screen_depth) {
448  case 8: {
449  // Correction de l'image de facon a liberer les niveaux de gris
450  // ROUGE, VERT, BLEU, JAUNE
451  unsigned char nivGrisMax = 255 - vpColor::id_unknown;
452  if (scale == 1) {
453  unsigned char *src_8 = (unsigned char *)I.bitmap;
454  unsigned char *dst_8 = (unsigned char *)Ximage->data;
455  unsigned int iwidth = I.getWidth();
456 
457  src_8 = src_8 + (int)(iP.get_i() * iwidth + iP.get_j());
458  dst_8 = dst_8 + (int)(iP.get_i() * width + iP.get_j());
459 
460  unsigned int i = 0;
461  while (i < h) {
462  unsigned int j = 0;
463  while (j < w) {
464  unsigned char nivGris = *(src_8 + j);
465  if (nivGris > nivGrisMax)
466  *(dst_8 + j) = 255;
467  else
468  *(dst_8 + j) = nivGris;
469  j++;
470  }
471  src_8 = src_8 + iwidth;
472  dst_8 = dst_8 + width;
473  i++;
474  }
475 
476  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
477  w, h);
478  } else {
479  // Correction de l'image de facon a liberer les niveaux de gris
480  // ROUGE, VERT, BLEU, JAUNE
481  int i_min = (std::max)((int)ceil(iP.get_i() / scale), 0);
482  int j_min = (std::max)((int)ceil(iP.get_j() / scale), 0);
483  int i_max = (std::min)((int)ceil((iP.get_i() + h) / scale), (int)height);
484  int j_max = (std::min)((int)ceil((iP.get_j() + w) / scale), (int)width);
485 
486  unsigned int i_min_ = (unsigned int)i_min;
487  unsigned int i_max_ = (unsigned int)i_max;
488  unsigned int j_min_ = (unsigned int)j_min;
489  unsigned int j_max_ = (unsigned int)j_max;
490 
491  for (unsigned int i = i_min_; i < i_max_; i++) {
492  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * width;
493  for (unsigned int j = j_min_; j < j_max_; j++) {
494  unsigned char nivGris = I[i * scale][j * scale];
495  if (nivGris > nivGrisMax)
496  dst_8[j] = 255;
497  else
498  dst_8[j] = nivGris;
499  }
500  }
501  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
502  }
503 
504  // Affichage de l'image dans la Pixmap.
505  XSetWindowBackgroundPixmap(display, window, pixmap);
506  break;
507  }
508  case 16: {
509  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
510  if (scale == 1) {
511  for (unsigned int i = (unsigned int)iP.get_i(); i < (unsigned int)(iP.get_i() + h); i++) {
512  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
513  unsigned short *dst_16 = (unsigned short *)dst_8;
514  for (unsigned int j = (unsigned int)iP.get_j(); j < (unsigned int)(iP.get_j() + w); j++) {
515  *(dst_16 + j) = (unsigned short)colortable[I[i][j]];
516  }
517  }
518 
519  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
520  w, h);
521  } else {
522  int i_min = (std::max)((int)ceil(iP.get_i() / scale), 0);
523  int j_min = (std::max)((int)ceil(iP.get_j() / scale), 0);
524  int i_max = (std::min)((int)ceil((iP.get_i() + h) / scale), (int)height);
525  int j_max = (std::min)((int)ceil((iP.get_j() + w) / scale), (int)width);
526 
527  unsigned int i_min_ = (unsigned int)i_min;
528  unsigned int i_max_ = (unsigned int)i_max;
529  unsigned int j_min_ = (unsigned int)j_min;
530  unsigned int j_max_ = (unsigned int)j_max;
531 
532  for (unsigned int i = i_min_; i < i_max_; i++) {
533  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
534  unsigned short *dst_16 = (unsigned short *)dst_8;
535  for (unsigned int j = j_min_; j < j_max_; j++) {
536  *(dst_16 + j) = (unsigned short)colortable[I[i * scale][j * scale]];
537  }
538  }
539 
540  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
541  }
542 
543  XSetWindowBackgroundPixmap(display, window, pixmap);
544  break;
545  }
546 
547  case 24:
548  default: {
549  if (scale == 1) {
550  unsigned int iwidth = I.getWidth();
551  unsigned char *src_8 = I.bitmap + (int)(iP.get_i() * iwidth + iP.get_j());
552  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(iP.get_i() * 4 * width + iP.get_j() * 4);
553 
554  if (XImageByteOrder(display) == 1) {
555  // big endian
556  unsigned int i = 0;
557  while (i < h) {
558  unsigned int j = 0;
559  while (j < w) {
560  unsigned char val = *(src_8 + j);
561  *(dst_32 + 4 * j) = vpRGBa::alpha_default;
562  *(dst_32 + 4 * j + 1) = val;
563  *(dst_32 + 4 * j + 2) = val;
564  *(dst_32 + 4 * j + 3) = val;
565  j++;
566  }
567  src_8 = src_8 + iwidth;
568  dst_32 = dst_32 + 4 * width;
569  i++;
570  }
571  } else {
572  // little endian
573  unsigned int i = 0;
574  while (i < h) {
575  unsigned int j = 0;
576  while (j < w) {
577  unsigned char val = *(src_8 + j);
578  *(dst_32 + 4 * j) = val;
579  *(dst_32 + 4 * j + 1) = val;
580  *(dst_32 + 4 * j + 2) = val;
581  *(dst_32 + 4 * j + 3) = vpRGBa::alpha_default;
582  j++;
583  }
584  src_8 = src_8 + iwidth;
585  dst_32 = dst_32 + 4 * width;
586  i++;
587  }
588  }
589 
590  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
591  w, h);
592  } else {
593  int i_min = (std::max)((int)ceil(iP.get_i() / scale), 0);
594  int j_min = (std::max)((int)ceil(iP.get_j() / scale), 0);
595  int i_max = (std::min)((int)ceil((iP.get_i() + h) / scale), (int)height);
596  int j_max = (std::min)((int)ceil((iP.get_j() + w) / scale), (int)width);
597 
598  unsigned int i_min_ = (unsigned int)i_min;
599  unsigned int i_max_ = (unsigned int)i_max;
600  unsigned int j_min_ = (unsigned int)j_min;
601  unsigned int j_max_ = (unsigned int)j_max;
602 
603  if (XImageByteOrder(display) == 1) {
604  // big endian
605  for (unsigned int i = i_min_; i < i_max_; i++) {
606  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
607  for (unsigned int j = j_min_; j < j_max_; j++) {
608  unsigned char val = I[i * scale][j * scale];
609  *(dst_32++) = vpRGBa::alpha_default;
610  *(dst_32++) = val;
611  *(dst_32++) = val;
612  *(dst_32++) = val;
613  }
614  }
615  } else {
616  // little endian
617  for (unsigned int i = i_min_; i < i_max_; i++) {
618  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
619  for (unsigned int j = j_min_; j < j_max_; j++) {
620  unsigned char val = I[i * scale][j * scale];
621  *(dst_32++) = val;
622  *(dst_32++) = val;
623  *(dst_32++) = val;
624  *(dst_32++) = vpRGBa::alpha_default;
625  }
626  }
627  }
628 
629  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
630  }
631 
632  XSetWindowBackgroundPixmap(display, window, pixmap);
633  break;
634  }
635  }
636  }
637 
638  void displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h,
639  unsigned int scale, unsigned int width, unsigned int height)
640  {
641  switch (screen_depth) {
642  case 16: {
643  if (scale == 1) {
644  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
645  for (unsigned int i = (unsigned int)iP.get_i(); i < (unsigned int)(iP.get_i() + h); i++) {
646  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
647  unsigned short *dst_16 = (unsigned short *)dst_8;
648  for (unsigned int j = (unsigned int)iP.get_j(); j < (unsigned int)(iP.get_j() + w); j++) {
649  vpRGBa val = I[i][j];
650  unsigned int r = val.R;
651  unsigned int g = val.G;
652  unsigned int b = val.B;
653  *(dst_16 + j) =
654  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
655  }
656  }
657  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
658  w, h);
659  } else {
660  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
661  int i_min = (std::max)((int)ceil(iP.get_i() / scale), 0);
662  int j_min = (std::max)((int)ceil(iP.get_j() / scale), 0);
663  int i_max = (std::min)((int)ceil((iP.get_i() + h) / scale), (int)height);
664  int j_max = (std::min)((int)ceil((iP.get_j() + w) / scale), (int)width);
665 
666  unsigned int i_min_ = (unsigned int)i_min;
667  unsigned int i_max_ = (unsigned int)i_max;
668  unsigned int j_min_ = (unsigned int)j_min;
669  unsigned int j_max_ = (unsigned int)j_max;
670 
671  for (unsigned int i = i_min_; i < i_max_; i++) {
672  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
673  unsigned short *dst_16 = (unsigned short *)dst_8;
674  for (unsigned int j = j_min_; j < j_max_; j++) {
675  vpRGBa val = I[i * scale][j * scale];
676  unsigned int r = val.R;
677  unsigned int g = val.G;
678  unsigned int b = val.B;
679  *(dst_16 + j) =
680  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
681  }
682  }
683  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
684  }
685 
686  XSetWindowBackgroundPixmap(display, window, pixmap);
687 
688  break;
689  }
690  case 24:
691  case 32: {
692  /*
693  * 32-bit source, 24/32-bit destination
694  */
695 
696  if (scale == 1) {
697  unsigned char *dst_32 = (unsigned char *)Ximage->data;
698  vpRGBa *src_32 = I.bitmap;
699 
700  unsigned int iwidth = I.getWidth();
701 
702  src_32 = src_32 + (int)(iP.get_i() * iwidth + iP.get_j());
703  dst_32 = dst_32 + (int)(iP.get_i() * 4 * width + iP.get_j() * 4);
704 
705  unsigned int i = 0;
706 
707  if (XImageByteOrder(display) == 1) {
708  // big endian
709  while (i < h) {
710  unsigned int j = 0;
711  while (j < w) {
712  *(dst_32 + 4 * j) = (src_32 + j)->A;
713  *(dst_32 + 4 * j + 1) = (src_32 + j)->R;
714  *(dst_32 + 4 * j + 2) = (src_32 + j)->G;
715  *(dst_32 + 4 * j + 3) = (src_32 + j)->B;
716 
717  j++;
718  }
719  src_32 = src_32 + iwidth;
720  dst_32 = dst_32 + 4 * width;
721  i++;
722  }
723 
724  } else {
725  // little endian
726  while (i < h) {
727  unsigned int j = 0;
728  while (j < w) {
729  *(dst_32 + 4 * j) = (src_32 + j)->B;
730  *(dst_32 + 4 * j + 1) = (src_32 + j)->G;
731  *(dst_32 + 4 * j + 2) = (src_32 + j)->R;
732  *(dst_32 + 4 * j + 3) = (src_32 + j)->A;
733 
734  j++;
735  }
736  src_32 = src_32 + iwidth;
737  dst_32 = dst_32 + 4 * width;
738  i++;
739  }
740  }
741 
742  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
743  w, h);
744  } else {
745  int i_min = (std::max)((int)ceil(iP.get_i() / scale), 0);
746  int j_min = (std::max)((int)ceil(iP.get_j() / scale), 0);
747  int i_max = (std::min)((int)ceil((iP.get_i() + h) / scale), (int)height);
748  int j_max = (std::min)((int)ceil((iP.get_j() + w) / scale), (int)width);
749 
750  unsigned int i_min_ = (unsigned int)i_min;
751  unsigned int i_max_ = (unsigned int)i_max;
752  unsigned int j_min_ = (unsigned int)j_min;
753  unsigned int j_max_ = (unsigned int)j_max;
754 
755  if (XImageByteOrder(display) == 1) {
756  // big endian
757  for (unsigned int i = i_min_; i < i_max_; i++) {
758  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
759  for (unsigned int j = j_min_; j < j_max_; j++) {
760  vpRGBa val = I[i * scale][j * scale];
761  *(dst_32++) = val.A;
762  *(dst_32++) = val.R;
763  *(dst_32++) = val.G;
764  *(dst_32++) = val.B;
765  }
766  }
767  } else {
768  // little endian
769  for (unsigned int i = i_min_; i < i_max_; i++) {
770  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
771  for (unsigned int j = j_min_; j < j_max_; j++) {
772  vpRGBa val = I[i * scale][j * scale];
773  *(dst_32++) = val.B;
774  *(dst_32++) = val.G;
775  *(dst_32++) = val.R;
776  *(dst_32++) = val.A;
777  }
778  }
779  }
780  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
781  }
782 
783  XSetWindowBackgroundPixmap(display, window, pixmap);
784  break;
785  }
786  default:
788  "Unsupported depth (%d bpp) for color display", screen_depth));
789  }
790  }
791 
792  void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
793  unsigned int scale)
794  {
795  if (color.id < vpColor::id_unknown)
796  XSetForeground(display, context, x_color[color.id]);
797  else {
798  xcolor.pad = 0;
799  xcolor.red = 256 * color.R;
800  xcolor.green = 256 * color.G;
801  xcolor.blue = 256 * color.B;
802  XAllocColor(display, lut, &xcolor);
803  XSetForeground(display, context, xcolor.pixel);
804  }
805 
806  XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
807 
808  XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
809  vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
810  }
811 
812  void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness, unsigned int scale)
813  {
814  if (color.id < vpColor::id_unknown)
815  XSetForeground(display, context, x_color[color.id]);
816  else {
817  xcolor.pad = 0;
818  xcolor.red = 256 * color.R;
819  xcolor.green = 256 * color.G;
820  xcolor.blue = 256 * color.B;
821  XAllocColor(display, lut, &xcolor);
822  XSetForeground(display, context, xcolor.pixel);
823  }
824 
825  if (thickness == 1) {
826  XDrawPoint(display, pixmap, context, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale));
827  } else {
828  XFillRectangle(display, pixmap, context, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale),
829  thickness, thickness);
830  }
831  }
832 
833  void displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color, bool fill,
834  unsigned int thickness, unsigned int scale)
835  {
836  if (color.id < vpColor::id_unknown)
837  XSetForeground(display, context, x_color[color.id]);
838  else {
839  xcolor.pad = 0;
840  xcolor.red = 256 * color.R;
841  xcolor.green = 256 * color.G;
842  xcolor.blue = 256 * color.B;
843  XAllocColor(display, lut, &xcolor);
844  XSetForeground(display, context, xcolor.pixel);
845  }
846  XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
847  if (fill == false) {
848  XDrawRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / scale),
849  vpMath::round(topLeft.get_v() / scale), w / scale, h / scale);
850  } else {
851  XFillRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / scale),
852  vpMath::round(topLeft.get_v() / scale), w / scale, h / scale);
853  }
854  }
855 
856  void flushDisplay()
857  {
858  XClearWindow(display, window);
859  XFlush(display);
860  }
861 
862  void flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h, unsigned int scale)
863  {
864  XClearArea(display, window, (int)(iP.get_u() / scale), (int)(iP.get_v() / scale), w / scale, h / scale, 0);
865  XFlush(display);
866  }
867 
868  bool getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale)
869  {
870  bool ret = false;
871  Window rootwin, childwin;
872  int root_x, root_y, win_x, win_y;
873  unsigned int modifier;
874 
875  // Event testing
876  if (blocking) {
877  XCheckMaskEvent(display, ButtonPressMask, &event);
878  XCheckMaskEvent(display, ButtonReleaseMask, &event);
879  XMaskEvent(display, ButtonPressMask, &event);
880  ret = true;
881  } else {
882  ret = XCheckMaskEvent(display, ButtonPressMask, &event);
883  }
884 
885  if (ret) {
886  // Get mouse position
887  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
888  ip.set_u((double)event.xbutton.x * scale);
889  ip.set_v((double)event.xbutton.y * scale);
890  switch (event.xbutton.button) {
891  case Button1:
892  button = vpMouseButton::button1;
893  break;
894  case Button2:
895  button = vpMouseButton::button2;
896  break;
897  case Button3:
898  button = vpMouseButton::button3;
899  break;
900  }
901  }
902  }
903 
904  return ret;
905  }
906 
907  bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale)
908  {
909  bool ret = false;
910  Window rootwin, childwin;
911  int root_x, root_y, win_x, win_y;
912  unsigned int modifier;
913 
914  // Event testing
915  if (blocking) {
916  XCheckMaskEvent(display, ButtonPressMask, &event);
917  XCheckMaskEvent(display, ButtonReleaseMask, &event);
918  XMaskEvent(display, ButtonReleaseMask, &event);
919  ret = true;
920  } else {
921  ret = XCheckMaskEvent(display, ButtonReleaseMask, &event);
922  }
923 
924  if (ret) {
925  /* Recuperation de la coordonnee du pixel clique. */
926  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
927  ip.set_u((double)event.xbutton.x * scale);
928  ip.set_v((double)event.xbutton.y * scale);
929  switch (event.xbutton.button) {
930  case Button1:
931  button = vpMouseButton::button1;
932  break;
933  case Button2:
934  button = vpMouseButton::button2;
935  break;
936  case Button3:
937  button = vpMouseButton::button3;
938  break;
939  }
940  }
941  }
942 
943  return ret;
944  }
945 
946  void getImage(vpImage<vpRGBa> &I, unsigned int width, unsigned int height)
947  {
948  XImage *xi;
949 
950  XCopyArea(display, window, pixmap, context, 0, 0, width, height, 0, 0);
951 
952  xi = XGetImage(display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap);
953 
954  I.resize(height, width);
955 
956  unsigned char *src_32 = NULL;
957  src_32 = (unsigned char *)xi->data;
958 
959  if (screen_depth == 16) {
960  for (unsigned int i = 0; i < I.getHeight(); i++) {
961  size_t i_ = i * width;
962  for (unsigned int j = 0; j < height; j++) {
963  size_t ij_ = i_ + j;
964  unsigned long pixel = XGetPixel(xi, (int)j, (int)i);
965  I.bitmap[ij_].R = (((pixel & RMask) << RShift) >> 8);
966  I.bitmap[ij_].G = (((pixel & GMask) << GShift) >> 8);
967  I.bitmap[ij_].B = (((pixel & BMask) << BShift) >> 8);
968  // On OSX the bottom/right corner (around the resizing icon) has
969  // alpha component with different values than 255. That's why we
970  // force alpha to vpRGBa::alpha_default
971  I.bitmap[ij_].A = vpRGBa::alpha_default;
972  }
973  }
974 
975  } else {
976  if (XImageByteOrder(display) == 1) {
977  // big endian
978  for (unsigned int i = 0; i < width * height; i++) {
979  // On OSX the bottom/right corner (around the resizing icon) has
980  // alpha component with different values than 255. That's why we
981  // force alpha to vpRGBa::alpha_default
982  I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4] ;
983  I.bitmap[i].R = src_32[i * 4 + 1];
984  I.bitmap[i].G = src_32[i * 4 + 2];
985  I.bitmap[i].B = src_32[i * 4 + 3];
986  }
987  } else {
988  // little endian
989  for (unsigned int i = 0; i < width * height; i++) {
990  I.bitmap[i].B = src_32[i * 4];
991  I.bitmap[i].G = src_32[i * 4 + 1];
992  I.bitmap[i].R = src_32[i * 4 + 2];
993  // On OSX the bottom/right corner (around the resizing icon) has
994  // alpha component with different values than 255. That's why we
995  // force alpha to vpRGBa::alpha_default
996  I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4 + 3];
997  }
998  }
999  }
1000  XDestroyImage(xi);
1001  }
1002 
1003  bool getKeyboardEvent(bool blocking)
1004  {
1005  bool ret = false;
1006 
1007  // Event testing
1008  if (blocking) {
1009  XMaskEvent(display, KeyPressMask, &event);
1010  ret = true;
1011  } else {
1012  ret = XCheckMaskEvent(display, KeyPressMask, &event);
1013  }
1014 
1015  return ret;
1016  }
1017 
1018  bool getKeyboardEvent(std::string &key, bool blocking)
1019  {
1020  bool ret = false;
1021  KeySym keysym;
1022  // int count;
1023  XComposeStatus compose_status;
1024  char buffer;
1025 
1026  // Event testing
1027  if (blocking) {
1028  XMaskEvent(display, KeyPressMask, &event);
1029  /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
1030  key = buffer;
1031  ret = true;
1032  } else {
1033  ret = XCheckMaskEvent(display, KeyPressMask, &event);
1034  if (ret) {
1035  /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
1036  key = buffer;
1037  }
1038  }
1039 
1040  return ret;
1041  }
1042 
1046  int getMsb(unsigned int u32val)
1047  {
1048  int i;
1049 
1050  for (i = 31; i >= 0; --i) {
1051  if (u32val & 0x80000000L)
1052  break;
1053  u32val <<= 1;
1054  }
1055  return i;
1056  }
1057 
1058  bool getPointerMotionEvent(vpImagePoint &ip, unsigned int scale)
1059  {
1060  bool ret = false;
1061 
1062  Window rootwin, childwin;
1063  int root_x, root_y, win_x, win_y;
1064  unsigned int modifier;
1065  // Event testing
1066  ret = XCheckMaskEvent(display, PointerMotionMask, &event);
1067 
1068  if (ret) {
1069  // Get mouse position
1070  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
1071  ip.set_u((double)event.xbutton.x * scale);
1072  ip.set_v((double)event.xbutton.y * scale);
1073  }
1074  }
1075 
1076  return ret;
1077  }
1078 
1079  bool getPointerPosition(vpImagePoint &ip, unsigned int scale)
1080  {
1081  bool ret = false;
1082  Window rootwin, childwin;
1083  int root_x, root_y, win_x, win_y;
1084  unsigned int modifier;
1085  // Event testing
1086  ret = true;
1087 
1088  if (ret) {
1089  // Get mouse position
1090  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
1091  ip.set_u((double)win_x * scale);
1092  ip.set_v((double)win_y * scale);
1093  }
1094  }
1095 
1096  return ret;
1097  }
1098 
1099  unsigned int getScreenDepth()
1100  {
1101  Display *display_;
1102  int screen_;
1103  unsigned int depth;
1104 
1105  if ((display_ = XOpenDisplay(NULL)) == NULL) {
1106  throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
1107  XDisplayName(NULL)));
1108  }
1109  screen_ = DefaultScreen(display_);
1110  depth = (unsigned int)DefaultDepth(display_, screen_);
1111 
1112  XCloseDisplay(display_);
1113 
1114  return (depth);
1115  }
1116 
1117  void getScreenSize(unsigned int &w, unsigned int &h)
1118  {
1119  Display *display_;
1120  int screen_;
1121 
1122  if ((display_ = XOpenDisplay(NULL)) == NULL) {
1123  throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
1124  XDisplayName(NULL)));
1125  }
1126  screen_ = DefaultScreen(display_);
1127  w = (unsigned int)DisplayWidth(display_, screen_);
1128  h = (unsigned int)DisplayHeight(display_, screen_);
1129 
1130  XCloseDisplay(display_);
1131  }
1132 
1133  void init(unsigned int win_width, unsigned int win_height, int win_x, int win_y, const std::string &win_title)
1134  {
1135  if (x_color == NULL) {
1136  // id_unknown = number of predefined colors
1137  x_color = new unsigned long[vpColor::id_unknown];
1138  }
1139  // setup X11
1140  XSizeHints hints;
1141 
1142  // Positionnement de la fenetre dans l'ecran.
1143  if ((win_x < 0) || (win_y < 0)) {
1144  hints.flags = 0;
1145  } else {
1146  hints.flags = USPosition;
1147  hints.x = win_x;
1148  hints.y = win_y;
1149  }
1150 
1151  if ((display = XOpenDisplay(NULL)) == NULL) {
1152  vpERROR_TRACE("Can't connect display on server %s.\n", XDisplayName(NULL));
1153  throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server."));
1154  }
1155 
1156  screen = DefaultScreen(display);
1157  lut = DefaultColormap(display, screen);
1158  screen_depth = (unsigned int)DefaultDepth(display, screen);
1159 
1160  vpTRACE("Screen depth: %d\n", screen_depth);
1161 
1162  if ((window = XCreateSimpleWindow(display, RootWindow(display, screen), win_x, win_y, win_width, win_height, 1,
1163  BlackPixel(display, screen), WhitePixel(display, screen))) == 0) {
1164  vpERROR_TRACE("Can't create window.");
1165  throw(vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create window."));
1166  }
1167 
1168  //
1169  // Create color table for 8 and 16 bits screen
1170  //
1171  if (screen_depth == 8) {
1172  lut = XCreateColormap(display, window, DefaultVisual(display, screen), AllocAll);
1173  xcolor.flags = DoRed | DoGreen | DoBlue;
1174 
1175  for (unsigned int i = 0; i < 256; i++) {
1176  xcolor.pixel = i;
1177  xcolor.red = 256 * i;
1178  xcolor.green = 256 * i;
1179  xcolor.blue = 256 * i;
1180  XStoreColor(display, lut, &xcolor);
1181  }
1182 
1183  XSetWindowColormap(display, window, lut);
1184  XInstallColormap(display, lut);
1185  }
1186 
1187  else if (screen_depth == 16) {
1188  for (unsigned int i = 0; i < 256; i++) {
1189  xcolor.pad = 0;
1190  xcolor.red = xcolor.green = xcolor.blue = 256 * i;
1191  if (XAllocColor(display, lut, &xcolor) == 0) {
1192  vpERROR_TRACE("Can't allocate 256 colors. Only %d allocated.", i);
1193  throw(vpDisplayException(vpDisplayException::colorAllocError, "Can't allocate 256 colors."));
1194  }
1195  colortable[i] = xcolor.pixel;
1196  }
1197 
1198  XSetWindowColormap(display, window, lut);
1199  XInstallColormap(display, lut);
1200 
1201  Visual *visual = DefaultVisual(display, screen);
1202  RMask = visual->red_mask;
1203  GMask = visual->green_mask;
1204  BMask = visual->blue_mask;
1205 
1206  RShift = 15 - getMsb(RMask); /* these are right-shifts */
1207  GShift = 15 - getMsb(GMask);
1208  BShift = 15 - getMsb(BMask);
1209  }
1210 
1211  vpColor pcolor; // predefined colors
1212 
1213  //
1214  // Create colors for overlay
1215  //
1216  switch (screen_depth) {
1217 
1218  case 8:
1219  // Color BLACK: default set to 0
1220 
1221  // Color WHITE: default set to 255
1222 
1223  // Color LIGHT GRAY.
1224  x_color[vpColor::id_lightGray] = 254;
1225  xcolor.pixel = x_color[vpColor::id_lightGray];
1226  xcolor.red = 256 * 192;
1227  xcolor.green = 256 * 192;
1228  xcolor.blue = 256 * 192;
1229  XStoreColor(display, lut, &xcolor);
1230 
1231  // Color GRAY.
1232  x_color[vpColor::id_gray] = 253;
1233  xcolor.pixel = x_color[vpColor::id_gray];
1234  xcolor.red = 256 * 128;
1235  xcolor.green = 256 * 128;
1236  xcolor.blue = 256 * 128;
1237  XStoreColor(display, lut, &xcolor);
1238 
1239  // Color DARK GRAY.
1240  x_color[vpColor::id_darkGray] = 252;
1241  xcolor.pixel = x_color[vpColor::id_darkGray];
1242  xcolor.red = 256 * 64;
1243  xcolor.green = 256 * 64;
1244  xcolor.blue = 256 * 64;
1245  XStoreColor(display, lut, &xcolor);
1246 
1247  // Color LIGHT RED.
1248  x_color[vpColor::id_lightRed] = 251;
1249  xcolor.pixel = x_color[vpColor::id_lightRed];
1250  xcolor.red = 256 * 255;
1251  xcolor.green = 256 * 140;
1252  xcolor.blue = 256 * 140;
1253  XStoreColor(display, lut, &xcolor);
1254 
1255  // Color RED.
1256  x_color[vpColor::id_red] = 250;
1257  xcolor.pixel = x_color[vpColor::id_red];
1258  xcolor.red = 256 * 255;
1259  xcolor.green = 0;
1260  xcolor.blue = 0;
1261  XStoreColor(display, lut, &xcolor);
1262 
1263  // Color DARK RED.
1264  x_color[vpColor::id_darkRed] = 249;
1265  xcolor.pixel = x_color[vpColor::id_darkRed];
1266  xcolor.red = 256 * 128;
1267  xcolor.green = 0;
1268  xcolor.blue = 0;
1269  XStoreColor(display, lut, &xcolor);
1270 
1271  // Color LIGHT GREEN.
1272  x_color[vpColor::id_lightGreen] = 248;
1273  xcolor.pixel = x_color[vpColor::id_lightGreen];
1274  xcolor.red = 256 * 140;
1275  xcolor.green = 256 * 255;
1276  xcolor.blue = 256 * 140;
1277  XStoreColor(display, lut, &xcolor);
1278 
1279  // Color GREEN.
1280  x_color[vpColor::id_green] = 247;
1281  xcolor.pixel = x_color[vpColor::id_green];
1282  xcolor.red = 0;
1283  xcolor.green = 256 * 255;
1284  xcolor.blue = 0;
1285  XStoreColor(display, lut, &xcolor);
1286 
1287  // Color DARK GREEN.
1288  x_color[vpColor::id_darkGreen] = 246;
1289  xcolor.pixel = x_color[vpColor::id_darkGreen];
1290  xcolor.red = 0;
1291  xcolor.green = 256 * 128;
1292  xcolor.blue = 0;
1293  XStoreColor(display, lut, &xcolor);
1294 
1295  // Color LIGHT BLUE.
1296  x_color[vpColor::id_lightBlue] = 245;
1297  xcolor.pixel = x_color[vpColor::id_lightBlue];
1298  xcolor.red = 256 * 140;
1299  xcolor.green = 256 * 140;
1300  xcolor.blue = 256 * 255;
1301  XStoreColor(display, lut, &xcolor);
1302 
1303  // Color BLUE.
1304  x_color[vpColor::id_blue] = 244;
1305  xcolor.pixel = x_color[vpColor::id_blue];
1306  xcolor.red = 0;
1307  xcolor.green = 0;
1308  xcolor.blue = 256 * 255;
1309  XStoreColor(display, lut, &xcolor);
1310 
1311  // Color DARK BLUE.
1312  x_color[vpColor::id_darkBlue] = 243;
1313  xcolor.pixel = x_color[vpColor::id_darkBlue];
1314  xcolor.red = 0;
1315  xcolor.green = 0;
1316  xcolor.blue = 256 * 128;
1317  XStoreColor(display, lut, &xcolor);
1318 
1319  // Color YELLOW.
1320  x_color[vpColor::id_yellow] = 242;
1321  xcolor.pixel = x_color[vpColor::id_yellow];
1322  xcolor.red = 256 * 255;
1323  xcolor.green = 256 * 255;
1324  xcolor.blue = 0;
1325  XStoreColor(display, lut, &xcolor);
1326 
1327  // Color ORANGE.
1328  x_color[vpColor::id_orange] = 241;
1329  xcolor.pixel = x_color[vpColor::id_orange];
1330  xcolor.red = 256 * 255;
1331  xcolor.green = 256 * 165;
1332  xcolor.blue = 0;
1333  XStoreColor(display, lut, &xcolor);
1334 
1335  // Color CYAN.
1336  x_color[vpColor::id_cyan] = 240;
1337  xcolor.pixel = x_color[vpColor::id_cyan];
1338  xcolor.red = 0;
1339  xcolor.green = 256 * 255;
1340  xcolor.blue = 256 * 255;
1341  XStoreColor(display, lut, &xcolor);
1342 
1343  // Color PURPLE.
1344  x_color[vpColor::id_purple] = 239;
1345  xcolor.pixel = x_color[vpColor::id_purple];
1346  xcolor.red = 256 * 128;
1347  xcolor.green = 0;
1348  xcolor.blue = 256 * 128;
1349  XStoreColor(display, lut, &xcolor);
1350 
1351  break;
1352 
1353  case 16:
1354  case 24:
1355  case 32: {
1356  xcolor.flags = DoRed | DoGreen | DoBlue;
1357 
1358  // Couleur BLACK.
1359  pcolor = vpColor::black;
1360  xcolor.pad = 0;
1361  xcolor.red = 256 * pcolor.R;
1362  xcolor.green = 256 * pcolor.G;
1363  xcolor.blue = 256 * pcolor.B;
1364  XAllocColor(display, lut, &xcolor);
1365  x_color[vpColor::id_black] = xcolor.pixel;
1366 
1367  // Color WHITE.
1368  pcolor = vpColor::white;
1369  xcolor.pad = 0;
1370  xcolor.red = 256 * pcolor.R;
1371  xcolor.green = 256 * pcolor.G;
1372  xcolor.blue = 256 * pcolor.B;
1373  XAllocColor(display, lut, &xcolor);
1374  x_color[vpColor::id_white] = xcolor.pixel;
1375 
1376  // Color LIGHT GRAY.
1377  pcolor = vpColor::lightGray;
1378  xcolor.pad = 0;
1379  xcolor.red = 256 * pcolor.R;
1380  xcolor.green = 256 * pcolor.G;
1381  xcolor.blue = 256 * pcolor.B;
1382  XAllocColor(display, lut, &xcolor);
1383  x_color[vpColor::id_lightGray] = xcolor.pixel;
1384 
1385  // Color GRAY.
1386  pcolor = vpColor::gray;
1387  xcolor.pad = 0;
1388  xcolor.red = 256 * pcolor.R;
1389  xcolor.green = 256 * pcolor.G;
1390  xcolor.blue = 256 * pcolor.B;
1391  XAllocColor(display, lut, &xcolor);
1392  x_color[vpColor::id_gray] = xcolor.pixel;
1393 
1394  // Color DARK GRAY.
1395  pcolor = vpColor::darkGray;
1396  xcolor.pad = 0;
1397  xcolor.red = 256 * pcolor.R;
1398  xcolor.green = 256 * pcolor.G;
1399  xcolor.blue = 256 * pcolor.B;
1400  XAllocColor(display, lut, &xcolor);
1401  x_color[vpColor::id_darkGray] = xcolor.pixel;
1402 
1403  // Color LIGHT RED.
1404  pcolor = vpColor::lightRed;
1405  xcolor.pad = 0;
1406  xcolor.red = 256 * pcolor.R;
1407  xcolor.green = 256 * pcolor.G;
1408  xcolor.blue = 256 * pcolor.B;
1409  XAllocColor(display, lut, &xcolor);
1410  x_color[vpColor::id_lightRed] = xcolor.pixel;
1411 
1412  // Color RED.
1413  pcolor = vpColor::red;
1414  xcolor.pad = 0;
1415  xcolor.red = 256 * pcolor.R;
1416  xcolor.green = 256 * pcolor.G;
1417  xcolor.blue = 256 * pcolor.B;
1418  XAllocColor(display, lut, &xcolor);
1419  x_color[vpColor::id_red] = xcolor.pixel;
1420 
1421  // Color DARK RED.
1422  pcolor = vpColor::darkRed;
1423  xcolor.pad = 0;
1424  xcolor.red = 256 * pcolor.R;
1425  xcolor.green = 256 * pcolor.G;
1426  xcolor.blue = 256 * pcolor.B;
1427  XAllocColor(display, lut, &xcolor);
1428  x_color[vpColor::id_darkRed] = xcolor.pixel;
1429 
1430  // Color LIGHT GREEN.
1431  pcolor = vpColor::lightGreen;
1432  xcolor.pad = 0;
1433  xcolor.red = 256 * pcolor.R;
1434  xcolor.green = 256 * pcolor.G;
1435  xcolor.blue = 256 * pcolor.B;
1436  XAllocColor(display, lut, &xcolor);
1437  x_color[vpColor::id_lightGreen] = xcolor.pixel;
1438 
1439  // Color GREEN.
1440  pcolor = vpColor::green;
1441  xcolor.pad = 0;
1442  xcolor.red = 256 * pcolor.R;
1443  xcolor.green = 256 * pcolor.G;
1444  xcolor.blue = 256 * pcolor.B;
1445  XAllocColor(display, lut, &xcolor);
1446  x_color[vpColor::id_green] = xcolor.pixel;
1447 
1448  // Color DARK GREEN.
1449  pcolor = vpColor::darkGreen;
1450  xcolor.pad = 0;
1451  xcolor.red = 256 * pcolor.R;
1452  xcolor.green = 256 * pcolor.G;
1453  xcolor.blue = 256 * pcolor.B;
1454  XAllocColor(display, lut, &xcolor);
1455  x_color[vpColor::id_darkGreen] = xcolor.pixel;
1456 
1457  // Color LIGHT BLUE.
1458  pcolor = vpColor::lightBlue;
1459  xcolor.pad = 0;
1460  xcolor.red = 256 * pcolor.R;
1461  xcolor.green = 256 * pcolor.G;
1462  xcolor.blue = 256 * pcolor.B;
1463  XAllocColor(display, lut, &xcolor);
1464  x_color[vpColor::id_lightBlue] = xcolor.pixel;
1465 
1466  // Color BLUE.
1467  pcolor = vpColor::blue;
1468  xcolor.pad = 0;
1469  xcolor.red = 256 * pcolor.R;
1470  xcolor.green = 256 * pcolor.G;
1471  xcolor.blue = 256 * pcolor.B;
1472  XAllocColor(display, lut, &xcolor);
1473  x_color[vpColor::id_blue] = xcolor.pixel;
1474 
1475  // Color DARK BLUE.
1476  pcolor = vpColor::darkBlue;
1477  xcolor.pad = 0;
1478  xcolor.red = 256 * pcolor.R;
1479  xcolor.green = 256 * pcolor.G;
1480  xcolor.blue = 256 * pcolor.B;
1481  XAllocColor(display, lut, &xcolor);
1482  x_color[vpColor::id_darkBlue] = xcolor.pixel;
1483 
1484  // Color YELLOW.
1485  pcolor = vpColor::yellow;
1486  xcolor.pad = 0;
1487  xcolor.red = 256 * pcolor.R;
1488  xcolor.green = 256 * pcolor.G;
1489  xcolor.blue = 256 * pcolor.B;
1490  XAllocColor(display, lut, &xcolor);
1491  x_color[vpColor::id_yellow] = xcolor.pixel;
1492 
1493  // Color ORANGE.
1494  pcolor = vpColor::orange;
1495  xcolor.pad = 0;
1496  xcolor.red = 256 * pcolor.R;
1497  xcolor.green = 256 * pcolor.G;
1498  xcolor.blue = 256 * pcolor.B;
1499  XAllocColor(display, lut, &xcolor);
1500  x_color[vpColor::id_orange] = xcolor.pixel;
1501 
1502  // Color CYAN.
1503  pcolor = vpColor::cyan;
1504  xcolor.pad = 0;
1505  xcolor.red = 256 * pcolor.R;
1506  xcolor.green = 256 * pcolor.G;
1507  xcolor.blue = 256 * pcolor.B;
1508  XAllocColor(display, lut, &xcolor);
1509  x_color[vpColor::id_cyan] = xcolor.pixel;
1510 
1511  // Color PURPLE.
1512  pcolor = vpColor::purple;
1513  xcolor.pad = 0;
1514  xcolor.red = 256 * pcolor.R;
1515  xcolor.green = 256 * pcolor.G;
1516  xcolor.blue = 256 * pcolor.B;
1517  XAllocColor(display, lut, &xcolor);
1518  x_color[vpColor::id_purple] = xcolor.pixel;
1519  break;
1520  }
1521  }
1522 
1523  XSetStandardProperties(display, window, win_title.c_str(), win_title.c_str(), None, 0, 0, &hints);
1524  XMapWindow(display, window);
1525  // Selection des evenements.
1526  XSelectInput(display, window,
1527  ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
1528  StructureNotifyMask | PointerMotionMask);
1529 
1530  /* Creation du contexte graphique */
1531  values.plane_mask = AllPlanes;
1532  values.fill_style = FillSolid;
1533  values.foreground = WhitePixel(display, screen);
1534  values.background = BlackPixel(display, screen);
1535  context = XCreateGC(display, window, GCPlaneMask | GCFillStyle | GCForeground | GCBackground, &values);
1536 
1537  if (context == NULL) {
1538  vpERROR_TRACE("Can't create graphics context.");
1539  throw(vpDisplayException(vpDisplayException::XWindowsError, "Can't create graphics context"));
1540  }
1541 
1542  // Pixmap creation.
1543  pixmap = XCreatePixmap(display, window, win_width, win_height, screen_depth);
1544 
1545  // Hangs when forward X11 is used to send the display to an other computer
1546  // do
1547  // XNextEvent ( display, &event );
1548  // while ( event.xany.type != Expose );
1549 
1550  {
1551  Ximage = XCreateImage(display, DefaultVisual(display, screen), screen_depth, ZPixmap, 0, NULL, win_width,
1552  win_height, XBitmapPad(display), 0);
1553 
1554  Ximage->data = (char *)malloc(win_height * (unsigned int)Ximage->bytes_per_line);
1555  ximage_data_init = true;
1556  }
1557 
1558  XSync(display, true);
1559 
1560  XStoreName(display, window, win_title.c_str());
1561  }
1562 
1563  void setFont(const std::string &fontname)
1564  {
1565  try {
1566  Font stringfont;
1567  stringfont = XLoadFont(display, fontname.c_str()); //"-adobe-times-bold-r-normal--18*");
1568  XSetFont(display, context, stringfont);
1569  } catch (...) {
1571  }
1572  }
1573 
1574  void setTitle(const std::string &title) { XStoreName(display, window, title.c_str()); }
1575 
1576  void setWindowPosition(int win_x, int win_y) { XMoveWindow(display, window, win_x, win_y); }
1577 
1578 private:
1579  Display *display;
1580  Window window;
1581  XImage *Ximage;
1582  Colormap lut;
1583  GC context;
1584  int screen;
1585  XEvent event;
1586  Pixmap pixmap;
1587  unsigned long *x_color; // Array of predefined colors
1588  unsigned int screen_depth;
1589  unsigned short colortable[256];
1590  XColor xcolor;
1591  XGCValues values;
1592  bool ximage_data_init;
1593  unsigned int RMask, GMask, BMask;
1594  int RShift, GShift, BShift;
1595 };
1596 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
1597 
1618 {
1619  setScale(scaleType, I.getWidth(), I.getHeight());
1620 
1621  init(I);
1622 }
1623 
1645 vpDisplayX::vpDisplayX(vpImage<unsigned char> &I, int x, int y, const std::string &title, vpScaleType scaleType)
1646  : vpDisplay(), m_impl(new Impl())
1647 {
1648  setScale(scaleType, I.getWidth(), I.getHeight());
1649  init(I, x, y, title);
1650 }
1651 
1671 vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, vpScaleType scaleType) : vpDisplay(), m_impl(new Impl())
1672 {
1673  setScale(scaleType, I.getWidth(), I.getHeight());
1674  init(I);
1675 }
1676 
1698 vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, int x, int y, const std::string &title, vpScaleType scaleType)
1699  : vpDisplay(), m_impl(new Impl())
1700 {
1701  setScale(scaleType, I.getWidth(), I.getHeight());
1702  init(I, x, y, title);
1703 }
1704 
1726 vpDisplayX::vpDisplayX(int x, int y, const std::string &title) : vpDisplay(), m_impl(new Impl())
1727 {
1728  m_windowXPosition = x;
1729  m_windowYPosition = y;
1730 
1731  m_title = title;
1732 }
1733 
1753 vpDisplayX::vpDisplayX() : vpDisplay(), m_impl(new Impl()) {}
1754 
1759 {
1760  closeDisplay();
1761  delete m_impl;
1762 }
1763 
1771 void vpDisplayX::init(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title)
1772 {
1773  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
1774  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
1775  }
1776 
1777  if (win_x != -1)
1778  m_windowXPosition = win_x;
1779  if (win_y != -1)
1780  m_windowYPosition = win_y;
1781 
1782  if (!win_title.empty())
1783  m_title = win_title;
1784 
1787 
1788  I.display = this;
1790 }
1791 
1800 void vpDisplayX::init(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title)
1801 {
1802  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
1803  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
1804  }
1805 
1806  if (win_x != -1)
1807  m_windowXPosition = win_x;
1808  if (win_y != -1)
1809  m_windowYPosition = win_y;
1810 
1811  if (!win_title.empty())
1812  m_title = win_title;
1813 
1816 
1817  I.display = this;
1819 }
1820 
1828 void vpDisplayX::init(unsigned int win_width, unsigned int win_height, int win_x, int win_y,
1829  const std::string &win_title)
1830 {
1831  setScale(m_scaleType, win_width, win_height);
1832 
1833  m_width = win_width / m_scale;
1834  m_height = win_height / m_scale;
1835 
1836  if (win_x != -1)
1837  m_windowXPosition = win_x;
1838  if (win_y != -1)
1839  m_windowYPosition = win_y;
1840 
1841  m_title = win_title;
1842 
1844 
1846 }
1847 
1862 void vpDisplayX::setFont(const std::string &fontname)
1863 {
1865  if (!fontname.empty()) {
1866  m_impl->setFont(fontname);
1867  }
1868  } else {
1869  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1870  }
1871 }
1872 
1877 void vpDisplayX::setTitle(const std::string &title)
1878 {
1880  m_title = title;
1881  if (!title.empty())
1882  m_impl->setTitle(title);
1883  } else {
1884  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1885  }
1886 }
1887 
1897 void vpDisplayX::setWindowPosition(int win_x, int win_y)
1898 {
1900  m_impl->setWindowPosition(win_x, win_y);
1901  } else {
1902  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1903  }
1904 }
1905 
1918 {
1920  m_impl->displayImage(I, m_scale, m_width, m_height);
1921  } else {
1922  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1923  }
1924 }
1925 
1938 {
1940  m_impl->displayImage(I, m_scale, m_width, m_height);
1941  } else {
1942  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1943  }
1944 }
1945 
1957 void vpDisplayX::displayImage(const unsigned char *bitmap)
1958 {
1960  m_impl->displayImage(bitmap, m_width, m_height);
1961  } else {
1962  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1963  }
1964 }
1965 
1981 void vpDisplayX::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w,
1982  unsigned int h)
1983 {
1985  m_impl->displayImageROI(I, iP, w, h, m_scale, m_width, m_height);
1986  } else {
1987  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1988  }
1989 }
1990 
2006 void vpDisplayX::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h)
2007 {
2009  m_impl->displayImageROI(I, iP, w, h, m_scale, m_width, m_height);
2010  } else {
2011  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2012  }
2013 }
2014 
2023 {
2025  m_impl->closeDisplay();
2026 
2028  }
2029 }
2030 
2037 {
2039  m_impl->flushDisplay();
2040  } else {
2041  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2042  }
2043 }
2044 
2052 void vpDisplayX::flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h)
2053 {
2055  m_impl->flushDisplayROI(iP, w, h, m_scale);
2056  } else {
2057  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2058  }
2059 }
2060 
2066 {
2068  m_impl->clearDisplay(color, m_width, m_height);
2069  } else {
2070  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2071  }
2072 }
2073 
2081 void vpDisplayX::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
2082  unsigned int h, unsigned int thickness)
2083 {
2085  double a = ip2.get_i() - ip1.get_i();
2086  double b = ip2.get_j() - ip1.get_j();
2087  double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
2088 
2089  // if ( ( a==0 ) && ( b==0 ) )
2090  if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
2091  (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
2092  // DisplayCrossLarge(i1,j1,3,col) ;
2093  } else {
2094  a /= lg;
2095  b /= lg;
2096 
2097  vpImagePoint ip3;
2098  ip3.set_i(ip2.get_i() - w * a);
2099  ip3.set_j(ip2.get_j() - w * b);
2100 
2101  vpImagePoint ip4;
2102  ip4.set_i(ip3.get_i() - b * h);
2103  ip4.set_j(ip3.get_j() + a * h);
2104 
2105  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2106  displayLine(ip2, ip4, color, thickness);
2107 
2108  ip4.set_i(ip3.get_i() + b * h);
2109  ip4.set_j(ip3.get_j() - a * h);
2110 
2111  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2112  displayLine(ip2, ip4, color, thickness);
2113 
2114  displayLine(ip1, ip2, color, thickness);
2115  }
2116  } else {
2117  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2118  }
2119 }
2120 
2132 void vpDisplayX::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
2133 {
2135  m_impl->displayCharString(ip, text, color, m_scale);
2136  } else {
2137  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2138  }
2139 }
2140 
2150 void vpDisplayX::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
2151  unsigned int thickness)
2152 {
2154  if (thickness == 1)
2155  thickness = 0;
2156  m_impl->displayCircle(center, radius, color, fill, thickness, m_scale);
2157  } else {
2158  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2159  }
2160 }
2161 
2169 void vpDisplayX::displayCross(const vpImagePoint &ip, unsigned int cross_size, const vpColor &color,
2170  unsigned int thickness)
2171 {
2173  double i = ip.get_i();
2174  double j = ip.get_j();
2175  vpImagePoint ip1, ip2;
2176 
2177  ip1.set_i(i - cross_size / 2);
2178  ip1.set_j(j);
2179  ip2.set_i(i + cross_size / 2);
2180  ip2.set_j(j);
2181  displayLine(ip1, ip2, color, thickness);
2182 
2183  ip1.set_i(i);
2184  ip1.set_j(j - cross_size / 2);
2185  ip2.set_i(i);
2186  ip2.set_j(j + cross_size / 2);
2187 
2188  displayLine(ip1, ip2, color, thickness);
2189  } else {
2190  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2191  }
2192 }
2199 void vpDisplayX::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2200  unsigned int thickness)
2201 {
2203  if (thickness == 1)
2204  thickness = 0;
2205 
2206  m_impl->displayDotLine(ip1, ip2, color, thickness, m_scale);
2207  } else {
2208  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2209  }
2210 }
2211 
2218 void vpDisplayX::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2219  unsigned int thickness)
2220 {
2222  if (thickness == 1)
2223  thickness = 0;
2224 
2225  m_impl->displayLine(ip1, ip2, color, thickness, m_scale);
2226  } else {
2227  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2228  }
2229 }
2230 
2237 void vpDisplayX::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
2238 {
2240  m_impl->displayPoint(ip, color, thickness, m_scale);
2241  } else {
2242  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2243  }
2244 }
2245 
2259 void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
2260  bool fill, unsigned int thickness)
2261 {
2263  if (thickness == 1)
2264  thickness = 0;
2265 
2266  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2267  } else {
2268  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2269  }
2270 }
2271 
2284 void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
2285  bool fill, unsigned int thickness)
2286 {
2288  if (thickness == 1)
2289  thickness = 0;
2290 
2291  unsigned int w = static_cast<unsigned int>(vpMath::round(bottomRight.get_u() - topLeft.get_u()));
2292  unsigned int h = static_cast<unsigned int>(vpMath::round(bottomRight.get_v() - topLeft.get_v()));
2293 
2294  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2295  } else {
2296  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2297  }
2298 }
2299 
2312 void vpDisplayX::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
2313 {
2315  if (thickness == 1)
2316  thickness = 0;
2317  vpImagePoint topLeft = rectangle.getTopLeft();
2318  unsigned int w = static_cast<unsigned int>(vpMath::round(rectangle.getWidth()));
2319  unsigned int h = static_cast<unsigned int>(vpMath::round(rectangle.getHeight()));
2320  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2321  } else {
2322  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2323  }
2324 }
2325 
2341 bool vpDisplayX::getClick(bool blocking)
2342 {
2343  bool ret = false;
2344 
2346  vpImagePoint ip;
2348  ret = m_impl->getClick(ip, button, blocking, m_scale);
2349  } else {
2350  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2351  }
2352  return ret;
2353 }
2354 
2370 bool vpDisplayX::getClick(vpImagePoint &ip, bool blocking)
2371 {
2372  bool ret = false;
2373 
2376  ret = m_impl->getClick(ip, button, blocking, m_scale);
2377  } else {
2378  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2379  }
2380  return ret;
2381 }
2382 
2403 {
2404  bool ret = false;
2405 
2407  ret = m_impl->getClick(ip, button, blocking, m_scale);
2408  } else {
2409  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2410  }
2411  return ret;
2412 }
2413 
2438 {
2439  bool ret = false;
2440 
2442  ret = m_impl->getClickUp(ip, button, blocking, m_scale);
2443  } else {
2444  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2445  }
2446  return ret;
2447 }
2448 
2449 /*
2450  Gets the displayed image (including the overlay plane)
2451  and returns an RGBa image. If a scale factor is set using setScale(), the
2452  size of the image is the size of the downscaled image.
2453 
2454  \param I : Image to get.
2455 */
2457 {
2459  m_impl->getImage(I, m_width, m_height);
2460  } else {
2461  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2462  }
2463 }
2464 
2468 unsigned int vpDisplayX::getScreenDepth() { return m_impl->getScreenDepth(); }
2469 
2474 void vpDisplayX::getScreenSize(unsigned int &w, unsigned int &h) { m_impl->getScreenSize(w, h); }
2475 
2480 {
2481  unsigned int width, height;
2482  getScreenSize(width, height);
2483  return width;
2484 }
2485 
2490 {
2491  unsigned int width, height;
2492  getScreenSize(width, height);
2493  return height;
2494 }
2495 
2516 bool vpDisplayX::getKeyboardEvent(bool blocking)
2517 {
2518  bool ret = false;
2519 
2521  ret = m_impl->getKeyboardEvent(blocking);
2522  } else {
2523  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2524  }
2525  return ret;
2526 }
2527 
2551 bool vpDisplayX::getKeyboardEvent(std::string &key, bool blocking)
2552 {
2553  bool ret = false;
2555  ret = m_impl->getKeyboardEvent(key, blocking);
2556  } else {
2557  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2558  }
2559  return ret;
2560 }
2574 {
2575 
2576  bool ret = false;
2578  ret = m_impl->getPointerMotionEvent(ip, m_scale);
2579  } else {
2580  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2581  }
2582  return ret;
2583 }
2584 
2596 {
2597  bool ret = false;
2599  ret = m_impl->getPointerPosition(ip, m_scale);
2600  } else {
2601  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2602  }
2603  return ret;
2604 }
2605 
2606 #elif !defined(VISP_BUILD_SHARED_LIBS)
2607 // Work around to avoid warning: libvisp_core.a(vpDisplayX.cpp.o) has no
2608 // symbols
2609 void dummy_vpDisplayX(){};
2610 #endif
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:158
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 black
Definition: vpColor.h:211
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 green
Definition: vpColor.h:220
static const vpColor gray
Definition: vpColor.h:214
Error that can be emited by the vpDisplay class and its derivates.
void displayImage(const vpImage< unsigned char > &I)
void setTitle(const std::string &title)
virtual ~vpDisplayX()
unsigned int getScreenDepth()
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height)
void closeDisplay()
void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)
void flushDisplay()
void clearDisplay(const vpColor &color=vpColor::white)
void getScreenSize(unsigned int &width, unsigned int &height)
bool getPointerPosition(vpImagePoint &ip)
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="")
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)
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
void setWindowPosition(int win_x, int win_y)
void getImage(vpImage< vpRGBa > &I)
get the window pixmap and put it in vpRGBa image
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
bool getClick(bool blocking=true)
void setFont(const std::string &font)
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)
unsigned int getScreenHeight()
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height)
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true)
bool getKeyboardEvent(bool blocking=true)
unsigned int getScreenWidth()
bool getPointerMotionEvent(vpImagePoint &ip)
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:178
unsigned int m_height
Definition: vpDisplay.h:216
vpScaleType m_scaleType
Definition: vpDisplay.h:219
unsigned int m_width
Definition: vpDisplay.h:215
static void display(const vpImage< unsigned char > &I)
int m_windowXPosition
display position
Definition: vpDisplay.h:212
std::string m_title
Definition: vpDisplay.h:217
int m_windowYPosition
display position
Definition: vpDisplay.h:214
unsigned int m_scale
Definition: vpDisplay.h:218
bool m_displayHasBeenInitialized
display has been initialized
Definition: vpDisplay.h:210
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Definition: vpDisplay.cpp:259
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:89
void set_j(double jj)
Definition: vpImagePoint.h:309
double get_j() const
Definition: vpImagePoint.h:132
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:143
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:121
double get_v() const
Definition: vpImagePoint.h:154
unsigned int getWidth() const
Definition: vpImage.h:247
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:800
Type * bitmap
points toward the bitmap
Definition: vpImage.h:144
unsigned int getHeight() const
Definition: vpImage.h:189
vpDisplay * display
Definition: vpImage.h:145
static double sqr(double x)
Definition: vpMath.h:127
static int round(double x)
Definition: vpMath.h:326
Definition: vpRGBa.h:67
unsigned char B
Blue component.
Definition: vpRGBa.h:146
unsigned char R
Red component.
Definition: vpRGBa.h:144
unsigned char G
Green component.
Definition: vpRGBa.h:145
@ alpha_default
Definition: vpRGBa.h:69
unsigned char A
Additionnal component.
Definition: vpRGBa.h:147
Defines a rectangle in the plane.
Definition: vpRect.h:80
double getWidth() const
Definition: vpRect.h:228
vpImagePoint getTopLeft() const
Definition: vpRect.h:200
double getHeight() const
Definition: vpRect.h:167
#define vpTRACE
Definition: vpDebug.h:416
#define vpERROR_TRACE
Definition: vpDebug.h:393