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