Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
displayXMulti.cpp
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  * Read an image on the disk and display it using X11.
33  *
34  * Authors:
35  * Eric Marchand
36  * Fabien Spindler
37  *
38  *****************************************************************************/
48 #include <visp3/core/vpConfig.h>
49 #include <visp3/core/vpDebug.h>
50 
51 #ifdef VISP_HAVE_X11
52 
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <visp3/core/vpImage.h>
57 #include <visp3/gui/vpDisplayX.h>
58 #include <visp3/io/vpImageIo.h>
59 
60 #include <visp3/core/vpIoTools.h>
61 #include <visp3/io/vpParseArgv.h>
62 
73 // List of allowed command line options
74 #define GETOPTARGS "cdi:o:h"
75 
87 void usage(const char *name, const char *badparam, std::string ipath, std::string opath, std::string user)
88 {
89  fprintf(stdout, "\n\
90 Read an image on the disk, display it using X11, display some\n\
91 features (line, circle, caracters) in overlay and finaly write \n\
92 the image and the overlayed features in an image on the disk.\n\
93 \n\
94 SYNOPSIS\n\
95  %s [-i <input image path>] [-o <output image path>]\n\
96  [-c] [-d] [-h]\n \
97 ", name);
98 
99  fprintf(stdout, "\n\
100 OPTIONS: Default\n\
101  -i <input image path> %s\n\
102  Set image input path.\n\
103  From this path read \"Klimt/Klimt.pgm\"\n\
104  and \"Klimt/Klimt.ppm\" images.\n\
105  Setting the VISP_INPUT_IMAGE_PATH environment\n\
106  variable produces the same behaviour than using\n\
107  this option.\n\
108 \n\
109  -o <output image path> %s\n\
110  Set image output path.\n\
111  From this directory, creates the \"%s\"\n\
112  subdirectory depending on the username, where \n\
113  Klimt_grey.overlay.ppm output image is written.\n\
114 \n\
115  -c\n\
116  Disable the mouse click. Useful to automate the \n\
117  execution of this program without humain intervention.\n\
118 \n\
119  -d \n\
120  Disable the image display. This can be useful \n\
121  for automatic tests using crontab under Unix or \n\
122  using the task manager under Windows.\n\
123 \n\
124  -h\n\
125  Print the help.\n\n", ipath.c_str(), opath.c_str(), user.c_str());
126 
127  if (badparam) {
128  fprintf(stderr, "ERROR: \n");
129  fprintf(stderr, "\nBad parameter [%s]\n", badparam);
130  }
131 }
132 
150 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &opath, bool &click_allowed,
151  const std::string &user, bool &display)
152 {
153  const char *optarg_;
154  int c;
155  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
156 
157  switch (c) {
158  case 'c':
159  click_allowed = false;
160  break;
161  case 'd':
162  display = false;
163  break;
164  case 'i':
165  ipath = optarg_;
166  break;
167  case 'o':
168  opath = optarg_;
169  break;
170  case 'h':
171  usage(argv[0], NULL, ipath, opath, user);
172  return false;
173  break;
174 
175  default:
176  usage(argv[0], optarg_, ipath, opath, user);
177  return false;
178  break;
179  }
180  }
181 
182  if ((c == 1) || (c == -1)) {
183  // standalone param or error
184  usage(argv[0], NULL, ipath, opath, user);
185  std::cerr << "ERROR: " << std::endl;
186  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
187  return false;
188  }
189 
190  return true;
191 }
192 
193 int main(int argc, const char **argv)
194 {
195  try {
196  std::string env_ipath;
197  std::string opt_ipath;
198  std::string opt_opath;
199  std::string ipath;
200  std::string opath;
201  std::string filename;
202  std::string username;
203  bool opt_click_allowed = true;
204  bool opt_display = true;
205 
206  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
207  // environment variable value
208  env_ipath = vpIoTools::getViSPImagesDataPath();
209 
210  // Set the default input path
211  if (!env_ipath.empty())
212  ipath = env_ipath;
213 
214 // Set the default output path
215 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
216  opt_opath = "/tmp";
217 #elif defined(_WIN32)
218  opt_opath = "C:\\temp";
219 #endif
220 
221  // Get the user login name
222  vpIoTools::getUserName(username);
223 
224  // Read the command line options
225  if (getOptions(argc, argv, opt_ipath, opt_opath, opt_click_allowed, username, opt_display) == false) {
226  exit(-1);
227  }
228 
229  // Get the option values
230  if (!opt_ipath.empty())
231  ipath = opt_ipath;
232  if (!opt_opath.empty())
233  opath = opt_opath;
234 
235  // Append to the output path string, the login name of the user
236  std::string odirname = vpIoTools::createFilePath(opath, username);
237 
238  // Test if the output path exist. If no try to create it
239  if (vpIoTools::checkDirectory(odirname) == false) {
240  try {
241  // Create the dirname
242  vpIoTools::makeDirectory(odirname);
243  } catch (...) {
244  usage(argv[0], NULL, ipath, opath, username);
245  std::cerr << std::endl << "ERROR:" << std::endl;
246  std::cerr << " Cannot create " << odirname << std::endl;
247  std::cerr << " Check your -o " << opath << " option " << std::endl;
248  exit(-1);
249  }
250  }
251 
252  // Compare ipath and env_ipath. If they differ, we take into account
253  // the input path comming from the command line option
254  if (!opt_ipath.empty() && !env_ipath.empty()) {
255  if (ipath != env_ipath) {
256  std::cout << std::endl << "WARNING: " << std::endl;
257  std::cout << " Since -i <visp image path=" << ipath << "> "
258  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
259  << " we skip the environment variable." << std::endl;
260  }
261  }
262 
263  // Test if an input path is set
264  if (opt_ipath.empty() && env_ipath.empty()) {
265  usage(argv[0], NULL, ipath, opath, username);
266  std::cerr << std::endl << "ERROR:" << std::endl;
267  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
268  << " environment variable to specify the location of the " << std::endl
269  << " image path where test images are located." << std::endl
270  << 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, "Klimt/Klimt.pgm");
281  vpImageIo::read(I1, filename);
282  } catch (...) {
283  std::cerr << std::endl << "ERROR:" << std::endl;
284  std::cerr << " Cannot read " << filename << std::endl;
285  std::cerr << " Check your -i " << ipath << " option " << std::endl
286  << " or VISP_INPUT_IMAGE_PATH environment variable." << std::endl;
287  exit(-1);
288  }
289  try {
290  // Load a color image from the disk
291  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
292  vpImageIo::read(I2, filename);
293  } catch (...) {
294  std::cerr << std::endl << "ERROR:" << std::endl;
295  std::cerr << " Cannot read " << filename << std::endl;
296  std::cerr << " Check your -i " << ipath << " option " << std::endl
297  << " or VISP_INPUT_IMAGE_PATH environment variable." << std::endl;
298  exit(-1);
299  }
300 
301  // For each image, open a X11 display
302  vpDisplayX display1;
303  vpDisplayX display2;
304 
305  if (opt_display) {
306  // Attach image 1 to display 1
307  display1.init(I1, 0, 0, "X11 Display 1...");
308  // Attach image 2 to display 2
309  display2.init(I2, 200, 200, "X11 Display 2...");
310  // Display the images
311  vpDisplay::display(I1);
312  vpDisplay::display(I2);
313 
314  // In the first display, display in overlay horizontal red lines
315  for (unsigned int i = 0; i < I1.getHeight(); i += 20) {
316  ip1.set_i(i);
317  ip1.set_j(0);
318  ip2.set_i(i);
319  ip2.set_j(I1.getWidth());
320  vpDisplay::displayLine(I1, ip1, ip2, vpColor::red);
321  }
322 
323  // In the first display, display in overlay vertical green dot lines
324  for (unsigned int i = 0; i < I1.getWidth(); i += 20) {
325  ip1.set_i(0);
326  ip1.set_j(i);
327  ip2.set_i(I1.getWidth());
328  ip2.set_j(i);
330  }
331 
332  // In the first display, display in overlay a blue arrow
333  ip1.set_i(0);
334  ip1.set_j(0);
335  ip2.set_i(100);
336  ip2.set_j(100);
337  vpDisplay::displayArrow(I1, ip1, ip2, vpColor::blue);
338 
339  // In the first display, display in overlay some circles. The
340  // position of the center is 200, 200 the radius is increased by 20
341  // pixels for each circle
342  for (unsigned int i = 0; i < 100; i += 20) {
343  ip.set_i(200);
344  ip.set_j(200);
345  vpDisplay::displayCircle(I1, ip, 20 + i, vpColor::yellow);
346  }
347 
348  // In the first display, display in overlay a yellow string
349  ip.set_i(100);
350  ip.set_j(100);
351  vpDisplay::displayText(I1, ip, "ViSP is a marvelous software", vpColor::blue);
352 
353  // Flush displays. The displays must be flushed to show the overlay.
354  // without this line, nothing will be displayed.
355  vpDisplay::flush(I1);
356  vpDisplay::flush(I2);
357 
358  // If click is allowed, wait for a blocking mouse click in the first
359  // display, to display a cross at the clicked pixel position
360  if (opt_click_allowed) {
361  std::cout << "\nA click in the first display to draw a cross..." << std::endl;
362  // Blocking wait for a click. Get the position of the selected pixel
363  // (i correspond to the row and j to the column coordinates in the
364  // image)
365  vpDisplay::getClick(I1, ip);
366  // Display a red cross on the click pixel position
367  std::cout << "Cross position: " << ip << std::endl;
369  vpDisplay::flush(I1);
370  } else {
371  ip.set_i(50);
372  ip.set_j(50);
373  // Display a red cross at position ip in the first display
374  std::cout << "Cross position: " << ip << std::endl;
376  vpDisplay::flush(I1);
377  }
378 
379  // Create a color image
380  vpImage<vpRGBa> Ioverlay;
381  // Updates the color image with the original loaded image 1 and the
382  // overlay
383  vpDisplay::getImage(I1, Ioverlay);
384 
385  // Write the color image on the disk
386  filename = vpIoTools::createFilePath(odirname, "Klimt_grey.overlay.ppm");
387  vpImageIo::write(Ioverlay, filename);
388 
389  // If click is allowed, wait for a mouse click to close the display
390  if (opt_click_allowed) {
391  std::cout << "\nA click in the second display to close the windows "
392  "and exit..."
393  << std::endl;
394  // Wait for a blocking mouse click
396  }
397  }
398  return EXIT_SUCCESS;
399  } catch (const vpException &e) {
400  std::cout << "Catch an exception: " << e << std::endl;
401  return EXIT_FAILURE;
402  }
403 }
404 #else
405 int main() {
406  std::cout << "You do not have X11 functionalities to display images..." << std::endl;
407  std::cout << "Tip if you are on a unix-like system:" << std::endl;
408  std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
409  return EXIT_SUCCESS;
410 }
411 #endif
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
Definition: vpDisplayX.cpp:258
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static bool checkDirectory(const char *dirname)
Definition: vpIoTools.cpp:467
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1316
unsigned int getWidth() const
Definition: vpImage.h:239
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:151
error that can be emited by ViSP classes.
Definition: vpException.h:71
static const vpColor green
Definition: vpColor.h:183
static void flush(const vpImage< unsigned char > &I)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
static const vpColor red
Definition: vpColor.h:180
static void write(const vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:375
static void makeDirectory(const char *dirname)
Definition: vpIoTools.cpp:597
void set_i(const double ii)
Definition: vpImagePoint.h:167
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1541
static void displayArrow(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)
static void display(const vpImage< unsigned char > &I)
static std::string getUserName()
Definition: vpIoTools.cpp:298
static void getImage(const vpImage< unsigned char > &Is, vpImage< vpRGBa > &Id)
Definition: vpDisplay.cpp:144
void set_j(const double jj)
Definition: vpImagePoint.h:178
static void displayCircle(const vpImage< unsigned char > &I, const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:207
unsigned int getHeight() const
Definition: vpImage.h:178
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
static const vpColor yellow
Definition: vpColor.h:188
static void displayDotLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
static const vpColor blue
Definition: vpColor.h:186