Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpDisplayX.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Image display.
32 */
33
38
39#include <visp3/core/vpConfig.h>
40#ifdef VISP_HAVE_X11
41
42#include <cmath> // std::fabs
43#include <iostream>
44#include <limits> // numeric_limits
45#include <stdio.h>
46#include <stdlib.h>
47
48// Display stuff
49#include <visp3/core/vpDisplay.h>
50#include <visp3/gui/vpDisplayX.h>
51
52// debug / exception
53#include <visp3/core/vpDisplayException.h>
54
55// math
56#include <visp3/core/vpMath.h>
57
58#ifndef DOXYGEN_SHOULD_SKIP_THIS
59
60#include <X11/Xlib.h>
61#include <X11/Xutil.h>
62
64
65// Work around to use this class with Eigen3
66#ifdef Success
67#undef Success // See http://eigen.tuxfamily.org/bz/show_bug.cgi?id=253
68#endif
69
70class vpDisplayX::Impl
71{
72public:
73 Impl()
74 : display(nullptr), window(), Ximage(nullptr), lut(), context(), screen(0), event(), pixmap(), x_color(nullptr),
75 screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
76 BShift(0)
77 { }
78
79 ~Impl() { }
80
81 void clearDisplay(const vpColor &color, unsigned int width, unsigned int height)
82 {
84 XSetWindowBackground(display, window, x_color[color.id]);
85 else {
86 xcolor.pad = 0;
87 xcolor.red = 256 * color.R;
88 xcolor.green = 256 * color.G;
89 xcolor.blue = 256 * color.B;
90 XAllocColor(display, lut, &xcolor);
91 XSetForeground(display, context, xcolor.pixel);
92 }
93
94 XClearWindow(display, window);
95
96 XFreePixmap(display, pixmap);
97 // Pixmap creation.
98 pixmap = XCreatePixmap(display, window, width, height, screen_depth);
99 }
100
101 void closeDisplay()
102 {
103 if (ximage_data_init == true)
104 free(Ximage->data);
105
106 Ximage->data = nullptr;
107 XDestroyImage(Ximage);
108
109 XFreePixmap(display, pixmap);
110
111 XFreeGC(display, context);
112 XDestroyWindow(display, window);
113 XCloseDisplay(display);
114
115 if (x_color != nullptr) {
116 delete[] x_color;
117 x_color = nullptr;
118 }
119 }
120
121 void displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color, unsigned int scale)
122 {
123 if (color.id < vpColor::id_unknown)
124 XSetForeground(display, context, x_color[color.id]);
125 else {
126 xcolor.pad = 0;
127 xcolor.red = 256 * color.R;
128 xcolor.green = 256 * color.G;
129 xcolor.blue = 256 * color.B;
130 XAllocColor(display, lut, &xcolor);
131 XSetForeground(display, context, xcolor.pixel);
132 }
133 XDrawString(display, pixmap, context, static_cast<int>(ip.get_u() / scale), static_cast<int>(ip.get_v() / scale), text.c_str(),
134 static_cast<int>(text.size()));
135 }
136
137 void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
138 unsigned int thickness, unsigned int scale)
139 {
140 if (color.id < vpColor::id_unknown)
141 XSetForeground(display, context, x_color[color.id]);
142 else {
143 xcolor.pad = 0;
144 xcolor.red = 256 * color.R;
145 xcolor.green = 256 * color.G;
146 xcolor.blue = 256 * color.B;
147 XAllocColor(display, lut, &xcolor);
148 XSetForeground(display, context, xcolor.pixel);
149 }
150
151 XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
152
153 if (fill == false) {
154 XDrawArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / scale),
155 vpMath::round((center.get_v() - radius) / scale), radius * 2 / scale, radius * 2 / scale, 0,
156 23040); /* 23040 = 360*64 */
157 }
158 else {
159 XFillArc(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 }
163 }
164
165 void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
166 unsigned int scale)
167 {
168 if (color.id < vpColor::id_unknown)
169 XSetForeground(display, context, x_color[color.id]);
170 else {
171 xcolor.pad = 0;
172 xcolor.red = 256 * color.R;
173 xcolor.green = 256 * color.G;
174 xcolor.blue = 256 * color.B;
175 XAllocColor(display, lut, &xcolor);
176 XSetForeground(display, context, xcolor.pixel);
177 }
178
179 XSetLineAttributes(display, context, thickness, LineOnOffDash, CapButt, JoinBevel);
180
181 XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
182 vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
183 }
184
185 void displayImage(const vpImage<unsigned char> &I, unsigned int scale, unsigned int width, unsigned int height)
186 {
187 switch (screen_depth) {
188 case 8: {
189 // Correction de l'image de facon a liberer les niveaux de gris
190 // ROUGE, VERT, BLEU, JAUNE
191 unsigned char nivGrisMax = 255 - vpColor::id_unknown;
192 if (scale == 1) {
193 unsigned char *src_8 = (unsigned char *)I.bitmap;
194 unsigned char *dst_8 = (unsigned char *)Ximage->data;
195 unsigned int i = 0;
196 unsigned int size = width * height;
197
198 while (i < size) {
199 unsigned char nivGris = src_8[i];
200 if (nivGris > nivGrisMax) {
201 dst_8[i] = 255;
202 }
203 else {
204 dst_8[i] = nivGris;
205 }
206 ++i;
207 }
208 }
209 else {
210 // Correction de l'image de facon a liberer les niveaux de gris
211 // ROUGE, VERT, BLEU, JAUNE
212 unsigned char *dst_8 = (unsigned char *)Ximage->data;
213 unsigned int k = 0;
214 for (unsigned int i = 0; i < height; i++) {
215 for (unsigned int j = 0; j < width; j++) {
216 unsigned char nivGris = I[i * scale][j * scale];
217 if (nivGris > nivGrisMax)
218 dst_8[k++] = 255;
219 else
220 dst_8[k++] = nivGris;
221 }
222 }
223 }
224
225 // Affichage de l'image dans la Pixmap.
226 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
227 XSetWindowBackgroundPixmap(display, window, pixmap);
228 break;
229 }
230 case 16: {
231 unsigned int bytes_per_line = static_cast<unsigned int>(Ximage->bytes_per_line);
232 if (scale == 1) {
233 for (unsigned int i = 0; i < height; i++) {
234 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
235 unsigned short *dst_16 = (unsigned short *)dst_8;
236 for (unsigned int j = 0; j < width; j++) {
237 *(dst_16 + j) = static_cast<unsigned short>(colortable[I[i][j]]);
238 }
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) = static_cast<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 }
276 else {
277 // little endian
278 while (bitmap < n) {
279 unsigned char val = *(bitmap++);
280 *(dst_32++) = val; // Blue
281 *(dst_32++) = val; // Green
282 *(dst_32++) = val; // Red
283 *(dst_32++) = vpRGBa::alpha_default;
284 }
285 }
286 }
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 }
300 else {
301 // little endian
302 for (unsigned int i = 0; i < height; i++) {
303 for (unsigned int j = 0; j < width; j++) {
304 unsigned char val = I[i * scale][j * scale];
305 *(dst_32++) = val; // Blue
306 *(dst_32++) = val; // Green
307 *(dst_32++) = val; // Red
308 *(dst_32++) = vpRGBa::alpha_default;
309 }
310 }
311 }
312 }
313
314 // Affichage de l'image dans la Pixmap.
315 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
316 XSetWindowBackgroundPixmap(display, window, pixmap);
317 break;
318 }
319 }
320 }
321
322 void displayImage(const vpImage<vpRGBa> &I, unsigned int scale, unsigned int width, unsigned int height)
323 {
324 switch (screen_depth) {
325 case 16: {
326 vpRGBa *bitmap = I.bitmap;
327 unsigned int r, g, b;
328 unsigned int bytes_per_line = static_cast<unsigned int>(Ximage->bytes_per_line);
329
330 if (scale == 1) {
331 for (unsigned int i = 0; i < height; i++) {
332 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
333 unsigned short *dst_16 = (unsigned short *)dst_8;
334 for (unsigned int j = 0; j < width; j++) {
335 r = bitmap->R;
336 g = bitmap->G;
337 b = bitmap->B;
338 *(dst_16 + j) =
339 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
340 bitmap++;
341 }
342 }
343 }
344 else {
345 for (unsigned int i = 0; i < height; i++) {
346 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
347 unsigned short *dst_16 = (unsigned short *)dst_8;
348 for (unsigned int j = 0; j < width; j++) {
349 vpRGBa val = I[i * scale][j * scale];
350 r = val.R;
351 g = val.G;
352 b = val.B;
353 *(dst_16 + j) =
354 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
355 bitmap++;
356 }
357 }
358 }
359
360 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
361 XSetWindowBackgroundPixmap(display, window, pixmap);
362
363 break;
364 }
365 case 24:
366 case 32: {
367 /*
368 * 32-bit source, 24/32-bit destination
369 */
370 unsigned char *dst_32 = nullptr;
371 dst_32 = (unsigned char *)Ximage->data;
372 if (scale == 1) {
373 vpRGBa *bitmap = I.bitmap;
374 unsigned int sizeI = width * height;
375 if (XImageByteOrder(display) == 1) {
376 // big endian
377 for (unsigned int i = 0; i < sizeI; i++) {
378 *(dst_32++) = bitmap->A;
379 *(dst_32++) = bitmap->R;
380 *(dst_32++) = bitmap->G;
381 *(dst_32++) = bitmap->B;
382 bitmap++;
383 }
384 }
385 else {
386 // little endian
387 for (unsigned int i = 0; i < sizeI; i++) {
388 *(dst_32++) = bitmap->B;
389 *(dst_32++) = bitmap->G;
390 *(dst_32++) = bitmap->R;
391 *(dst_32++) = bitmap->A;
392 bitmap++;
393 }
394 }
395 }
396 else {
397 if (XImageByteOrder(display) == 1) {
398 // big endian
399 for (unsigned int i = 0; i < height; i++) {
400 for (unsigned int j = 0; j < width; j++) {
401 vpRGBa val = I[i * scale][j * scale];
402 *(dst_32++) = val.A;
403 *(dst_32++) = val.R;
404 *(dst_32++) = val.G;
405 *(dst_32++) = val.B;
406 }
407 }
408 }
409 else {
410 // little endian
411 for (unsigned int i = 0; i < height; i++) {
412 for (unsigned int j = 0; j < width; j++) {
413 vpRGBa val = I[i * scale][j * scale];
414 *(dst_32++) = val.B;
415 *(dst_32++) = val.G;
416 *(dst_32++) = val.R;
417 *(dst_32++) = val.A;
418 }
419 }
420 }
421 }
422
423 // Affichage de l'image dans la Pixmap.
424 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
425 XSetWindowBackgroundPixmap(display, window, pixmap);
426 break;
427 }
428 default:
429 throw(vpDisplayException(vpDisplayException::depthNotSupportedError,
430 "Unsupported depth (%d bpp) for color display", screen_depth));
431 }
432 }
433
434 void displayImage(const unsigned char *bitmap, unsigned int width, unsigned int height)
435 {
436 unsigned char *dst_32 = (unsigned char *)Ximage->data;
437 for (unsigned int i = 0; i < width * height; i++) {
438 *(dst_32++) = *bitmap; // red component.
439 *(dst_32++) = *bitmap; // green component.
440 *(dst_32++) = *bitmap; // blue component.
441 *(dst_32++) = *bitmap; // luminance component.
442 bitmap++;
443 }
444
445 // Affichage de l'image dans la Pixmap.
446 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, width, height);
447 XSetWindowBackgroundPixmap(display, window, pixmap);
448 }
449
450 void displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w, unsigned int h,
451 unsigned int scale, unsigned int width, unsigned int height)
452 {
453 switch (screen_depth) {
454 case 8: {
455 // Correction de l'image de facon a liberer les niveaux de gris
456 // ROUGE, VERT, BLEU, JAUNE
457 unsigned char nivGrisMax = 255 - vpColor::id_unknown;
458 if (scale == 1) {
459 unsigned char *src_8 = (unsigned char *)I.bitmap;
460 unsigned char *dst_8 = (unsigned char *)Ximage->data;
461 unsigned int iwidth = I.getWidth();
462
463 src_8 = src_8 + static_cast<int>(iP.get_i() * iwidth + iP.get_j());
464 dst_8 = dst_8 + static_cast<int>(iP.get_i() * width + iP.get_j());
465
466 unsigned int i = 0;
467 while (i < h) {
468 unsigned int j = 0;
469 while (j < w) {
470 unsigned char nivGris = *(src_8 + j);
471 if (nivGris > nivGrisMax)
472 *(dst_8 + j) = 255;
473 else
474 *(dst_8 + j) = nivGris;
475 ++j;
476 }
477 src_8 = src_8 + iwidth;
478 dst_8 = dst_8 + width;
479 ++i;
480 }
481
482 XPutImage(display, pixmap, context, Ximage, static_cast<int>(iP.get_u()), static_cast<int>(iP.get_v()), static_cast<int>(iP.get_u()), static_cast<int>(iP.get_v()),
483 w, h);
484 }
485 else {
486 // Correction de l'image de facon a liberer les niveaux de gris
487 // ROUGE, VERT, BLEU, JAUNE
488 int i_min = std::max<int>(static_cast<int>(ceil(iP.get_i() / scale)), 0);
489 int j_min = std::max<int>(static_cast<int>(ceil(iP.get_j() / scale)), 0);
490 int i_max = std::min<int>(static_cast<int>(ceil((iP.get_i() + h) / scale)), static_cast<int>(height));
491 int j_max = std::min<int>(static_cast<int>(ceil((iP.get_j() + w) / scale)), static_cast<int>(width));
492
493 unsigned int i_min_ = static_cast<unsigned int>(i_min);
494 unsigned int i_max_ = static_cast<unsigned int>(i_max);
495 unsigned int j_min_ = static_cast<unsigned int>(j_min);
496 unsigned int j_max_ = static_cast<unsigned int>(j_max);
497
498 for (unsigned int i = i_min_; i < i_max_; i++) {
499 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * width;
500 for (unsigned int j = j_min_; j < j_max_; j++) {
501 unsigned char nivGris = I[i * scale][j * scale];
502 if (nivGris > nivGrisMax)
503 dst_8[j] = 255;
504 else
505 dst_8[j] = nivGris;
506 }
507 }
508 XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
509 }
510
511 // Affichage de l'image dans la Pixmap.
512 XSetWindowBackgroundPixmap(display, window, pixmap);
513 break;
514 }
515 case 16: {
516 unsigned int bytes_per_line = static_cast<unsigned int>(Ximage->bytes_per_line);
517 if (scale == 1) {
518 for (unsigned int i = static_cast<unsigned int>(iP.get_i()); i < static_cast<unsigned int>(iP.get_i() + h); i++) {
519 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
520 unsigned short *dst_16 = (unsigned short *)dst_8;
521 for (unsigned int j = static_cast<unsigned int>(iP.get_j()); j < static_cast<unsigned int>(iP.get_j() + w); j++) {
522 *(dst_16 + j) = static_cast<unsigned short>(colortable[I[i][j]]);
523 }
524 }
525
526 XPutImage(display, pixmap, context, Ximage, static_cast<int>(iP.get_u()), static_cast<int>(iP.get_v()), static_cast<int>(iP.get_u()), static_cast<int>(iP.get_v()),
527 w, h);
528 }
529 else {
530 int i_min = std::max<int>(static_cast<int>(ceil(iP.get_i() / scale)), 0);
531 int j_min = std::max<int>(static_cast<int>(ceil(iP.get_j() / scale)), 0);
532 int i_max = std::min<int>(static_cast<int>(ceil((iP.get_i() + h) / scale)), static_cast<int>(height));
533 int j_max = std::min<int>(static_cast<int>(ceil((iP.get_j() + w) / scale)), static_cast<int>(width));
534
535 unsigned int i_min_ = static_cast<unsigned int>(i_min);
536 unsigned int i_max_ = static_cast<unsigned int>(i_max);
537 unsigned int j_min_ = static_cast<unsigned int>(j_min);
538 unsigned int j_max_ = static_cast<unsigned int>(j_max);
539
540 for (unsigned int i = i_min_; i < i_max_; i++) {
541 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
542 unsigned short *dst_16 = (unsigned short *)dst_8;
543 for (unsigned int j = j_min_; j < j_max_; j++) {
544 *(dst_16 + j) = static_cast<unsigned short>(colortable[I[i * scale][j * scale]]);
545 }
546 }
547
548 XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
549 }
550
551 XSetWindowBackgroundPixmap(display, window, pixmap);
552 break;
553 }
554
555 case 24:
556 default: {
557 if (scale == 1) {
558 unsigned int iwidth = I.getWidth();
559 unsigned char *src_8 = I.bitmap + static_cast<int>(iP.get_i() * iwidth + iP.get_j());
560 unsigned char *dst_32 = (unsigned char *)Ximage->data + static_cast<int>(iP.get_i() * 4 * width + iP.get_j() * 4);
561
562 if (XImageByteOrder(display) == 1) {
563 // big endian
564 unsigned int i = 0;
565 while (i < h) {
566 unsigned int j = 0;
567 while (j < w) {
568 unsigned char val = *(src_8 + j);
569 *(dst_32 + 4 * j) = vpRGBa::alpha_default;
570 *(dst_32 + 4 * j + 1) = val;
571 *(dst_32 + 4 * j + 2) = val;
572 *(dst_32 + 4 * j + 3) = val;
573 ++j;
574 }
575 src_8 = src_8 + iwidth;
576 dst_32 = dst_32 + 4 * width;
577 ++i;
578 }
579 }
580 else {
581 // little endian
582 unsigned int i = 0;
583 while (i < h) {
584 unsigned int j = 0;
585 while (j < w) {
586 unsigned char val = *(src_8 + j);
587 *(dst_32 + 4 * j) = val;
588 *(dst_32 + 4 * j + 1) = val;
589 *(dst_32 + 4 * j + 2) = val;
590 *(dst_32 + 4 * j + 3) = vpRGBa::alpha_default;
591 ++j;
592 }
593 src_8 = src_8 + iwidth;
594 dst_32 = dst_32 + 4 * width;
595 ++i;
596 }
597 }
598
599 XPutImage(display, pixmap, context, Ximage, static_cast<int>(iP.get_u()), static_cast<int>(iP.get_v()), static_cast<int>(iP.get_u()), static_cast<int>(iP.get_v()),
600 w, h);
601 }
602 else {
603 int i_min = std::max<int>(static_cast<int>(ceil(iP.get_i() / scale)), 0);
604 int j_min = std::max<int>(static_cast<int>(ceil(iP.get_j() / scale)), 0);
605 int i_max = std::min<int>(static_cast<int>(ceil((iP.get_i() + h) / scale)), static_cast<int>(height));
606 int j_max = std::min<int>(static_cast<int>(ceil((iP.get_j() + w) / scale)), static_cast<int>(width));
607
608 unsigned int i_min_ = static_cast<unsigned int>(i_min);
609 unsigned int i_max_ = static_cast<unsigned int>(i_max);
610 unsigned int j_min_ = static_cast<unsigned int>(j_min);
611 unsigned int j_max_ = static_cast<unsigned int>(j_max);
612
613 if (XImageByteOrder(display) == 1) {
614 // big endian
615 for (unsigned int i = i_min_; i < i_max_; i++) {
616 unsigned char *dst_32 = (unsigned char *)Ximage->data + static_cast<int>(i * 4 * width + j_min_ * 4);
617 for (unsigned int j = j_min_; j < j_max_; j++) {
618 unsigned char val = I[i * scale][j * scale];
619 *(dst_32++) = vpRGBa::alpha_default;
620 *(dst_32++) = val;
621 *(dst_32++) = val;
622 *(dst_32++) = val;
623 }
624 }
625 }
626 else {
627 // little endian
628 for (unsigned int i = i_min_; i < i_max_; i++) {
629 unsigned char *dst_32 = (unsigned char *)Ximage->data + static_cast<int>(i * 4 * width + j_min_ * 4);
630 for (unsigned int j = j_min_; j < j_max_; j++) {
631 unsigned char val = I[i * scale][j * scale];
632 *(dst_32++) = val;
633 *(dst_32++) = val;
634 *(dst_32++) = val;
635 *(dst_32++) = vpRGBa::alpha_default;
636 }
637 }
638 }
639
640 XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
641 }
642
643 XSetWindowBackgroundPixmap(display, window, pixmap);
644 break;
645 }
646 }
647 }
648
649 void displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h,
650 unsigned int scale, unsigned int width, unsigned int height)
651 {
652 switch (screen_depth) {
653 case 16: {
654 if (scale == 1) {
655 unsigned int bytes_per_line = static_cast<unsigned int>(Ximage->bytes_per_line);
656 for (unsigned int i = static_cast<unsigned int>(iP.get_i()); i < static_cast<unsigned int>(iP.get_i() + h); i++) {
657 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
658 unsigned short *dst_16 = (unsigned short *)dst_8;
659 for (unsigned int j = static_cast<unsigned int>(iP.get_j()); j < static_cast<unsigned int>(iP.get_j() + w); j++) {
660 vpRGBa val = I[i][j];
661 unsigned int r = val.R;
662 unsigned int g = val.G;
663 unsigned int b = val.B;
664 *(dst_16 + j) =
665 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
666 }
667 }
668 XPutImage(display, pixmap, context, Ximage, static_cast<int>(iP.get_u()), static_cast<int>(iP.get_v()), static_cast<int>(iP.get_u()), static_cast<int>(iP.get_v()),
669 w, h);
670 }
671 else {
672 unsigned int bytes_per_line = static_cast<unsigned int>(Ximage->bytes_per_line);
673 int i_min = std::max<int>(static_cast<int>(ceil(iP.get_i() / scale)), 0);
674 int j_min = std::max<int>(static_cast<int>(ceil(iP.get_j() / scale)), 0);
675 int i_max = std::min<int>(static_cast<int>(ceil((iP.get_i() + h) / scale)), static_cast<int>(height));
676 int j_max = std::min<int>(static_cast<int>(ceil((iP.get_j() + w) / scale)), static_cast<int>(width));
677
678 unsigned int i_min_ = static_cast<unsigned int>(i_min);
679 unsigned int i_max_ = static_cast<unsigned int>(i_max);
680 unsigned int j_min_ = static_cast<unsigned int>(j_min);
681 unsigned int j_max_ = static_cast<unsigned int>(j_max);
682
683 for (unsigned int i = i_min_; i < i_max_; i++) {
684 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
685 unsigned short *dst_16 = (unsigned short *)dst_8;
686 for (unsigned int j = j_min_; j < j_max_; j++) {
687 vpRGBa val = I[i * scale][j * scale];
688 unsigned int r = val.R;
689 unsigned int g = val.G;
690 unsigned int b = val.B;
691 *(dst_16 + j) =
692 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
693 }
694 }
695 XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
696 }
697
698 XSetWindowBackgroundPixmap(display, window, pixmap);
699
700 break;
701 }
702 case 24:
703 case 32: {
704 /*
705 * 32-bit source, 24/32-bit destination
706 */
707
708 if (scale == 1) {
709 unsigned char *dst_32 = (unsigned char *)Ximage->data;
710 vpRGBa *src_32 = I.bitmap;
711
712 unsigned int iwidth = I.getWidth();
713
714 src_32 = src_32 + static_cast<int>(iP.get_i() * iwidth + iP.get_j());
715 dst_32 = dst_32 + static_cast<int>(iP.get_i() * 4 * width + iP.get_j() * 4);
716
717 unsigned int i = 0;
718
719 if (XImageByteOrder(display) == 1) {
720 // big endian
721 while (i < h) {
722 unsigned int j = 0;
723 while (j < w) {
724 *(dst_32 + 4 * j) = (src_32 + j)->A;
725 *(dst_32 + 4 * j + 1) = (src_32 + j)->R;
726 *(dst_32 + 4 * j + 2) = (src_32 + j)->G;
727 *(dst_32 + 4 * j + 3) = (src_32 + j)->B;
728
729 ++j;
730 }
731 src_32 = src_32 + iwidth;
732 dst_32 = dst_32 + 4 * width;
733 ++i;
734 }
735
736 }
737 else {
738 // little endian
739 while (i < h) {
740 unsigned int j = 0;
741 while (j < w) {
742 *(dst_32 + 4 * j) = (src_32 + j)->B;
743 *(dst_32 + 4 * j + 1) = (src_32 + j)->G;
744 *(dst_32 + 4 * j + 2) = (src_32 + j)->R;
745 *(dst_32 + 4 * j + 3) = (src_32 + j)->A;
746
747 ++j;
748 }
749 src_32 = src_32 + iwidth;
750 dst_32 = dst_32 + 4 * width;
751 ++i;
752 }
753 }
754
755 XPutImage(display, pixmap, context, Ximage, static_cast<int>(iP.get_u()), static_cast<int>(iP.get_v()), static_cast<int>(iP.get_u()), static_cast<int>(iP.get_v()),
756 w, h);
757 }
758 else {
759 int i_min = std::max<int>(static_cast<int>(ceil(iP.get_i() / scale)), 0);
760 int j_min = std::max<int>(static_cast<int>(ceil(iP.get_j() / scale)), 0);
761 int i_max = std::min<int>(static_cast<int>(ceil((iP.get_i() + h) / scale)), static_cast<int>(height));
762 int j_max = std::min<int>(static_cast<int>(ceil((iP.get_j() + w) / scale)), static_cast<int>(width));
763
764 unsigned int i_min_ = static_cast<unsigned int>(i_min);
765 unsigned int i_max_ = static_cast<unsigned int>(i_max);
766 unsigned int j_min_ = static_cast<unsigned int>(j_min);
767 unsigned int j_max_ = static_cast<unsigned int>(j_max);
768
769 if (XImageByteOrder(display) == 1) {
770 // big endian
771 for (unsigned int i = i_min_; i < i_max_; i++) {
772 unsigned char *dst_32 = (unsigned char *)Ximage->data + static_cast<int>(i * 4 * width + j_min_ * 4);
773 for (unsigned int j = j_min_; j < j_max_; j++) {
774 vpRGBa val = I[i * scale][j * scale];
775 *(dst_32++) = val.A;
776 *(dst_32++) = val.R;
777 *(dst_32++) = val.G;
778 *(dst_32++) = val.B;
779 }
780 }
781 }
782 else {
783 // little endian
784 for (unsigned int i = i_min_; i < i_max_; i++) {
785 unsigned char *dst_32 = (unsigned char *)Ximage->data + static_cast<int>(i * 4 * width + j_min_ * 4);
786 for (unsigned int j = j_min_; j < j_max_; j++) {
787 vpRGBa val = I[i * scale][j * scale];
788 *(dst_32++) = val.B;
789 *(dst_32++) = val.G;
790 *(dst_32++) = val.R;
791 *(dst_32++) = val.A;
792 }
793 }
794 }
795 XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
796 }
797
798 XSetWindowBackgroundPixmap(display, window, pixmap);
799 break;
800 }
801 default:
802 throw(vpDisplayException(vpDisplayException::depthNotSupportedError,
803 "Unsupported depth (%d bpp) for color display", screen_depth));
804 }
805 }
806
807 void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness,
808 unsigned int scale)
809 {
810 if (color.id < vpColor::id_unknown)
811 XSetForeground(display, context, x_color[color.id]);
812 else {
813 xcolor.pad = 0;
814 xcolor.red = 256 * color.R;
815 xcolor.green = 256 * color.G;
816 xcolor.blue = 256 * color.B;
817 XAllocColor(display, lut, &xcolor);
818 XSetForeground(display, context, xcolor.pixel);
819 }
820
821 XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
822
823 XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / scale), vpMath::round(ip1.get_v() / scale),
824 vpMath::round(ip2.get_u() / scale), vpMath::round(ip2.get_v() / scale));
825 }
826
827 void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness, unsigned int scale)
828 {
829 if (color.id < vpColor::id_unknown)
830 XSetForeground(display, context, x_color[color.id]);
831 else {
832 xcolor.pad = 0;
833 xcolor.red = 256 * color.R;
834 xcolor.green = 256 * color.G;
835 xcolor.blue = 256 * color.B;
836 XAllocColor(display, lut, &xcolor);
837 XSetForeground(display, context, xcolor.pixel);
838 }
839
840 if (thickness == 1) {
841 XDrawPoint(display, pixmap, context, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale));
842 }
843 else {
844 XFillRectangle(display, pixmap, context, vpMath::round(ip.get_u() / scale), vpMath::round(ip.get_v() / scale),
845 thickness, thickness);
846 }
847 }
848
849 void displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color, bool fill,
850 unsigned int thickness, unsigned int scale)
851 {
852 if (color.id < vpColor::id_unknown)
853 XSetForeground(display, context, x_color[color.id]);
854 else {
855 xcolor.pad = 0;
856 xcolor.red = 256 * color.R;
857 xcolor.green = 256 * color.G;
858 xcolor.blue = 256 * color.B;
859 XAllocColor(display, lut, &xcolor);
860 XSetForeground(display, context, xcolor.pixel);
861 }
862 XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
863 if (fill == false) {
864 XDrawRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / scale),
865 vpMath::round(topLeft.get_v() / scale), w / scale, h / scale);
866 }
867 else {
868 XFillRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / scale),
869 vpMath::round(topLeft.get_v() / scale), w / scale, h / scale);
870 }
871 }
872
873 void flushDisplay()
874 {
875 XClearWindow(display, window);
876 XFlush(display);
877 }
878
879 void flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h, unsigned int scale)
880 {
881 XClearArea(display, window, static_cast<int>(iP.get_u() / scale), static_cast<int>(iP.get_v() / scale), w / scale, h / scale, 0);
882 XFlush(display);
883 }
884
885 bool getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale)
886 {
887 bool ret = false;
888 Window rootwin, childwin;
889 int root_x, root_y, win_x, win_y;
890 unsigned int modifier;
891
892 // Event testing
893 if (blocking) {
894 XCheckMaskEvent(display, ButtonPressMask, &event);
895 XCheckMaskEvent(display, ButtonReleaseMask, &event);
896 XMaskEvent(display, ButtonPressMask, &event);
897 ret = true;
898 }
899 else {
900 ret = XCheckMaskEvent(display, ButtonPressMask, &event);
901 }
902
903 if (ret) {
904 // Get mouse position
905 if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
906 ip.set_u(static_cast<double>(event.xbutton.x) * scale);
907 ip.set_v(static_cast<double>(event.xbutton.y) * scale);
908 switch (event.xbutton.button) {
909 case Button1:
910 button = vpMouseButton::button1;
911 break;
912 case Button2:
913 button = vpMouseButton::button2;
914 break;
915 case Button3:
916 button = vpMouseButton::button3;
917 break;
918 }
919 }
920 }
921
922 return ret;
923 }
924
925 bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking, unsigned int scale)
926 {
927 bool ret = false;
928 Window rootwin, childwin;
929 int root_x, root_y, win_x, win_y;
930 unsigned int modifier;
931
932 // Event testing
933 if (blocking) {
934 XCheckMaskEvent(display, ButtonPressMask, &event);
935 XCheckMaskEvent(display, ButtonReleaseMask, &event);
936 XMaskEvent(display, ButtonReleaseMask, &event);
937 ret = true;
938 }
939 else {
940 ret = XCheckMaskEvent(display, ButtonReleaseMask, &event);
941 }
942
943 if (ret) {
944 /* Recuperation de la coordonnee du pixel clique. */
945 if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
946 ip.set_u(static_cast<double>(event.xbutton.x) * scale);
947 ip.set_v(static_cast<double>(event.xbutton.y) * scale);
948 switch (event.xbutton.button) {
949 case Button1:
950 button = vpMouseButton::button1;
951 break;
952 case Button2:
953 button = vpMouseButton::button2;
954 break;
955 case Button3:
956 button = vpMouseButton::button3;
957 break;
958 }
959 }
960 }
961
962 return ret;
963 }
964
965 void getImage(vpImage<vpRGBa> &I, unsigned int width, unsigned int height)
966 {
967 XImage *xi;
968
969 XCopyArea(display, window, pixmap, context, 0, 0, width, height, 0, 0);
970
971 xi = XGetImage(display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap);
972
973 I.resize(height, width);
974
975 unsigned char *src_32 = nullptr;
976 src_32 = (unsigned char *)xi->data;
977
978 if (screen_depth == 16) {
979 for (unsigned int i = 0; i < I.getHeight(); i++) {
980 size_t i_ = i * width;
981 for (unsigned int j = 0; j < height; j++) {
982 size_t ij_ = i_ + j;
983 unsigned long pixel = XGetPixel(xi, static_cast<int>(j), static_cast<int>(i));
984 I.bitmap[ij_].R = (((pixel & RMask) << RShift) >> 8);
985 I.bitmap[ij_].G = (((pixel & GMask) << GShift) >> 8);
986 I.bitmap[ij_].B = (((pixel & BMask) << BShift) >> 8);
987 // On OSX the bottom/right corner (around the resizing icon) has
988 // alpha component with different values than 255. That's why we
989 // force alpha to vpRGBa::alpha_default
990 I.bitmap[ij_].A = vpRGBa::alpha_default;
991 }
992 }
993
994 }
995 else {
996 if (XImageByteOrder(display) == 1) {
997 // big endian
998 for (unsigned int i = 0; i < width * height; i++) {
999 // On OSX the bottom/right corner (around the resizing icon) has
1000 // alpha component with different values than 255. That's why we
1001 // force alpha to vpRGBa::alpha_default
1002 I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4] ;
1003 I.bitmap[i].R = src_32[i * 4 + 1];
1004 I.bitmap[i].G = src_32[i * 4 + 2];
1005 I.bitmap[i].B = src_32[i * 4 + 3];
1006 }
1007 }
1008 else {
1009 // little endian
1010 for (unsigned int i = 0; i < width * height; i++) {
1011 I.bitmap[i].B = src_32[i * 4];
1012 I.bitmap[i].G = src_32[i * 4 + 1];
1013 I.bitmap[i].R = src_32[i * 4 + 2];
1014 // On OSX the bottom/right corner (around the resizing icon) has
1015 // alpha component with different values than 255. That's why we
1016 // force alpha to vpRGBa::alpha_default
1017 I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4 + 3];
1018 }
1019 }
1020 }
1021 XDestroyImage(xi);
1022 }
1023
1024 bool getKeyboardEvent(bool blocking)
1025 {
1026 bool ret = false;
1027
1028 // Event testing
1029 if (blocking) {
1030 XMaskEvent(display, KeyPressMask, &event);
1031 ret = true;
1032 }
1033 else {
1034 ret = XCheckMaskEvent(display, KeyPressMask, &event);
1035 }
1036
1037 return ret;
1038 }
1039
1040 bool getKeyboardEvent(std::string &key, bool blocking)
1041 {
1042 bool ret = false;
1043 KeySym keysym;
1044 // int count;
1045 XComposeStatus compose_status;
1046 char buffer;
1047
1048 // Event testing
1049 if (blocking) {
1050 XMaskEvent(display, KeyPressMask, &event);
1051 /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
1052 key = buffer;
1053 ret = true;
1054 }
1055 else {
1056 ret = XCheckMaskEvent(display, KeyPressMask, &event);
1057 if (ret) {
1058 /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
1059 key = buffer;
1060 }
1061 }
1062
1063 return ret;
1064 }
1065
1069 int getMsb(unsigned int u32val)
1070 {
1071 int i;
1072
1073 for (i = 31; i >= 0; --i) {
1074 if (u32val & 0x80000000L)
1075 break;
1076 u32val <<= 1;
1077 }
1078 return i;
1079 }
1080
1081 bool getPointerMotionEvent(vpImagePoint &ip, unsigned int scale)
1082 {
1083 bool ret = false;
1084
1085 Window rootwin, childwin;
1086 int root_x, root_y, win_x, win_y;
1087 unsigned int modifier;
1088 // Event testing
1089 ret = XCheckMaskEvent(display, PointerMotionMask, &event);
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(static_cast<double>(event.xbutton.x) * scale);
1095 ip.set_v(static_cast<double>(event.xbutton.y) * scale);
1096 }
1097 }
1098
1099 return ret;
1100 }
1101
1102 bool getPointerPosition(vpImagePoint &ip, unsigned int scale)
1103 {
1104 bool ret = false;
1105 Window rootwin, childwin;
1106 int root_x, root_y, win_x, win_y;
1107 unsigned int modifier;
1108 // Event testing
1109 ret = true;
1110
1111 if (ret) {
1112 // Get mouse position
1113 if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
1114 ip.set_u(static_cast<double>(win_x) * scale);
1115 ip.set_v(static_cast<double>(win_y) * scale);
1116 }
1117 }
1118
1119 return ret;
1120 }
1121
1122 unsigned int getScreenDepth()
1123 {
1124 Display *display_;
1125 int screen_;
1126 unsigned int depth;
1127
1128 if ((display_ = XOpenDisplay(nullptr)) == nullptr) {
1129 throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
1130 XDisplayName(nullptr)));
1131 }
1132 screen_ = DefaultScreen(display_);
1133 depth = static_cast<unsigned int>(DefaultDepth(display_, screen_));
1134
1135 XCloseDisplay(display_);
1136
1137 return (depth);
1138 }
1139
1140 void getScreenSize(unsigned int &w, unsigned int &h)
1141 {
1142 Display *display_;
1143 int screen_;
1144
1145 if ((display_ = XOpenDisplay(nullptr)) == nullptr) {
1146 throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
1147 XDisplayName(nullptr)));
1148 }
1149 screen_ = DefaultScreen(display_);
1150 w = static_cast<unsigned int>(DisplayWidth(display_, screen_));
1151 h = static_cast<unsigned int>(DisplayHeight(display_, screen_));
1152
1153 XCloseDisplay(display_);
1154 }
1155
1156 void init(unsigned int win_width, unsigned int win_height, int win_x, int win_y, const std::string &win_title)
1157 {
1158 if (x_color == nullptr) {
1159 // id_unknown = number of predefined colors
1160 x_color = new unsigned long[vpColor::id_unknown];
1161 }
1162 // setup X11
1163 XSizeHints hints;
1164
1165 // Positionnement de la fenetre dans l'ecran.
1166 if ((win_x < 0) || (win_y < 0)) {
1167 hints.flags = 0;
1168 }
1169 else {
1170 hints.flags = USPosition;
1171 hints.x = win_x;
1172 hints.y = win_y;
1173 }
1174
1175 if ((display = XOpenDisplay(nullptr)) == nullptr) {
1176 throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.", XDisplayName(nullptr)));
1177 }
1178
1179 screen = DefaultScreen(display);
1180 lut = DefaultColormap(display, screen);
1181 screen_depth = static_cast<unsigned int>(DefaultDepth(display, screen));
1182
1183 if ((window = XCreateSimpleWindow(display, RootWindow(display, screen), win_x, win_y, win_width, win_height, 1,
1184 BlackPixel(display, screen), WhitePixel(display, screen))) == 0) {
1185 throw(vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create window."));
1186 }
1187
1188 //
1189 // Create color table for 8 and 16 bits screen
1190 //
1191 if (screen_depth == 8) {
1192 lut = XCreateColormap(display, window, DefaultVisual(display, screen), AllocAll);
1193 xcolor.flags = DoRed | DoGreen | DoBlue;
1194
1195 for (unsigned int i = 0; i < 256; i++) {
1196 xcolor.pixel = i;
1197 xcolor.red = 256 * i;
1198 xcolor.green = 256 * i;
1199 xcolor.blue = 256 * i;
1200 XStoreColor(display, lut, &xcolor);
1201 }
1202
1203 XSetWindowColormap(display, window, lut);
1204 XInstallColormap(display, lut);
1205 }
1206
1207 else if (screen_depth == 16) {
1208 for (unsigned int i = 0; i < 256; i++) {
1209 xcolor.pad = 0;
1210 xcolor.red = xcolor.green = xcolor.blue = 256 * i;
1211 if (XAllocColor(display, lut, &xcolor) == 0) {
1212 throw(vpDisplayException(vpDisplayException::colorAllocError, "Can't allocate 256 colors. Only %d allocated.", i));
1213 }
1214 colortable[i] = xcolor.pixel;
1215 }
1216
1217 XSetWindowColormap(display, window, lut);
1218 XInstallColormap(display, lut);
1219
1220 Visual *visual = DefaultVisual(display, screen);
1221 RMask = visual->red_mask;
1222 GMask = visual->green_mask;
1223 BMask = visual->blue_mask;
1224
1225 RShift = 15 - getMsb(RMask); /* these are right-shifts */
1226 GShift = 15 - getMsb(GMask);
1227 BShift = 15 - getMsb(BMask);
1228 }
1229
1230 vpColor pcolor; // predefined colors
1231
1232 //
1233 // Create colors for overlay
1234 //
1235 switch (screen_depth) {
1236
1237 case 8:
1238 // Color BLACK: default set to 0
1239
1240 // Color WHITE: default set to 255
1241
1242 // Color LIGHT GRAY.
1243 x_color[vpColor::id_lightGray] = 254;
1244 xcolor.pixel = x_color[vpColor::id_lightGray];
1245 xcolor.red = 256 * 192;
1246 xcolor.green = 256 * 192;
1247 xcolor.blue = 256 * 192;
1248 XStoreColor(display, lut, &xcolor);
1249
1250 // Color GRAY.
1251 x_color[vpColor::id_gray] = 253;
1252 xcolor.pixel = x_color[vpColor::id_gray];
1253 xcolor.red = 256 * 128;
1254 xcolor.green = 256 * 128;
1255 xcolor.blue = 256 * 128;
1256 XStoreColor(display, lut, &xcolor);
1257
1258 // Color DARK GRAY.
1259 x_color[vpColor::id_darkGray] = 252;
1260 xcolor.pixel = x_color[vpColor::id_darkGray];
1261 xcolor.red = 256 * 64;
1262 xcolor.green = 256 * 64;
1263 xcolor.blue = 256 * 64;
1264 XStoreColor(display, lut, &xcolor);
1265
1266 // Color LIGHT RED.
1267 x_color[vpColor::id_lightRed] = 251;
1268 xcolor.pixel = x_color[vpColor::id_lightRed];
1269 xcolor.red = 256 * 255;
1270 xcolor.green = 256 * 140;
1271 xcolor.blue = 256 * 140;
1272 XStoreColor(display, lut, &xcolor);
1273
1274 // Color RED.
1275 x_color[vpColor::id_red] = 250;
1276 xcolor.pixel = x_color[vpColor::id_red];
1277 xcolor.red = 256 * 255;
1278 xcolor.green = 0;
1279 xcolor.blue = 0;
1280 XStoreColor(display, lut, &xcolor);
1281
1282 // Color DARK RED.
1283 x_color[vpColor::id_darkRed] = 249;
1284 xcolor.pixel = x_color[vpColor::id_darkRed];
1285 xcolor.red = 256 * 128;
1286 xcolor.green = 0;
1287 xcolor.blue = 0;
1288 XStoreColor(display, lut, &xcolor);
1289
1290 // Color LIGHT GREEN.
1291 x_color[vpColor::id_lightGreen] = 248;
1292 xcolor.pixel = x_color[vpColor::id_lightGreen];
1293 xcolor.red = 256 * 140;
1294 xcolor.green = 256 * 255;
1295 xcolor.blue = 256 * 140;
1296 XStoreColor(display, lut, &xcolor);
1297
1298 // Color GREEN.
1299 x_color[vpColor::id_green] = 247;
1300 xcolor.pixel = x_color[vpColor::id_green];
1301 xcolor.red = 0;
1302 xcolor.green = 256 * 255;
1303 xcolor.blue = 0;
1304 XStoreColor(display, lut, &xcolor);
1305
1306 // Color DARK GREEN.
1307 x_color[vpColor::id_darkGreen] = 246;
1308 xcolor.pixel = x_color[vpColor::id_darkGreen];
1309 xcolor.red = 0;
1310 xcolor.green = 256 * 128;
1311 xcolor.blue = 0;
1312 XStoreColor(display, lut, &xcolor);
1313
1314 // Color LIGHT BLUE.
1315 x_color[vpColor::id_lightBlue] = 245;
1316 xcolor.pixel = x_color[vpColor::id_lightBlue];
1317 xcolor.red = 256 * 140;
1318 xcolor.green = 256 * 140;
1319 xcolor.blue = 256 * 255;
1320 XStoreColor(display, lut, &xcolor);
1321
1322 // Color BLUE.
1323 x_color[vpColor::id_blue] = 244;
1324 xcolor.pixel = x_color[vpColor::id_blue];
1325 xcolor.red = 0;
1326 xcolor.green = 0;
1327 xcolor.blue = 256 * 255;
1328 XStoreColor(display, lut, &xcolor);
1329
1330 // Color DARK BLUE.
1331 x_color[vpColor::id_darkBlue] = 243;
1332 xcolor.pixel = x_color[vpColor::id_darkBlue];
1333 xcolor.red = 0;
1334 xcolor.green = 0;
1335 xcolor.blue = 256 * 128;
1336 XStoreColor(display, lut, &xcolor);
1337
1338 // Color YELLOW.
1339 x_color[vpColor::id_yellow] = 242;
1340 xcolor.pixel = x_color[vpColor::id_yellow];
1341 xcolor.red = 256 * 255;
1342 xcolor.green = 256 * 255;
1343 xcolor.blue = 0;
1344 XStoreColor(display, lut, &xcolor);
1345
1346 // Color ORANGE.
1347 x_color[vpColor::id_orange] = 241;
1348 xcolor.pixel = x_color[vpColor::id_orange];
1349 xcolor.red = 256 * 255;
1350 xcolor.green = 256 * 165;
1351 xcolor.blue = 0;
1352 XStoreColor(display, lut, &xcolor);
1353
1354 // Color CYAN.
1355 x_color[vpColor::id_cyan] = 240;
1356 xcolor.pixel = x_color[vpColor::id_cyan];
1357 xcolor.red = 0;
1358 xcolor.green = 256 * 255;
1359 xcolor.blue = 256 * 255;
1360 XStoreColor(display, lut, &xcolor);
1361
1362 // Color PURPLE.
1363 x_color[vpColor::id_purple] = 239;
1364 xcolor.pixel = x_color[vpColor::id_purple];
1365 xcolor.red = 256 * 128;
1366 xcolor.green = 0;
1367 xcolor.blue = 256 * 128;
1368 XStoreColor(display, lut, &xcolor);
1369
1370 break;
1371
1372 case 16:
1373 case 24:
1374 case 32: {
1375 xcolor.flags = DoRed | DoGreen | DoBlue;
1376
1377 // Couleur BLACK.
1378 pcolor = vpColor::black;
1379 xcolor.pad = 0;
1380 xcolor.red = 256 * pcolor.R;
1381 xcolor.green = 256 * pcolor.G;
1382 xcolor.blue = 256 * pcolor.B;
1383 XAllocColor(display, lut, &xcolor);
1384 x_color[vpColor::id_black] = xcolor.pixel;
1385
1386 // Color WHITE.
1387 pcolor = vpColor::white;
1388 xcolor.pad = 0;
1389 xcolor.red = 256 * pcolor.R;
1390 xcolor.green = 256 * pcolor.G;
1391 xcolor.blue = 256 * pcolor.B;
1392 XAllocColor(display, lut, &xcolor);
1393 x_color[vpColor::id_white] = xcolor.pixel;
1394
1395 // Color LIGHT GRAY.
1396 pcolor = vpColor::lightGray;
1397 xcolor.pad = 0;
1398 xcolor.red = 256 * pcolor.R;
1399 xcolor.green = 256 * pcolor.G;
1400 xcolor.blue = 256 * pcolor.B;
1401 XAllocColor(display, lut, &xcolor);
1402 x_color[vpColor::id_lightGray] = xcolor.pixel;
1403
1404 // Color GRAY.
1405 pcolor = vpColor::gray;
1406 xcolor.pad = 0;
1407 xcolor.red = 256 * pcolor.R;
1408 xcolor.green = 256 * pcolor.G;
1409 xcolor.blue = 256 * pcolor.B;
1410 XAllocColor(display, lut, &xcolor);
1411 x_color[vpColor::id_gray] = xcolor.pixel;
1412
1413 // Color DARK GRAY.
1414 pcolor = vpColor::darkGray;
1415 xcolor.pad = 0;
1416 xcolor.red = 256 * pcolor.R;
1417 xcolor.green = 256 * pcolor.G;
1418 xcolor.blue = 256 * pcolor.B;
1419 XAllocColor(display, lut, &xcolor);
1420 x_color[vpColor::id_darkGray] = xcolor.pixel;
1421
1422 // Color LIGHT RED.
1423 pcolor = vpColor::lightRed;
1424 xcolor.pad = 0;
1425 xcolor.red = 256 * pcolor.R;
1426 xcolor.green = 256 * pcolor.G;
1427 xcolor.blue = 256 * pcolor.B;
1428 XAllocColor(display, lut, &xcolor);
1429 x_color[vpColor::id_lightRed] = xcolor.pixel;
1430
1431 // Color RED.
1432 pcolor = vpColor::red;
1433 xcolor.pad = 0;
1434 xcolor.red = 256 * pcolor.R;
1435 xcolor.green = 256 * pcolor.G;
1436 xcolor.blue = 256 * pcolor.B;
1437 XAllocColor(display, lut, &xcolor);
1438 x_color[vpColor::id_red] = xcolor.pixel;
1439
1440 // Color DARK RED.
1441 pcolor = vpColor::darkRed;
1442 xcolor.pad = 0;
1443 xcolor.red = 256 * pcolor.R;
1444 xcolor.green = 256 * pcolor.G;
1445 xcolor.blue = 256 * pcolor.B;
1446 XAllocColor(display, lut, &xcolor);
1447 x_color[vpColor::id_darkRed] = xcolor.pixel;
1448
1449 // Color LIGHT GREEN.
1450 pcolor = vpColor::lightGreen;
1451 xcolor.pad = 0;
1452 xcolor.red = 256 * pcolor.R;
1453 xcolor.green = 256 * pcolor.G;
1454 xcolor.blue = 256 * pcolor.B;
1455 XAllocColor(display, lut, &xcolor);
1456 x_color[vpColor::id_lightGreen] = xcolor.pixel;
1457
1458 // Color GREEN.
1459 pcolor = vpColor::green;
1460 xcolor.pad = 0;
1461 xcolor.red = 256 * pcolor.R;
1462 xcolor.green = 256 * pcolor.G;
1463 xcolor.blue = 256 * pcolor.B;
1464 XAllocColor(display, lut, &xcolor);
1465 x_color[vpColor::id_green] = xcolor.pixel;
1466
1467 // Color DARK GREEN.
1468 pcolor = vpColor::darkGreen;
1469 xcolor.pad = 0;
1470 xcolor.red = 256 * pcolor.R;
1471 xcolor.green = 256 * pcolor.G;
1472 xcolor.blue = 256 * pcolor.B;
1473 XAllocColor(display, lut, &xcolor);
1474 x_color[vpColor::id_darkGreen] = xcolor.pixel;
1475
1476 // Color LIGHT BLUE.
1477 pcolor = vpColor::lightBlue;
1478 xcolor.pad = 0;
1479 xcolor.red = 256 * pcolor.R;
1480 xcolor.green = 256 * pcolor.G;
1481 xcolor.blue = 256 * pcolor.B;
1482 XAllocColor(display, lut, &xcolor);
1483 x_color[vpColor::id_lightBlue] = xcolor.pixel;
1484
1485 // Color BLUE.
1486 pcolor = vpColor::blue;
1487 xcolor.pad = 0;
1488 xcolor.red = 256 * pcolor.R;
1489 xcolor.green = 256 * pcolor.G;
1490 xcolor.blue = 256 * pcolor.B;
1491 XAllocColor(display, lut, &xcolor);
1492 x_color[vpColor::id_blue] = xcolor.pixel;
1493
1494 // Color DARK BLUE.
1495 pcolor = vpColor::darkBlue;
1496 xcolor.pad = 0;
1497 xcolor.red = 256 * pcolor.R;
1498 xcolor.green = 256 * pcolor.G;
1499 xcolor.blue = 256 * pcolor.B;
1500 XAllocColor(display, lut, &xcolor);
1501 x_color[vpColor::id_darkBlue] = xcolor.pixel;
1502
1503 // Color YELLOW.
1504 pcolor = vpColor::yellow;
1505 xcolor.pad = 0;
1506 xcolor.red = 256 * pcolor.R;
1507 xcolor.green = 256 * pcolor.G;
1508 xcolor.blue = 256 * pcolor.B;
1509 XAllocColor(display, lut, &xcolor);
1510 x_color[vpColor::id_yellow] = xcolor.pixel;
1511
1512 // Color ORANGE.
1513 pcolor = vpColor::orange;
1514 xcolor.pad = 0;
1515 xcolor.red = 256 * pcolor.R;
1516 xcolor.green = 256 * pcolor.G;
1517 xcolor.blue = 256 * pcolor.B;
1518 XAllocColor(display, lut, &xcolor);
1519 x_color[vpColor::id_orange] = xcolor.pixel;
1520
1521 // Color CYAN.
1522 pcolor = vpColor::cyan;
1523 xcolor.pad = 0;
1524 xcolor.red = 256 * pcolor.R;
1525 xcolor.green = 256 * pcolor.G;
1526 xcolor.blue = 256 * pcolor.B;
1527 XAllocColor(display, lut, &xcolor);
1528 x_color[vpColor::id_cyan] = xcolor.pixel;
1529
1530 // Color PURPLE.
1531 pcolor = vpColor::purple;
1532 xcolor.pad = 0;
1533 xcolor.red = 256 * pcolor.R;
1534 xcolor.green = 256 * pcolor.G;
1535 xcolor.blue = 256 * pcolor.B;
1536 XAllocColor(display, lut, &xcolor);
1537 x_color[vpColor::id_purple] = xcolor.pixel;
1538 break;
1539 }
1540 }
1541
1542 XSetStandardProperties(display, window, win_title.c_str(), win_title.c_str(), None, 0, 0, &hints);
1543 XMapWindow(display, window);
1544 // Selection des evenements.
1545 XSelectInput(display, window,
1546 ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
1547 StructureNotifyMask | PointerMotionMask);
1548
1549 /* Creation du contexte graphique */
1550 values.plane_mask = AllPlanes;
1551 values.fill_style = FillSolid;
1552 values.foreground = WhitePixel(display, screen);
1553 values.background = BlackPixel(display, screen);
1554 context = XCreateGC(display, window, GCPlaneMask | GCFillStyle | GCForeground | GCBackground, &values);
1555
1556 if (context == nullptr) {
1557 throw(vpDisplayException(vpDisplayException::XWindowsError, "Can't create graphics context"));
1558 }
1559
1560 // Pixmap creation.
1561 pixmap = XCreatePixmap(display, window, win_width, win_height, screen_depth);
1562
1563 // Hangs when forward X11 is used to send the display to an other computer
1564 // do
1565 // XNextEvent ( display, &event );
1566 // while ( event.xany.type != Expose );
1567
1568 {
1569 Ximage = XCreateImage(display, DefaultVisual(display, screen), screen_depth, ZPixmap, 0, nullptr, win_width,
1570 win_height, XBitmapPad(display), 0);
1571
1572 Ximage->data = (char *)malloc(win_height * static_cast<unsigned int>(Ximage->bytes_per_line));
1573 ximage_data_init = true;
1574 }
1575
1576 XSync(display, true);
1577
1578 XStoreName(display, window, win_title.c_str());
1579 }
1580
1581 void setFont(const std::string &fontname)
1582 {
1583 try {
1584 Font stringfont;
1585 stringfont = XLoadFont(display, fontname.c_str()); //"-adobe-times-bold-r-normal--18*");
1586 XSetFont(display, context, stringfont);
1587 }
1588 catch (...) {
1589 throw(vpDisplayException(vpDisplayException::notInitializedError, "Bad font"));
1590 }
1591 }
1592
1593 void setTitle(const std::string &title) { XStoreName(display, window, title.c_str()); }
1594
1595 void setWindowPosition(int win_x, int win_y) { XMoveWindow(display, window, win_x, win_y); }
1596
1597private:
1598 Display *display;
1599 Window window;
1600 XImage *Ximage;
1601 Colormap lut;
1602 GC context;
1603 int screen;
1604 XEvent event;
1605 Pixmap pixmap;
1606 unsigned long *x_color; // Array of predefined colors
1607 unsigned int screen_depth;
1608 unsigned short colortable[256];
1609 XColor xcolor;
1610 XGCValues values;
1611 bool ximage_data_init;
1612 unsigned int RMask, GMask, BMask;
1613 int RShift, GShift, BShift;
1614};
1615#endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
1616
1637{
1638 setScale(scaleType, I.getWidth(), I.getHeight());
1639
1640 init(I);
1641}
1642
1664vpDisplayX::vpDisplayX(vpImage<unsigned char> &I, int x, int y, const std::string &title, vpScaleType scaleType)
1665 : vpDisplay(), m_impl(new Impl())
1666{
1667 setScale(scaleType, I.getWidth(), I.getHeight());
1668 init(I, x, y, title);
1669}
1670
1690vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, vpScaleType scaleType) : vpDisplay(), m_impl(new Impl())
1691{
1692 setScale(scaleType, I.getWidth(), I.getHeight());
1693 init(I);
1694}
1695
1717vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, int x, int y, const std::string &title, vpScaleType scaleType)
1718 : vpDisplay(), m_impl(new Impl())
1719{
1720 setScale(scaleType, I.getWidth(), I.getHeight());
1721 init(I, x, y, title);
1722}
1723
1749vpDisplayX::vpDisplayX(int x, int y, const std::string &title) : vpDisplay(), m_impl(new Impl())
1750{
1753
1754 m_title = title;
1755}
1756
1780vpDisplayX::vpDisplayX() : vpDisplay(), m_impl(new Impl()) { }
1781
1786{
1787 closeDisplay();
1788 delete m_impl;
1789}
1790
1798void vpDisplayX::init(vpImage<unsigned char> &I, int win_x, int win_y, const std::string &win_title)
1799{
1800 if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
1801 throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
1802 }
1803
1804 if (win_x != -1)
1805 m_windowXPosition = win_x;
1806 if (win_y != -1)
1807 m_windowYPosition = win_y;
1808
1809 if (!win_title.empty())
1810 m_title = win_title;
1811
1812 setScale(m_scaleType, I.getWidth(), I.getHeight());
1813 init(I.getWidth(), I.getHeight(), m_windowXPosition, m_windowYPosition, m_title);
1814
1815 I.display = this;
1817}
1818
1827void vpDisplayX::init(vpImage<vpRGBa> &I, int win_x, int win_y, const std::string &win_title)
1828{
1829 if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
1830 throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
1831 }
1832
1833 if (win_x != -1)
1834 m_windowXPosition = win_x;
1835 if (win_y != -1)
1836 m_windowYPosition = win_y;
1837
1838 if (!win_title.empty())
1839 m_title = win_title;
1840
1841 setScale(m_scaleType, I.getWidth(), I.getHeight());
1842 init(I.getWidth(), I.getHeight(), m_windowXPosition, m_windowYPosition, m_title);
1843
1844 I.display = this;
1846}
1847
1855void vpDisplayX::init(unsigned int win_width, unsigned int win_height, int win_x, int win_y,
1856 const std::string &win_title)
1857{
1858 setScale(m_scaleType, win_width, win_height);
1859
1860 m_width = win_width / m_scale;
1861 m_height = win_height / m_scale;
1862
1863 if (win_x != -1)
1864 m_windowXPosition = win_x;
1865 if (win_y != -1)
1866 m_windowYPosition = win_y;
1867
1868 m_title = win_title;
1869
1871
1873}
1874
1889void vpDisplayX::setFont(const std::string &fontname)
1890{
1892 if (!fontname.empty()) {
1893 m_impl->setFont(fontname);
1894 }
1895 }
1896 else {
1898 }
1899}
1900
1905void vpDisplayX::setTitle(const std::string &title)
1906{
1908 m_title = title;
1909 if (!title.empty())
1910 m_impl->setTitle(title);
1911 }
1912 else {
1914 }
1915}
1916
1926void vpDisplayX::setWindowPosition(int win_x, int win_y)
1927{
1929 m_impl->setWindowPosition(win_x, win_y);
1930 }
1931 else {
1933 }
1934}
1935
1948{
1950 m_impl->displayImage(I, m_scale, m_width, m_height);
1951 }
1952 else {
1954 }
1955}
1956
1969{
1971 m_impl->displayImage(I, m_scale, m_width, m_height);
1972 }
1973 else {
1975 }
1976}
1977
1989void vpDisplayX::displayImage(const unsigned char *bitmap)
1990{
1992 m_impl->displayImage(bitmap, m_width, m_height);
1993 }
1994 else {
1996 }
1997}
1998
2013void vpDisplayX::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w,
2014 unsigned int h)
2015{
2017 m_impl->displayImageROI(I, iP, w, h, m_scale, m_width, m_height);
2018 }
2019 else {
2021 }
2022}
2023
2038void vpDisplayX::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h)
2039{
2041 m_impl->displayImageROI(I, iP, w, h, m_scale, m_width, m_height);
2042 }
2043 else {
2045 }
2046}
2047
2056{
2058 m_impl->closeDisplay();
2059
2061 }
2062}
2063
2070{
2072 m_impl->flushDisplay();
2073 }
2074 else {
2076 }
2077}
2078
2087void vpDisplayX::flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h)
2088{
2090 m_impl->flushDisplayROI(iP, w, h, m_scale);
2091 }
2092 else {
2094 }
2095}
2096
2102{
2104 m_impl->clearDisplay(color, m_width, m_height);
2105 }
2106 else {
2108 }
2109}
2110
2120void vpDisplayX::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
2121 unsigned int h, unsigned int thickness)
2122{
2124 double a = ip2.get_i() - ip1.get_i();
2125 double b = ip2.get_j() - ip1.get_j();
2126 double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
2127
2128 // if ( ( a==0 ) && ( b==0 ) )
2129 if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
2130 (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
2131 // DisplayCrossLarge(i1,j1,3,col) ;
2132 }
2133 else {
2134 a /= lg;
2135 b /= lg;
2136
2137 vpImagePoint ip3;
2138 ip3.set_i(ip2.get_i() - w * a);
2139 ip3.set_j(ip2.get_j() - w * b);
2140
2141 vpImagePoint ip4;
2142 ip4.set_i(ip3.get_i() - b * h);
2143 ip4.set_j(ip3.get_j() + a * h);
2144
2145 if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2146 displayLine(ip2, ip4, color, thickness);
2147
2148 ip4.set_i(ip3.get_i() + b * h);
2149 ip4.set_j(ip3.get_j() - a * h);
2150
2151 if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2152 displayLine(ip2, ip4, color, thickness);
2153
2154 displayLine(ip1, ip2, color, thickness);
2155 }
2156 }
2157 else {
2159 }
2160}
2161
2173void vpDisplayX::displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color)
2174{
2176 m_impl->displayText(ip, text, color, m_scale);
2177 }
2178 else {
2180 }
2181}
2182
2192void vpDisplayX::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
2193 unsigned int thickness)
2194{
2196 if (thickness == 1)
2197 thickness = 0;
2198 m_impl->displayCircle(center, radius, color, fill, thickness, m_scale);
2199 }
2200 else {
2202 }
2203}
2204
2212void vpDisplayX::displayCross(const vpImagePoint &ip, unsigned int cross_size, const vpColor &color,
2213 unsigned int thickness)
2214{
2216 double i = ip.get_i();
2217 double j = ip.get_j();
2218 vpImagePoint ip1, ip2;
2219
2220 ip1.set_i(i - cross_size / 2);
2221 ip1.set_j(j);
2222 ip2.set_i(i + cross_size / 2);
2223 ip2.set_j(j);
2224 displayLine(ip1, ip2, color, thickness);
2225
2226 ip1.set_i(i);
2227 ip1.set_j(j - cross_size / 2);
2228 ip2.set_i(i);
2229 ip2.set_j(j + cross_size / 2);
2230
2231 displayLine(ip1, ip2, color, thickness);
2232 }
2233 else {
2235 }
2236}
2237
2244void vpDisplayX::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2245 unsigned int thickness)
2246{
2248 if (thickness == 1)
2249 thickness = 0;
2250
2251 m_impl->displayDotLine(ip1, ip2, color, thickness, m_scale);
2252 }
2253 else {
2255 }
2256}
2257
2265void vpDisplayX::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2266 unsigned int thickness)
2267{
2269 if (thickness == 1)
2270 thickness = 0;
2271 m_impl->displayLine(ip1, ip2, color, thickness, m_scale);
2272 }
2273 else {
2275 }
2276}
2277
2284void vpDisplayX::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
2285{
2287 m_impl->displayPoint(ip, color, thickness, m_scale);
2288 }
2289 else {
2291 }
2292}
2293
2308void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
2309 bool fill, unsigned int thickness)
2310{
2312 if (thickness == 1)
2313 thickness = 0;
2314
2315 m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2316 }
2317 else {
2319 }
2320}
2321
2334void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
2335 bool fill, unsigned int thickness)
2336{
2338 if (thickness == 1)
2339 thickness = 0;
2340
2341 unsigned int w = static_cast<unsigned int>(vpMath::round(bottomRight.get_u() - topLeft.get_u()));
2342 unsigned int h = static_cast<unsigned int>(vpMath::round(bottomRight.get_v() - topLeft.get_v()));
2343
2344 m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2345 }
2346 else {
2348 }
2349}
2350
2363void vpDisplayX::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
2364{
2366 if (thickness == 1)
2367 thickness = 0;
2368 vpImagePoint topLeft = rectangle.getTopLeft();
2369 unsigned int w = static_cast<unsigned int>(vpMath::round(rectangle.getWidth()));
2370 unsigned int h = static_cast<unsigned int>(vpMath::round(rectangle.getHeight()));
2371 m_impl->displayRectangle(topLeft, w, h, color, fill, thickness, m_scale);
2372 }
2373 else {
2375 }
2376}
2377
2393bool vpDisplayX::getClick(bool blocking)
2394{
2395 bool ret = false;
2396
2398 vpImagePoint ip;
2400 ret = m_impl->getClick(ip, button, blocking, m_scale);
2401 }
2402 else {
2404 }
2405 return ret;
2406}
2407
2423bool vpDisplayX::getClick(vpImagePoint &ip, bool blocking)
2424{
2425 bool ret = false;
2426
2429 ret = m_impl->getClick(ip, button, blocking, m_scale);
2430 }
2431 else {
2433 }
2434 return ret;
2435}
2436
2457{
2458 bool ret = false;
2459
2461 ret = m_impl->getClick(ip, button, blocking, m_scale);
2462 }
2463 else {
2465 }
2466 return ret;
2467}
2468
2493{
2494 bool ret = false;
2495
2497 ret = m_impl->getClickUp(ip, button, blocking, m_scale);
2498 }
2499 else {
2501 }
2502 return ret;
2503}
2504
2505/*
2506 Gets the displayed image (including the overlay plane)
2507 and returns an RGBa image. If a scale factor is set using setScale(), the
2508 size of the image is the size of the down scaled image.
2509
2510 \param I : Image to get.
2511*/
2513{
2515 m_impl->getImage(I, m_width, m_height);
2516 }
2517 else {
2519 }
2520}
2521
2525unsigned int vpDisplayX::getScreenDepth() { return m_impl->getScreenDepth(); }
2526
2532void vpDisplayX::getScreenSize(unsigned int &w, unsigned int &h) { m_impl->getScreenSize(w, h); }
2533
2538{
2539 unsigned int width, height;
2540 getScreenSize(width, height);
2541 return width;
2542}
2543
2548{
2549 unsigned int width, height;
2550 getScreenSize(width, height);
2551 return height;
2552}
2553
2575{
2576 bool ret = false;
2577
2579 ret = m_impl->getKeyboardEvent(blocking);
2580 }
2581 else {
2583 }
2584 return ret;
2585}
2586
2610bool vpDisplayX::getKeyboardEvent(std::string &key, bool blocking)
2611{
2612 bool ret = false;
2614 ret = m_impl->getKeyboardEvent(key, blocking);
2615 }
2616 else {
2618 }
2619 return ret;
2620}
2621
2634{
2635
2636 bool ret = false;
2638 ret = m_impl->getPointerMotionEvent(ip, m_scale);
2639 }
2640 else {
2642 }
2643 return ret;
2644}
2645
2657{
2658 bool ret = false;
2660 ret = m_impl->getPointerPosition(ip, m_scale);
2661 }
2662 else {
2664 }
2665 return ret;
2666}
2667
2668END_VISP_NAMESPACE
2669
2670#elif !defined(VISP_BUILD_SHARED_LIBS)
2671// Work around to avoid warning: libvisp_gui.a(vpDisplayX.cpp.o) has no symbols
2672void dummy_vpDisplayX() { }
2673#endif
Class to define RGB colors available for display functionalities.
Definition vpColor.h:157
static const vpColor white
Definition vpColor.h:193
static const vpColor red
Definition vpColor.h:198
static const vpColor darkGray
Definition vpColor.h:196
static const vpColor cyan
Definition vpColor.h:207
static const vpColor orange
Definition vpColor.h:208
static const vpColor darkRed
Definition vpColor.h:199
static const vpColor blue
Definition vpColor.h:204
static const vpColor lightGray
Definition vpColor.h:194
static const vpColor lightBlue
Definition vpColor.h:203
static const vpColor darkGreen
Definition vpColor.h:202
static const vpColor darkBlue
Definition vpColor.h:205
static const vpColor purple
Definition vpColor.h:209
static const vpColor lightGreen
Definition vpColor.h:200
static const vpColor yellow
Definition vpColor.h:206
@ id_lightBlue
Definition vpColor.h:173
@ id_yellow
Definition vpColor.h:176
@ id_darkGray
Definition vpColor.h:166
@ id_green
Definition vpColor.h:171
@ id_darkRed
Definition vpColor.h:169
@ id_lightGray
Definition vpColor.h:164
@ id_red
Definition vpColor.h:168
@ id_lightRed
Definition vpColor.h:167
@ id_white
Definition vpColor.h:163
@ id_black
Definition vpColor.h:162
@ id_blue
Definition vpColor.h:174
@ id_darkGreen
Definition vpColor.h:172
@ id_gray
Definition vpColor.h:165
@ id_lightGreen
Definition vpColor.h:170
@ id_purple
Definition vpColor.h:179
@ id_orange
Definition vpColor.h:178
@ id_cyan
Definition vpColor.h:177
@ id_darkBlue
Definition vpColor.h:175
@ id_unknown
Definition vpColor.h:181
static const vpColor lightRed
Definition vpColor.h:197
static const vpColor black
Definition vpColor.h:192
static const vpColor green
Definition vpColor.h:201
static const vpColor gray
Definition vpColor.h:195
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.
bool getPointerPosition(vpImagePoint &ip) VP_OVERRIDE
unsigned int getScreenDepth()
unsigned int getScreenWidth() VP_OVERRIDE
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) VP_OVERRIDE
void setFont(const std::string &font) VP_OVERRIDE
unsigned int getScreenHeight() VP_OVERRIDE
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1) VP_OVERRIDE
virtual ~vpDisplayX() VP_OVERRIDE
void getImage(vpImage< vpRGBa > &I) VP_OVERRIDE
Get the window pixmap and put it in vpRGBa image.
void getScreenSize(unsigned int &width, unsigned int &height) VP_OVERRIDE
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true) VP_OVERRIDE
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1) VP_OVERRIDE
void flushDisplay() VP_OVERRIDE
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="") VP_OVERRIDE
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height) VP_OVERRIDE
bool getKeyboardEvent(bool blocking=true) VP_OVERRIDE
void clearDisplay(const vpColor &color=vpColor::white) VP_OVERRIDE
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
bool getClick(bool blocking=true) VP_OVERRIDE
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
void setWindowPosition(int win_x, int win_y) VP_OVERRIDE
bool getPointerMotionEvent(vpImagePoint &ip) VP_OVERRIDE
void displayImage(const vpImage< unsigned char > &I) VP_OVERRIDE
void displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color=vpColor::green) VP_OVERRIDE
void closeDisplay() VP_OVERRIDE
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height) VP_OVERRIDE
void setTitle(const std::string &title) VP_OVERRIDE
unsigned int m_height
Definition vpDisplay.h:928
vpScaleType m_scaleType
Definition vpDisplay.h:931
unsigned int m_width
Definition vpDisplay.h:927
int m_windowXPosition
display position
Definition vpDisplay.h:924
std::string m_title
Definition vpDisplay.h:929
int m_windowYPosition
display position
Definition vpDisplay.h:926
unsigned int m_scale
Definition vpDisplay.h:930
bool m_displayHasBeenInitialized
display has been initialized
Definition vpDisplay.h:922
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:131
unsigned int getWidth() const
Definition vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:544
Type * bitmap
points toward the bitmap
Definition vpImage.h:135
unsigned int getHeight() const
Definition vpImage.h:181
static double sqr(double x)
Definition vpMath.h:203
static int round(double x)
Definition vpMath.h:413
unsigned char B
Blue component.
Definition vpRGBa.h:327
unsigned char R
Red component.
Definition vpRGBa.h:325
unsigned char G
Green component.
Definition vpRGBa.h:326
@ alpha_default
Definition vpRGBa.h:76
unsigned char A
Additional component.
Definition vpRGBa.h:328
Defines a rectangle in the plane.
Definition vpRect.h:79
double getWidth() const
Definition vpRect.h:227
vpImagePoint getTopLeft() const
Definition vpRect.h:199
double getHeight() const
Definition vpRect.h:166