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