ViSP  3.0.0
displayXMulti.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Read an image on the disk and display it using X11.
32  *
33  * Authors:
34  * Eric Marchand
35  * Fabien Spindler
36  *
37  *****************************************************************************/
47 #include <visp3/core/vpDebug.h>
48 #include <visp3/core/vpConfig.h>
49 
50 #ifdef VISP_HAVE_X11
51 
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <visp3/core/vpImage.h>
56 #include <visp3/io/vpImageIo.h>
57 #include <visp3/gui/vpDisplayX.h>
58 
59 #include <visp3/io/vpParseArgv.h>
60 #include <visp3/core/vpIoTools.h>
61 
72 // List of allowed command line options
73 #define GETOPTARGS "cdi:o:h"
74 
75 void usage(const char *name, const char *badparam, std::string ipath, std::string opath, std::string user);
76 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &opath, bool &click_allowed,
77  std::string user, bool &display);
78 
90 void usage(const char *name, const char *badparam, std::string ipath, std::string opath, std::string user)
91 {
92  fprintf(stdout, "\n\
93 Read an image on the disk, display it using X11, display some\n\
94 features (line, circle, caracters) in overlay and finaly write \n\
95 the image and the overlayed features in an image on the disk.\n\
96 \n\
97 SYNOPSIS\n\
98  %s [-i <input image path>] [-o <output image path>]\n\
99  [-c] [-d] [-h]\n \
100 ", name);
101 
102  fprintf(stdout, "\n\
103 OPTIONS: Default\n\
104  -i <input image path> %s\n\
105  Set image input path.\n\
106  From this path read \"ViSP-images/Klimt/Klimt.pgm\"\n\
107  and \"ViSP-images/Klimt/Klimt.ppm\" images.\n\
108  Setting the VISP_INPUT_IMAGE_PATH environment\n\
109  variable produces the same behaviour than using\n\
110  this option.\n\
111 \n\
112  -o <output image path> %s\n\
113  Set image output path.\n\
114  From this directory, creates the \"%s\"\n\
115  subdirectory depending on the username, where \n\
116  Klimt_grey.overlay.ppm output image is written.\n\
117 \n\
118  -c\n\
119  Disable the mouse click. Useful to automate the \n\
120  execution of this program without humain intervention.\n\
121 \n\
122  -d \n\
123  Disable the image display. This can be useful \n\
124  for automatic tests using crontab under Unix or \n\
125  using the task manager under Windows.\n\
126 \n\
127  -h\n\
128  Print the help.\n\n",
129  ipath.c_str(), opath.c_str(), user.c_str());
130 
131  if (badparam) {
132  fprintf(stderr, "ERROR: \n" );
133  fprintf(stderr, "\nBad parameter [%s]\n", badparam);
134  }
135 }
136 
154 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &opath, bool &click_allowed,
155  std::string user, bool &display)
156 {
157  const char *optarg_;
158  int c;
159  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
160 
161  switch (c) {
162  case 'c': click_allowed = false; break;
163  case 'd': display = false; break;
164  case 'i': ipath = optarg_; break;
165  case 'o': opath = optarg_; break;
166  case 'h': usage(argv[0], NULL, ipath, opath, user); return false; break;
167 
168  default:
169  usage(argv[0], optarg_, ipath, opath, user); return false; break;
170  }
171  }
172 
173  if ((c == 1) || (c == -1)) {
174  // standalone param or error
175  usage(argv[0], NULL, ipath, opath, user);
176  std::cerr << "ERROR: " << std::endl;
177  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
178  return false;
179  }
180 
181  return true;
182 }
183 
184 int
185 main(int argc, const char ** argv)
186 {
187  try {
188  std::string env_ipath;
189  std::string opt_ipath;
190  std::string opt_opath;
191  std::string ipath;
192  std::string opath;
193  std::string filename;
194  std::string username;
195  bool opt_click_allowed = true;
196  bool opt_display = true;
197 
198  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH environment variable value
199  env_ipath = vpIoTools::getViSPImagesDataPath();
200 
201  // Set the default input path
202  if (! env_ipath.empty())
203  ipath = env_ipath;
204 
205  // Set the default output path
206 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
207  opt_opath = "/tmp";
208 #elif defined(_WIN32)
209  opt_opath = "C:\\temp";
210 #endif
211 
212  // Get the user login name
213  vpIoTools::getUserName(username);
214 
215  // Read the command line options
216  if (getOptions(argc, argv, opt_ipath, opt_opath,
217  opt_click_allowed, username, opt_display) == false) {
218  exit (-1);
219  }
220 
221  // Get the option values
222  if (!opt_ipath.empty())
223  ipath = opt_ipath;
224  if (!opt_opath.empty())
225  opath = opt_opath;
226 
227  // Append to the output path string, the login name of the user
228  std::string odirname = vpIoTools::createFilePath(opath, username);
229 
230  // Test if the output path exist. If no try to create it
231  if (vpIoTools::checkDirectory(odirname) == false) {
232  try {
233  // Create the dirname
234  vpIoTools::makeDirectory(odirname);
235  }
236  catch (...) {
237  usage(argv[0], NULL, ipath, opath, username);
238  std::cerr << std::endl
239  << "ERROR:" << std::endl;
240  std::cerr << " Cannot create " << odirname << std::endl;
241  std::cerr << " Check your -o " << opath << " option " << std::endl;
242  exit(-1);
243  }
244  }
245 
246  // Compare ipath and env_ipath. If they differ, we take into account
247  // the input path comming from the command line option
248  if (!opt_ipath.empty() && !env_ipath.empty()) {
249  if (ipath != env_ipath) {
250  std::cout << std::endl
251  << "WARNING: " << std::endl;
252  std::cout << " Since -i <visp image path=" << ipath << "> "
253  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
254  << " we skip the environment variable." << std::endl;
255  }
256  }
257 
258  // Test if an input path is set
259  if (opt_ipath.empty() && env_ipath.empty()){
260  usage(argv[0], NULL, ipath, opath, username);
261  std::cerr << std::endl
262  << "ERROR:" << std::endl;
263  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH "
264  << std::endl
265  << " environment variable to specify the location of the " << std::endl
266  << " image path where test images are located." << std::endl << std::endl;
267  exit(-1);
268  }
269 
270  // Create two color images
271  vpImage<vpRGBa> I1, I2 ;
272  vpImagePoint ip, ip1, ip2;
273 
274  try {
275  // Load a grey image from the disk
276  filename = vpIoTools::createFilePath(ipath, "ViSP-images/Klimt/Klimt.pgm");
277  vpImageIo::read(I1, filename) ;
278  }
279  catch(...)
280  {
281  std::cerr << std::endl
282  << "ERROR:" << std::endl;
283  std::cerr << " Cannot read " << filename << std::endl;
284  std::cerr << " Check your -i " << ipath << " option " << std::endl
285  << " or VISP_INPUT_IMAGE_PATH environment variable."
286  << std::endl;
287  exit(-1);
288  }
289  try {
290  // Load a color image from the disk
291  filename = vpIoTools::createFilePath(ipath, "ViSP-images/Klimt/Klimt.ppm");
292  vpImageIo::read(I2, filename) ;
293  }
294  catch(...)
295  {
296  std::cerr << std::endl
297  << "ERROR:" << std::endl;
298  std::cerr << " Cannot read " << filename << std::endl;
299  std::cerr << " Check your -i " << ipath << " option " << std::endl
300  << " or VISP_INPUT_IMAGE_PATH environment variable."
301  << std::endl;
302  exit(-1);
303  }
304 
305  // For each image, open a X11 display
306  vpDisplayX display1;
307  vpDisplayX display2;
308 
309  if (opt_display) {
310  // Attach image 1 to display 1
311  display1.init(I1, 0, 0,"X11 Display 1...") ;
312  // Attach image 2 to display 2
313  display2.init(I2, 200, 200,"X11 Display 2...") ;
314  // Display the images
315  vpDisplay::display(I1) ;
316  vpDisplay::display(I2) ;
317 
318  // In the first display, display in overlay horizontal red lines
319  for (unsigned int i=0 ; i < I1.getHeight() ; i+=20) {
320  ip1.set_i( i );
321  ip1.set_j( 0 );
322  ip2.set_i( i );
323  ip2.set_j( I1.getWidth() );
324  vpDisplay::displayLine(I1, ip1, ip2, vpColor::red) ;
325  }
326 
327  // In the first display, display in overlay vertical green dot lines
328  for (unsigned int i=0 ; i < I1.getWidth() ; i+=20) {
329  ip1.set_i( 0 );
330  ip1.set_j( i );
331  ip2.set_i( I1.getWidth() );
332  ip2.set_j( i );
334  }
335 
336  // In the first display, display in overlay a blue arrow
337  ip1.set_i( 0 );
338  ip1.set_j( 0 );
339  ip2.set_i( 100 );
340  ip2.set_j( 100 );
341  vpDisplay::displayArrow(I1, ip1, ip2, vpColor::blue) ;
342 
343  // In the first display, display in overlay some circles. The
344  // position of the center is 200, 200 the radius is increased by 20
345  // pixels for each circle
346  for (unsigned int i=0 ; i < 100 ; i+=20) {
347  ip.set_i( 200 );
348  ip.set_j( 200 );
350  }
351 
352  // In the first display, display in overlay a yellow string
353  ip.set_i( 100 );
354  ip.set_j( 100 );
355  vpDisplay::displayText(I1, ip,
356  "ViSP is a marvelous software",
357  vpColor::blue) ;
358 
359  //Flush displays. The displays must be flushed to show the overlay.
360  //without this line, nothing will be displayed.
361  vpDisplay::flush(I1);
362  vpDisplay::flush(I2);
363 
364  // If click is allowed, wait for a blocking mouse click in the first
365  // display, to display a cross at the clicked pixel position
366  if (opt_click_allowed) {
367  std::cout << "\nA click in the first display to draw a cross..." << std::endl;
368  // Blocking wait for a click. Get the position of the selected pixel
369  // (i correspond to the row and j to the column coordinates in the image)
370  vpDisplay::getClick(I1, ip);
371  // Display a red cross on the click pixel position
372  std::cout << "Cross position: " << ip << std::endl;
374  vpDisplay::flush(I1);
375  }
376  else {
377  ip.set_i( 50 );
378  ip.set_j( 50 );
379  // Display a red cross at position ip in the first display
380  std::cout << "Cross position: " << ip<< std::endl;
382  vpDisplay::flush(I1);
383  }
384 
385  // Create a color image
386  vpImage<vpRGBa> Ioverlay ;
387  // Updates the color image with the original loaded image 1 and the overlay
388  vpDisplay::getImage(I1, Ioverlay) ;
389 
390  // Write the color image on the disk
391  filename = vpIoTools::createFilePath(odirname, "Klimt_grey.overlay.ppm");
392  vpImageIo::write(Ioverlay, filename) ;
393 
394  // If click is allowed, wait for a mouse click to close the display
395  if (opt_click_allowed) {
396  std::cout << "\nA click in the second display to close the windows and exit..." << std::endl;
397  // Wait for a blocking mouse click
398  vpDisplay::getClick(I2) ;
399  }
400  }
401  return 0;
402  }
403  catch(vpException e) {
404  std::cout << "Catch an exception: " << e << std::endl;
405  return 1;
406  }
407 }
408 #else
409 int
410 main()
411 {
412  vpERROR_TRACE("You do not have X11 functionalities to display images...");
413 }
414 
415 #endif
416 
virtual void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)=0
static void write(const vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:472
virtual void displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)=0
static bool checkDirectory(const char *dirname)
Definition: vpIoTools.cpp:335
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1091
unsigned int getWidth() const
Definition: vpImage.h:161
#define vpERROR_TRACE
Definition: vpDebug.h:391
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Definition: vpDisplay.cpp:888
Define the X11 console to display images.
Definition: vpDisplayX.h:148
error that can be emited by ViSP classes.
Definition: vpException.h:73
static const vpColor green
Definition: vpColor.h:166
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:2233
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:76
static const vpColor red
Definition: vpColor.h:163
static void makeDirectory(const char *dirname)
Definition: vpIoTools.cpp:404
void set_i(const double ii)
Definition: vpImagePoint.h:154
static std::string createFilePath(const std::string &parent, const std::string child)
Definition: vpIoTools.cpp:1265
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:206
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
static std::string getUserName()
Definition: vpIoTools.cpp:161
static void getImage(const vpImage< unsigned char > &Is, vpImage< vpRGBa > &Id)
Definition: vpDisplay.cpp:324
virtual void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)=0
void set_j(const double jj)
Definition: vpImagePoint.h:165
unsigned int getHeight() const
Definition: vpImage.h:152
virtual bool getClick(bool blocking=true)=0
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
virtual void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)=0
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
Definition: vpDisplayX.cpp:190
static void read(vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:274
static const vpColor yellow
Definition: vpColor.h:171
static const vpColor blue
Definition: vpColor.h:169