Visual Servoing Platform version 3.5.0
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
75class vpDisplayX::Impl
76{
77public:
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
1590private:
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
1658vpDisplayX::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
1712vpDisplayX::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
1740vpDisplayX::vpDisplayX(int x, int y, const std::string &title)
1741 : vpDisplay(), m_impl(new Impl())
1742{
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
1789void 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
1818void 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
1846void 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
1879void vpDisplayX::setFont(const std::string &fontname)
1880{
1882 if (!fontname.empty()) {
1883 m_impl->setFont(fontname);
1884 }
1885 } else {
1887 }
1888}
1889
1894void vpDisplayX::setTitle(const std::string &title)
1895{
1897 m_title = title;
1898 if (!title.empty())
1899 m_impl->setTitle(title);
1900 } else {
1902 }
1903}
1904
1914void vpDisplayX::setWindowPosition(int win_x, int win_y)
1915{
1917 m_impl->setWindowPosition(win_x, win_y);
1918 } else {
1920 }
1921}
1922
1935{
1937 m_impl->displayImage(I, m_scale, m_width, m_height);
1938 } else {
1940 }
1941}
1942
1955{
1957 m_impl->displayImage(I, m_scale, m_width, m_height);
1958 } else {
1960 }
1961}
1962
1974void vpDisplayX::displayImage(const unsigned char *bitmap)
1975{
1977 m_impl->displayImage(bitmap, m_width, m_height);
1978 } else {
1980 }
1981}
1982
1998void 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 {
2005 }
2006}
2007
2023void 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 {
2030 }
2031}
2032
2041{
2043 m_impl->closeDisplay();
2044
2046 }
2047}
2048
2055{
2057 m_impl->flushDisplay();
2058 } else {
2060 }
2061}
2062
2070void vpDisplayX::flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h)
2071{
2073 m_impl->flushDisplayROI(iP, w, h, m_scale);
2074 } else {
2076 }
2077}
2078
2084{
2086 m_impl->clearDisplay(color, m_width, m_height);
2087 } else {
2089 }
2090}
2091
2099void 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 {
2136 }
2137}
2138
2150void vpDisplayX::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
2151{
2153 m_impl->displayCharString(ip, text, color, m_scale);
2154 } else {
2156 }
2157 }
2158
2168void 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 {
2177 }
2178}
2179
2187void 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 {
2209 }
2210}
2217void 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 {
2227 }
2228}
2229
2236void 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 {
2246 }
2247}
2248
2255void vpDisplayX::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
2256{
2258 m_impl->displayPoint(ip, color, thickness, m_scale);
2259 } else {
2261 }
2262}
2263
2277void 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 {
2287 }
2288}
2289
2302void 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 {
2315 }
2316}
2317
2330void 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 {
2341 }
2342}
2343
2359bool 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 {
2369 }
2370 return ret;
2371}
2372
2388bool vpDisplayX::getClick(vpImagePoint &ip, bool blocking)
2389{
2390 bool ret = false;
2391
2394 ret = m_impl->getClick(ip, button, blocking, m_scale);
2395 } else {
2397 }
2398 return ret;
2399}
2400
2421{
2422 bool ret = false;
2423
2425 ret = m_impl->getClick(ip, button, blocking, m_scale);
2426 } else {
2428 }
2429 return ret;
2430}
2431
2456{
2457 bool ret = false;
2458
2460 ret = m_impl->getClickUp(ip, button, blocking, m_scale);
2461 } else {
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 {
2480 }
2481}
2482
2487{
2488 return m_impl->getScreenDepth();
2489}
2490
2495void 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
2541{
2542 bool ret = false;
2543
2545 ret = m_impl->getKeyboardEvent(blocking);
2546 } else {
2548 }
2549 return ret;
2550}
2551
2575bool vpDisplayX::getKeyboardEvent(std::string &key, bool blocking)
2576{
2577 bool ret = false;
2579 ret = m_impl->getKeyboardEvent(key, blocking);
2580 } else {
2582 }
2583 return ret;
2584}
2598{
2599
2600 bool ret = false;
2602 ret = m_impl->getPointerMotionEvent(ip, m_scale);
2603 } else {
2605 }
2606 return ret;
2607}
2608
2620{
2621 bool ret = false;
2623 ret = m_impl->getPointerPosition(ip, m_scale);
2624 } else {
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
2633void dummy_vpDisplayX(){};
2634#endif
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:158
static const vpColor white
Definition: vpColor.h:212
vpColorIdentifier id
Definition: vpColor.h:206
static const vpColor red
Definition: vpColor.h:217
static const vpColor darkGray
Definition: vpColor.h:215
static const vpColor black
Definition: vpColor.h:211
static const vpColor cyan
Definition: vpColor.h:226
static const vpColor orange
Definition: vpColor.h:227
static const vpColor darkRed
Definition: vpColor.h:218
static const vpColor blue
Definition: vpColor.h:223
static const vpColor lightGray
Definition: vpColor.h:213
static const vpColor lightBlue
Definition: vpColor.h:222
static const vpColor darkGreen
Definition: vpColor.h:221
static const vpColor darkBlue
Definition: vpColor.h:224
static const vpColor purple
Definition: vpColor.h:228
static const vpColor lightGreen
Definition: vpColor.h:219
static const vpColor yellow
Definition: vpColor.h:225
@ id_lightBlue
Definition: vpColor.h:184
@ id_yellow
Definition: vpColor.h:190
@ id_darkGray
Definition: vpColor.h:170
@ id_green
Definition: vpColor.h:180
@ id_darkRed
Definition: vpColor.h:176
@ id_lightGray
Definition: vpColor.h:166
@ id_red
Definition: vpColor.h:174
@ id_lightRed
Definition: vpColor.h:172
@ id_white
Definition: vpColor.h:164
@ id_black
Definition: vpColor.h:162
@ id_blue
Definition: vpColor.h:186
@ id_darkGreen
Definition: vpColor.h:182
@ id_gray
Definition: vpColor.h:168
@ id_lightGreen
Definition: vpColor.h:178
@ id_purple
Definition: vpColor.h:196
@ id_orange
Definition: vpColor.h:194
@ id_cyan
Definition: vpColor.h:192
@ id_darkBlue
Definition: vpColor.h:188
@ id_unknown
Definition: vpColor.h:199
static const vpColor lightRed
Definition: vpColor.h:216
static const vpColor green
Definition: vpColor.h:220
static const vpColor gray
Definition: vpColor.h:214
Error that can be emited by the vpDisplay class and its derivates.
void displayImage(const vpImage< unsigned char > &I)
void setTitle(const std::string &title)
virtual ~vpDisplayX()
unsigned int getScreenDepth()
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height)
void closeDisplay()
void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)
void flushDisplay()
void clearDisplay(const vpColor &color=vpColor::white)
void getScreenSize(unsigned int &width, unsigned int &height)
bool getPointerPosition(vpImagePoint &ip)
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="")
void displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
void setWindowPosition(int win_x, int win_y)
void getImage(vpImage< vpRGBa > &I)
get the window pixmap and put it in vpRGBa image
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
bool getClick(bool blocking=true)
void setFont(const std::string &font)
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)
unsigned int getScreenHeight()
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height)
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true)
bool getKeyboardEvent(bool blocking=true)
unsigned int getScreenWidth()
bool getPointerMotionEvent(vpImagePoint &ip)
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:178
unsigned int m_height
Definition: vpDisplay.h:216
vpScaleType m_scaleType
Definition: vpDisplay.h:219
unsigned int m_width
Definition: vpDisplay.h:215
static void display(const vpImage< unsigned char > &I)
int m_windowXPosition
display position
Definition: vpDisplay.h:212
std::string m_title
Definition: vpDisplay.h:217
int m_windowYPosition
display position
Definition: vpDisplay.h:214
unsigned int m_scale
Definition: vpDisplay.h:218
bool m_displayHasBeenInitialized
display has been initialized
Definition: vpDisplay.h:210
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Definition: vpDisplay.cpp:259
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
void set_j(double jj)
Definition: vpImagePoint.h:177
double get_j() const
Definition: vpImagePoint.h:214
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
void set_i(double ii)
Definition: vpImagePoint.h:166
double get_u() const
Definition: vpImagePoint.h:262
void set_u(double u)
Definition: vpImagePoint.h:225
void set_v(double v)
Definition: vpImagePoint.h:236
double get_i() const
Definition: vpImagePoint.h:203
double get_v() const
Definition: vpImagePoint.h:273
unsigned int getWidth() const
Definition: vpImage.h:246
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:800
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
unsigned int getHeight() const
Definition: vpImage.h:188
vpDisplay * display
Definition: vpImage.h:144
static double sqr(double x)
Definition: vpMath.h:116
static int round(double x)
Definition: vpMath.h:247
Definition: vpRGBa.h:67
unsigned char B
Blue component.
Definition: vpRGBa.h:150
unsigned char R
Red component.
Definition: vpRGBa.h:148
unsigned char G
Green component.
Definition: vpRGBa.h:149
@ alpha_default
Definition: vpRGBa.h:69
unsigned char A
Additionnal component.
Definition: vpRGBa.h:151
Defines a rectangle in the plane.
Definition: vpRect.h:80
double getWidth() const
Definition: vpRect.h:228
vpImagePoint getTopLeft() const
Definition: vpRect.h:200
double getHeight() const
Definition: vpRect.h:167
#define vpTRACE
Definition: vpDebug.h:416
#define vpERROR_TRACE
Definition: vpDebug.h:393