1 /****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See http://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * Image display.
33 *
34 * Authors:
35 * Fabien Spindler
36 * Anthony Saunier
37 *
38 *****************************************************************************/
39
40 /*!
41 \file vpDisplayX.cpp
42 \brief Define the X11 console to display images.
43 */
44
45 #include <visp3/core/vpConfig.h>
46 #ifdef VISP_HAVE_X11
47
48 #include <cmath> // std::fabs
49 #include <iostream>
50 #include <limits> // numeric_limits
51 #include <stdio.h>
52 #include <stdlib.h>
53
54 // Display stuff
55 #include <visp3/core/vpDisplay.h>
56 #include <visp3/gui/vpDisplayX.h>
57
58 // debug / exception
59 #include <visp3/core/vpDebug.h>
60 #include <visp3/core/vpDisplayException.h>
61
62 // math
63 #include <visp3/core/vpMath.h>
64
65 /*!
66 Constructor : initialize a display to visualize a gray level image
67 (8 bits).
68
69 \param I : Image to be displayed (not that image has to be initialized)
70 \param scaleType : If this parameter is set to:
71 - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
72 is fully displayed in the screen;
73 - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
74 same than the image size.
75 - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
76 and the columns.
77 - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
78 and the columns.
79 - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
80 and the columns.
81 - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
82 and the columns.
83 */
vpDisplayX(vpImage<unsigned char> & I,vpScaleType scaleType)84 vpDisplayX::vpDisplayX(vpImage<unsigned char> &I, vpScaleType scaleType)
85 : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
86 screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
87 BShift(0)
88 {
89 setScale(scaleType, I.getWidth(), I.getHeight());
90
91 init(I);
92 }
93
94 /*!
95 Constructor : initialize a display to visualize a gray level image
96 (8 bits).
97
98 \param I : Image to be displayed (not that image has to be initialized)
99 \param x, y : The window is set at position x,y (column index, row index).
100 \param title : Window title.
101 \param scaleType : If this parameter is set to:
102 - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
103 is fully displayed in the screen;
104 - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
105 same than the image size.
106 - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
107 and the columns.
108 - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
109 and the columns.
110 - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
111 and the columns.
112 - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
113 and the columns.
114 */
vpDisplayX(vpImage<unsigned char> & I,int x,int y,const std::string & title,vpScaleType scaleType)115 vpDisplayX::vpDisplayX(vpImage<unsigned char> &I, int x, int y, const std::string &title, vpScaleType scaleType)
116 : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
117 screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
118 BShift(0)
119 {
120 setScale(scaleType, I.getWidth(), I.getHeight());
121 init(I, x, y, title);
122 }
123
124 /*!
125 Constructor : initialize a display to visualize a RGBa image
126 (32 bits).
127
128 \param I : Image to be displayed (not that image has to be initialized).
129 \param scaleType : If this parameter is set to:
130 - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
131 is fully displayed in the screen;
132 - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
133 same than the image size.
134 - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
135 and the columns.
136 - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
137 and the columns.
138 - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
139 and the columns.
140 - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
141 and the columns.
142 */
vpDisplayX(vpImage<vpRGBa> & I,vpScaleType scaleType)143 vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, vpScaleType scaleType)
144 : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
145 screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
146 BShift(0)
147 {
148 setScale(scaleType, I.getWidth(), I.getHeight());
149 init(I);
150 }
151
152 /*!
153 Constructor : initialize a display to visualize a RGBa image
154 (32 bits).
155
156 \param I : Image to be displayed (not that image has to be initialized).
157 \param x, y : The window is set at position x,y (column index, row index).
158 \param title : Window title.
159 \param scaleType : If this parameter is set to:
160 - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
161 is fully displayed in the screen;
162 - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
163 same than the image size.
164 - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
165 and the columns.
166 - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
167 and the columns.
168 - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
169 and the columns.
170 - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
171 and the columns.
172 */
vpDisplayX(vpImage<vpRGBa> & I,int x,int y,const std::string & title,vpScaleType scaleType)173 vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, int x, int y, const std::string &title, vpScaleType scaleType)
174 : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
175 screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
176 BShift(0)
177 {
178 setScale(scaleType, I.getWidth(), I.getHeight());
179 init(I, x, y, title);
180 }
181
182 /*!
183 Constructor that just initialize the display position in the screen
184 and the display title.
185
186 \param x, y : The window is set at position x,y (column index, row index).
187 \param title : Window title.
188
189 To initialize the display size, you need to call init().
190
191 \code
192 #include <visp3/core/vpImage.h>
193 #include <visp3/gui/vpDisplayX.h>
194
195 int main()
196 {
197 vpDisplayX d(100, 200, "My display");
198 vpImage<unsigned char> I(240, 384);
199 d.init(I);
200 }
201 \endcode
202 */
vpDisplayX(int x,int y,const std::string & title)203 vpDisplayX::vpDisplayX(int x, int y, const std::string &title)
204 : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
205 screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
206 BShift(0)
207 {
208 m_windowXPosition = x;
209 m_windowYPosition = y;
210
211 m_title = title;
212 }
213
214 /*!
215 Basic constructor.
216
217 To initialize the window position, title and size you may call
218 init(vpImage<unsigned char> &, int, int, const std::string &) or
219 init(vpImage<vpRGBa> &, int, int, const std::string &).
220
221 \code
222 #include <visp3/core/vpImage.h>
223 #include <visp3/gui/vpDisplayX.h>
224
225 int main()
226 {
227 vpDisplayX d;
228 vpImage<unsigned char> I(240, 384);
229 d.init(I, 100, 200, "My display");
230 }
231 \endcode
232 */
vpDisplayX()233 vpDisplayX::vpDisplayX()
234 : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
235 screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
236 BShift(0)
237 {
238 }
239
240 /*!
241 Destructor.
242 */
~vpDisplayX()243 vpDisplayX::~vpDisplayX() { closeDisplay(); }
244
245 /*!
246 Initialize the display (size, position and title) of a gray level image.
247
248 \param I : Image to be displayed (not that image has to be initialized)
249 \param x, y : The window is set at position x,y (column index, row index).
250 \param title : Window title.
251 */
init(vpImage<unsigned char> & I,int x,int y,const std::string & title)252 void vpDisplayX::init(vpImage<unsigned char> &I, int x, int y, const std::string &title)
253 {
254 setScale(m_scaleType, I.getWidth(), I.getHeight());
255
256 if (x_color == NULL) {
257 // id_unknown = number of predefined colors
258 x_color = new unsigned long[vpColor::id_unknown];
259 }
260
261 XSizeHints hints;
262 if (x != -1)
263 m_windowXPosition = x;
264 if (y != -1)
265 m_windowYPosition = y;
266
267 if (!title.empty())
268 m_title = title;
269
270 // Positionnement de la fenetre dans l'ecran.
271 if ((m_windowXPosition < 0) || (m_windowYPosition < 0)) {
272 hints.flags = 0;
273 } else {
274 hints.flags = USPosition;
275 hints.x = m_windowXPosition;
276 hints.y = m_windowYPosition;
277 }
278
279 // setup X11 --------------------------------------------------
280 m_width = I.getWidth() / m_scale;
281 m_height = I.getHeight() / m_scale;
282 display = XOpenDisplay(NULL);
283 if (display == NULL) {
284 vpERROR_TRACE("Can't connect display on server %s.\n", XDisplayName(NULL));
285 throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server."));
286 }
287
288 screen = DefaultScreen(display);
289 lut = DefaultColormap(display, screen);
290 screen_depth = (unsigned int)DefaultDepth(display, screen);
291
292 if ((window = XCreateSimpleWindow(display, RootWindow(display, screen), m_windowXPosition, m_windowYPosition, m_width,
293 m_height, 1, BlackPixel(display, screen), WhitePixel(display, screen))) == 0) {
294 vpERROR_TRACE("Can't create window.");
295 throw(vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create window."));
296 }
297
298 //
299 // Create color table for 8 and 16 bits screen
300 //
301 if (screen_depth == 8) {
302 lut = XCreateColormap(display, window, DefaultVisual(display, screen), AllocAll);
303 xcolor.flags = DoRed | DoGreen | DoBlue;
304
305 for (unsigned int i = 0; i < 256; i++) {
306 xcolor.pixel = i;
307 xcolor.red = 256 * i;
308 xcolor.green = 256 * i;
309 xcolor.blue = 256 * i;
310 XStoreColor(display, lut, &xcolor);
311 }
312
313 XSetWindowColormap(display, window, lut);
314 XInstallColormap(display, lut);
315 }
316
317 else if (screen_depth == 16) {
318 for (unsigned int i = 0; i < 256; i++) {
319 xcolor.pad = 0;
320 xcolor.red = xcolor.green = xcolor.blue = 256 * i;
321 if (XAllocColor(display, lut, &xcolor) == 0) {
322 vpERROR_TRACE("Can't allocate 256 colors. Only %d allocated.", i);
323 throw(vpDisplayException(vpDisplayException::colorAllocError, "Can't allocate 256 colors."));
324 }
325 colortable[i] = xcolor.pixel;
326 }
327
328 XSetWindowColormap(display, window, lut);
329 XInstallColormap(display, lut);
330
331 Visual *visual = DefaultVisual(display, screen);
332 RMask = visual->red_mask;
333 GMask = visual->green_mask;
334 BMask = visual->blue_mask;
335
336 RShift = 15 - getMsb(RMask); /* these are right-shifts */
337 GShift = 15 - getMsb(GMask);
338 BShift = 15 - getMsb(BMask);
339 }
340
341 //
342 // Create colors for overlay
343 //
344 switch (screen_depth) {
345 case 8:
346 // Color BLACK and WHITE are set properly by default.
347
348 // Color LIGHT GRAY.
349 x_color[vpColor::id_lightGray] = 254;
350 xcolor.pixel = x_color[vpColor::id_lightGray];
351 xcolor.red = 256 * 192;
352 xcolor.green = 256 * 192;
353 xcolor.blue = 256 * 192;
354 XStoreColor(display, lut, &xcolor);
355
356 // Color GRAY.
357 x_color[vpColor::id_gray] = 253;
358 xcolor.pixel = x_color[vpColor::id_gray];
359 xcolor.red = 256 * 128;
360 xcolor.green = 256 * 128;
361 xcolor.blue = 256 * 128;
362 XStoreColor(display, lut, &xcolor);
363
364 // Color DARK GRAY.
365 x_color[vpColor::id_darkGray] = 252;
366 xcolor.pixel = x_color[vpColor::id_darkGray];
367 xcolor.red = 256 * 64;
368 xcolor.green = 256 * 64;
369 xcolor.blue = 256 * 64;
370 XStoreColor(display, lut, &xcolor);
371
372 // Color LIGHT RED.
373 x_color[vpColor::id_lightRed] = 251;
374 xcolor.pixel = x_color[vpColor::id_lightRed];
375 xcolor.red = 256 * 255;
376 xcolor.green = 256 * 140;
377 xcolor.blue = 256 * 140;
378 XStoreColor(display, lut, &xcolor);
379
380 // Color RED.
381 x_color[vpColor::id_red] = 250;
382 xcolor.pixel = x_color[vpColor::id_red];
383 xcolor.red = 256 * 255;
384 xcolor.green = 0;
385 xcolor.blue = 0;
386 XStoreColor(display, lut, &xcolor);
387
388 // Color DARK RED.
389 x_color[vpColor::id_darkRed] = 249;
390 xcolor.pixel = x_color[vpColor::id_darkRed];
391 xcolor.red = 256 * 128;
392 xcolor.green = 0;
393 xcolor.blue = 0;
394 XStoreColor(display, lut, &xcolor);
395
396 // Color LIGHT GREEN.
397 x_color[vpColor::id_lightGreen] = 248;
398 xcolor.pixel = x_color[vpColor::id_lightGreen];
399 xcolor.red = 256 * 140;
400 xcolor.green = 256 * 255;
401 xcolor.blue = 256 * 140;
402 XStoreColor(display, lut, &xcolor);
403
404 // Color GREEN.
405 x_color[vpColor::id_green] = 247;
406 xcolor.pixel = x_color[vpColor::id_green];
407 xcolor.red = 0;
408 xcolor.green = 256 * 255;
409 xcolor.blue = 0;
410 XStoreColor(display, lut, &xcolor);
411
412 // Color DARK GREEN.
413 x_color[vpColor::id_darkGreen] = 246;
414 xcolor.pixel = x_color[vpColor::id_darkGreen];
415 xcolor.red = 0;
416 xcolor.green = 256 * 128;
417 xcolor.blue = 0;
418 XStoreColor(display, lut, &xcolor);
419
420 // Color LIGHT BLUE.
421 x_color[vpColor::id_lightBlue] = 245;
422 xcolor.pixel = x_color[vpColor::id_lightBlue];
423 xcolor.red = 256 * 140;
424 xcolor.green = 256 * 140;
425 xcolor.blue = 256 * 255;
426 XStoreColor(display, lut, &xcolor);
427
428 // Color BLUE.
429 x_color[vpColor::id_blue] = 244;
430 xcolor.pixel = x_color[vpColor::id_blue];
431 xcolor.red = 0;
432 xcolor.green = 0;
433 xcolor.blue = 256 * 255;
434 XStoreColor(display, lut, &xcolor);
435
436 // Color DARK BLUE.
437 x_color[vpColor::id_darkBlue] = 243;
438 xcolor.pixel = x_color[vpColor::id_darkBlue];
439 xcolor.red = 0;
440 xcolor.green = 0;
441 xcolor.blue = 256 * 128;
442 XStoreColor(display, lut, &xcolor);
443
444 // Color YELLOW.
445 x_color[vpColor::id_yellow] = 242;
446 xcolor.pixel = x_color[vpColor::id_yellow];
447 xcolor.red = 256 * 255;
448 xcolor.green = 256 * 255;
449 xcolor.blue = 0;
450 XStoreColor(display, lut, &xcolor);
451
452 // Color ORANGE.
453 x_color[vpColor::id_orange] = 241;
454 xcolor.pixel = x_color[vpColor::id_orange];
455 xcolor.red = 256 * 255;
456 xcolor.green = 256 * 165;
457 xcolor.blue = 0;
458 XStoreColor(display, lut, &xcolor);
459
460 // Color CYAN.
461 x_color[vpColor::id_cyan] = 240;
462 xcolor.pixel = x_color[vpColor::id_cyan];
463 xcolor.red = 0;
464 xcolor.green = 256 * 255;
465 xcolor.blue = 256 * 255;
466 XStoreColor(display, lut, &xcolor);
467
468 // Color PURPLE.
469 x_color[vpColor::id_purple] = 239;
470 xcolor.pixel = x_color[vpColor::id_purple];
471 xcolor.red = 256 * 128;
472 xcolor.green = 0;
473 xcolor.blue = 256 * 128;
474 XStoreColor(display, lut, &xcolor);
475
476 break;
477
478 case 16:
479 case 24:
480 case 32: {
481 xcolor.flags = DoRed | DoGreen | DoBlue;
482
483 // Couleur BLACK.
484 xcolor.pad = 0;
485 xcolor.red = 0;
486 xcolor.green = 0;
487 xcolor.blue = 0;
488 XAllocColor(display, lut, &xcolor);
489 x_color[vpColor::id_black] = xcolor.pixel;
490
491 // Couleur WHITE.
492 xcolor.pad = 0;
493 xcolor.red = 256 * 255;
494 xcolor.green = 256 * 255;
495 xcolor.blue = 256 * 255;
496 XAllocColor(display, lut, &xcolor);
497 x_color[vpColor::id_white] = xcolor.pixel;
498
499 // Couleur LIGHT GRAY.
500 xcolor.pad = 0;
501 xcolor.red = 256 * 192;
502 xcolor.green = 256 * 192;
503 xcolor.blue = 256 * 192;
504 XAllocColor(display, lut, &xcolor);
505 x_color[vpColor::id_lightGray] = xcolor.pixel;
506
507 // Couleur GRAY.
508 xcolor.pad = 0;
509 xcolor.red = 256 * 128;
510 xcolor.green = 256 * 128;
511 xcolor.blue = 256 * 128;
512 XAllocColor(display, lut, &xcolor);
513 x_color[vpColor::id_gray] = xcolor.pixel;
514
515 // Couleur DARK GRAY.
516 xcolor.pad = 0;
517 xcolor.red = 256 * 64;
518 xcolor.green = 256 * 64;
519 xcolor.blue = 256 * 64;
520 XAllocColor(display, lut, &xcolor);
521 x_color[vpColor::id_darkGray] = xcolor.pixel;
522
523 // Couleur LIGHT RED.
524 xcolor.pad = 0;
525 xcolor.red = 256 * 255;
526 xcolor.green = 256 * 140;
527 xcolor.blue = 256 * 140;
528 XAllocColor(display, lut, &xcolor);
529 x_color[vpColor::id_lightRed] = xcolor.pixel;
530
531 // Couleur RED.
532 xcolor.pad = 0;
533 xcolor.red = 256 * 255;
534 xcolor.green = 0;
535 xcolor.blue = 0;
536 XAllocColor(display, lut, &xcolor);
537 x_color[vpColor::id_red] = xcolor.pixel;
538
539 // Couleur DARK RED.
540 xcolor.pad = 0;
541 xcolor.red = 256 * 128;
542 xcolor.green = 0;
543 xcolor.blue = 0;
544 XAllocColor(display, lut, &xcolor);
545 x_color[vpColor::id_darkRed] = xcolor.pixel;
546
547 // Couleur LIGHT GREEN.
548 xcolor.pad = 0;
549 xcolor.red = 256 * 140;
550 xcolor.green = 256 * 255;
551 xcolor.blue = 256 * 140;
552 XAllocColor(display, lut, &xcolor);
553 x_color[vpColor::id_lightGreen] = xcolor.pixel;
554
555 // Couleur GREEN.
556 xcolor.pad = 0;
557 xcolor.red = 0;
558 xcolor.green = 256 * 255;
559 xcolor.blue = 0;
560 XAllocColor(display, lut, &xcolor);
561 x_color[vpColor::id_green] = xcolor.pixel;
562
563 // Couleur DARK GREEN.
564 xcolor.pad = 0;
565 xcolor.red = 0;
566 xcolor.green = 256 * 128;
567 xcolor.blue = 0;
568 XAllocColor(display, lut, &xcolor);
569 x_color[vpColor::id_darkGreen] = xcolor.pixel;
570
571 // Couleur LIGHT Blue.
572 xcolor.pad = 0;
573 xcolor.red = 256 * 140;
574 xcolor.green = 256 * 140;
575 xcolor.blue = 256 * 255;
576 XAllocColor(display, lut, &xcolor);
577 x_color[vpColor::id_lightBlue] = xcolor.pixel;
578
579 // Couleur BLUE.
580 xcolor.pad = 0;
581 xcolor.red = 0;
582 xcolor.green = 0;
583 xcolor.blue = 256 * 255;
584 XAllocColor(display, lut, &xcolor);
585 x_color[vpColor::id_blue] = xcolor.pixel;
586
587 // Couleur DARK BLUE.
588 xcolor.pad = 0;
589 xcolor.red = 0;
590 xcolor.green = 0;
591 xcolor.blue = 256 * 128;
592 XAllocColor(display, lut, &xcolor);
593 x_color[vpColor::id_darkBlue] = xcolor.pixel;
594
595 // Couleur YELLOW.
596 xcolor.pad = 0;
597 xcolor.red = 256 * 255;
598 xcolor.green = 256 * 255;
599 xcolor.blue = 0;
600 XAllocColor(display, lut, &xcolor);
601 x_color[vpColor::id_yellow] = xcolor.pixel;
602
603 // Couleur ORANGE.
604 xcolor.pad = 0;
605 xcolor.red = 256 * 255;
606 xcolor.green = 256 * 165;
607 xcolor.blue = 0;
608 XAllocColor(display, lut, &xcolor);
609 x_color[vpColor::id_orange] = xcolor.pixel;
610
611 // Couleur CYAN.
612 xcolor.pad = 0;
613 xcolor.red = 0;
614 xcolor.green = 256 * 255;
615 xcolor.blue = 256 * 255;
616 XAllocColor(display, lut, &xcolor);
617 x_color[vpColor::id_cyan] = xcolor.pixel;
618
619 // Couleur PURPLE.
620 xcolor.pad = 0;
621 xcolor.red = 256 * 128;
622 xcolor.green = 0;
623 xcolor.blue = 256 * 128;
624 XAllocColor(display, lut, &xcolor);
625 x_color[vpColor::id_purple] = xcolor.pixel;
626 break;
627 }
628 }
629
630 XSetStandardProperties(display, window, this->m_title.c_str(), this->m_title.c_str(), None, 0, 0, &hints);
631 XMapWindow(display, window);
632 // Selection des evenements.
633 XSelectInput(display, window,
634 ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
635 StructureNotifyMask | PointerMotionMask);
636
637 // graphic context creation
638 values.plane_mask = AllPlanes;
639 values.fill_style = FillSolid;
640 values.foreground = WhitePixel(display, screen);
641 values.background = BlackPixel(display, screen);
642 context = XCreateGC(display, window, GCPlaneMask | GCFillStyle | GCForeground | GCBackground, &values);
643
644 if (context == NULL) {
645 vpERROR_TRACE("Can't create graphics context.");
646 throw(vpDisplayException(vpDisplayException::XWindowsError, "Can't create graphics context"));
647 }
648
649 // Pixmap creation.
650 pixmap = XCreatePixmap(display, window, m_width, m_height, screen_depth);
651
652 // Hangs when forward X11 is used to send the display to an other computer
653 // do
654 // XNextEvent ( display, &event );
655 // while ( event.xany.type != Expose );
656
657 {
658 Ximage = XCreateImage(display, DefaultVisual(display, screen), screen_depth, ZPixmap, 0, NULL, m_width, m_height,
659 XBitmapPad(display), 0);
660
661 Ximage->data = (char *)malloc(m_height * (unsigned int)Ximage->bytes_per_line);
662 ximage_data_init = true;
663 }
664 m_displayHasBeenInitialized = true;
665
666 XStoreName(display, window, m_title.c_str());
667
668 XSync(display, 1);
669
670 I.display = this;
671 }
672
673 /*!
674 Initialize the display (size, position and title) of a color
675 image in RGBa format.
676
677 \param I : Image to be displayed (note that image has to be initialized)
678 \param x, y : The window is set at position x,y (column index, row index).
679 \param title : Window title.
680 */
init(vpImage<vpRGBa> & I,int x,int y,const std::string & title)681 void vpDisplayX::init(vpImage<vpRGBa> &I, int x, int y, const std::string &title)
682 {
683 setScale(m_scaleType, I.getWidth(), I.getHeight());
684
685 XSizeHints hints;
686 if (x != -1)
687 m_windowXPosition = x;
688 if (y != -1)
689 m_windowYPosition = y;
690
691 if (x_color == NULL) {
692 // id_unknown = number of predefined colors
693 x_color = new unsigned long[vpColor::id_unknown];
694 }
695
696 if (!title.empty())
697 m_title = title;
698
699 // Positionnement de la fenetre dans l'ecran.
700 if ((m_windowXPosition < 0) || (m_windowYPosition < 0)) {
701 hints.flags = 0;
702 } else {
703 hints.flags = USPosition;
704 hints.x = m_windowXPosition;
705 hints.y = m_windowYPosition;
706 }
707
708 // setup X11 --------------------------------------------------
709 m_width = I.getWidth() / m_scale;
710 m_height = I.getHeight() / m_scale;
711
712 if ((display = XOpenDisplay(NULL)) == NULL) {
713 vpERROR_TRACE("Can't connect display on server %s.\n", XDisplayName(NULL));
714 throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server."));
715 }
716
717 screen = DefaultScreen(display);
718 lut = DefaultColormap(display, screen);
719 screen_depth = (unsigned int)DefaultDepth(display, screen);
720
721 vpDEBUG_TRACE(1, "Screen depth: %d\n", screen_depth);
722
723 if ((window = XCreateSimpleWindow(display, RootWindow(display, screen), m_windowXPosition, m_windowYPosition, m_width,
724 m_height, 1, BlackPixel(display, screen), WhitePixel(display, screen))) == 0) {
725 vpERROR_TRACE("Can't create window.");
726 throw(vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create window."));
727 }
728
729 //
730 // Create color table for 8 and 16 bits screen
731 //
732 if (screen_depth == 8) {
733 lut = XCreateColormap(display, window, DefaultVisual(display, screen), AllocAll);
734 xcolor.flags = DoRed | DoGreen | DoBlue;
735
736 for (unsigned int i = 0; i < 256; i++) {
737 xcolor.pixel = i;
738 xcolor.red = 256 * i;
739 xcolor.green = 256 * i;
740 xcolor.blue = 256 * i;
741 XStoreColor(display, lut, &xcolor);
742 }
743
744 XSetWindowColormap(display, window, lut);
745 XInstallColormap(display, lut);
746 }
747
748 else if (screen_depth == 16) {
749 for (unsigned int i = 0; i < 256; i++) {
750 xcolor.pad = 0;
751 xcolor.red = xcolor.green = xcolor.blue = 256 * i;
752 if (XAllocColor(display, lut, &xcolor) == 0) {
753 vpERROR_TRACE("Can't allocate 256 colors. Only %d allocated.", i);
754 throw(vpDisplayException(vpDisplayException::colorAllocError, "Can't allocate 256 colors."));
755 }
756 colortable[i] = xcolor.pixel;
757 }
758
759 Visual *visual = DefaultVisual(display, screen);
760 RMask = visual->red_mask;
761 GMask = visual->green_mask;
762 BMask = visual->blue_mask;
763
764 RShift = 15 - getMsb(RMask); /* these are right-shifts */
765 GShift = 15 - getMsb(GMask);
766 BShift = 15 - getMsb(BMask);
767
768 XSetWindowColormap(display, window, lut);
769 XInstallColormap(display, lut);
770 }
771
772 //
773 // Create colors for overlay
774 //
775 switch (screen_depth) {
776
777 case 8:
778 // Color BLACK and WHITE are set properly.
779
780 // Color LIGHT GRAY.
781 x_color[vpColor::id_lightGray] = 254;
782 xcolor.pixel = x_color[vpColor::id_lightGray];
783 xcolor.red = 256 * 192;
784 xcolor.green = 256 * 192;
785 xcolor.blue = 256 * 192;
786 XStoreColor(display, lut, &xcolor);
787
788 // Color GRAY.
789 x_color[vpColor::id_gray] = 253;
790 xcolor.pixel = x_color[vpColor::id_gray];
791 xcolor.red = 256 * 128;
792 xcolor.green = 256 * 128;
793 xcolor.blue = 256 * 128;
794 XStoreColor(display, lut, &xcolor);
795
796 // Color DARK GRAY.
797 x_color[vpColor::id_darkGray] = 252;
798 xcolor.pixel = x_color[vpColor::id_darkGray];
799 xcolor.red = 256 * 64;
800 xcolor.green = 256 * 64;
801 xcolor.blue = 256 * 64;
802 XStoreColor(display, lut, &xcolor);
803
804 // Color LIGHT RED.
805 x_color[vpColor::id_lightRed] = 251;
806 xcolor.pixel = x_color[vpColor::id_lightRed];
807 xcolor.red = 256 * 255;
808 xcolor.green = 256 * 140;
809 xcolor.blue = 256 * 140;
810 XStoreColor(display, lut, &xcolor);
811
812 // Color RED.
813 x_color[vpColor::id_red] = 250;
814 xcolor.pixel = x_color[vpColor::id_red];
815 xcolor.red = 256 * 255;
816 xcolor.green = 0;
817 xcolor.blue = 0;
818 XStoreColor(display, lut, &xcolor);
819
820 // Color DARK RED.
821 x_color[vpColor::id_darkRed] = 249;
822 xcolor.pixel = x_color[vpColor::id_darkRed];
823 xcolor.red = 256 * 128;
824 xcolor.green = 0;
825 xcolor.blue = 0;
826 XStoreColor(display, lut, &xcolor);
827
828 // Color LIGHT GREEN.
829 x_color[vpColor::id_lightGreen] = 248;
830 xcolor.pixel = x_color[vpColor::id_lightGreen];
831 xcolor.red = 256 * 140;
832 xcolor.green = 256 * 255;
833 xcolor.blue = 256 * 140;
834 XStoreColor(display, lut, &xcolor);
835
836 // Color GREEN.
837 x_color[vpColor::id_green] = 247;
838 xcolor.pixel = x_color[vpColor::id_green];
839 xcolor.red = 0;
840 xcolor.green = 256 * 255;
841 xcolor.blue = 0;
842 XStoreColor(display, lut, &xcolor);
843
844 // Color DARK GREEN.
845 x_color[vpColor::id_darkGreen] = 246;
846 xcolor.pixel = x_color[vpColor::id_darkGreen];
847 xcolor.red = 0;
848 xcolor.green = 256 * 128;
849 xcolor.blue = 0;
850 XStoreColor(display, lut, &xcolor);
851
852 // Color LIGHT BLUE.
853 x_color[vpColor::id_lightBlue] = 245;
854 xcolor.pixel = x_color[vpColor::id_lightBlue];
855 xcolor.red = 256 * 140;
856 xcolor.green = 256 * 140;
857 xcolor.blue = 256 * 255;
858 XStoreColor(display, lut, &xcolor);
859
860 // Color BLUE.
861 x_color[vpColor::id_blue] = 244;
862 xcolor.pixel = x_color[vpColor::id_blue];
863 xcolor.red = 0;
864 xcolor.green = 0;
865 xcolor.blue = 256 * 255;
866 XStoreColor(display, lut, &xcolor);
867
868 // Color DARK BLUE.
869 x_color[vpColor::id_darkBlue] = 243;
870 xcolor.pixel = x_color[vpColor::id_darkBlue];
871 xcolor.red = 0;
872 xcolor.green = 0;
873 xcolor.blue = 256 * 128;
874 XStoreColor(display, lut, &xcolor);
875
876 // Color YELLOW.
877 x_color[vpColor::id_yellow] = 242;
878 xcolor.pixel = x_color[vpColor::id_yellow];
879 xcolor.red = 256 * 255;
880 xcolor.green = 256 * 255;
881 xcolor.blue = 0;
882 XStoreColor(display, lut, &xcolor);
883
884 // Color ORANGE.
885 x_color[vpColor::id_orange] = 241;
886 xcolor.pixel = x_color[vpColor::id_orange];
887 xcolor.red = 256 * 255;
888 xcolor.green = 256 * 165;
889 xcolor.blue = 0;
890 XStoreColor(display, lut, &xcolor);
891
892 // Color CYAN.
893 x_color[vpColor::id_cyan] = 240;
894 xcolor.pixel = x_color[vpColor::id_cyan];
895 xcolor.red = 0;
896 xcolor.green = 256 * 255;
897 xcolor.blue = 256 * 255;
898 XStoreColor(display, lut, &xcolor);
899
900 // Color PURPLE.
901 x_color[vpColor::id_purple] = 239;
902 xcolor.pixel = x_color[vpColor::id_purple];
903 xcolor.red = 256 * 128;
904 xcolor.green = 0;
905 xcolor.blue = 256 * 128;
906 XStoreColor(display, lut, &xcolor);
907
908 break;
909
910 case 16:
911 case 24:
912 case 32: {
913 xcolor.flags = DoRed | DoGreen | DoBlue;
914
915 // Couleur BLACK.
916 xcolor.pad = 0;
917 xcolor.red = 0;
918 xcolor.green = 0;
919 xcolor.blue = 0;
920 XAllocColor(display, lut, &xcolor);
921 x_color[vpColor::id_black] = xcolor.pixel;
922
923 // Couleur WHITE.
924 xcolor.pad = 0;
925 xcolor.red = 256 * 255;
926 xcolor.green = 256 * 255;
927 xcolor.blue = 256 * 255;
928 XAllocColor(display, lut, &xcolor);
929 x_color[vpColor::id_white] = xcolor.pixel;
930
931 // Couleur LIGHT GRAY.
932 xcolor.pad = 0;
933 xcolor.red = 256 * 192;
934 xcolor.green = 256 * 192;
935 xcolor.blue = 256 * 192;
936 XAllocColor(display, lut, &xcolor);
937 x_color[vpColor::id_lightGray] = xcolor.pixel;
938
939 // Couleur GRAY.
940 xcolor.pad = 0;
941 xcolor.red = 256 * 128;
942 xcolor.green = 256 * 128;
943 xcolor.blue = 256 * 128;
944 XAllocColor(display, lut, &xcolor);
945 x_color[vpColor::id_gray] = xcolor.pixel;
946
947 // Couleur DARK GRAY.
948 xcolor.pad = 0;
949 xcolor.red = 256 * 64;
950 xcolor.green = 256 * 64;
951 xcolor.blue = 256 * 64;
952 XAllocColor(display, lut, &xcolor);
953 x_color[vpColor::id_darkGray] = xcolor.pixel;
954
955 // Couleur LIGHT RED.
956 xcolor.pad = 0;
957 xcolor.red = 256 * 255;
958 xcolor.green = 256 * 140;
959 xcolor.blue = 256 * 140;
960 XAllocColor(display, lut, &xcolor);
961 x_color[vpColor::id_lightRed] = xcolor.pixel;
962
963 // Couleur RED.
964 xcolor.pad = 0;
965 xcolor.red = 256 * 255;
966 xcolor.green = 0;
967 xcolor.blue = 0;
968 XAllocColor(display, lut, &xcolor);
969 x_color[vpColor::id_red] = xcolor.pixel;
970
971 // Couleur DARK RED.
972 xcolor.pad = 0;
973 xcolor.red = 256 * 128;
974 xcolor.green = 0;
975 xcolor.blue = 0;
976 XAllocColor(display, lut, &xcolor);
977 x_color[vpColor::id_darkRed] = xcolor.pixel;
978
979 // Couleur LIGHT GREEN.
980 xcolor.pad = 0;
981 xcolor.red = 256 * 140;
982 xcolor.green = 256 * 255;
983 xcolor.blue = 256 * 140;
984 XAllocColor(display, lut, &xcolor);
985 x_color[vpColor::id_lightGreen] = xcolor.pixel;
986
987 // Couleur GREEN.
988 xcolor.pad = 0;
989 xcolor.red = 0;
990 xcolor.green = 256 * 255;
991 xcolor.blue = 0;
992 XAllocColor(display, lut, &xcolor);
993 x_color[vpColor::id_green] = xcolor.pixel;
994
995 // Couleur DARK GREEN.
996 xcolor.pad = 0;
997 xcolor.red = 0;
998 xcolor.green = 256 * 128;
999 xcolor.blue = 0;
1000 XAllocColor(display, lut, &xcolor);
1001 x_color[vpColor::id_darkGreen] = xcolor.pixel;
1002
1003 // Couleur LIGHT Blue.
1004 xcolor.pad = 0;
1005 xcolor.red = 256 * 140;
1006 xcolor.green = 256 * 140;
1007 xcolor.blue = 256 * 255;
1008 XAllocColor(display, lut, &xcolor);
1009 x_color[vpColor::id_lightBlue] = xcolor.pixel;
1010
1011 // Couleur BLUE.
1012 xcolor.pad = 0;
1013 xcolor.red = 0;
1014 xcolor.green = 0;
1015 xcolor.blue = 256 * 255;
1016 XAllocColor(display, lut, &xcolor);
1017 x_color[vpColor::id_blue] = xcolor.pixel;
1018
1019 // Couleur DARK BLUE.
1020 xcolor.pad = 0;
1021 xcolor.red = 0;
1022 xcolor.green = 0;
1023 xcolor.blue = 256 * 128;
1024 XAllocColor(display, lut, &xcolor);
1025 x_color[vpColor::id_darkBlue] = xcolor.pixel;
1026
1027 // Couleur YELLOW.
1028 xcolor.pad = 0;
1029 xcolor.red = 256 * 255;
1030 xcolor.green = 256 * 255;
1031 xcolor.blue = 0;
1032 XAllocColor(display, lut, &xcolor);
1033 x_color[vpColor::id_yellow] = xcolor.pixel;
1034
1035 // Couleur ORANGE.
1036 xcolor.pad = 0;
1037 xcolor.red = 256 * 255;
1038 xcolor.green = 256 * 165;
1039 xcolor.blue = 0;
1040 XAllocColor(display, lut, &xcolor);
1041 x_color[vpColor::id_orange] = xcolor.pixel;
1042
1043 // Couleur CYAN.
1044 xcolor.pad = 0;
1045 xcolor.red = 0;
1046 xcolor.green = 256 * 255;
1047 xcolor.blue = 256 * 255;
1048 XAllocColor(display, lut, &xcolor);
1049 x_color[vpColor::id_cyan] = xcolor.pixel;
1050
1051 // Couleur PURPLE.
1052 xcolor.pad = 0;
1053 xcolor.red = 256 * 128;
1054 xcolor.green = 0;
1055 xcolor.blue = 256 * 128;
1056 XAllocColor(display, lut, &xcolor);
1057 x_color[vpColor::id_purple] = xcolor.pixel;
1058 break;
1059 }
1060 }
1061
1062 XSetStandardProperties(display, window, this->m_title.c_str(), this->m_title.c_str(), None, 0, 0, &hints);
1063 XMapWindow(display, window);
1064 // Selection des evenements.
1065 XSelectInput(display, window,
1066 ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
1067 StructureNotifyMask | PointerMotionMask);
1068
1069 // Creation du contexte graphique
1070 values.plane_mask = AllPlanes;
1071 values.fill_style = FillSolid;
1072 values.foreground = WhitePixel(display, screen);
1073 values.background = BlackPixel(display, screen);
1074 context = XCreateGC(display, window, GCPlaneMask | GCFillStyle | GCForeground | GCBackground, &values);
1075
1076 if (context == NULL) {
1077 vpERROR_TRACE("Can't create graphics context.");
1078 throw(vpDisplayException(vpDisplayException::XWindowsError, "Can't create graphics context"));
1079 }
1080
1081 // Pixmap creation.
1082 pixmap = XCreatePixmap(display, window, m_width, m_height, screen_depth);
1083
1084 // Hangs when forward X11 is used to send the display to an other computer
1085 // do
1086 // XNextEvent ( display, &event );
1087 // while ( event.xany.type != Expose );
1088
1089 {
1090 Ximage = XCreateImage(display, DefaultVisual(display, screen), screen_depth, ZPixmap, 0, NULL, m_width, m_height,
1091 XBitmapPad(display), 0);
1092
1093 Ximage->data = (char *)malloc(m_height * (unsigned int)Ximage->bytes_per_line);
1094 ximage_data_init = true;
1095 }
1096 m_displayHasBeenInitialized = true;
1097
1098 XSync(display, true);
1099
1100 XStoreName(display, window, m_title.c_str());
1101
1102 I.display = this;
1103 }
1104
1105 /*!
1106 Initialize the display size, position and title.
1107
1108 \param w, h : Width and height of the window.
1109 \param x, y : The window is set at position x,y (column index, row index).
1110 \param title : Window title.
1111 */
init(unsigned int w,unsigned int h,int x,int y,const std::string & title)1112 void vpDisplayX::init(unsigned int w, unsigned int h, int x, int y, const std::string &title)
1113 {
1114 setScale(m_scaleType, w, h);
1115
1116 if (x_color == NULL) {
1117 // id_unknown = number of predefined colors
1118 x_color = new unsigned long[vpColor::id_unknown];
1119 }
1120 /* setup X11 -------------------------------------------------------------
1121 */
1122 this->m_width = w / m_scale;
1123 this->m_height = h / m_scale;
1124
1125 XSizeHints hints;
1126
1127 if (x != -1)
1128 m_windowXPosition = x;
1129 if (y != -1)
1130 m_windowYPosition = y;
1131 // Positionnement de la fenetre dans l'ecran.
1132 if ((m_windowXPosition < 0) || (m_windowYPosition < 0)) {
1133 hints.flags = 0;
1134 } else {
1135 hints.flags = USPosition;
1136 hints.x = m_windowXPosition;
1137 hints.y = m_windowYPosition;
1138 }
1139
1140 m_title = title;
1141
1142 if ((display = XOpenDisplay(NULL)) == NULL) {
1143 vpERROR_TRACE("Can't connect display on server %s.\n", XDisplayName(NULL));
1144 throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server."));
1145 }
1146
1147 screen = DefaultScreen(display);
1148 lut = DefaultColormap(display, screen);
1149 screen_depth = (unsigned int)DefaultDepth(display, screen);
1150
1151 vpTRACE("Screen depth: %d\n", screen_depth);
1152
1153 if ((window = XCreateSimpleWindow(display, RootWindow(display, screen), m_windowXPosition, m_windowYPosition, m_width,
1154 m_height, 1, BlackPixel(display, screen), WhitePixel(display, screen))) == 0) {
1155 vpERROR_TRACE("Can't create window.");
1156 throw(vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create window."));
1157 }
1158
1159 //
1160 // Create color table for 8 and 16 bits screen
1161 //
1162 if (screen_depth == 8) {
1163 lut = XCreateColormap(display, window, DefaultVisual(display, screen), AllocAll);
1164 xcolor.flags = DoRed | DoGreen | DoBlue;
1165
1166 for (unsigned int i = 0; i < 256; i++) {
1167 xcolor.pixel = i;
1168 xcolor.red = 256 * i;
1169 xcolor.green = 256 * i;
1170 xcolor.blue = 256 * i;
1171 XStoreColor(display, lut, &xcolor);
1172 }
1173
1174 XSetWindowColormap(display, window, lut);
1175 XInstallColormap(display, lut);
1176 }
1177
1178 else if (screen_depth == 16) {
1179 for (unsigned int i = 0; i < 256; i++) {
1180 xcolor.pad = 0;
1181 xcolor.red = xcolor.green = xcolor.blue = 256 * i;
1182 if (XAllocColor(display, lut, &xcolor) == 0) {
1183 vpERROR_TRACE("Can't allocate 256 colors. Only %d allocated.", i);
1184 throw(vpDisplayException(vpDisplayException::colorAllocError, "Can't allocate 256 colors."));
1185 }
1186 colortable[i] = xcolor.pixel;
1187 }
1188
1189 XSetWindowColormap(display, window, lut);
1190 XInstallColormap(display, lut);
1191
1192 Visual *visual = DefaultVisual(display, screen);
1193 RMask = visual->red_mask;
1194 GMask = visual->green_mask;
1195 BMask = visual->blue_mask;
1196
1197 RShift = 15 - getMsb(RMask); /* these are right-shifts */
1198 GShift = 15 - getMsb(GMask);
1199 BShift = 15 - getMsb(BMask);
1200 }
1201
1202 vpColor pcolor; // predefined colors
1203
1204 //
1205 // Create colors for overlay
1206 //
1207 switch (screen_depth) {
1208
1209 case 8:
1210 // Color BLACK: default set to 0
1211
1212 // Color WHITE: default set to 255
1213
1214 // Color LIGHT GRAY.
1215 pcolor = vpColor::lightGray;
1216 xcolor.pixel = 254; // affected to 254
1217 xcolor.red = 256 * pcolor.R;
1218 xcolor.green = 256 * pcolor.G;
1219 xcolor.blue = 256 * pcolor.B;
1220 XStoreColor(display, lut, &xcolor);
1221
1222 // Color GRAY.
1223 pcolor = vpColor::gray;
1224 xcolor.pixel = 253; // affected to 253
1225 xcolor.red = 256 * pcolor.R;
1226 xcolor.green = 256 * pcolor.G;
1227 xcolor.blue = 256 * pcolor.B;
1228 XStoreColor(display, lut, &xcolor);
1229
1230 // Color DARK GRAY.
1231 pcolor = vpColor::darkGray;
1232 xcolor.pixel = 252; // affected to 252
1233 xcolor.red = 256 * pcolor.R;
1234 xcolor.green = 256 * pcolor.G;
1235 xcolor.blue = 256 * pcolor.B;
1236 XStoreColor(display, lut, &xcolor);
1237
1238 // Color LIGHT RED.
1239 pcolor = vpColor::lightRed;
1240 xcolor.pixel = 251; // affected to 251
1241 xcolor.red = 256 * pcolor.R;
1242 xcolor.green = 256 * pcolor.G;
1243 xcolor.blue = 256 * pcolor.B;
1244 XStoreColor(display, lut, &xcolor);
1245
1246 // Color RED.
1247 pcolor = vpColor::red;
1248 xcolor.pixel = 250; // affected to 250
1249 xcolor.red = 256 * pcolor.R;
1250 xcolor.green = 256 * pcolor.G;
1251 xcolor.blue = 256 * pcolor.B;
1252 XStoreColor(display, lut, &xcolor);
1253
1254 // Color DARK RED.
1255 pcolor = vpColor::darkRed;
1256 xcolor.pixel = 249; // affected to 249
1257 xcolor.red = 256 * pcolor.R;
1258 xcolor.green = 256 * pcolor.G;
1259 xcolor.blue = 256 * pcolor.B;
1260 XStoreColor(display, lut, &xcolor);
1261
1262 // Color LIGHT GREEN.
1263 pcolor = vpColor::lightGreen;
1264 xcolor.pixel = 248; // affected to 248
1265 xcolor.red = 256 * pcolor.R;
1266 xcolor.green = 256 * pcolor.G;
1267 xcolor.blue = 256 * pcolor.B;
1268 XStoreColor(display, lut, &xcolor);
1269
1270 // Color GREEN.
1271 pcolor = vpColor::green;
1272 xcolor.pixel = 247; // affected to 247
1273 xcolor.red = 256 * pcolor.R;
1274 xcolor.green = 256 * pcolor.G;
1275 xcolor.blue = 256 * pcolor.B;
1276 XStoreColor(display, lut, &xcolor);
1277
1278 // Color DARK GREEN.
1279 pcolor = vpColor::darkGreen;
1280 xcolor.pixel = 246; // affected to 246
1281 xcolor.red = 256 * pcolor.R;
1282 xcolor.green = 256 * pcolor.G;
1283 xcolor.blue = 256 * pcolor.B;
1284 XStoreColor(display, lut, &xcolor);
1285
1286 // Color LIGHT BLUE.
1287 pcolor = vpColor::lightBlue;
1288 xcolor.pixel = 245; // affected to 245
1289 xcolor.red = 256 * pcolor.R;
1290 xcolor.green = 256 * pcolor.G;
1291 xcolor.blue = 256 * pcolor.B;
1292 XStoreColor(display, lut, &xcolor);
1293
1294 // Color BLUE.
1295 pcolor = vpColor::blue;
1296 xcolor.pixel = 244; // affected to 244
1297 xcolor.red = 256 * pcolor.R;
1298 xcolor.green = 256 * pcolor.G;
1299 xcolor.blue = 256 * pcolor.B;
1300 XStoreColor(display, lut, &xcolor);
1301
1302 // Color DARK BLUE.
1303 pcolor = vpColor::darkBlue;
1304 xcolor.pixel = 243; // affected to 243
1305 xcolor.red = 256 * pcolor.R;
1306 xcolor.green = 256 * pcolor.G;
1307 xcolor.blue = 256 * pcolor.B;
1308 XStoreColor(display, lut, &xcolor);
1309
1310 // Color YELLOW.
1311 pcolor = vpColor::yellow;
1312 xcolor.pixel = 242; // affected to 242
1313 xcolor.red = 256 * pcolor.R;
1314 xcolor.green = 256 * pcolor.G;
1315 xcolor.blue = 256 * pcolor.B;
1316 XStoreColor(display, lut, &xcolor);
1317
1318 // Color ORANGE.
1319 pcolor = vpColor::orange;
1320 xcolor.pixel = 241; // affected to 241
1321 xcolor.red = 256 * pcolor.R;
1322 xcolor.green = 256 * pcolor.G;
1323 xcolor.blue = 256 * pcolor.B;
1324 XStoreColor(display, lut, &xcolor);
1325
1326 // Color CYAN.
1327 pcolor = vpColor::cyan;
1328 xcolor.pixel = 240; // affected to 240
1329 xcolor.red = 256 * pcolor.R;
1330 xcolor.green = 256 * pcolor.G;
1331 xcolor.blue = 256 * pcolor.B;
1332 XStoreColor(display, lut, &xcolor);
1333
1334 // Color PURPLE.
1335 pcolor = vpColor::purple;
1336 xcolor.pixel = 239; // affected to 239
1337 xcolor.red = 256 * pcolor.R;
1338 xcolor.green = 256 * pcolor.G;
1339 xcolor.blue = 256 * pcolor.B;
1340 XStoreColor(display, lut, &xcolor);
1341
1342 break;
1343
1344 case 16:
1345 case 24: {
1346 xcolor.flags = DoRed | DoGreen | DoBlue;
1347
1348 // Couleur BLACK.
1349 pcolor = vpColor::black;
1350 xcolor.pad = 0;
1351 xcolor.red = 256 * pcolor.R;
1352 xcolor.green = 256 * pcolor.G;
1353 xcolor.blue = 256 * pcolor.B;
1354 XAllocColor(display, lut, &xcolor);
1355 x_color[vpColor::id_black] = xcolor.pixel;
1356
1357 // Color WHITE.
1358 pcolor = vpColor::white;
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_white] = xcolor.pixel;
1365
1366 // Color LIGHT GRAY.
1367 pcolor = vpColor::lightGray;
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_lightGray] = xcolor.pixel;
1374
1375 // Color GRAY.
1376 pcolor = vpColor::gray;
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_gray] = xcolor.pixel;
1383
1384 // Color DARK GRAY.
1385 pcolor = vpColor::darkGray;
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_darkGray] = xcolor.pixel;
1392
1393 // Color LIGHT RED.
1394 pcolor = vpColor::lightRed;
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_lightRed] = xcolor.pixel;
1401
1402 // Color RED.
1403 pcolor = vpColor::red;
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_red] = xcolor.pixel;
1410
1411 // Color DARK RED.
1412 pcolor = vpColor::darkRed;
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_darkRed] = xcolor.pixel;
1419
1420 // Color LIGHT GREEN.
1421 pcolor = vpColor::lightGreen;
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_lightGreen] = xcolor.pixel;
1428
1429 // Color GREEN.
1430 pcolor = vpColor::green;
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_green] = xcolor.pixel;
1437
1438 // Color DARK GREEN.
1439 pcolor = vpColor::darkGreen;
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_darkGreen] = xcolor.pixel;
1446
1447 // Color LIGHT BLUE.
1448 pcolor = vpColor::lightBlue;
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_lightBlue] = xcolor.pixel;
1455
1456 // Color BLUE.
1457 pcolor = vpColor::blue;
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_blue] = xcolor.pixel;
1464
1465 // Color DARK BLUE.
1466 pcolor = vpColor::darkBlue;
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_darkBlue] = xcolor.pixel;
1473
1474 // Color YELLOW.
1475 pcolor = vpColor::yellow;
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_yellow] = xcolor.pixel;
1482
1483 // Color ORANGE.
1484 pcolor = vpColor::orange;
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_orange] = xcolor.pixel;
1491
1492 // Color CYAN.
1493 pcolor = vpColor::cyan;
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_cyan] = xcolor.pixel;
1500
1501 // Color PURPLE.
1502 pcolor = vpColor::purple;
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_purple] = xcolor.pixel;
1509 break;
1510 }
1511 }
1512
1513 XSetStandardProperties(display, window, this->m_title.c_str(), this->m_title.c_str(), None, 0, 0, &hints);
1514 XMapWindow(display, window);
1515 // Selection des evenements.
1516 XSelectInput(display, window,
1517 ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
1518 StructureNotifyMask | PointerMotionMask);
1519
1520 /* Creation du contexte graphique */
1521 values.plane_mask = AllPlanes;
1522 values.fill_style = FillSolid;
1523 values.foreground = WhitePixel(display, screen);
1524 values.background = BlackPixel(display, screen);
1525 context = XCreateGC(display, window, GCPlaneMask | GCFillStyle | GCForeground | GCBackground, &values);
1526
1527 if (context == NULL) {
1528 vpERROR_TRACE("Can't create graphics context.");
1529 throw(vpDisplayException(vpDisplayException::XWindowsError, "Can't create graphics context"));
1530 }
1531
1532 // Pixmap creation.
1533 pixmap = XCreatePixmap(display, window, m_width, m_height, screen_depth);
1534
1535 // Hangs when forward X11 is used to send the display to an other computer
1536 // do
1537 // XNextEvent ( display, &event );
1538 // while ( event.xany.type != Expose );
1539
1540 {
1541 Ximage = XCreateImage(display, DefaultVisual(display, screen), screen_depth, ZPixmap, 0, NULL, m_width, m_height,
1542 XBitmapPad(display), 0);
1543
1544 Ximage->data = (char *)malloc(m_height * (unsigned int)Ximage->bytes_per_line);
1545 ximage_data_init = true;
1546 }
1547 m_displayHasBeenInitialized = true;
1548
1549 XSync(display, true);
1550
1551 XStoreName(display, window, m_title.c_str());
1552 }
1553
1554 /*!
1555
1556 Set the font used to display a text in overlay. The display is
1557 performed using displayCharString().
1558
1559 \param font : The expected font name. The available fonts are given by
1560 the "xlsfonts" binary. To choose a font you can also use the
1561 "xfontsel" binary.
1562
1563 \note Under UNIX, to know all the available fonts, use the
1564 "xlsfonts" binary in a terminal. You can also use the "xfontsel" binary.
1565
1566 \sa displayCharString()
1567 */
setFont(const std::string & font)1568 void vpDisplayX::setFont(const std::string &font)
1569 {
1570 if (m_displayHasBeenInitialized) {
1571 if (!font.empty()) {
1572 try {
1573 Font stringfont;
1574 stringfont = XLoadFont(display, font.c_str()); //"-adobe-times-bold-r-normal--18*");
1575 XSetFont(display, context, stringfont);
1576 } catch (...) {
1577 throw(vpDisplayException(vpDisplayException::notInitializedError, "Bad font"));
1578 }
1579 }
1580 } else {
1581 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1582 }
1583 }
1584
1585 /*!
1586 Set the window title.
1587 \param title : Window title.
1588 */
setTitle(const std::string & title)1589 void vpDisplayX::setTitle(const std::string &title)
1590 {
1591 if (m_displayHasBeenInitialized) {
1592 m_title = title;
1593 if (!title.empty())
1594 XStoreName(display, window, m_title.c_str());
1595 } else {
1596 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1597 }
1598 }
1599
1600 /*!
1601 Set the window position in the screen.
1602
1603 \param winx, winy : Position of the upper-left window's border in the
1604 screen.
1605
1606 \exception vpDisplayException::notInitializedError : If the video
1607 device is not initialized.
1608 */
setWindowPosition(int winx,int winy)1609 void vpDisplayX::setWindowPosition(int winx, int winy)
1610 {
1611 if (m_displayHasBeenInitialized) {
1612 XMoveWindow(display, window, winx, winy);
1613 } else {
1614 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1615 }
1616 }
1617
1618 /*!
1619 Display the gray level image \e I (8bits).
1620
1621 \warning Display has to be initialized.
1622
1623 \warning Suppress the overlay drawing.
1624
1625 \param I : Image to display.
1626
1627 \sa init(), closeDisplay()
1628 */
displayImage(const vpImage<unsigned char> & I)1629 void vpDisplayX::displayImage(const vpImage<unsigned char> &I)
1630 {
1631 if (m_displayHasBeenInitialized) {
1632 switch (screen_depth) {
1633 case 8: {
1634 // Correction de l'image de facon a liberer les niveaux de gris
1635 // ROUGE, VERT, BLEU, JAUNE
1636 unsigned char nivGrisMax = 255 - vpColor::id_unknown;
1637 if (m_scale == 1) {
1638 unsigned char *src_8 = (unsigned char *)I.bitmap;
1639 unsigned char *dst_8 = (unsigned char *)Ximage->data;
1640 unsigned int i = 0;
1641 unsigned int size = m_width * m_height;
1642
1643 while (i < size) {
1644 unsigned char nivGris = src_8[i];
1645 if (nivGris > nivGrisMax)
1646 dst_8[i] = 255;
1647 else
1648 dst_8[i] = nivGris;
1649 i++;
1650 }
1651 } else {
1652 // Correction de l'image de facon a liberer les niveaux de gris
1653 // ROUGE, VERT, BLEU, JAUNE
1654 unsigned char *dst_8 = (unsigned char *)Ximage->data;
1655 unsigned int k = 0;
1656 for (unsigned int i = 0; i < m_height; i++) {
1657 for (unsigned int j = 0; j < m_width; j++) {
1658 unsigned char nivGris = I[i * m_scale][j * m_scale];
1659 if (nivGris > nivGrisMax)
1660 dst_8[k++] = 255;
1661 else
1662 dst_8[k++] = nivGris;
1663 }
1664 }
1665 }
1666
1667 // Affichage de l'image dans la Pixmap.
1668 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1669 XSetWindowBackgroundPixmap(display, window, pixmap);
1670 break;
1671 }
1672 case 16: {
1673 unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
1674 if (m_scale == 1) {
1675 for (unsigned int i = 0; i < m_height; i++) {
1676 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
1677 unsigned short *dst_16 = (unsigned short *)dst_8;
1678 for (unsigned int j = 0; j < m_width; j++) {
1679 *(dst_16 + j) = (unsigned short)colortable[I[i][j]];
1680 }
1681 }
1682 } else {
1683 for (unsigned int i = 0; i < m_height; i++) {
1684 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
1685 unsigned short *dst_16 = (unsigned short *)dst_8;
1686 for (unsigned int j = 0; j < m_width; j++) {
1687 *(dst_16 + j) = (unsigned short)colortable[I[i * m_scale][j * m_scale]];
1688 }
1689 }
1690 }
1691
1692 // Affichage de l'image dans la Pixmap.
1693 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1694 XSetWindowBackgroundPixmap(display, window, pixmap);
1695 break;
1696 }
1697
1698 case 24:
1699 default: {
1700 unsigned char *dst_32 = (unsigned char *)Ximage->data;
1701 if (m_scale == 1) {
1702 unsigned int size_ = m_width * m_height;
1703 unsigned char *bitmap = I.bitmap;
1704 unsigned char *n = I.bitmap + size_;
1705 // for (unsigned int i = 0; i < size; i++) // suppression de
1706 // l'iterateur i
1707 if (XImageByteOrder(display) == 1) {
1708 // big endian
1709 while (bitmap < n) {
1710 unsigned char val = *(bitmap++);
1711 *(dst_32++) = vpRGBa::alpha_default;
1712 *(dst_32++) = val; // Red
1713 *(dst_32++) = val; // Green
1714 *(dst_32++) = val; // Blue
1715 }
1716 } else {
1717 // little endian
1718 while (bitmap < n) {
1719 unsigned char val = *(bitmap++);
1720 *(dst_32++) = val; // Blue
1721 *(dst_32++) = val; // Green
1722 *(dst_32++) = val; // Red
1723 *(dst_32++) = vpRGBa::alpha_default;
1724 }
1725 }
1726 } else {
1727 if (XImageByteOrder(display) == 1) {
1728 // big endian
1729 for (unsigned int i = 0; i < m_height; i++) {
1730 for (unsigned int j = 0; j < m_width; j++) {
1731 unsigned char val = I[i * m_scale][j * m_scale];
1732 *(dst_32++) = vpRGBa::alpha_default;
1733 *(dst_32++) = val; // Red
1734 *(dst_32++) = val; // Green
1735 *(dst_32++) = val; // Blue
1736 }
1737 }
1738 } else {
1739 // little endian
1740 for (unsigned int i = 0; i < m_height; i++) {
1741 for (unsigned int j = 0; j < m_width; j++) {
1742 unsigned char val = I[i * m_scale][j * m_scale];
1743 *(dst_32++) = val; // Blue
1744 *(dst_32++) = val; // Green
1745 *(dst_32++) = val; // Red
1746 *(dst_32++) = vpRGBa::alpha_default;
1747 }
1748 }
1749 }
1750 }
1751
1752 // Affichage de l'image dans la Pixmap.
1753 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1754 XSetWindowBackgroundPixmap(display, window, pixmap);
1755 break;
1756 }
1757 }
1758 } else {
1759 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1760 }
1761 }
1762 /*!
1763 Display the color image \e I in RGBa format (32bits).
1764
1765 \warning Display has to be initialized.
1766
1767 \warning Suppress the overlay drawing.
1768
1769 \param I : Image to display.
1770
1771 \sa init(), closeDisplay()
1772 */
displayImage(const vpImage<vpRGBa> & I)1773 void vpDisplayX::displayImage(const vpImage<vpRGBa> &I)
1774 {
1775 if (m_displayHasBeenInitialized) {
1776 switch (screen_depth) {
1777 case 16: {
1778 vpRGBa *bitmap = I.bitmap;
1779 unsigned int r, g, b;
1780 unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
1781
1782 if (m_scale == 1) {
1783 for (unsigned int i = 0; i < m_height; i++) {
1784 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
1785 unsigned short *dst_16 = (unsigned short *)dst_8;
1786 for (unsigned int j = 0; j < m_width; j++) {
1787 r = bitmap->R;
1788 g = bitmap->G;
1789 b = bitmap->B;
1790 *(dst_16 + j) =
1791 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
1792 bitmap++;
1793 }
1794 }
1795 } else {
1796 for (unsigned int i = 0; i < m_height; i++) {
1797 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
1798 unsigned short *dst_16 = (unsigned short *)dst_8;
1799 for (unsigned int j = 0; j < m_width; j++) {
1800 vpRGBa val = I[i * m_scale][j * m_scale];
1801 r = val.R;
1802 g = val.G;
1803 b = val.B;
1804 *(dst_16 + j) =
1805 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
1806 bitmap++;
1807 }
1808 }
1809 }
1810
1811 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1812 XSetWindowBackgroundPixmap(display, window, pixmap);
1813
1814 break;
1815 }
1816 case 24:
1817 case 32: {
1818 /*
1819 * 32-bit source, 24/32-bit destination
1820 */
1821 unsigned char *dst_32 = NULL;
1822 dst_32 = (unsigned char *)Ximage->data;
1823 if (m_scale == 1) {
1824 vpRGBa *bitmap = I.bitmap;
1825 unsigned int sizeI = m_width * m_height;
1826 if (XImageByteOrder(display) == 1) {
1827 // big endian
1828 for (unsigned int i = 0; i < sizeI; i++) {
1829 *(dst_32++) = bitmap->A;
1830 *(dst_32++) = bitmap->R;
1831 *(dst_32++) = bitmap->G;
1832 *(dst_32++) = bitmap->B;
1833 bitmap++;
1834 }
1835 } else {
1836 // little endian
1837 for (unsigned int i = 0; i < sizeI; i++) {
1838 *(dst_32++) = bitmap->B;
1839 *(dst_32++) = bitmap->G;
1840 *(dst_32++) = bitmap->R;
1841 *(dst_32++) = bitmap->A;
1842 bitmap++;
1843 }
1844 }
1845 } else {
1846 if (XImageByteOrder(display) == 1) {
1847 // big endian
1848 for (unsigned int i = 0; i < m_height; i++) {
1849 for (unsigned int j = 0; j < m_width; j++) {
1850 vpRGBa val = I[i * m_scale][j * m_scale];
1851 *(dst_32++) = val.A;
1852 *(dst_32++) = val.R;
1853 *(dst_32++) = val.G;
1854 *(dst_32++) = val.B;
1855 }
1856 }
1857 } else {
1858 // little endian
1859 for (unsigned int i = 0; i < m_height; i++) {
1860 for (unsigned int j = 0; j < m_width; j++) {
1861 vpRGBa val = I[i * m_scale][j * m_scale];
1862 *(dst_32++) = val.B;
1863 *(dst_32++) = val.G;
1864 *(dst_32++) = val.R;
1865 *(dst_32++) = val.A;
1866 }
1867 }
1868 }
1869 }
1870
1871 // Affichage de l'image dans la Pixmap.
1872 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1873 XSetWindowBackgroundPixmap(display, window, pixmap);
1874 break;
1875 }
1876 default:
1877 throw(vpDisplayException(vpDisplayException::depthNotSupportedError,
1878 "Unsupported depth (%d bpp) for color display", screen_depth));
1879 }
1880 } else {
1881 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1882 }
1883 }
1884
1885 /*!
1886 Display an image with a reference to the bitmap.
1887
1888 \warning Display has to be initialized.
1889
1890 \warning Suppress the overlay drawing.
1891
1892 \param bitmap : Pointer to the image bitmap.
1893
1894 \sa init(), closeDisplay()
1895 */
displayImage(const unsigned char * bitmap)1896 void vpDisplayX::displayImage(const unsigned char *bitmap)
1897 {
1898
1899 if (m_displayHasBeenInitialized) {
1900 unsigned char *dst_32 = (unsigned char *)Ximage->data;
1901 for (unsigned int i = 0; i < m_width * m_height; i++) {
1902 *(dst_32++) = *bitmap; // red component.
1903 *(dst_32++) = *bitmap; // green component.
1904 *(dst_32++) = *bitmap; // blue component.
1905 *(dst_32++) = *bitmap; // luminance component.
1906 bitmap++;
1907 }
1908
1909 // Affichage de l'image dans la Pixmap.
1910 XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1911 XSetWindowBackgroundPixmap(display, window, pixmap);
1912 } else {
1913 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1914 }
1915 }
1916
1917 /*!
1918 Display a selection of the gray level image \e I (8bits).
1919
1920 \warning Display has to be initialized.
1921
1922 \warning Suppress the overlay drawing in the region of interest.
1923
1924 \param I : Image to display.
1925
1926 \param iP : Top left corner of the region of interest
1927
1928 \param w, h : Width and height of the region of interest
1929
1930 \sa init(), closeDisplay()
1931 */
displayImageROI(const vpImage<unsigned char> & I,const vpImagePoint & iP,unsigned int w,unsigned int h)1932 void vpDisplayX::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w,
1933 unsigned int h)
1934 {
1935 if (m_displayHasBeenInitialized) {
1936 switch (screen_depth) {
1937 case 8: {
1938 // Correction de l'image de facon a liberer les niveaux de gris
1939 // ROUGE, VERT, BLEU, JAUNE
1940 unsigned char nivGrisMax = 255 - vpColor::id_unknown;
1941 if (m_scale == 1) {
1942 unsigned char *src_8 = (unsigned char *)I.bitmap;
1943 unsigned char *dst_8 = (unsigned char *)Ximage->data;
1944 unsigned int iwidth = I.getWidth();
1945
1946 src_8 = src_8 + (int)(iP.get_i() * iwidth + iP.get_j());
1947 dst_8 = dst_8 + (int)(iP.get_i() * m_width + iP.get_j());
1948
1949 unsigned int i = 0;
1950 while (i < h) {
1951 unsigned int j = 0;
1952 while (j < w) {
1953 unsigned char nivGris = *(src_8 + j);
1954 if (nivGris > nivGrisMax)
1955 *(dst_8 + j) = 255;
1956 else
1957 *(dst_8 + j) = nivGris;
1958 j++;
1959 }
1960 src_8 = src_8 + iwidth;
1961 dst_8 = dst_8 + m_width;
1962 i++;
1963 }
1964
1965 XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
1966 w, h);
1967 } else {
1968 // Correction de l'image de facon a liberer les niveaux de gris
1969 // ROUGE, VERT, BLEU, JAUNE
1970 int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
1971 int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
1972 int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
1973 int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
1974
1975 unsigned int i_min_ = (unsigned int)i_min;
1976 unsigned int i_max_ = (unsigned int)i_max;
1977 unsigned int j_min_ = (unsigned int)j_min;
1978 unsigned int j_max_ = (unsigned int)j_max;
1979
1980 for (unsigned int i = i_min_; i < i_max_; i++) {
1981 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * m_width;
1982 for (unsigned int j = j_min_; j < j_max_; j++) {
1983 unsigned char nivGris = I[i * m_scale][j * m_scale];
1984 if (nivGris > nivGrisMax)
1985 dst_8[j] = 255;
1986 else
1987 dst_8[j] = nivGris;
1988 }
1989 }
1990 XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
1991 }
1992
1993 // Affichage de l'image dans la Pixmap.
1994 XSetWindowBackgroundPixmap(display, window, pixmap);
1995 break;
1996 }
1997 case 16: {
1998 unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
1999 if (m_scale == 1) {
2000 for (unsigned int i = (unsigned int)iP.get_i(); i < (unsigned int)(iP.get_i() + h); i++) {
2001 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
2002 unsigned short *dst_16 = (unsigned short *)dst_8;
2003 for (unsigned int j = (unsigned int)iP.get_j(); j < (unsigned int)(iP.get_j() + w); j++) {
2004 *(dst_16 + j) = (unsigned short)colortable[I[i][j]];
2005 }
2006 }
2007
2008 XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
2009 w, h);
2010 } else {
2011 int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
2012 int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
2013 int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
2014 int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
2015
2016 unsigned int i_min_ = (unsigned int)i_min;
2017 unsigned int i_max_ = (unsigned int)i_max;
2018 unsigned int j_min_ = (unsigned int)j_min;
2019 unsigned int j_max_ = (unsigned int)j_max;
2020
2021 for (unsigned int i = i_min_; i < i_max_; i++) {
2022 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
2023 unsigned short *dst_16 = (unsigned short *)dst_8;
2024 for (unsigned int j = j_min_; j < j_max_; j++) {
2025 *(dst_16 + j) = (unsigned short)colortable[I[i * m_scale][j * m_scale]];
2026 }
2027 }
2028
2029 XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
2030 }
2031
2032 XSetWindowBackgroundPixmap(display, window, pixmap);
2033 break;
2034 }
2035
2036 case 24:
2037 default: {
2038 if (m_scale == 1) {
2039 unsigned int iwidth = I.getWidth();
2040 unsigned char *src_8 = I.bitmap + (int)(iP.get_i() * iwidth + iP.get_j());
2041 unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(iP.get_i() * 4 * m_width + iP.get_j() * 4);
2042
2043 if (XImageByteOrder(display) == 1) {
2044 // big endian
2045 unsigned int i = 0;
2046 while (i < h) {
2047 unsigned int j = 0;
2048 while (j < w) {
2049 unsigned char val = *(src_8 + j);
2050 *(dst_32 + 4 * j) = vpRGBa::alpha_default;
2051 *(dst_32 + 4 * j + 1) = val;
2052 *(dst_32 + 4 * j + 2) = val;
2053 *(dst_32 + 4 * j + 3) = val;
2054 j++;
2055 }
2056 src_8 = src_8 + iwidth;
2057 dst_32 = dst_32 + 4 * m_width;
2058 i++;
2059 }
2060 } else {
2061 // little endian
2062 unsigned int i = 0;
2063 while (i < h) {
2064 unsigned int j = 0;
2065 while (j < w) {
2066 unsigned char val = *(src_8 + j);
2067 *(dst_32 + 4 * j) = val;
2068 *(dst_32 + 4 * j + 1) = val;
2069 *(dst_32 + 4 * j + 2) = val;
2070 *(dst_32 + 4 * j + 3) = vpRGBa::alpha_default;
2071 j++;
2072 }
2073 src_8 = src_8 + iwidth;
2074 dst_32 = dst_32 + 4 * m_width;
2075 i++;
2076 }
2077 }
2078
2079 XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
2080 w, h);
2081 } else {
2082 int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
2083 int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
2084 int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
2085 int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
2086
2087 unsigned int i_min_ = (unsigned int)i_min;
2088 unsigned int i_max_ = (unsigned int)i_max;
2089 unsigned int j_min_ = (unsigned int)j_min;
2090 unsigned int j_max_ = (unsigned int)j_max;
2091
2092 if (XImageByteOrder(display) == 1) {
2093 // big endian
2094 for (unsigned int i = i_min_; i < i_max_; i++) {
2095 unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * m_width + j_min_ * 4);
2096 for (unsigned int j = j_min_; j < j_max_; j++) {
2097 unsigned char val = I[i * m_scale][j * m_scale];
2098 *(dst_32++) = vpRGBa::alpha_default;
2099 *(dst_32++) = val;
2100 *(dst_32++) = val;
2101 *(dst_32++) = val;
2102 }
2103 }
2104 } else {
2105 // little endian
2106 for (unsigned int i = i_min_; i < i_max_; i++) {
2107 unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * m_width + j_min_ * 4);
2108 for (unsigned int j = j_min_; j < j_max_; j++) {
2109 unsigned char val = I[i * m_scale][j * m_scale];
2110 *(dst_32++) = val;
2111 *(dst_32++) = val;
2112 *(dst_32++) = val;
2113 *(dst_32++) = vpRGBa::alpha_default;
2114 }
2115 }
2116 }
2117
2118 XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
2119 }
2120
2121 XSetWindowBackgroundPixmap(display, window, pixmap);
2122 break;
2123 }
2124 }
2125 } else {
2126 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2127 }
2128 }
2129
2130 /*!
2131 Display a selection of the color image \e I in RGBa format (32bits).
2132
2133 \warning Display has to be initialized.
2134
2135 \warning Suppress the overlay drawing in the region of interest.
2136
2137 \param I : Image to display.
2138
2139 \param iP : Top left corner of the region of interest
2140
2141 \param w, h : Width and height of the region of interest
2142
2143 \sa init(), closeDisplay()
2144 */
displayImageROI(const vpImage<vpRGBa> & I,const vpImagePoint & iP,unsigned int w,unsigned int h)2145 void vpDisplayX::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w,
2146 unsigned int h)
2147 {
2148 if (m_displayHasBeenInitialized) {
2149 switch (screen_depth) {
2150 case 16: {
2151 if (m_scale == 1) {
2152 unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
2153 for (unsigned int i = (unsigned int)iP.get_i(); i < (unsigned int)(iP.get_i() + h); i++) {
2154 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
2155 unsigned short *dst_16 = (unsigned short *)dst_8;
2156 for (unsigned int j = (unsigned int)iP.get_j(); j < (unsigned int)(iP.get_j() + w); j++) {
2157 vpRGBa val = I[i][j];
2158 unsigned int r = val.R;
2159 unsigned int g = val.G;
2160 unsigned int b = val.B;
2161 *(dst_16 + j) =
2162 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
2163 }
2164 }
2165 XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
2166 w, h);
2167 } else {
2168 unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
2169 int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
2170 int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
2171 int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
2172 int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
2173
2174 unsigned int i_min_ = (unsigned int)i_min;
2175 unsigned int i_max_ = (unsigned int)i_max;
2176 unsigned int j_min_ = (unsigned int)j_min;
2177 unsigned int j_max_ = (unsigned int)j_max;
2178
2179 for (unsigned int i = i_min_; i < i_max_; i++) {
2180 unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
2181 unsigned short *dst_16 = (unsigned short *)dst_8;
2182 for (unsigned int j = j_min_; j < j_max_; j++) {
2183 vpRGBa val = I[i * m_scale][j * m_scale];
2184 unsigned int r = val.R;
2185 unsigned int g = val.G;
2186 unsigned int b = val.B;
2187 *(dst_16 + j) =
2188 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
2189 }
2190 }
2191 XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
2192 }
2193
2194 XSetWindowBackgroundPixmap(display, window, pixmap);
2195
2196 break;
2197 }
2198 case 24:
2199 case 32: {
2200 /*
2201 * 32-bit source, 24/32-bit destination
2202 */
2203
2204 if (m_scale == 1) {
2205 unsigned char *dst_32 = (unsigned char *)Ximage->data;
2206 vpRGBa *src_32 = I.bitmap;
2207
2208 unsigned int iwidth = I.getWidth();
2209
2210 src_32 = src_32 + (int)(iP.get_i() * iwidth + iP.get_j());
2211 dst_32 = dst_32 + (int)(iP.get_i() * 4 * m_width + iP.get_j() * 4);
2212
2213 unsigned int i = 0;
2214
2215 if (XImageByteOrder(display) == 1) {
2216 // big endian
2217 while (i < h) {
2218 unsigned int j = 0;
2219 while (j < w) {
2220 *(dst_32 + 4 * j) = (src_32 + j)->A;
2221 *(dst_32 + 4 * j + 1) = (src_32 + j)->R;
2222 *(dst_32 + 4 * j + 2) = (src_32 + j)->G;
2223 *(dst_32 + 4 * j + 3) = (src_32 + j)->B;
2224
2225 j++;
2226 }
2227 src_32 = src_32 + iwidth;
2228 dst_32 = dst_32 + 4 * m_width;
2229 i++;
2230 }
2231
2232 } else {
2233 // little endian
2234 while (i < h) {
2235 unsigned int j = 0;
2236 while (j < w) {
2237 *(dst_32 + 4 * j) = (src_32 + j)->B;
2238 *(dst_32 + 4 * j + 1) = (src_32 + j)->G;
2239 *(dst_32 + 4 * j + 2) = (src_32 + j)->R;
2240 *(dst_32 + 4 * j + 3) = (src_32 + j)->A;
2241
2242 j++;
2243 }
2244 src_32 = src_32 + iwidth;
2245 dst_32 = dst_32 + 4 * m_width;
2246 i++;
2247 }
2248 }
2249
2250 XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
2251 w, h);
2252 } else {
2253 int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
2254 int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
2255 int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
2256 int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
2257
2258 unsigned int i_min_ = (unsigned int)i_min;
2259 unsigned int i_max_ = (unsigned int)i_max;
2260 unsigned int j_min_ = (unsigned int)j_min;
2261 unsigned int j_max_ = (unsigned int)j_max;
2262
2263 if (XImageByteOrder(display) == 1) {
2264 // big endian
2265 for (unsigned int i = i_min_; i < i_max_; i++) {
2266 unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * m_width + j_min_ * 4);
2267 for (unsigned int j = j_min_; j < j_max_; j++) {
2268 vpRGBa val = I[i * m_scale][j * m_scale];
2269 *(dst_32++) = val.A;
2270 *(dst_32++) = val.R;
2271 *(dst_32++) = val.G;
2272 *(dst_32++) = val.B;
2273 }
2274 }
2275 } else {
2276 // little endian
2277 for (unsigned int i = i_min_; i < i_max_; i++) {
2278 unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * m_width + j_min_ * 4);
2279 for (unsigned int j = j_min_; j < j_max_; j++) {
2280 vpRGBa val = I[i * m_scale][j * m_scale];
2281 *(dst_32++) = val.B;
2282 *(dst_32++) = val.G;
2283 *(dst_32++) = val.R;
2284 *(dst_32++) = val.A;
2285 }
2286 }
2287 }
2288 XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
2289 }
2290
2291 XSetWindowBackgroundPixmap(display, window, pixmap);
2292 break;
2293 }
2294 default:
2295 throw(vpDisplayException(vpDisplayException::depthNotSupportedError,
2296 "Unsupported depth (%d bpp) for color display", screen_depth));
2297 }
2298 } else {
2299 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2300 }
2301 }
2302
2303 /*!
2304
2305 Close the window.
2306
2307 \sa init()
2308
2309 */
closeDisplay()2310 void vpDisplayX::closeDisplay()
2311 {
2312 if (m_displayHasBeenInitialized) {
2313 if (ximage_data_init == true)
2314 free(Ximage->data);
2315
2316 Ximage->data = NULL;
2317 XDestroyImage(Ximage);
2318
2319 XFreePixmap(display, pixmap);
2320
2321 XFreeGC(display, context);
2322 XDestroyWindow(display, window);
2323 XCloseDisplay(display);
2324
2325 m_displayHasBeenInitialized = false;
2326
2327 if (x_color != NULL) {
2328 delete[] x_color;
2329 x_color = NULL;
2330 }
2331 }
2332 }
2333
2334 /*!
2335 Flushes the X buffer.
2336 It's necessary to use this function to see the results of any drawing.
2337
2338 */
flushDisplay()2339 void vpDisplayX::flushDisplay()
2340 {
2341 if (m_displayHasBeenInitialized) {
2342 XClearWindow(display, window);
2343 XFlush(display);
2344 } else {
2345 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2346 }
2347 }
2348
2349 /*!
2350 Flushes a part of the X buffer.
2351 It's necessary to use this function to see the results of any drawing.
2352
2353 \param iP : Top left corner of the region of interest
2354 \param w,h : Width and height of the region of interest
2355 */
flushDisplayROI(const vpImagePoint & iP,unsigned int w,unsigned int h)2356 void vpDisplayX::flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h)
2357 {
2358 if (m_displayHasBeenInitialized) {
2359 XClearArea(display, window, (int)(iP.get_u() / m_scale), (int)(iP.get_v() / m_scale), w / m_scale, h / m_scale, 0);
2360 XFlush(display);
2361 } else {
2362 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2363 }
2364 }
2365
2366 /*!
2367 Set the window backgroud to \e color.
2368 \param color : Background color.
2369 */
clearDisplay(const vpColor & color)2370 void vpDisplayX::clearDisplay(const vpColor &color)
2371 {
2372 if (m_displayHasBeenInitialized) {
2373
2374 if (color.id < vpColor::id_unknown)
2375 XSetWindowBackground(display, window, x_color[color.id]);
2376 else {
2377 xcolor.pad = 0;
2378 xcolor.red = 256 * color.R;
2379 xcolor.green = 256 * color.G;
2380 xcolor.blue = 256 * color.B;
2381 XAllocColor(display, lut, &xcolor);
2382 XSetForeground(display, context, xcolor.pixel);
2383 }
2384
2385 XClearWindow(display, window);
2386
2387 XFreePixmap(display, pixmap);
2388 // Pixmap creation.
2389 pixmap = XCreatePixmap(display, window, m_width, m_height, screen_depth);
2390 } else {
2391 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2392 }
2393 }
2394
2395 /*!
2396 Display an arrow from image point \e ip1 to image point \e ip2.
2397 \param ip1,ip2 : Initial and final image point.
2398 \param color : Arrow color.
2399 \param w,h : Width and height of the arrow.
2400 \param thickness : Thickness of the lines used to display the arrow.
2401 */
displayArrow(const vpImagePoint & ip1,const vpImagePoint & ip2,const vpColor & color,unsigned int w,unsigned int h,unsigned int thickness)2402 void vpDisplayX::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
2403 unsigned int h, unsigned int thickness)
2404 {
2405 if (m_displayHasBeenInitialized) {
2406 double a = ip2.get_i() - ip1.get_i();
2407 double b = ip2.get_j() - ip1.get_j();
2408 double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
2409
2410 // if ( ( a==0 ) && ( b==0 ) )
2411 if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
2412 (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
2413 // DisplayCrossLarge(i1,j1,3,col) ;
2414 } else {
2415 a /= lg;
2416 b /= lg;
2417
2418 vpImagePoint ip3;
2419 ip3.set_i(ip2.get_i() - w * a);
2420 ip3.set_j(ip2.get_j() - w * b);
2421
2422 vpImagePoint ip4;
2423 ip4.set_i(ip3.get_i() - b * h);
2424 ip4.set_j(ip3.get_j() + a * h);
2425
2426 if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2427 displayLine(ip2, ip4, color, thickness);
2428
2429 ip4.set_i(ip3.get_i() + b * h);
2430 ip4.set_j(ip3.get_j() - a * h);
2431
2432 if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2433 displayLine(ip2, ip4, color, thickness);
2434
2435 displayLine(ip1, ip2, color, thickness);
2436 }
2437 } else {
2438 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2439 }
2440 }
2441
2442 /*!
2443 Display a string at the image point \e ip location.
2444
2445 To select the font used to display the string, use setFont().
2446
2447 \param ip : Upper left image point location of the string in the display.
2448 \param text : String to display in overlay.
2449 \param color : String color.
2450
2451 \sa setFont()
2452 */
displayCharString(const vpImagePoint & ip,const char * text,const vpColor & color)2453 void vpDisplayX::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
2454 {
2455 if (m_displayHasBeenInitialized) {
2456 if (color.id < vpColor::id_unknown)
2457 XSetForeground(display, context, x_color[color.id]);
2458 else {
2459 xcolor.pad = 0;
2460 xcolor.red = 256 * color.R;
2461 xcolor.green = 256 * color.G;
2462 xcolor.blue = 256 * color.B;
2463 XAllocColor(display, lut, &xcolor);
2464 XSetForeground(display, context, xcolor.pixel);
2465 }
2466 XDrawString(display, pixmap, context, (int)(ip.get_u() / m_scale), (int)(ip.get_v() / m_scale), text,
2467 (int)strlen(text));
2468 } else {
2469 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2470 }
2471 }
2472
2473 /*!
2474 Display a circle.
2475 \param center : Circle center position.
2476 \param radius : Circle radius.
2477 \param color : Circle color.
2478 \param fill : When set to true fill the circle.
2479 \param thickness : Thickness of the circle. This parameter is only useful
2480 when \e fill is set to false.
2481 */
displayCircle(const vpImagePoint & center,unsigned int radius,const vpColor & color,bool fill,unsigned int thickness)2482 void vpDisplayX::displayCircle(const vpImagePoint ¢er, unsigned int radius, const vpColor &color, bool fill,
2483 unsigned int thickness)
2484 {
2485 if (m_displayHasBeenInitialized) {
2486 if (thickness == 1)
2487 thickness = 0;
2488 if (color.id < vpColor::id_unknown)
2489 XSetForeground(display, context, x_color[color.id]);
2490 else {
2491 xcolor.pad = 0;
2492 xcolor.red = 256 * color.R;
2493 xcolor.green = 256 * color.G;
2494 xcolor.blue = 256 * color.B;
2495 XAllocColor(display, lut, &xcolor);
2496 XSetForeground(display, context, xcolor.pixel);
2497 }
2498
2499 XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
2500
2501 if (fill == false) {
2502 XDrawArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / m_scale),
2503 vpMath::round((center.get_v() - radius) / m_scale), radius * 2 / m_scale, radius * 2 / m_scale, 0,
2504 23040); /* 23040 = 360*64 */
2505 } else {
2506 XFillArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / m_scale),
2507 vpMath::round((center.get_v() - radius) / m_scale), radius * 2 / m_scale, radius * 2 / m_scale, 0,
2508 23040); /* 23040 = 360*64 */
2509 }
2510 } else {
2511 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2512 }
2513 }
2514
2515 /*!
2516 Display a cross at the image point \e ip location.
2517 \param ip : Cross location.
2518 \param cross_size : Size (width and height) of the cross.
2519 \param color : Cross color.
2520 \param thickness : Thickness of the lines used to display the cross.
2521 */
displayCross(const vpImagePoint & ip,unsigned int cross_size,const vpColor & color,unsigned int thickness)2522 void vpDisplayX::displayCross(const vpImagePoint &ip, unsigned int cross_size, const vpColor &color,
2523 unsigned int thickness)
2524 {
2525 if (m_displayHasBeenInitialized) {
2526 double i = ip.get_i();
2527 double j = ip.get_j();
2528 vpImagePoint ip1, ip2;
2529
2530 ip1.set_i(i - cross_size / 2);
2531 ip1.set_j(j);
2532 ip2.set_i(i + cross_size / 2);
2533 ip2.set_j(j);
2534 displayLine(ip1, ip2, color, thickness);
2535
2536 ip1.set_i(i);
2537 ip1.set_j(j - cross_size / 2);
2538 ip2.set_i(i);
2539 ip2.set_j(j + cross_size / 2);
2540
2541 displayLine(ip1, ip2, color, thickness);
2542 } else {
2543 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2544 }
2545 }
2546 /*!
2547 Display a dashed line from image point \e ip1 to image point \e ip2.
2548 \param ip1,ip2 : Initial and final image points.
2549 \param color : Line color.
2550 \param thickness : Line thickness.
2551 */
displayDotLine(const vpImagePoint & ip1,const vpImagePoint & ip2,const vpColor & color,unsigned int thickness)2552 void vpDisplayX::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2553 unsigned int thickness)
2554 {
2555 if (m_displayHasBeenInitialized) {
2556 if (thickness == 1)
2557 thickness = 0;
2558
2559 if (color.id < vpColor::id_unknown)
2560 XSetForeground(display, context, x_color[color.id]);
2561 else {
2562 xcolor.pad = 0;
2563 xcolor.red = 256 * color.R;
2564 xcolor.green = 256 * color.G;
2565 xcolor.blue = 256 * color.B;
2566 XAllocColor(display, lut, &xcolor);
2567 XSetForeground(display, context, xcolor.pixel);
2568 }
2569
2570 XSetLineAttributes(display, context, thickness, LineOnOffDash, CapButt, JoinBevel);
2571
2572 XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale),
2573 vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale));
2574 } else {
2575 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2576 }
2577 }
2578
2579 /*!
2580 Display a line from image point \e ip1 to image point \e ip2.
2581 \param ip1,ip2 : Initial and final image points.
2582 \param color : Line color.
2583 \param thickness : Line thickness.
2584 */
displayLine(const vpImagePoint & ip1,const vpImagePoint & ip2,const vpColor & color,unsigned int thickness)2585 void vpDisplayX::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2586 unsigned int thickness)
2587 {
2588 if (m_displayHasBeenInitialized) {
2589 if (thickness == 1)
2590 thickness = 0;
2591
2592 if (color.id < vpColor::id_unknown)
2593 XSetForeground(display, context, x_color[color.id]);
2594 else {
2595 xcolor.pad = 0;
2596 xcolor.red = 256 * color.R;
2597 xcolor.green = 256 * color.G;
2598 xcolor.blue = 256 * color.B;
2599 XAllocColor(display, lut, &xcolor);
2600 XSetForeground(display, context, xcolor.pixel);
2601 }
2602
2603 XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
2604
2605 XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale),
2606 vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale));
2607 } else {
2608 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2609 }
2610 }
2611
2612 /*!
2613 Display a point at the image point \e ip location.
2614 \param ip : Point location.
2615 \param color : Point color.
2616 \param thickness : Point thickness.
2617 */
displayPoint(const vpImagePoint & ip,const vpColor & color,unsigned int thickness)2618 void vpDisplayX::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
2619 {
2620 if (m_displayHasBeenInitialized) {
2621 if (color.id < vpColor::id_unknown)
2622 XSetForeground(display, context, x_color[color.id]);
2623 else {
2624 xcolor.pad = 0;
2625 xcolor.red = 256 * color.R;
2626 xcolor.green = 256 * color.G;
2627 xcolor.blue = 256 * color.B;
2628 XAllocColor(display, lut, &xcolor);
2629 XSetForeground(display, context, xcolor.pixel);
2630 }
2631
2632 if (thickness == 1) {
2633 XDrawPoint(display, pixmap, context, vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale));
2634 } else {
2635 XFillRectangle(display, pixmap, context, vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale),
2636 thickness, thickness);
2637 }
2638
2639 } else {
2640 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2641 }
2642 }
2643
2644 /*!
2645 Display a rectangle with \e topLeft as the top-left corner and \e
2646 width and \e height the rectangle size.
2647
2648 \param topLeft : Top-left corner of the rectangle.
2649 \param w,h : Rectangle size in terms of width and height.
2650 \param color : Rectangle color.
2651 \param fill : When set to true fill the rectangle.
2652
2653 \param thickness : Thickness of the four lines used to display the
2654 rectangle. This parameter is only useful when \e fill is set to
2655 false.
2656 */
displayRectangle(const vpImagePoint & topLeft,unsigned int w,unsigned int h,const vpColor & color,bool fill,unsigned int thickness)2657 void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
2658 bool fill, unsigned int thickness)
2659 {
2660 if (m_displayHasBeenInitialized) {
2661 if (thickness == 1)
2662 thickness = 0;
2663 if (color.id < vpColor::id_unknown)
2664 XSetForeground(display, context, x_color[color.id]);
2665 else {
2666 xcolor.pad = 0;
2667 xcolor.red = 256 * color.R;
2668 xcolor.green = 256 * color.G;
2669 xcolor.blue = 256 * color.B;
2670 XAllocColor(display, lut, &xcolor);
2671 XSetForeground(display, context, xcolor.pixel);
2672 }
2673 XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
2674 if (fill == false) {
2675 XDrawRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / m_scale),
2676 vpMath::round(topLeft.get_v() / m_scale), w / m_scale, h / m_scale);
2677 } else {
2678 XFillRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / m_scale),
2679 vpMath::round(topLeft.get_v() / m_scale), w / m_scale, h / m_scale);
2680 }
2681 } else {
2682 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2683 }
2684 }
2685
2686 /*!
2687 Display a rectangle.
2688
2689 \param topLeft : Top-left corner of the rectangle.
2690 \param bottomRight : Bottom-right corner of the rectangle.
2691 \param color : Rectangle color.
2692 \param fill : When set to true fill the rectangle.
2693
2694 \param thickness : Thickness of the four lines used to display the
2695 rectangle. This parameter is only useful when \e fill is set to
2696 false.
2697 */
displayRectangle(const vpImagePoint & topLeft,const vpImagePoint & bottomRight,const vpColor & color,bool fill,unsigned int thickness)2698 void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
2699 bool fill, unsigned int thickness)
2700 {
2701 if (m_displayHasBeenInitialized) {
2702 if (thickness == 1)
2703 thickness = 0;
2704 if (color.id < vpColor::id_unknown)
2705 XSetForeground(display, context, x_color[color.id]);
2706 else {
2707 xcolor.pad = 0;
2708 xcolor.red = 256 * color.R;
2709 xcolor.green = 256 * color.G;
2710 xcolor.blue = 256 * color.B;
2711 XAllocColor(display, lut, &xcolor);
2712 XSetForeground(display, context, xcolor.pixel);
2713 }
2714
2715 XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
2716
2717 vpImagePoint topLeft_ = topLeft / m_scale;
2718 vpImagePoint bottomRight_ = bottomRight / m_scale;
2719 unsigned int w = (unsigned int)vpMath::round(std::fabs(bottomRight_.get_u() - topLeft_.get_u()));
2720 unsigned int h = (unsigned int)vpMath::round(std::fabs(bottomRight_.get_v() - topLeft_.get_v()));
2721 if (fill == false) {
2722
2723 XDrawRectangle(display, pixmap, context,
2724 vpMath::round(topLeft_.get_u() < bottomRight_.get_u() ? topLeft_.get_u() : bottomRight_.get_u()),
2725 vpMath::round(topLeft_.get_v() < bottomRight_.get_v() ? topLeft_.get_v() : bottomRight_.get_v()),
2726 w > 0 ? w : 1, h > 0 ? h : 1);
2727 } else {
2728 XFillRectangle(display, pixmap, context,
2729 vpMath::round(topLeft_.get_u() < bottomRight_.get_u() ? topLeft_.get_u() : bottomRight_.get_u()),
2730 vpMath::round(topLeft_.get_v() < bottomRight_.get_v() ? topLeft_.get_v() : bottomRight_.get_v()),
2731 w, h);
2732 }
2733 } else {
2734 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2735 }
2736 }
2737
2738 /*!
2739 Display a rectangle.
2740
2741 \param rectangle : Rectangle characteristics.
2742 \param color : Rectangle color.
2743 \param fill : When set to true fill the rectangle.
2744
2745 \param thickness : Thickness of the four lines used to display the
2746 rectangle. This parameter is only useful when \e fill is set to
2747 false.
2748
2749 */
displayRectangle(const vpRect & rectangle,const vpColor & color,bool fill,unsigned int thickness)2750 void vpDisplayX::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
2751 {
2752 if (m_displayHasBeenInitialized) {
2753 if (thickness == 1)
2754 thickness = 0;
2755 if (color.id < vpColor::id_unknown)
2756 XSetForeground(display, context, x_color[color.id]);
2757 else {
2758 xcolor.pad = 0;
2759 xcolor.red = 256 * color.R;
2760 xcolor.green = 256 * color.G;
2761 xcolor.blue = 256 * color.B;
2762 XAllocColor(display, lut, &xcolor);
2763 XSetForeground(display, context, xcolor.pixel);
2764 }
2765
2766 XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
2767
2768 if (fill == false) {
2769 XDrawRectangle(display, pixmap, context, vpMath::round(rectangle.getLeft() / m_scale),
2770 vpMath::round(rectangle.getTop() / m_scale),
2771 (unsigned int)vpMath::round(rectangle.getWidth() / m_scale - 1),
2772 (unsigned int)vpMath::round(rectangle.getHeight() / m_scale - 1));
2773 } else {
2774 XFillRectangle(display, pixmap, context, vpMath::round(rectangle.getLeft() / m_scale),
2775 vpMath::round(rectangle.getTop() / m_scale),
2776 (unsigned int)vpMath::round(rectangle.getWidth() / m_scale),
2777 (unsigned int)vpMath::round(rectangle.getHeight() / m_scale));
2778 }
2779
2780 } else {
2781 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2782 }
2783 }
2784
2785 /*!
2786
2787 Wait for a click from one of the mouse button.
2788
2789 \param blocking [in] : Blocking behavior.
2790 - When set to true, this method waits until a mouse button is
2791 pressed and then returns always true.
2792 - When set to false, returns true only if a mouse button is
2793 pressed, otherwise returns false.
2794
2795 \return
2796 - true if a button was clicked. This is always the case if blocking is set
2797 to \e true.
2798 - false if no button was clicked. This can occur if blocking is set
2799 to \e false.
2800 */
getClick(bool blocking)2801 bool vpDisplayX::getClick(bool blocking)
2802 {
2803
2804 bool ret = false;
2805
2806 if (m_displayHasBeenInitialized) {
2807 Window rootwin, childwin;
2808 int root_x, root_y, win_x, win_y;
2809 unsigned int modifier;
2810
2811 // Event testing
2812 if (blocking) {
2813 XCheckMaskEvent(display, ButtonPressMask, &event);
2814 XCheckMaskEvent(display, ButtonReleaseMask, &event);
2815 XMaskEvent(display, ButtonPressMask, &event);
2816 ret = true;
2817 } else {
2818 ret = XCheckMaskEvent(display, ButtonPressMask, &event);
2819 }
2820
2821 if (ret) {
2822 /* Recuperation de la coordonnee du pixel clique. */
2823 if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
2824 }
2825 }
2826 } else {
2827 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2828 }
2829 return ret;
2830 }
2831
2832 /*!
2833
2834 Wait for a click from one of the mouse button and get the position
2835 of the clicked image point.
2836
2837 \param ip [out] : The coordinates of the clicked image point.
2838
2839 \param blocking [in] : true for a blocking behaviour waiting a mouse
2840 button click, false for a non blocking behaviour.
2841
2842 \return
2843 - true if a button was clicked. This is always the case if blocking is set
2844 to \e true.
2845 - false if no button was clicked. This can occur if blocking is set
2846 to \e false.
2847 */
getClick(vpImagePoint & ip,bool blocking)2848 bool vpDisplayX::getClick(vpImagePoint &ip, bool blocking)
2849 {
2850
2851 bool ret = false;
2852 if (m_displayHasBeenInitialized) {
2853
2854 Window rootwin, childwin;
2855 int root_x, root_y, win_x, win_y;
2856 unsigned int modifier;
2857 // Event testing
2858 if (blocking) {
2859 XCheckMaskEvent(display, ButtonPressMask, &event);
2860 XCheckMaskEvent(display, ButtonReleaseMask, &event);
2861 XMaskEvent(display, ButtonPressMask, &event);
2862 ret = true;
2863 } else {
2864 ret = XCheckMaskEvent(display, ButtonPressMask, &event);
2865 }
2866
2867 if (ret) {
2868 // Get mouse position
2869 if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
2870 ip.set_u((double)event.xbutton.x * m_scale);
2871 ip.set_v((double)event.xbutton.y * m_scale);
2872 }
2873 }
2874 } else {
2875 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2876 }
2877 return ret;
2878 }
2879
2880 /*!
2881
2882 Wait for a mouse button click and get the position of the clicked
2883 pixel. The button used to click is also set.
2884
2885 \param ip [out] : The coordinates of the clicked image point.
2886
2887 \param button [out] : The button used to click.
2888
2889 \param blocking [in] :
2890 - When set to true, this method waits until a mouse button is
2891 pressed and then returns always true.
2892 - When set to false, returns true only if a mouse button is
2893 pressed, otherwise returns false.
2894
2895 \return true if a mouse button is pressed, false otherwise. If a
2896 button is pressed, the location of the mouse pointer is updated in
2897 \e ip.
2898 */
getClick(vpImagePoint & ip,vpMouseButton::vpMouseButtonType & button,bool blocking)2899 bool vpDisplayX::getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking)
2900 {
2901
2902 bool ret = false;
2903 if (m_displayHasBeenInitialized) {
2904
2905 Window rootwin, childwin;
2906 int root_x, root_y, win_x, win_y;
2907 unsigned int modifier;
2908
2909 // Event testing
2910 if (blocking) {
2911 XCheckMaskEvent(display, ButtonPressMask, &event);
2912 XCheckMaskEvent(display, ButtonReleaseMask, &event);
2913 XMaskEvent(display, ButtonPressMask, &event);
2914 ret = true;
2915 } else {
2916 ret = XCheckMaskEvent(display, ButtonPressMask, &event);
2917 }
2918
2919 if (ret) {
2920 // Get mouse position
2921 if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
2922 ip.set_u((double)event.xbutton.x * m_scale);
2923 ip.set_v((double)event.xbutton.y * m_scale);
2924 switch (event.xbutton.button) {
2925 case Button1:
2926 button = vpMouseButton::button1;
2927 break;
2928 case Button2:
2929 button = vpMouseButton::button2;
2930 break;
2931 case Button3:
2932 button = vpMouseButton::button3;
2933 break;
2934 }
2935 }
2936 }
2937 } else {
2938 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2939 }
2940 return ret;
2941 }
2942
2943 /*!
2944
2945 Wait for a mouse button click release and get the position of the
2946 image point were the click release occurs. The button used to click is
2947 also set. Same method as getClick(unsigned int&, unsigned int&,
2948 vpMouseButton::vpMouseButtonType &, bool).
2949
2950 \param ip [out] : Position of the clicked image point.
2951
2952 \param button [in] : Button used to click.
2953
2954 \param blocking [in] : true for a blocking behaviour waiting a mouse
2955 button click, false for a non blocking behaviour.
2956
2957 \return
2958 - true if a button was clicked. This is always the case if blocking is set
2959 to \e true.
2960 - false if no button was clicked. This can occur if blocking is set
2961 to \e false.
2962
2963 \sa getClick(vpImagePoint &, vpMouseButton::vpMouseButtonType &, bool)
2964
2965 */
getClickUp(vpImagePoint & ip,vpMouseButton::vpMouseButtonType & button,bool blocking)2966 bool vpDisplayX::getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking)
2967 {
2968
2969 bool ret = false;
2970 if (m_displayHasBeenInitialized) {
2971 Window rootwin, childwin;
2972 int root_x, root_y, win_x, win_y;
2973 unsigned int modifier;
2974
2975 // Event testing
2976 if (blocking) {
2977 XCheckMaskEvent(display, ButtonPressMask, &event);
2978 XCheckMaskEvent(display, ButtonReleaseMask, &event);
2979 XMaskEvent(display, ButtonReleaseMask, &event);
2980 ret = true;
2981 } else {
2982 ret = XCheckMaskEvent(display, ButtonReleaseMask, &event);
2983 }
2984
2985 if (ret) {
2986 /* Recuperation de la coordonnee du pixel clique. */
2987 if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
2988 ip.set_u((double)event.xbutton.x * m_scale);
2989 ip.set_v((double)event.xbutton.y * m_scale);
2990 switch (event.xbutton.button) {
2991 case Button1:
2992 button = vpMouseButton::button1;
2993 break;
2994 case Button2:
2995 button = vpMouseButton::button2;
2996 break;
2997 case Button3:
2998 button = vpMouseButton::button3;
2999 break;
3000 }
3001 }
3002 }
3003 } else {
3004 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3005 }
3006 return ret;
3007 }
3008
3009 /*
3010 Gets the displayed image (including the overlay plane)
3011 and returns an RGBa image. If a scale factor is set using setScale(), the
3012 size of the image is the size of the downscaled image.
3013
3014 \param I : Image to get.
3015 */
getImage(vpImage<vpRGBa> & I)3016 void vpDisplayX::getImage(vpImage<vpRGBa> &I)
3017 {
3018 if (m_displayHasBeenInitialized) {
3019 XImage *xi;
3020
3021 XCopyArea(display, window, pixmap, context, 0, 0, m_width, m_height, 0, 0);
3022
3023 xi = XGetImage(display, pixmap, 0, 0, m_width, m_height, AllPlanes, ZPixmap);
3024
3025 I.resize(m_height, m_width);
3026
3027 unsigned char *src_32 = NULL;
3028 src_32 = (unsigned char *)xi->data;
3029
3030 if (screen_depth == 16) {
3031 for (unsigned int i = 0; i < I.getHeight(); i++) {
3032 size_t i_ = i * m_width;
3033 for (unsigned int j = 0; j < m_height; j++) {
3034 size_t ij_ = i_ + j;
3035 unsigned long pixel = XGetPixel(xi, (int)j, (int)i);
3036 I.bitmap[ij_].R = (((pixel & RMask) << RShift) >> 8);
3037 I.bitmap[ij_].G = (((pixel & GMask) << GShift) >> 8);
3038 I.bitmap[ij_].B = (((pixel & BMask) << BShift) >> 8);
3039 // On OSX the bottom/right corner (arround the resizing icon) has
3040 // alpha component with different values than 255. That's why we
3041 // force alpha to vpRGBa::alpha_default
3042 I.bitmap[ij_].A = vpRGBa::alpha_default;
3043 }
3044 }
3045
3046 } else {
3047 if (XImageByteOrder(display) == 1) {
3048 // big endian
3049 for (unsigned int i = 0; i < m_width * m_height; i++) {
3050 // On OSX the bottom/right corner (arround the resizing icon) has
3051 // alpha component with different values than 255. That's why we
3052 // force alpha to vpRGBa::alpha_default
3053 I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4] ;
3054 I.bitmap[i].R = src_32[i * 4 + 1];
3055 I.bitmap[i].G = src_32[i * 4 + 2];
3056 I.bitmap[i].B = src_32[i * 4 + 3];
3057 }
3058 } else {
3059 // little endian
3060 for (unsigned int i = 0; i < m_width * m_height; i++) {
3061 I.bitmap[i].B = src_32[i * 4];
3062 I.bitmap[i].G = src_32[i * 4 + 1];
3063 I.bitmap[i].R = src_32[i * 4 + 2];
3064 // On OSX the bottom/right corner (arround the resizing icon) has
3065 // alpha component with different values than 255. That's why we
3066 // force alpha to vpRGBa::alpha_default
3067 I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4 + 3];
3068 }
3069 }
3070 }
3071 XDestroyImage(xi);
3072 } else {
3073 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3074 }
3075 }
3076
3077 /*!
3078 Gets the window depth (8, 16, 24, 32).
3079 */
getScreenDepth()3080 unsigned int vpDisplayX::getScreenDepth()
3081 {
3082 Display *display_;
3083 int screen_;
3084 unsigned int depth;
3085
3086 if ((display_ = XOpenDisplay(NULL)) == NULL) {
3087 throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
3088 XDisplayName(NULL)));
3089 }
3090 screen_ = DefaultScreen(display_);
3091 depth = (unsigned int)DefaultDepth(display_, screen_);
3092
3093 XCloseDisplay(display_);
3094
3095 return (depth);
3096 }
3097
3098 /*!
3099 Gets screen resolution in pixels.
3100 \param w, h : Horizontal and vertical screen resolution.
3101 */
getScreenSize(unsigned int & w,unsigned int & h)3102 void vpDisplayX::getScreenSize(unsigned int &w, unsigned int &h)
3103 {
3104 Display *display_;
3105 int screen_;
3106
3107 if ((display_ = XOpenDisplay(NULL)) == NULL) {
3108 throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
3109 XDisplayName(NULL)));
3110 }
3111 screen_ = DefaultScreen(display_);
3112 w = (unsigned int)DisplayWidth(display_, screen_);
3113 h = (unsigned int)DisplayHeight(display_, screen_);
3114
3115 XCloseDisplay(display_);
3116 }
3117
3118 /*!
3119 Gets the screen horizontal resolution in pixels.
3120 */
getScreenWidth()3121 unsigned int vpDisplayX::getScreenWidth()
3122 {
3123 unsigned int width, height;
3124 getScreenSize(width, height);
3125 return width;
3126 }
3127
3128 /*!
3129 Gets the screen vertical resolution in pixels.
3130 */
getScreenHeight()3131 unsigned int vpDisplayX::getScreenHeight()
3132 {
3133 unsigned int width, height;
3134 getScreenSize(width, height);
3135 return height;
3136 }
3137
3138 /*!
3139
3140 Get a keyboard event.
3141
3142 \param blocking [in] : Blocking behavior.
3143 - When set to true, this method waits until a key is
3144 pressed and then returns always true.
3145 - When set to false, returns true only if a key is
3146 pressed, otherwise returns false.
3147
3148 \return
3149 - true if a key was pressed. This is always the case if blocking is set
3150 to \e true.
3151 - false if no key was pressed. This can occur if blocking is set
3152 to \e false.
3153
3154 \exception vpDisplayException::notInitializedError : If the display
3155 was not initialized.
3156
3157 */
getKeyboardEvent(bool blocking)3158 bool vpDisplayX::getKeyboardEvent(bool blocking)
3159 {
3160
3161 bool ret = false;
3162
3163 if (m_displayHasBeenInitialized) {
3164 // Event testing
3165 if (blocking) {
3166 XMaskEvent(display, KeyPressMask, &event);
3167 ret = true;
3168 } else {
3169 ret = XCheckMaskEvent(display, KeyPressMask, &event);
3170 }
3171 } else {
3172 vpERROR_TRACE("X not initialized ");
3173 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3174 }
3175 return ret;
3176 }
3177 /*!
3178
3179 Get a keyboard event.
3180
3181 \param blocking [in] : Blocking behavior.
3182 - When set to true, this method waits until a key is
3183 pressed and then returns always true.
3184 - When set to false, returns true only if a key is
3185 pressed, otherwise returns false.
3186
3187 \param key [out]: If possible, an ISO Latin-1 character
3188 corresponding to the keyboard key.
3189
3190 \return
3191 - true if a key was pressed. This is always the case if blocking is set
3192 to \e true.
3193 - false if no key was pressed. This can occur if blocking is set
3194 to \e false.
3195
3196 \exception vpDisplayException::notInitializedError : If the display
3197 was not initialized.
3198
3199 */
getKeyboardEvent(std::string & key,bool blocking)3200 bool vpDisplayX::getKeyboardEvent(std::string &key, bool blocking)
3201 {
3202 bool ret = false;
3203 KeySym keysym;
3204 // int count;
3205 XComposeStatus compose_status;
3206 char buffer;
3207
3208 if (m_displayHasBeenInitialized) {
3209 // Event testing
3210 if (blocking) {
3211 XMaskEvent(display, KeyPressMask, &event);
3212 /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
3213 key = buffer;
3214 ret = true;
3215 } else {
3216 ret = XCheckMaskEvent(display, KeyPressMask, &event);
3217 if (ret) {
3218 /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
3219 key = buffer;
3220 }
3221 }
3222 } else {
3223 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3224 }
3225 return ret;
3226 }
3227 /*!
3228
3229 Get the coordinates of the mouse pointer.
3230
3231 \param ip [out] : The coordinates of the mouse pointer.
3232
3233 \return true if a pointer motion event was received, false otherwise.
3234
3235 \exception vpDisplayException::notInitializedError : If the display
3236 was not initialized.
3237
3238 */
getPointerMotionEvent(vpImagePoint & ip)3239 bool vpDisplayX::getPointerMotionEvent(vpImagePoint &ip)
3240 {
3241
3242 bool ret = false;
3243 if (m_displayHasBeenInitialized) {
3244
3245 Window rootwin, childwin;
3246 int root_x, root_y, win_x, win_y;
3247 unsigned int modifier;
3248 // Event testing
3249 ret = XCheckMaskEvent(display, PointerMotionMask, &event);
3250
3251 if (ret) {
3252 // Get mouse position
3253 if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
3254 ip.set_u((double)event.xbutton.x * m_scale);
3255 ip.set_v((double)event.xbutton.y * m_scale);
3256 }
3257 }
3258 } else {
3259 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3260 }
3261 return ret;
3262 }
3263
3264 /*!
3265 Get the coordinates of the mouse pointer.
3266
3267 \param ip [out] : The coordinates of the mouse pointer.
3268
3269 \return true.
3270
3271 \exception vpDisplayException::notInitializedError : If the display
3272 was not initialized.
3273 */
getPointerPosition(vpImagePoint & ip)3274 bool vpDisplayX::getPointerPosition(vpImagePoint &ip)
3275 {
3276
3277 bool ret = false;
3278 if (m_displayHasBeenInitialized) {
3279
3280 Window rootwin, childwin;
3281 int root_x, root_y, win_x, win_y;
3282 unsigned int modifier;
3283 // Event testing
3284 ret = true;
3285
3286 if (ret) {
3287 // Get mouse position
3288 if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
3289 ip.set_u((double)win_x * m_scale);
3290 ip.set_v((double)win_y * m_scale);
3291 }
3292 }
3293 } else {
3294 throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3295 }
3296 return ret;
3297 }
3298
3299 /*!
3300 Get the position of the most significant bit.
3301 */
getMsb(unsigned int u32val)3302 int vpDisplayX::getMsb(unsigned int u32val)
3303 {
3304 int i;
3305
3306 for (i = 31; i >= 0; --i) {
3307 if (u32val & 0x80000000L)
3308 break;
3309 u32val <<= 1;
3310 }
3311 return i;
3312 }
3313
3314 #elif !defined(VISP_BUILD_SHARED_LIBS)
3315 // Work arround to avoid warning: libvisp_core.a(vpDisplayX.cpp.o) has no
3316 // symbols
dummy_vpDisplayX()3317 void dummy_vpDisplayX(){};
3318 #endif
3319