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