Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
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 arround 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 
86  ~Impl() {}
87 
88  void clearDisplay(const vpColor &color, unsigned int width, unsigned int height)
89  {
90  if (color.id < vpColor::id_unknown)
91  XSetWindowBackground(display, window, x_color[color.id]);
92  else {
93  xcolor.pad = 0;
94  xcolor.red = 256 * color.R;
95  xcolor.green = 256 * color.G;
96  xcolor.blue = 256 * color.B;
97  XAllocColor(display, lut, &xcolor);
98  XSetForeground(display, context, xcolor.pixel);
99  }
100 
101  XClearWindow(display, window);
102 
103  XFreePixmap(display, pixmap);
104  // Pixmap creation.
105  pixmap = XCreatePixmap(display, window, width, height, screen_depth);
106  }
107 
108  void closeDisplay()
109  {
110  if (ximage_data_init == true)
111  free(Ximage->data);
112 
113  Ximage->data = NULL;
114  XDestroyImage(Ximage);
115 
116  XFreePixmap(display, pixmap);
117 
118  XFreeGC(display, context);
119  XDestroyWindow(display, window);
120  XCloseDisplay(display);
121 
122  if (x_color != NULL) {
123  delete[] x_color;
124  x_color = NULL;
125  }
126  }
127 
128  void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color, unsigned int scale)
129  {
130  if (color.id < vpColor::id_unknown)
131  XSetForeground(display, context, x_color[color.id]);
132  else {
133  xcolor.pad = 0;
134  xcolor.red = 256 * color.R;
135  xcolor.green = 256 * color.G;
136  xcolor.blue = 256 * color.B;
137  XAllocColor(display, lut, &xcolor);
138  XSetForeground(display, context, xcolor.pixel);
139  }
140  XDrawString(display, pixmap, context, (int)(ip.get_u() / scale), (int)(ip.get_v() / scale), text,
141  (int)strlen(text));
142  }
143 
144  void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
145  unsigned int thickness, unsigned int scale)
146  {
147  if (color.id < vpColor::id_unknown)
148  XSetForeground(display, context, x_color[color.id]);
149  else {
150  xcolor.pad = 0;
151  xcolor.red = 256 * color.R;
152  xcolor.green = 256 * color.G;
153  xcolor.blue = 256 * color.B;
154  XAllocColor(display, lut, &xcolor);
155  XSetForeground(display, context, xcolor.pixel);
156  }
157 
158  XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
159 
160  if (fill == false) {
161  XDrawArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / scale),
162  vpMath::round((center.get_v() - radius) / scale), radius * 2 / scale, radius * 2 / scale, 0,
163  23040); /* 23040 = 360*64 */
164  } else {
165  XFillArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / scale),
166  vpMath::round((center.get_v() - radius) / scale), radius * 2 / scale, radius * 2 / scale, 0,
167  23040); /* 23040 = 360*64 */
168  }
169  }
170 
171  void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
172  unsigned int thickness, unsigned int scale)
173  {
174  if (color.id < vpColor::id_unknown)
175  XSetForeground(display, context, x_color[color.id]);
176  else {
177  xcolor.pad = 0;
178  xcolor.red = 256 * color.R;
179  xcolor.green = 256 * color.G;
180  xcolor.blue = 256 * color.B;
181  XAllocColor(display, lut, &xcolor);
182  XSetForeground(display, context, xcolor.pixel);
183  }
184 
185  XSetLineAttributes(display, context, thickness, LineOnOffDash, CapButt, JoinBevel);
186 
187  XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
188  vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
189  }
190 
191  void displayImage(const vpImage<unsigned char> &I, unsigned int scale, unsigned int width, unsigned int height)
192  {
193  switch (screen_depth) {
194  case 8: {
195  // Correction de l'image de facon a liberer les niveaux de gris
196  // ROUGE, VERT, BLEU, JAUNE
197  unsigned char nivGrisMax = 255 - vpColor::id_unknown;
198  if (scale == 1) {
199  unsigned char *src_8 = (unsigned char *)I.bitmap;
200  unsigned char *dst_8 = (unsigned char *)Ximage->data;
201  unsigned int i = 0;
202  unsigned int size = width * height;
203 
204  while (i < size) {
205  unsigned char nivGris = src_8[i];
206  if (nivGris > nivGrisMax)
207  dst_8[i] = 255;
208  else
209  dst_8[i] = nivGris;
210  i++;
211  }
212  } else {
213  // Correction de l'image de facon a liberer les niveaux de gris
214  // ROUGE, VERT, BLEU, JAUNE
215  unsigned char *dst_8 = (unsigned char *)Ximage->data;
216  unsigned int k = 0;
217  for (unsigned int i = 0; i < height; i++) {
218  for (unsigned int j = 0; j < width; j++) {
219  unsigned char nivGris = I[i * scale][j * scale];
220  if (nivGris > nivGrisMax)
221  dst_8[k++] = 255;
222  else
223  dst_8[k++] = nivGris;
224  }
225  }
226  }
227 
228  // Affichage de l'image dans la Pixmap.
229  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
230  XSetWindowBackgroundPixmap(display, window, pixmap);
231  break;
232  }
233  case 16: {
234  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
235  if (scale == 1) {
236  for (unsigned int i = 0; i < height; i++) {
237  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
238  unsigned short *dst_16 = (unsigned short *)dst_8;
239  for (unsigned int j = 0; j < width; j++) {
240  *(dst_16 + j) = (unsigned short)colortable[I[i][j]];
241  }
242  }
243  } else {
244  for (unsigned int i = 0; i < height; i++) {
245  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
246  unsigned short *dst_16 = (unsigned short *)dst_8;
247  for (unsigned int j = 0; j < width; j++) {
248  *(dst_16 + j) = (unsigned short)colortable[I[i * scale][j * scale]];
249  }
250  }
251  }
252 
253  // Affichage de l'image dans la Pixmap.
254  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
255  XSetWindowBackgroundPixmap(display, window, pixmap);
256  break;
257  }
258 
259  case 24:
260  default: {
261  unsigned char *dst_32 = (unsigned char *)Ximage->data;
262  if (scale == 1) {
263  unsigned int size_ = width * height;
264  unsigned char *bitmap = I.bitmap;
265  unsigned char *n = I.bitmap + size_;
266  // for (unsigned int i = 0; i < size; i++) // suppression de
267  // l'iterateur i
268  if (XImageByteOrder(display) == 1) {
269  // big endian
270  while (bitmap < n) {
271  unsigned char val = *(bitmap++);
272  *(dst_32++) = vpRGBa::alpha_default;
273  *(dst_32++) = val; // Red
274  *(dst_32++) = val; // Green
275  *(dst_32++) = val; // Blue
276  }
277  } else {
278  // little endian
279  while (bitmap < n) {
280  unsigned char val = *(bitmap++);
281  *(dst_32++) = val; // Blue
282  *(dst_32++) = val; // Green
283  *(dst_32++) = val; // Red
284  *(dst_32++) = vpRGBa::alpha_default;
285  }
286  }
287  } else {
288  if (XImageByteOrder(display) == 1) {
289  // big endian
290  for (unsigned int i = 0; i < height; i++) {
291  for (unsigned int j = 0; j < width; j++) {
292  unsigned char val = I[i * scale][j * scale];
293  *(dst_32++) = vpRGBa::alpha_default;
294  *(dst_32++) = val; // Red
295  *(dst_32++) = val; // Green
296  *(dst_32++) = val; // Blue
297  }
298  }
299  } else {
300  // little endian
301  for (unsigned int i = 0; i < height; i++) {
302  for (unsigned int j = 0; j < width; j++) {
303  unsigned char val = I[i * scale][j * scale];
304  *(dst_32++) = val; // Blue
305  *(dst_32++) = val; // Green
306  *(dst_32++) = val; // Red
307  *(dst_32++) = vpRGBa::alpha_default;
308  }
309  }
310  }
311  }
312 
313  // Affichage de l'image dans la Pixmap.
314  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
315  XSetWindowBackgroundPixmap(display, window, pixmap);
316  break;
317  }
318  }
319  }
320 
321  void displayImage(const vpImage<vpRGBa> &I, unsigned int scale, unsigned int width, unsigned int height)
322  {
323  switch (screen_depth) {
324  case 16: {
325  vpRGBa *bitmap = I.bitmap;
326  unsigned int r, g, b;
327  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
328 
329  if (scale == 1) {
330  for (unsigned int i = 0; i < height; i++) {
331  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
332  unsigned short *dst_16 = (unsigned short *)dst_8;
333  for (unsigned int j = 0; j < width; j++) {
334  r = bitmap->R;
335  g = bitmap->G;
336  b = bitmap->B;
337  *(dst_16 + j) =
338  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
339  bitmap++;
340  }
341  }
342  } else {
343  for (unsigned int i = 0; i < height; i++) {
344  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
345  unsigned short *dst_16 = (unsigned short *)dst_8;
346  for (unsigned int j = 0; j < width; j++) {
347  vpRGBa val = I[i * scale][j * scale];
348  r = val.R;
349  g = val.G;
350  b = val.B;
351  *(dst_16 + j) =
352  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
353  bitmap++;
354  }
355  }
356  }
357 
358  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
359  XSetWindowBackgroundPixmap(display, window, pixmap);
360 
361  break;
362  }
363  case 24:
364  case 32: {
365  /*
366  * 32-bit source, 24/32-bit destination
367  */
368  unsigned char *dst_32 = NULL;
369  dst_32 = (unsigned char *)Ximage->data;
370  if (scale == 1) {
371  vpRGBa *bitmap = I.bitmap;
372  unsigned int sizeI = width * height;
373  if (XImageByteOrder(display) == 1) {
374  // big endian
375  for (unsigned int i = 0; i < sizeI; i++) {
376  *(dst_32++) = bitmap->A;
377  *(dst_32++) = bitmap->R;
378  *(dst_32++) = bitmap->G;
379  *(dst_32++) = bitmap->B;
380  bitmap++;
381  }
382  } else {
383  // little endian
384  for (unsigned int i = 0; i < sizeI; i++) {
385  *(dst_32++) = bitmap->B;
386  *(dst_32++) = bitmap->G;
387  *(dst_32++) = bitmap->R;
388  *(dst_32++) = bitmap->A;
389  bitmap++;
390  }
391  }
392  } else {
393  if (XImageByteOrder(display) == 1) {
394  // big endian
395  for (unsigned int i = 0; i < height; i++) {
396  for (unsigned int j = 0; j < width; j++) {
397  vpRGBa val = I[i * scale][j * scale];
398  *(dst_32++) = val.A;
399  *(dst_32++) = val.R;
400  *(dst_32++) = val.G;
401  *(dst_32++) = val.B;
402  }
403  }
404  } else {
405  // little endian
406  for (unsigned int i = 0; i < height; i++) {
407  for (unsigned int j = 0; j < width; j++) {
408  vpRGBa val = I[i * scale][j * scale];
409  *(dst_32++) = val.B;
410  *(dst_32++) = val.G;
411  *(dst_32++) = val.R;
412  *(dst_32++) = val.A;
413  }
414  }
415  }
416  }
417 
418  // Affichage de l'image dans la Pixmap.
419  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
420  XSetWindowBackgroundPixmap(display, window, pixmap);
421  break;
422  }
423  default:
425  "Unsupported depth (%d bpp) for color display", screen_depth));
426  }
427  }
428 
429  void displayImage(const unsigned char *bitmap, unsigned int width, unsigned int height)
430  {
431  unsigned char *dst_32 = (unsigned char *)Ximage->data;
432  for (unsigned int i = 0; i < width * height; i++) {
433  *(dst_32++) = *bitmap; // red component.
434  *(dst_32++) = *bitmap; // green component.
435  *(dst_32++) = *bitmap; // blue component.
436  *(dst_32++) = *bitmap; // luminance component.
437  bitmap++;
438  }
439 
440  // Affichage de l'image dans la Pixmap.
441  XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
442  XSetWindowBackgroundPixmap(display, window, pixmap);
443  }
444 
446  const vpImagePoint &iP, unsigned int w, unsigned int h,
447  unsigned int scale, unsigned int width, unsigned int height)
448  {
449  switch (screen_depth) {
450  case 8: {
451  // Correction de l'image de facon a liberer les niveaux de gris
452  // ROUGE, VERT, BLEU, JAUNE
453  unsigned char nivGrisMax = 255 - vpColor::id_unknown;
454  if (scale == 1) {
455  unsigned char *src_8 = (unsigned char *)I.bitmap;
456  unsigned char *dst_8 = (unsigned char *)Ximage->data;
457  unsigned int iwidth = I.getWidth();
458 
459  src_8 = src_8 + (int)(iP.get_i() * iwidth + iP.get_j());
460  dst_8 = dst_8 + (int)(iP.get_i() * width + iP.get_j());
461 
462  unsigned int i = 0;
463  while (i < h) {
464  unsigned int j = 0;
465  while (j < w) {
466  unsigned char nivGris = *(src_8 + j);
467  if (nivGris > nivGrisMax)
468  *(dst_8 + j) = 255;
469  else
470  *(dst_8 + j) = nivGris;
471  j++;
472  }
473  src_8 = src_8 + iwidth;
474  dst_8 = dst_8 + width;
475  i++;
476  }
477 
478  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
479  w, h);
480  } else {
481  // Correction de l'image de facon a liberer les niveaux de gris
482  // ROUGE, VERT, BLEU, JAUNE
483  int i_min = (std::max)((int)ceil(iP.get_i() / scale), 0);
484  int j_min = (std::max)((int)ceil(iP.get_j() / scale), 0);
485  int i_max = (std::min)((int)ceil((iP.get_i() + h) / scale), (int)height);
486  int j_max = (std::min)((int)ceil((iP.get_j() + w) / scale), (int)width);
487 
488  unsigned int i_min_ = (unsigned int)i_min;
489  unsigned int i_max_ = (unsigned int)i_max;
490  unsigned int j_min_ = (unsigned int)j_min;
491  unsigned int j_max_ = (unsigned int)j_max;
492 
493  for (unsigned int i = i_min_; i < i_max_; i++) {
494  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * width;
495  for (unsigned int j = j_min_; j < j_max_; j++) {
496  unsigned char nivGris = I[i * scale][j * scale];
497  if (nivGris > nivGrisMax)
498  dst_8[j] = 255;
499  else
500  dst_8[j] = nivGris;
501  }
502  }
503  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
504  }
505 
506  // Affichage de l'image dans la Pixmap.
507  XSetWindowBackgroundPixmap(display, window, pixmap);
508  break;
509  }
510  case 16: {
511  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
512  if (scale == 1) {
513  for (unsigned int i = (unsigned int)iP.get_i(); i < (unsigned int)(iP.get_i() + h); i++) {
514  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
515  unsigned short *dst_16 = (unsigned short *)dst_8;
516  for (unsigned int j = (unsigned int)iP.get_j(); j < (unsigned int)(iP.get_j() + w); j++) {
517  *(dst_16 + j) = (unsigned short)colortable[I[i][j]];
518  }
519  }
520 
521  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
522  w, h);
523  } else {
524  int i_min = (std::max)((int)ceil(iP.get_i() / scale), 0);
525  int j_min = (std::max)((int)ceil(iP.get_j() / scale), 0);
526  int i_max = (std::min)((int)ceil((iP.get_i() + h) / scale), (int)height);
527  int j_max = (std::min)((int)ceil((iP.get_j() + w) / scale), (int)width);
528 
529  unsigned int i_min_ = (unsigned int)i_min;
530  unsigned int i_max_ = (unsigned int)i_max;
531  unsigned int j_min_ = (unsigned int)j_min;
532  unsigned int j_max_ = (unsigned int)j_max;
533 
534  for (unsigned int i = i_min_; i < i_max_; i++) {
535  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
536  unsigned short *dst_16 = (unsigned short *)dst_8;
537  for (unsigned int j = j_min_; j < j_max_; j++) {
538  *(dst_16 + j) = (unsigned short)colortable[I[i * scale][j * scale]];
539  }
540  }
541 
542  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
543  }
544 
545  XSetWindowBackgroundPixmap(display, window, pixmap);
546  break;
547  }
548 
549  case 24:
550  default: {
551  if (scale == 1) {
552  unsigned int iwidth = I.getWidth();
553  unsigned char *src_8 = I.bitmap + (int)(iP.get_i() * iwidth + iP.get_j());
554  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(iP.get_i() * 4 * width + iP.get_j() * 4);
555 
556  if (XImageByteOrder(display) == 1) {
557  // big endian
558  unsigned int i = 0;
559  while (i < h) {
560  unsigned int j = 0;
561  while (j < w) {
562  unsigned char val = *(src_8 + j);
563  *(dst_32 + 4 * j) = vpRGBa::alpha_default;
564  *(dst_32 + 4 * j + 1) = val;
565  *(dst_32 + 4 * j + 2) = val;
566  *(dst_32 + 4 * j + 3) = val;
567  j++;
568  }
569  src_8 = src_8 + iwidth;
570  dst_32 = dst_32 + 4 * width;
571  i++;
572  }
573  } else {
574  // little endian
575  unsigned int i = 0;
576  while (i < h) {
577  unsigned int j = 0;
578  while (j < w) {
579  unsigned char val = *(src_8 + j);
580  *(dst_32 + 4 * j) = val;
581  *(dst_32 + 4 * j + 1) = val;
582  *(dst_32 + 4 * j + 2) = val;
583  *(dst_32 + 4 * j + 3) = vpRGBa::alpha_default;
584  j++;
585  }
586  src_8 = src_8 + iwidth;
587  dst_32 = dst_32 + 4 * width;
588  i++;
589  }
590  }
591 
592  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
593  w, h);
594  } else {
595  int i_min = (std::max)((int)ceil(iP.get_i() / scale), 0);
596  int j_min = (std::max)((int)ceil(iP.get_j() / scale), 0);
597  int i_max = (std::min)((int)ceil((iP.get_i() + h) / scale), (int)height);
598  int j_max = (std::min)((int)ceil((iP.get_j() + w) / scale), (int)width);
599 
600  unsigned int i_min_ = (unsigned int)i_min;
601  unsigned int i_max_ = (unsigned int)i_max;
602  unsigned int j_min_ = (unsigned int)j_min;
603  unsigned int j_max_ = (unsigned int)j_max;
604 
605  if (XImageByteOrder(display) == 1) {
606  // big endian
607  for (unsigned int i = i_min_; i < i_max_; i++) {
608  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
609  for (unsigned int j = j_min_; j < j_max_; j++) {
610  unsigned char val = I[i * scale][j * scale];
611  *(dst_32++) = vpRGBa::alpha_default;
612  *(dst_32++) = val;
613  *(dst_32++) = val;
614  *(dst_32++) = val;
615  }
616  }
617  } else {
618  // little endian
619  for (unsigned int i = i_min_; i < i_max_; i++) {
620  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
621  for (unsigned int j = j_min_; j < j_max_; j++) {
622  unsigned char val = I[i * scale][j * scale];
623  *(dst_32++) = val;
624  *(dst_32++) = val;
625  *(dst_32++) = val;
626  *(dst_32++) = vpRGBa::alpha_default;
627  }
628  }
629  }
630 
631  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
632  }
633 
634  XSetWindowBackgroundPixmap(display, window, pixmap);
635  break;
636  }
637  }
638  }
639 
640  void displayImageROI(const vpImage<vpRGBa> &I,
641  const vpImagePoint &iP, unsigned int w, unsigned int h,
642  unsigned int scale, unsigned int width, unsigned int height)
643  {
644  switch (screen_depth) {
645  case 16: {
646  if (scale == 1) {
647  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
648  for (unsigned int i = (unsigned int)iP.get_i(); i < (unsigned int)(iP.get_i() + h); i++) {
649  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
650  unsigned short *dst_16 = (unsigned short *)dst_8;
651  for (unsigned int j = (unsigned int)iP.get_j(); j < (unsigned int)(iP.get_j() + w); j++) {
652  vpRGBa val = I[i][j];
653  unsigned int r = val.R;
654  unsigned int g = val.G;
655  unsigned int b = val.B;
656  *(dst_16 + j) =
657  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
658  }
659  }
660  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
661  w, h);
662  } else {
663  unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
664  int i_min = (std::max)((int)ceil(iP.get_i() / scale), 0);
665  int j_min = (std::max)((int)ceil(iP.get_j() / scale), 0);
666  int i_max = (std::min)((int)ceil((iP.get_i() + h) / scale), (int)height);
667  int j_max = (std::min)((int)ceil((iP.get_j() + w) / scale), (int)width);
668 
669  unsigned int i_min_ = (unsigned int)i_min;
670  unsigned int i_max_ = (unsigned int)i_max;
671  unsigned int j_min_ = (unsigned int)j_min;
672  unsigned int j_max_ = (unsigned int)j_max;
673 
674  for (unsigned int i = i_min_; i < i_max_; i++) {
675  unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
676  unsigned short *dst_16 = (unsigned short *)dst_8;
677  for (unsigned int j = j_min_; j < j_max_; j++) {
678  vpRGBa val = I[i * scale][j * scale];
679  unsigned int r = val.R;
680  unsigned int g = val.G;
681  unsigned int b = val.B;
682  *(dst_16 + j) =
683  (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
684  }
685  }
686  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
687  }
688 
689  XSetWindowBackgroundPixmap(display, window, pixmap);
690 
691  break;
692  }
693  case 24:
694  case 32: {
695  /*
696  * 32-bit source, 24/32-bit destination
697  */
698 
699  if (scale == 1) {
700  unsigned char *dst_32 = (unsigned char *)Ximage->data;
701  vpRGBa *src_32 = I.bitmap;
702 
703  unsigned int iwidth = I.getWidth();
704 
705  src_32 = src_32 + (int)(iP.get_i() * iwidth + iP.get_j());
706  dst_32 = dst_32 + (int)(iP.get_i() * 4 * width + iP.get_j() * 4);
707 
708  unsigned int i = 0;
709 
710  if (XImageByteOrder(display) == 1) {
711  // big endian
712  while (i < h) {
713  unsigned int j = 0;
714  while (j < w) {
715  *(dst_32 + 4 * j) = (src_32 + j)->A;
716  *(dst_32 + 4 * j + 1) = (src_32 + j)->R;
717  *(dst_32 + 4 * j + 2) = (src_32 + j)->G;
718  *(dst_32 + 4 * j + 3) = (src_32 + j)->B;
719 
720  j++;
721  }
722  src_32 = src_32 + iwidth;
723  dst_32 = dst_32 + 4 * width;
724  i++;
725  }
726 
727  } else {
728  // little endian
729  while (i < h) {
730  unsigned int j = 0;
731  while (j < w) {
732  *(dst_32 + 4 * j) = (src_32 + j)->B;
733  *(dst_32 + 4 * j + 1) = (src_32 + j)->G;
734  *(dst_32 + 4 * j + 2) = (src_32 + j)->R;
735  *(dst_32 + 4 * j + 3) = (src_32 + j)->A;
736 
737  j++;
738  }
739  src_32 = src_32 + iwidth;
740  dst_32 = dst_32 + 4 * width;
741  i++;
742  }
743  }
744 
745  XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
746  w, h);
747  } else {
748  int i_min = (std::max)((int)ceil(iP.get_i() / scale), 0);
749  int j_min = (std::max)((int)ceil(iP.get_j() / scale), 0);
750  int i_max = (std::min)((int)ceil((iP.get_i() + h) / scale), (int)height);
751  int j_max = (std::min)((int)ceil((iP.get_j() + w) / scale), (int)width);
752 
753  unsigned int i_min_ = (unsigned int)i_min;
754  unsigned int i_max_ = (unsigned int)i_max;
755  unsigned int j_min_ = (unsigned int)j_min;
756  unsigned int j_max_ = (unsigned int)j_max;
757 
758  if (XImageByteOrder(display) == 1) {
759  // big endian
760  for (unsigned int i = i_min_; i < i_max_; i++) {
761  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
762  for (unsigned int j = j_min_; j < j_max_; j++) {
763  vpRGBa val = I[i * scale][j * scale];
764  *(dst_32++) = val.A;
765  *(dst_32++) = val.R;
766  *(dst_32++) = val.G;
767  *(dst_32++) = val.B;
768  }
769  }
770  } else {
771  // little endian
772  for (unsigned int i = i_min_; i < i_max_; i++) {
773  unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * width + j_min_ * 4);
774  for (unsigned int j = j_min_; j < j_max_; j++) {
775  vpRGBa val = I[i * scale][j * scale];
776  *(dst_32++) = val.B;
777  *(dst_32++) = val.G;
778  *(dst_32++) = val.R;
779  *(dst_32++) = val.A;
780  }
781  }
782  }
783  XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
784  }
785 
786  XSetWindowBackgroundPixmap(display, window, pixmap);
787  break;
788  }
789  default:
791  "Unsupported depth (%d bpp) for color display", screen_depth));
792  }
793  }
794 
795  void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
796  unsigned int thickness, unsigned int scale)
797  {
798  if (color.id < vpColor::id_unknown)
799  XSetForeground(display, context, x_color[color.id]);
800  else {
801  xcolor.pad = 0;
802  xcolor.red = 256 * color.R;
803  xcolor.green = 256 * color.G;
804  xcolor.blue = 256 * color.B;
805  XAllocColor(display, lut, &xcolor);
806  XSetForeground(display, context, xcolor.pixel);
807  }
808 
809  XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
810 
811  XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
812  vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
813  }
814 
815  void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness, unsigned int scale)
816  {
817  if (color.id < vpColor::id_unknown)
818  XSetForeground(display, context, x_color[color.id]);
819  else {
820  xcolor.pad = 0;
821  xcolor.red = 256 * color.R;
822  xcolor.green = 256 * color.G;
823  xcolor.blue = 256 * color.B;
824  XAllocColor(display, lut, &xcolor);
825  XSetForeground(display, context, xcolor.pixel);
826  }
827 
828  if (thickness == 1) {
829  XDrawPoint(display, pixmap, context, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale));
830  } else {
831  XFillRectangle(display, pixmap, context, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale),
832  thickness, thickness);
833  }
834  }
835 
836  void displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
837  bool fill, unsigned int thickness, unsigned int scale)
838  {
839  if (color.id < vpColor::id_unknown)
840  XSetForeground(display, context, x_color[color.id]);
841  else {
842  xcolor.pad = 0;
843  xcolor.red = 256 * color.R;
844  xcolor.green = 256 * color.G;
845  xcolor.blue = 256 * color.B;
846  XAllocColor(display, lut, &xcolor);
847  XSetForeground(display, context, xcolor.pixel);
848  }
849  XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
850  if (fill == false) {
851  XDrawRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / scale),
852  vpMath::round(topLeft.get_v() / scale), w / scale, h / scale);
853  } else {
854  XFillRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / scale),
855  vpMath::round(topLeft.get_v() / scale), w / scale, h / scale);
856  }
857  }
858 
859  void flushDisplay()
860  {
861  XClearWindow(display, window);
862  XFlush(display);
863  }
864 
865  void flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h, unsigned int scale)
866  {
867  XClearArea(display, window, (int)(iP.get_u() / scale), (int)(iP.get_v() / scale), w / scale, h / scale, 0);
868  XFlush(display);
869  }
870 
871  bool getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale)
872  {
873  bool ret = false;
874  Window rootwin, childwin;
875  int root_x, root_y, win_x, win_y;
876  unsigned int modifier;
877 
878  // Event testing
879  if (blocking) {
880  XCheckMaskEvent(display, ButtonPressMask, &event);
881  XCheckMaskEvent(display, ButtonReleaseMask, &event);
882  XMaskEvent(display, ButtonPressMask, &event);
883  ret = true;
884  } else {
885  ret = XCheckMaskEvent(display, ButtonPressMask, &event);
886  }
887 
888  if (ret) {
889  // Get mouse position
890  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
891  ip.set_u((double)event.xbutton.x * scale);
892  ip.set_v((double)event.xbutton.y * scale);
893  switch (event.xbutton.button) {
894  case Button1:
895  button = vpMouseButton::button1;
896  break;
897  case Button2:
898  button = vpMouseButton::button2;
899  break;
900  case Button3:
901  button = vpMouseButton::button3;
902  break;
903  }
904  }
905  }
906 
907  return ret;
908  }
909 
910  bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale)
911  {
912  bool ret = false;
913  Window rootwin, childwin;
914  int root_x, root_y, win_x, win_y;
915  unsigned int modifier;
916 
917  // Event testing
918  if (blocking) {
919  XCheckMaskEvent(display, ButtonPressMask, &event);
920  XCheckMaskEvent(display, ButtonReleaseMask, &event);
921  XMaskEvent(display, ButtonReleaseMask, &event);
922  ret = true;
923  } else {
924  ret = XCheckMaskEvent(display, ButtonReleaseMask, &event);
925  }
926 
927  if (ret) {
928  /* Recuperation de la coordonnee du pixel clique. */
929  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
930  ip.set_u((double)event.xbutton.x * scale);
931  ip.set_v((double)event.xbutton.y * scale);
932  switch (event.xbutton.button) {
933  case Button1:
934  button = vpMouseButton::button1;
935  break;
936  case Button2:
937  button = vpMouseButton::button2;
938  break;
939  case Button3:
940  button = vpMouseButton::button3;
941  break;
942  }
943  }
944  }
945 
946  return ret;
947  }
948 
949  void getImage(vpImage<vpRGBa> &I, unsigned int width, unsigned int height)
950  {
951  XImage *xi;
952 
953  XCopyArea(display, window, pixmap, context, 0, 0, width, height, 0, 0);
954 
955  xi = XGetImage(display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap);
956 
957  I.resize(height, width);
958 
959  unsigned char *src_32 = NULL;
960  src_32 = (unsigned char *)xi->data;
961 
962  if (screen_depth == 16) {
963  for (unsigned int i = 0; i < I.getHeight(); i++) {
964  size_t i_ = i * width;
965  for (unsigned int j = 0; j < height; j++) {
966  size_t ij_ = i_ + j;
967  unsigned long pixel = XGetPixel(xi, (int)j, (int)i);
968  I.bitmap[ij_].R = (((pixel & RMask) << RShift) >> 8);
969  I.bitmap[ij_].G = (((pixel & GMask) << GShift) >> 8);
970  I.bitmap[ij_].B = (((pixel & BMask) << BShift) >> 8);
971  // On OSX the bottom/right corner (arround the resizing icon) has
972  // alpha component with different values than 255. That's why we
973  // force alpha to vpRGBa::alpha_default
974  I.bitmap[ij_].A = vpRGBa::alpha_default;
975  }
976  }
977 
978  } else {
979  if (XImageByteOrder(display) == 1) {
980  // big endian
981  for (unsigned int i = 0; i < width * height; i++) {
982  // On OSX the bottom/right corner (arround the resizing icon) has
983  // alpha component with different values than 255. That's why we
984  // force alpha to vpRGBa::alpha_default
985  I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4] ;
986  I.bitmap[i].R = src_32[i * 4 + 1];
987  I.bitmap[i].G = src_32[i * 4 + 2];
988  I.bitmap[i].B = src_32[i * 4 + 3];
989  }
990  } else {
991  // little endian
992  for (unsigned int i = 0; i < width * height; i++) {
993  I.bitmap[i].B = src_32[i * 4];
994  I.bitmap[i].G = src_32[i * 4 + 1];
995  I.bitmap[i].R = src_32[i * 4 + 2];
996  // On OSX the bottom/right corner (arround the resizing icon) has
997  // alpha component with different values than 255. That's why we
998  // force alpha to vpRGBa::alpha_default
999  I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4 + 3];
1000  }
1001  }
1002  }
1003  XDestroyImage(xi);
1004  }
1005 
1006  bool getKeyboardEvent(bool blocking)
1007  {
1008  bool ret = false;
1009 
1010  // Event testing
1011  if (blocking) {
1012  XMaskEvent(display, KeyPressMask, &event);
1013  ret = true;
1014  } else {
1015  ret = XCheckMaskEvent(display, KeyPressMask, &event);
1016  }
1017 
1018  return ret;
1019  }
1020 
1021  bool getKeyboardEvent(std::string &key, bool blocking)
1022  {
1023  bool ret = false;
1024  KeySym keysym;
1025  // int count;
1026  XComposeStatus compose_status;
1027  char buffer;
1028 
1029  // Event testing
1030  if (blocking) {
1031  XMaskEvent(display, KeyPressMask, &event);
1032  /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
1033  key = buffer;
1034  ret = true;
1035  } else {
1036  ret = XCheckMaskEvent(display, KeyPressMask, &event);
1037  if (ret) {
1038  /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
1039  key = buffer;
1040  }
1041  }
1042 
1043  return ret;
1044  }
1045 
1049  int getMsb(unsigned int u32val)
1050  {
1051  int i;
1052 
1053  for (i = 31; i >= 0; --i) {
1054  if (u32val & 0x80000000L)
1055  break;
1056  u32val <<= 1;
1057  }
1058  return i;
1059  }
1060 
1061  bool getPointerMotionEvent(vpImagePoint &ip, unsigned int scale)
1062  {
1063  bool ret = false;
1064 
1065  Window rootwin, childwin;
1066  int root_x, root_y, win_x, win_y;
1067  unsigned int modifier;
1068  // Event testing
1069  ret = XCheckMaskEvent(display, PointerMotionMask, &event);
1070 
1071  if (ret) {
1072  // Get mouse position
1073  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
1074  ip.set_u((double)event.xbutton.x * scale);
1075  ip.set_v((double)event.xbutton.y * scale);
1076  }
1077  }
1078 
1079  return ret;
1080  }
1081 
1082  bool getPointerPosition(vpImagePoint &ip, unsigned int scale)
1083  {
1084  bool ret = false;
1085  Window rootwin, childwin;
1086  int root_x, root_y, win_x, win_y;
1087  unsigned int modifier;
1088  // Event testing
1089  ret = true;
1090 
1091  if (ret) {
1092  // Get mouse position
1093  if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
1094  ip.set_u((double)win_x * scale);
1095  ip.set_v((double)win_y * scale);
1096  }
1097  }
1098 
1099  return ret;
1100  }
1101 
1102  unsigned int getScreenDepth()
1103  {
1104  Display *display_;
1105  int screen_;
1106  unsigned int depth;
1107 
1108  if ((display_ = XOpenDisplay(NULL)) == NULL) {
1109  throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
1110  XDisplayName(NULL)));
1111  }
1112  screen_ = DefaultScreen(display_);
1113  depth = (unsigned int)DefaultDepth(display_, screen_);
1114 
1115  XCloseDisplay(display_);
1116 
1117  return (depth);
1118  }
1119 
1120  void getScreenSize(unsigned int &w, unsigned int &h)
1121  {
1122  Display *display_;
1123  int screen_;
1124 
1125  if ((display_ = XOpenDisplay(NULL)) == NULL) {
1126  throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
1127  XDisplayName(NULL)));
1128  }
1129  screen_ = DefaultScreen(display_);
1130  w = (unsigned int)DisplayWidth(display_, screen_);
1131  h = (unsigned int)DisplayHeight(display_, screen_);
1132 
1133  XCloseDisplay(display_);
1134  }
1135 
1136  void init(unsigned int win_width, unsigned int win_height, int win_x, int win_y, const std::string &win_title)
1137  {
1138  if (x_color == NULL) {
1139  // id_unknown = number of predefined colors
1140  x_color = new unsigned long[vpColor::id_unknown];
1141  }
1142  // setup X11
1143  XSizeHints hints;
1144 
1145  // Positionnement de la fenetre dans l'ecran.
1146  if ((win_x < 0) || (win_y < 0)) {
1147  hints.flags = 0;
1148  } else {
1149  hints.flags = USPosition;
1150  hints.x = win_x;
1151  hints.y = win_y;
1152  }
1153 
1154  if ((display = XOpenDisplay(NULL)) == NULL) {
1155  vpERROR_TRACE("Can't connect display on server %s.\n", XDisplayName(NULL));
1156  throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server."));
1157  }
1158 
1159  screen = DefaultScreen(display);
1160  lut = DefaultColormap(display, screen);
1161  screen_depth = (unsigned int)DefaultDepth(display, screen);
1162 
1163  vpTRACE("Screen depth: %d\n", screen_depth);
1164 
1165  if ((window = XCreateSimpleWindow(display, RootWindow(display, screen),
1166  win_x, win_y,
1167  win_width, win_height,
1168  1, BlackPixel(display, screen), WhitePixel(display, screen))) == 0) {
1169  vpERROR_TRACE("Can't create window.");
1170  throw(vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create window."));
1171  }
1172 
1173  //
1174  // Create color table for 8 and 16 bits screen
1175  //
1176  if (screen_depth == 8) {
1177  lut = XCreateColormap(display, window, DefaultVisual(display, screen), AllocAll);
1178  xcolor.flags = DoRed | DoGreen | DoBlue;
1179 
1180  for (unsigned int i = 0; i < 256; i++) {
1181  xcolor.pixel = i;
1182  xcolor.red = 256 * i;
1183  xcolor.green = 256 * i;
1184  xcolor.blue = 256 * i;
1185  XStoreColor(display, lut, &xcolor);
1186  }
1187 
1188  XSetWindowColormap(display, window, lut);
1189  XInstallColormap(display, lut);
1190  }
1191 
1192  else if (screen_depth == 16) {
1193  for (unsigned int i = 0; i < 256; i++) {
1194  xcolor.pad = 0;
1195  xcolor.red = xcolor.green = xcolor.blue = 256 * i;
1196  if (XAllocColor(display, lut, &xcolor) == 0) {
1197  vpERROR_TRACE("Can't allocate 256 colors. Only %d allocated.", i);
1198  throw(vpDisplayException(vpDisplayException::colorAllocError, "Can't allocate 256 colors."));
1199  }
1200  colortable[i] = xcolor.pixel;
1201  }
1202 
1203  XSetWindowColormap(display, window, lut);
1204  XInstallColormap(display, lut);
1205 
1206  Visual *visual = DefaultVisual(display, screen);
1207  RMask = visual->red_mask;
1208  GMask = visual->green_mask;
1209  BMask = visual->blue_mask;
1210 
1211  RShift = 15 - getMsb(RMask); /* these are right-shifts */
1212  GShift = 15 - getMsb(GMask);
1213  BShift = 15 - getMsb(BMask);
1214  }
1215 
1216  vpColor pcolor; // predefined colors
1217 
1218  //
1219  // Create colors for overlay
1220  //
1221  switch (screen_depth) {
1222 
1223  case 8:
1224  // Color BLACK: default set to 0
1225 
1226  // Color WHITE: default set to 255
1227 
1228  // Color LIGHT GRAY.
1229  x_color[vpColor::id_lightGray] = 254;
1230  xcolor.pixel = x_color[vpColor::id_lightGray];
1231  xcolor.red = 256 * 192;
1232  xcolor.green = 256 * 192;
1233  xcolor.blue = 256 * 192;
1234  XStoreColor(display, lut, &xcolor);
1235 
1236  // Color GRAY.
1237  x_color[vpColor::id_gray] = 253;
1238  xcolor.pixel = x_color[vpColor::id_gray];
1239  xcolor.red = 256 * 128;
1240  xcolor.green = 256 * 128;
1241  xcolor.blue = 256 * 128;
1242  XStoreColor(display, lut, &xcolor);
1243 
1244  // Color DARK GRAY.
1245  x_color[vpColor::id_darkGray] = 252;
1246  xcolor.pixel = x_color[vpColor::id_darkGray];
1247  xcolor.red = 256 * 64;
1248  xcolor.green = 256 * 64;
1249  xcolor.blue = 256 * 64;
1250  XStoreColor(display, lut, &xcolor);
1251 
1252  // Color LIGHT RED.
1253  x_color[vpColor::id_lightRed] = 251;
1254  xcolor.pixel = x_color[vpColor::id_lightRed];
1255  xcolor.red = 256 * 255;
1256  xcolor.green = 256 * 140;
1257  xcolor.blue = 256 * 140;
1258  XStoreColor(display, lut, &xcolor);
1259 
1260  // Color RED.
1261  x_color[vpColor::id_red] = 250;
1262  xcolor.pixel = x_color[vpColor::id_red];
1263  xcolor.red = 256 * 255;
1264  xcolor.green = 0;
1265  xcolor.blue = 0;
1266  XStoreColor(display, lut, &xcolor);
1267 
1268  // Color DARK RED.
1269  x_color[vpColor::id_darkRed] = 249;
1270  xcolor.pixel = x_color[vpColor::id_darkRed];
1271  xcolor.red = 256 * 128;
1272  xcolor.green = 0;
1273  xcolor.blue = 0;
1274  XStoreColor(display, lut, &xcolor);
1275 
1276  // Color LIGHT GREEN.
1277  x_color[vpColor::id_lightGreen] = 248;
1278  xcolor.pixel = x_color[vpColor::id_lightGreen];
1279  xcolor.red = 256 * 140;
1280  xcolor.green = 256 * 255;
1281  xcolor.blue = 256 * 140;
1282  XStoreColor(display, lut, &xcolor);
1283 
1284  // Color GREEN.
1285  x_color[vpColor::id_green] = 247;
1286  xcolor.pixel = x_color[vpColor::id_green];
1287  xcolor.red = 0;
1288  xcolor.green = 256 * 255;
1289  xcolor.blue = 0;
1290  XStoreColor(display, lut, &xcolor);
1291 
1292  // Color DARK GREEN.
1293  x_color[vpColor::id_darkGreen] = 246;
1294  xcolor.pixel = x_color[vpColor::id_darkGreen];
1295  xcolor.red = 0;
1296  xcolor.green = 256 * 128;
1297  xcolor.blue = 0;
1298  XStoreColor(display, lut, &xcolor);
1299 
1300  // Color LIGHT BLUE.
1301  x_color[vpColor::id_lightBlue] = 245;
1302  xcolor.pixel = x_color[vpColor::id_lightBlue];
1303  xcolor.red = 256 * 140;
1304  xcolor.green = 256 * 140;
1305  xcolor.blue = 256 * 255;
1306  XStoreColor(display, lut, &xcolor);
1307 
1308  // Color BLUE.
1309  x_color[vpColor::id_blue] = 244;
1310  xcolor.pixel = x_color[vpColor::id_blue];
1311  xcolor.red = 0;
1312  xcolor.green = 0;
1313  xcolor.blue = 256 * 255;
1314  XStoreColor(display, lut, &xcolor);
1315 
1316  // Color DARK BLUE.
1317  x_color[vpColor::id_darkBlue] = 243;
1318  xcolor.pixel = x_color[vpColor::id_darkBlue];
1319  xcolor.red = 0;
1320  xcolor.green = 0;
1321  xcolor.blue = 256 * 128;
1322  XStoreColor(display, lut, &xcolor);
1323 
1324  // Color YELLOW.
1325  x_color[vpColor::id_yellow] = 242;
1326  xcolor.pixel = x_color[vpColor::id_yellow];
1327  xcolor.red = 256 * 255;
1328  xcolor.green = 256 * 255;
1329  xcolor.blue = 0;
1330  XStoreColor(display, lut, &xcolor);
1331 
1332  // Color ORANGE.
1333  x_color[vpColor::id_orange] = 241;
1334  xcolor.pixel = x_color[vpColor::id_orange];
1335  xcolor.red = 256 * 255;
1336  xcolor.green = 256 * 165;
1337  xcolor.blue = 0;
1338  XStoreColor(display, lut, &xcolor);
1339 
1340  // Color CYAN.
1341  x_color[vpColor::id_cyan] = 240;
1342  xcolor.pixel = x_color[vpColor::id_cyan];
1343  xcolor.red = 0;
1344  xcolor.green = 256 * 255;
1345  xcolor.blue = 256 * 255;
1346  XStoreColor(display, lut, &xcolor);
1347 
1348  // Color PURPLE.
1349  x_color[vpColor::id_purple] = 239;
1350  xcolor.pixel = x_color[vpColor::id_purple];
1351  xcolor.red = 256 * 128;
1352  xcolor.green = 0;
1353  xcolor.blue = 256 * 128;
1354  XStoreColor(display, lut, &xcolor);
1355 
1356  break;
1357 
1358  case 16:
1359  case 24:
1360  case 32: {
1361  xcolor.flags = DoRed | DoGreen | DoBlue;
1362 
1363  // Couleur BLACK.
1364  pcolor = vpColor::black;
1365  xcolor.pad = 0;
1366  xcolor.red = 256 * pcolor.R;
1367  xcolor.green = 256 * pcolor.G;
1368  xcolor.blue = 256 * pcolor.B;
1369  XAllocColor(display, lut, &xcolor);
1370  x_color[vpColor::id_black] = xcolor.pixel;
1371 
1372  // Color WHITE.
1373  pcolor = vpColor::white;
1374  xcolor.pad = 0;
1375  xcolor.red = 256 * pcolor.R;
1376  xcolor.green = 256 * pcolor.G;
1377  xcolor.blue = 256 * pcolor.B;
1378  XAllocColor(display, lut, &xcolor);
1379  x_color[vpColor::id_white] = xcolor.pixel;
1380 
1381  // Color LIGHT GRAY.
1382  pcolor = vpColor::lightGray;
1383  xcolor.pad = 0;
1384  xcolor.red = 256 * pcolor.R;
1385  xcolor.green = 256 * pcolor.G;
1386  xcolor.blue = 256 * pcolor.B;
1387  XAllocColor(display, lut, &xcolor);
1388  x_color[vpColor::id_lightGray] = xcolor.pixel;
1389 
1390  // Color GRAY.
1391  pcolor = vpColor::gray;
1392  xcolor.pad = 0;
1393  xcolor.red = 256 * pcolor.R;
1394  xcolor.green = 256 * pcolor.G;
1395  xcolor.blue = 256 * pcolor.B;
1396  XAllocColor(display, lut, &xcolor);
1397  x_color[vpColor::id_gray] = xcolor.pixel;
1398 
1399  // Color DARK GRAY.
1400  pcolor = vpColor::darkGray;
1401  xcolor.pad = 0;
1402  xcolor.red = 256 * pcolor.R;
1403  xcolor.green = 256 * pcolor.G;
1404  xcolor.blue = 256 * pcolor.B;
1405  XAllocColor(display, lut, &xcolor);
1406  x_color[vpColor::id_darkGray] = xcolor.pixel;
1407 
1408  // Color LIGHT RED.
1409  pcolor = vpColor::lightRed;
1410  xcolor.pad = 0;
1411  xcolor.red = 256 * pcolor.R;
1412  xcolor.green = 256 * pcolor.G;
1413  xcolor.blue = 256 * pcolor.B;
1414  XAllocColor(display, lut, &xcolor);
1415  x_color[vpColor::id_lightRed] = xcolor.pixel;
1416 
1417  // Color RED.
1418  pcolor = vpColor::red;
1419  xcolor.pad = 0;
1420  xcolor.red = 256 * pcolor.R;
1421  xcolor.green = 256 * pcolor.G;
1422  xcolor.blue = 256 * pcolor.B;
1423  XAllocColor(display, lut, &xcolor);
1424  x_color[vpColor::id_red] = xcolor.pixel;
1425 
1426  // Color DARK RED.
1427  pcolor = vpColor::darkRed;
1428  xcolor.pad = 0;
1429  xcolor.red = 256 * pcolor.R;
1430  xcolor.green = 256 * pcolor.G;
1431  xcolor.blue = 256 * pcolor.B;
1432  XAllocColor(display, lut, &xcolor);
1433  x_color[vpColor::id_darkRed] = xcolor.pixel;
1434 
1435  // Color LIGHT GREEN.
1436  pcolor = vpColor::lightGreen;
1437  xcolor.pad = 0;
1438  xcolor.red = 256 * pcolor.R;
1439  xcolor.green = 256 * pcolor.G;
1440  xcolor.blue = 256 * pcolor.B;
1441  XAllocColor(display, lut, &xcolor);
1442  x_color[vpColor::id_lightGreen] = xcolor.pixel;
1443 
1444  // Color GREEN.
1445  pcolor = vpColor::green;
1446  xcolor.pad = 0;
1447  xcolor.red = 256 * pcolor.R;
1448  xcolor.green = 256 * pcolor.G;
1449  xcolor.blue = 256 * pcolor.B;
1450  XAllocColor(display, lut, &xcolor);
1451  x_color[vpColor::id_green] = xcolor.pixel;
1452 
1453  // Color DARK GREEN.
1454  pcolor = vpColor::darkGreen;
1455  xcolor.pad = 0;
1456  xcolor.red = 256 * pcolor.R;
1457  xcolor.green = 256 * pcolor.G;
1458  xcolor.blue = 256 * pcolor.B;
1459  XAllocColor(display, lut, &xcolor);
1460  x_color[vpColor::id_darkGreen] = xcolor.pixel;
1461 
1462  // Color LIGHT BLUE.
1463  pcolor = vpColor::lightBlue;
1464  xcolor.pad = 0;
1465  xcolor.red = 256 * pcolor.R;
1466  xcolor.green = 256 * pcolor.G;
1467  xcolor.blue = 256 * pcolor.B;
1468  XAllocColor(display, lut, &xcolor);
1469  x_color[vpColor::id_lightBlue] = xcolor.pixel;
1470 
1471  // Color BLUE.
1472  pcolor = vpColor::blue;
1473  xcolor.pad = 0;
1474  xcolor.red = 256 * pcolor.R;
1475  xcolor.green = 256 * pcolor.G;
1476  xcolor.blue = 256 * pcolor.B;
1477  XAllocColor(display, lut, &xcolor);
1478  x_color[vpColor::id_blue] = xcolor.pixel;
1479 
1480  // Color DARK BLUE.
1481  pcolor = vpColor::darkBlue;
1482  xcolor.pad = 0;
1483  xcolor.red = 256 * pcolor.R;
1484  xcolor.green = 256 * pcolor.G;
1485  xcolor.blue = 256 * pcolor.B;
1486  XAllocColor(display, lut, &xcolor);
1487  x_color[vpColor::id_darkBlue] = xcolor.pixel;
1488 
1489  // Color YELLOW.
1490  pcolor = vpColor::yellow;
1491  xcolor.pad = 0;
1492  xcolor.red = 256 * pcolor.R;
1493  xcolor.green = 256 * pcolor.G;
1494  xcolor.blue = 256 * pcolor.B;
1495  XAllocColor(display, lut, &xcolor);
1496  x_color[vpColor::id_yellow] = xcolor.pixel;
1497 
1498  // Color ORANGE.
1499  pcolor = vpColor::orange;
1500  xcolor.pad = 0;
1501  xcolor.red = 256 * pcolor.R;
1502  xcolor.green = 256 * pcolor.G;
1503  xcolor.blue = 256 * pcolor.B;
1504  XAllocColor(display, lut, &xcolor);
1505  x_color[vpColor::id_orange] = xcolor.pixel;
1506 
1507  // Color CYAN.
1508  pcolor = vpColor::cyan;
1509  xcolor.pad = 0;
1510  xcolor.red = 256 * pcolor.R;
1511  xcolor.green = 256 * pcolor.G;
1512  xcolor.blue = 256 * pcolor.B;
1513  XAllocColor(display, lut, &xcolor);
1514  x_color[vpColor::id_cyan] = xcolor.pixel;
1515 
1516  // Color PURPLE.
1517  pcolor = vpColor::purple;
1518  xcolor.pad = 0;
1519  xcolor.red = 256 * pcolor.R;
1520  xcolor.green = 256 * pcolor.G;
1521  xcolor.blue = 256 * pcolor.B;
1522  XAllocColor(display, lut, &xcolor);
1523  x_color[vpColor::id_purple] = xcolor.pixel;
1524  break;
1525  }
1526  }
1527 
1528  XSetStandardProperties(display, window, win_title.c_str(), win_title.c_str(), None, 0, 0, &hints);
1529  XMapWindow(display, window);
1530  // Selection des evenements.
1531  XSelectInput(display, window,
1532  ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
1533  StructureNotifyMask | PointerMotionMask);
1534 
1535  /* Creation du contexte graphique */
1536  values.plane_mask = AllPlanes;
1537  values.fill_style = FillSolid;
1538  values.foreground = WhitePixel(display, screen);
1539  values.background = BlackPixel(display, screen);
1540  context = XCreateGC(display, window, GCPlaneMask | GCFillStyle | GCForeground | GCBackground, &values);
1541 
1542  if (context == NULL) {
1543  vpERROR_TRACE("Can't create graphics context.");
1544  throw(vpDisplayException(vpDisplayException::XWindowsError, "Can't create graphics context"));
1545  }
1546 
1547  // Pixmap creation.
1548  pixmap = XCreatePixmap(display, window, win_width, win_height, screen_depth);
1549 
1550  // Hangs when forward X11 is used to send the display to an other computer
1551  // do
1552  // XNextEvent ( display, &event );
1553  // while ( event.xany.type != Expose );
1554 
1555  {
1556  Ximage = XCreateImage(display, DefaultVisual(display, screen), screen_depth, ZPixmap, 0, NULL,
1557  win_width, win_height,
1558  XBitmapPad(display), 0);
1559 
1560  Ximage->data = (char *)malloc(win_height * (unsigned int)Ximage->bytes_per_line);
1561  ximage_data_init = true;
1562  }
1563 
1564  XSync(display, true);
1565 
1566  XStoreName(display, window, win_title.c_str());
1567  }
1568 
1569  void setFont(const std::string &fontname)
1570  {
1571  try {
1572  Font stringfont;
1573  stringfont = XLoadFont(display, fontname.c_str()); //"-adobe-times-bold-r-normal--18*");
1574  XSetFont(display, context, stringfont);
1575  } catch (...) {
1577  }
1578  }
1579 
1580  void setTitle(const std::string &title)
1581  {
1582  XStoreName(display, window, title.c_str());
1583  }
1584 
1585  void setWindowPosition(int win_x, int win_y)
1586  {
1587  XMoveWindow(display, window, win_x, win_y);
1588  }
1589 
1590 private:
1591  Display *display;
1592  Window window;
1593  XImage *Ximage;
1594  Colormap lut;
1595  GC context;
1596  int screen;
1597  XEvent event;
1598  Pixmap pixmap;
1599  unsigned long *x_color; // Array of predefined colors
1600  unsigned int screen_depth;
1601  unsigned short colortable[256];
1602  XColor xcolor;
1603  XGCValues values;
1604  bool ximage_data_init;
1605  unsigned int RMask, GMask, BMask;
1606  int RShift, GShift, BShift;
1607 };
1608 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
1609 
1630  : vpDisplay(), m_impl(new Impl())
1631 {
1632  setScale(scaleType, I.getWidth(), I.getHeight());
1633 
1634  init(I);
1635 }
1636 
1658 vpDisplayX::vpDisplayX(vpImage<unsigned char> &I, int x, int y, const std::string &title, vpScaleType scaleType)
1659  : vpDisplay(), m_impl(new Impl())
1660 {
1661  setScale(scaleType, I.getWidth(), I.getHeight());
1662  init(I, x, y, title);
1663 }
1664 
1685  : vpDisplay(), m_impl(new Impl())
1686 {
1687  setScale(scaleType, I.getWidth(), I.getHeight());
1688  init(I);
1689 }
1690 
1712 vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, int x, int y, const std::string &title, vpScaleType scaleType)
1713  : vpDisplay(), m_impl(new Impl())
1714 {
1715  setScale(scaleType, I.getWidth(), I.getHeight());
1716  init(I, x, y, title);
1717 }
1718 
1740 vpDisplayX::vpDisplayX(int x, int y, const std::string &title)
1741  : vpDisplay(), m_impl(new Impl())
1742 {
1743  m_windowXPosition = x;
1744  m_windowYPosition = y;
1745 
1746  m_title = title;
1747 }
1748 
1769  : vpDisplay(), m_impl(new Impl())
1770 {
1771 }
1772 
1777 {
1778  closeDisplay();
1779  delete m_impl;
1780 }
1781 
1789 void vpDisplayX::init(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title)
1790 {
1791  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
1792  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
1793  }
1794 
1795  if (win_x != -1)
1796  m_windowXPosition = win_x;
1797  if (win_y != -1)
1798  m_windowYPosition = win_y;
1799 
1800  if (!win_title.empty())
1801  m_title = win_title;
1802 
1805 
1806  I.display = this;
1808 }
1809 
1818 void vpDisplayX::init(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title)
1819 {
1820  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
1821  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
1822  }
1823 
1824  if (win_x != -1)
1825  m_windowXPosition = win_x;
1826  if (win_y != -1)
1827  m_windowYPosition = win_y;
1828 
1829  if (!win_title.empty())
1830  m_title = win_title;
1831 
1834 
1835  I.display = this;
1837 }
1838 
1846 void vpDisplayX::init(unsigned int win_width, unsigned int win_height, int win_x, int win_y, const std::string &win_title)
1847 {
1848  setScale(m_scaleType, win_width, win_height);
1849 
1850  m_width = win_width / m_scale;
1851  m_height = win_height / m_scale;
1852 
1853  if (win_x != -1)
1854  m_windowXPosition = win_x;
1855  if (win_y != -1)
1856  m_windowYPosition = win_y;
1857 
1858  m_title = win_title;
1859 
1861 
1863 }
1864 
1879 void vpDisplayX::setFont(const std::string &fontname)
1880 {
1882  if (!fontname.empty()) {
1883  m_impl->setFont(fontname);
1884  }
1885  } else {
1886  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1887  }
1888 }
1889 
1894 void vpDisplayX::setTitle(const std::string &title)
1895 {
1897  m_title = title;
1898  if (!title.empty())
1899  m_impl->setTitle(title);
1900  } else {
1901  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1902  }
1903 }
1904 
1914 void vpDisplayX::setWindowPosition(int win_x, int win_y)
1915 {
1917  m_impl->setWindowPosition(win_x, win_y);
1918  } else {
1919  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1920  }
1921 }
1922 
1935 {
1937  m_impl->displayImage(I, m_scale, m_width, m_height);
1938  } else {
1939  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1940  }
1941 }
1942 
1955 {
1957  m_impl->displayImage(I, m_scale, m_width, m_height);
1958  } else {
1959  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1960  }
1961 }
1962 
1974 void vpDisplayX::displayImage(const unsigned char *bitmap)
1975 {
1977  m_impl->displayImage(bitmap, m_width, m_height);
1978  } else {
1979  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1980  }
1981 }
1982 
1998 void vpDisplayX::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w,
1999  unsigned int h)
2000 {
2002  m_impl->displayImageROI(I, iP, w, h, m_scale, m_width, m_height);
2003  } else {
2004  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2005  }
2006 }
2007 
2023 void vpDisplayX::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w,
2024  unsigned int h)
2025 {
2027  m_impl->displayImageROI(I, iP, w, h, m_scale, m_width, m_height);
2028  } else {
2029  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2030  }
2031 }
2032 
2041 {
2043  m_impl->closeDisplay();
2044 
2046  }
2047 }
2048 
2055 {
2057  m_impl->flushDisplay();
2058  } else {
2059  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2060  }
2061 }
2062 
2070 void vpDisplayX::flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h)
2071 {
2073  m_impl->flushDisplayROI(iP, w, h, m_scale);
2074  } else {
2075  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2076  }
2077 }
2078 
2084 {
2086  m_impl->clearDisplay(color, m_width, m_height);
2087  } else {
2088  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2089  }
2090 }
2091 
2099 void vpDisplayX::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
2100  unsigned int h, unsigned int thickness)
2101 {
2103  double a = ip2.get_i() - ip1.get_i();
2104  double b = ip2.get_j() - ip1.get_j();
2105  double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
2106 
2107  // if ( ( a==0 ) && ( b==0 ) )
2108  if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
2109  (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
2110  // DisplayCrossLarge(i1,j1,3,col) ;
2111  } else {
2112  a /= lg;
2113  b /= lg;
2114 
2115  vpImagePoint ip3;
2116  ip3.set_i(ip2.get_i() - w * a);
2117  ip3.set_j(ip2.get_j() - w * b);
2118 
2119  vpImagePoint ip4;
2120  ip4.set_i(ip3.get_i() - b * h);
2121  ip4.set_j(ip3.get_j() + a * h);
2122 
2123  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2124  displayLine(ip2, ip4, color, thickness);
2125 
2126  ip4.set_i(ip3.get_i() + b * h);
2127  ip4.set_j(ip3.get_j() - a * h);
2128 
2129  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2130  displayLine(ip2, ip4, color, thickness);
2131 
2132  displayLine(ip1, ip2, color, thickness);
2133  }
2134  } else {
2135  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2136  }
2137 }
2138 
2150 void vpDisplayX::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
2151 {
2153  m_impl->displayCharString(ip, text, color, m_scale);
2154  } else {
2155  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2156  }
2157  }
2158 
2168 void vpDisplayX::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
2169  unsigned int thickness)
2170 {
2172  if (thickness == 1)
2173  thickness = 0;
2174  m_impl->displayCircle(center, radius, color, fill, thickness, m_scale);
2175  } else {
2176  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2177  }
2178 }
2179 
2187 void vpDisplayX::displayCross(const vpImagePoint &ip, unsigned int cross_size, const vpColor &color,
2188  unsigned int thickness)
2189 {
2191  double i = ip.get_i();
2192  double j = ip.get_j();
2193  vpImagePoint ip1, ip2;
2194 
2195  ip1.set_i(i - cross_size / 2);
2196  ip1.set_j(j);
2197  ip2.set_i(i + cross_size / 2);
2198  ip2.set_j(j);
2199  displayLine(ip1, ip2, color, thickness);
2200 
2201  ip1.set_i(i);
2202  ip1.set_j(j - cross_size / 2);
2203  ip2.set_i(i);
2204  ip2.set_j(j + cross_size / 2);
2205 
2206  displayLine(ip1, ip2, color, thickness);
2207  } else {
2208  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2209  }
2210 }
2217 void vpDisplayX::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2218  unsigned int thickness)
2219 {
2221  if (thickness == 1)
2222  thickness = 0;
2223 
2224  m_impl->displayDotLine(ip1, ip2, color, thickness, m_scale);
2225  } else {
2226  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2227  }
2228 }
2229 
2236 void vpDisplayX::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2237  unsigned int thickness)
2238 {
2240  if (thickness == 1)
2241  thickness = 0;
2242 
2243  m_impl->displayLine(ip1, ip2, color, thickness, m_scale);
2244  } else {
2245  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2246  }
2247 }
2248 
2255 void vpDisplayX::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
2256 {
2258  m_impl->displayPoint(ip, color, thickness, m_scale);
2259  } else {
2260  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2261  }
2262 }
2263 
2277 void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
2278  bool fill, unsigned int thickness)
2279 {
2281  if (thickness == 1)
2282  thickness = 0;
2283 
2284  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2285  } else {
2286  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2287  }
2288 }
2289 
2302 void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
2303  bool fill, unsigned int thickness)
2304 {
2306  if (thickness == 1)
2307  thickness = 0;
2308 
2309  unsigned int w = static_cast<unsigned int>(vpMath::round(bottomRight.get_u() - topLeft.get_u()));
2310  unsigned int h = static_cast<unsigned int>(vpMath::round(bottomRight.get_v() - topLeft.get_v()));
2311 
2312  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2313  } else {
2314  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2315  }
2316 }
2317 
2330 void vpDisplayX::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
2331 {
2333  if (thickness == 1)
2334  thickness = 0;
2335  vpImagePoint topLeft = rectangle.getTopLeft();
2336  unsigned int w = static_cast<unsigned int>(vpMath::round(rectangle.getWidth()));
2337  unsigned int h = static_cast<unsigned int>(vpMath::round(rectangle.getHeight()));
2338  m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2339  } else {
2340  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2341  }
2342 }
2343 
2359 bool vpDisplayX::getClick(bool blocking)
2360 {
2361  bool ret = false;
2362 
2364  vpImagePoint ip;
2366  ret = m_impl->getClick(ip, button, blocking, m_scale);
2367  } else {
2368  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2369  }
2370  return ret;
2371 }
2372 
2388 bool vpDisplayX::getClick(vpImagePoint &ip, bool blocking)
2389 {
2390  bool ret = false;
2391 
2394  ret = m_impl->getClick(ip, button, blocking, m_scale);
2395  } else {
2396  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2397  }
2398  return ret;
2399 }
2400 
2421 {
2422  bool ret = false;
2423 
2425  ret = m_impl->getClick(ip, button, blocking, m_scale);
2426  } else {
2427  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2428  }
2429  return ret;
2430 }
2431 
2456 {
2457  bool ret = false;
2458 
2460  ret = m_impl->getClickUp(ip, button, blocking, m_scale);
2461  } else {
2462  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2463  }
2464  return ret;
2465 }
2466 
2467 /*
2468  Gets the displayed image (including the overlay plane)
2469  and returns an RGBa image. If a scale factor is set using setScale(), the
2470  size of the image is the size of the downscaled image.
2471 
2472  \param I : Image to get.
2473 */
2475 {
2477  m_impl->getImage(I, m_width, m_height);
2478  } else {
2479  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2480  }
2481 }
2482 
2487 {
2488  return m_impl->getScreenDepth();
2489 }
2490 
2495 void vpDisplayX::getScreenSize(unsigned int &w, unsigned int &h)
2496 {
2497  m_impl->getScreenSize(w, h);
2498 }
2499 
2504 {
2505  unsigned int width, height;
2506  getScreenSize(width, height);
2507  return width;
2508 }
2509 
2514 {
2515  unsigned int width, height;
2516  getScreenSize(width, height);
2517  return height;
2518 }
2519 
2540 bool vpDisplayX::getKeyboardEvent(bool blocking)
2541 {
2542  bool ret = false;
2543 
2545  ret = m_impl->getKeyboardEvent(blocking);
2546  } else {
2547  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2548  }
2549  return ret;
2550 }
2551 
2575 bool vpDisplayX::getKeyboardEvent(std::string &key, bool blocking)
2576 {
2577  bool ret = false;
2579  ret = m_impl->getKeyboardEvent(key, blocking);
2580  } else {
2581  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2582  }
2583  return ret;
2584 }
2598 {
2599 
2600  bool ret = false;
2602  ret = m_impl->getPointerMotionEvent(ip, m_scale);
2603  } else {
2604  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2605  }
2606  return ret;
2607 }
2608 
2620 {
2621  bool ret = false;
2623  ret = m_impl->getPointerPosition(ip, m_scale);
2624  } else {
2625  throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2626  }
2627  return ret;
2628 }
2629 
2630 #elif !defined(VISP_BUILD_SHARED_LIBS)
2631 // Work arround to avoid warning: libvisp_core.a(vpDisplayX.cpp.o) has no
2632 // symbols
2633 void dummy_vpDisplayX(){};
2634 #endif
unsigned int m_height
Definition: vpDisplay.h:216
void closeDisplay()
void clearDisplay(const vpColor &color=vpColor::white)
vpDisplay * display
Definition: vpImage.h:144
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="")
double get_i() const
Definition: vpImagePoint.h:203
int m_windowYPosition
display position
Definition: vpDisplay.h:214
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:177
unsigned int getScreenDepth()
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true)
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:800
unsigned char B
Blue component.
Definition: vpRGBa.h:150
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
static const vpColor black
Definition: vpColor.h:211
void set_u(double u)
Definition: vpImagePoint.h:225
static const vpColor darkRed
Definition: vpColor.h:218
#define vpERROR_TRACE
Definition: vpDebug.h:393
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:157
static const vpColor lightGray
Definition: vpColor.h:213
void displayImage(const vpImage< unsigned char > &I)
void flushDisplay()
static const vpColor darkBlue
Definition: vpColor.h:224
unsigned char G
Green component.
Definition: vpRGBa.h:149
bool m_displayHasBeenInitialized
display has been initialized
Definition: vpDisplay.h:210
static const vpColor green
Definition: vpColor.h:220
vpImagePoint getTopLeft() const
Definition: vpRect.h:200
static const vpColor lightRed
Definition: vpColor.h:216
Definition: vpRGBa.h:66
static const vpColor red
Definition: vpColor.h:217
bool getPointerPosition(vpImagePoint &ip)
static const vpColor orange
Definition: vpColor.h:227
unsigned int getScreenWidth()
bool getClick(bool blocking=true)
vpColorIdentifier id
Definition: vpColor.h:206
double get_u() const
Definition: vpImagePoint.h:262
int m_windowXPosition
display position
Definition: vpDisplay.h:212
double getWidth() const
Definition: vpRect.h:228
static const vpColor cyan
Definition: vpColor.h:226
static const vpColor lightGreen
Definition: vpColor.h:219
void set_i(double ii)
Definition: vpImagePoint.h:166
unsigned int m_scale
Definition: vpDisplay.h:218
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Definition: vpDisplay.cpp:259
#define vpTRACE
Definition: vpDebug.h:416
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
static double sqr(double x)
Definition: vpMath.h:116
void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)
static void display(const vpImage< unsigned char > &I)
void getScreenSize(unsigned int &width, unsigned int &height)
double get_j() const
Definition: vpImagePoint.h:214
unsigned char A
Additionnal component.
Definition: vpRGBa.h:151
vpScaleType m_scaleType
Definition: vpDisplay.h:219
bool getKeyboardEvent(bool blocking=true)
std::string m_title
Definition: vpDisplay.h:217
static const vpColor gray
Definition: vpColor.h:214
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
virtual ~vpDisplayX()
static const vpColor darkGray
Definition: vpColor.h:215
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
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)
static int round(double x)
Definition: vpMath.h:247
void set_j(double jj)
Definition: vpImagePoint.h:177
Error that can be emited by the vpDisplay class and its derivates.
void set_v(double v)
Definition: vpImagePoint.h:236
unsigned int getHeight() const
Definition: vpImage.h:188
unsigned int m_width
Definition: vpDisplay.h:215
unsigned char R
Red component.
Definition: vpRGBa.h:148
double getHeight() const
Definition: vpRect.h:167
void setTitle(const std::string &title)
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height)
Defines a rectangle in the plane.
Definition: vpRect.h:79
void setFont(const std::string &font)
static const vpColor darkGreen
Definition: vpColor.h:221
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
void setWindowPosition(int win_x, int win_y)
static const vpColor yellow
Definition: vpColor.h:225
static const vpColor lightBlue
Definition: vpColor.h:222
static const vpColor purple
Definition: vpColor.h:228
static const vpColor white
Definition: vpColor.h:212
unsigned int getWidth() const
Definition: vpImage.h:246
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)
double get_v() const
Definition: vpImagePoint.h:273
bool getPointerMotionEvent(vpImagePoint &ip)
void getImage(vpImage< vpRGBa > &I)
get the window pixmap and put it in vpRGBa image
unsigned int getScreenHeight()
static const vpColor blue
Definition: vpColor.h:223
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height)
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)