Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
displayX.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 <iostream>
49 #include <stdlib.h>
50 #include <visp3/core/vpConfig.h>
51 
52 #ifdef VISP_HAVE_X11
53 
54 #include <visp3/core/vpImage.h>
55 #include <visp3/core/vpIoTools.h>
56 #include <visp3/core/vpTime.h>
57 #include <visp3/gui/vpDisplayX.h>
58 #include <visp3/io/vpImageIo.h>
59 #include <visp3/io/vpParseArgv.h>
60 
61 
71 // List of allowed command line options
72 #define GETOPTARGS "cdi:o:p:h"
73 
85 void usage(const char *name, const char *badparam, std::string ipath, std::string opath, std::string user)
86 {
87  fprintf(stdout, "\n\
88 Read an image on the disk, display it using X11, display some\n\
89 features (line, circle, caracters) in overlay and finaly write \n\
90 the image and the overlayed features in an image on the disk.\n\
91 \n\
92 SYNOPSIS\n\
93  %s [-i <input image path>] [-o <output image path>]\n\
94  [-c] [-d] [-h]\n \
95 ", name);
96 
97  fprintf(stdout, "\n\
98 OPTIONS: Default\n\
99  -i <input image path> %s\n\
100  Set image input path.\n\
101  From this path read \"Klimt/Klimt.pgm\"\n\
102  image.\n\
103  Setting the VISP_INPUT_IMAGE_PATH environment\n\
104  variable produces the same behaviour than using\n\
105  this option.\n\
106 \n\
107  -o <output image path> %s\n\
108  Set image output path.\n\
109  From this directory, creates the \"%s\"\n\
110  subdirectory depending on the username, where \n\
111  Klimt_grey.overlay.ppm output image is written.\n\
112 \n\
113  -c\n\
114  Disable the mouse click. Useful to automate the \n\
115  execution of this program without humain intervention.\n\
116 \n\
117  -d \n\
118  Disable the image display. This can be useful \n\
119  for automatic tests using crontab under Unix or \n\
120  using the task manager under Windows.\n\
121 \n\
122  -h\n\
123  Print the help.\n\n", ipath.c_str(), opath.c_str(), user.c_str());
124 
125  if (badparam) {
126  fprintf(stderr, "ERROR: \n");
127  fprintf(stderr, "\nBad parameter [%s]\n", badparam);
128  }
129 }
130 
149 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &opath, bool &click_allowed,
150  const std::string &user, bool &display)
151 {
152  const char *optarg_;
153  int c;
154  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
155 
156  switch (c) {
157  case 'c':
158  click_allowed = false;
159  break;
160  case 'd':
161  display = false;
162  break;
163  case 'i':
164  ipath = optarg_;
165  break;
166  case 'o':
167  opath = optarg_;
168  break;
169  case 'h':
170  usage(argv[0], NULL, ipath, opath, user);
171  return false;
172  break;
173 
174  default:
175  usage(argv[0], optarg_, ipath, opath, user);
176  return false;
177  break;
178  }
179  }
180 
181  if ((c == 1) || (c == -1)) {
182  // standalone param or error
183  usage(argv[0], NULL, ipath, opath, user);
184  std::cerr << "ERROR: " << std::endl;
185  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
186  return false;
187  }
188 
189  return true;
190 }
191 
192 int main(int argc, const char **argv)
193 {
194  try {
195  std::string env_ipath;
196  std::string opt_ipath;
197  std::string opt_opath;
198  std::string ipath;
199  std::string opath;
200  std::string filename;
201  std::string username;
202  bool opt_click_allowed = true;
203  bool opt_display = true;
204 
205  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
206  // environment variable value
207  env_ipath = vpIoTools::getViSPImagesDataPath();
208 
209  // Set the default input path
210  if (!env_ipath.empty())
211  ipath = env_ipath;
212 
213 // Set the default output path
214 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
215  opt_opath = "/tmp";
216 #elif defined(_WIN32)
217  opt_opath = "C:\\temp";
218 #endif
219 
220  // Get the user login name
221  vpIoTools::getUserName(username);
222 
223  // Read the command line options
224  if (getOptions(argc, argv, opt_ipath, opt_opath, opt_click_allowed, username, opt_display) == false) {
225  exit(-1);
226  }
227 
228  // Get the option values
229  if (!opt_ipath.empty())
230  ipath = opt_ipath;
231  if (!opt_opath.empty())
232  opath = opt_opath;
233 
234  // Append to the output path string, the login name of the user
235  std::string odirname = vpIoTools::createFilePath(opath, username);
236 
237  // Test if the output path exist. If no try to create it
238  if (vpIoTools::checkDirectory(odirname) == false) {
239  try {
240  // Create the dirname
241  vpIoTools::makeDirectory(odirname);
242  } catch (...) {
243  usage(argv[0], NULL, ipath, opath, username);
244  std::cerr << std::endl << "ERROR:" << std::endl;
245  std::cerr << " Cannot create " << odirname << std::endl;
246  std::cerr << " Check your -o " << opath << " option " << std::endl;
247  exit(-1);
248  }
249  }
250 
251  // Compare ipath and env_ipath. If they differ, we take into account
252  // the input path comming from the command line option
253  if (!opt_ipath.empty() && !env_ipath.empty()) {
254  if (ipath != env_ipath) {
255  std::cout << std::endl << "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 << "ERROR:" << std::endl;
266  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
267  << " environment variable to specify the location of the " << std::endl
268  << " image path where test images are located." << std::endl
269  << std::endl;
270  exit(-1);
271  }
272 
273  // Create a grey level image
275  vpImagePoint ip, ip1, ip2;
276 
277  // Load a grey image from the disk
278  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
279  vpImageIo::read(I, filename);
280 
281  // Create a display using X11
282  vpDisplayX display;
283 
284  if (opt_display) {
285  // For this grey level image, open a X11 display at position 100,100
286  // in the screen, and with title "X11 display"
287  display.init(I, 100, 100, "X11 display");
288 
289  // Display the image
291 
292  // Display in overlay a red cross at position 10,10 in the
293  // image. The lines are 10 pixels long
294  ip.set_i(100);
295  ip.set_j(10);
296 
298 
299  // Display in overlay horizontal red lines
300  for (unsigned i = 0; i < I.getHeight(); i += 20) {
301  ip1.set_i(i);
302  ip1.set_j(0);
303  ip2.set_i(i);
304  ip2.set_j(I.getWidth());
305  vpDisplay::displayLine(I, ip1, ip2, vpColor::red);
306  }
307 
308  // Display a ligne in the diagonal
309  ip1.set_i(-10);
310  ip1.set_j(-10);
311  ip2.set_i(I.getHeight() + 10);
312  ip2.set_j(I.getWidth() + 10);
313 
314  vpDisplay::displayLine(I, ip1, ip2, vpColor::red);
315 
316  // Display in overlay vertical green dot lines
317  for (unsigned i = 0; i < I.getWidth(); i += 20) {
318  ip1.set_i(0);
319  ip1.set_j(i);
320  ip2.set_i(I.getWidth());
321  ip2.set_j(i);
323  }
324 
325  // Display a rectangle
326  ip.set_i(I.getHeight() - 45);
327  ip.set_j(-10);
329 
330  // Display in overlay a blue arrow
331  ip1.set_i(0);
332  ip1.set_j(0);
333  ip2.set_i(100);
334  ip2.set_j(100);
336 
337  // Display in overlay some circles. The position of the center is 200,
338  // 200 the radius is increased by 20 pixels for each circle
339 
340  for (unsigned int i = 0; i < 100; i += 20) {
341  ip.set_i(80);
342  ip.set_j(80);
344  }
345 
346  ip.set_i(-10);
347  ip.set_j(300);
349 
350  // Display in overlay a yellow string
351  ip.set_i(85);
352  ip.set_j(100);
353  vpDisplay::displayText(I, ip, "ViSP is a marvelous software", vpColor::yellow);
354  // Flush the display
355  vpDisplay::flush(I);
356 
357  // Create a color image
358  vpImage<vpRGBa> Ioverlay;
359  // Updates the color image with the original loaded image and the
360  // overlay
361  vpDisplay::getImage(I, Ioverlay);
362 
363  // Write the color image on the disk
364  filename = vpIoTools::createFilePath(odirname, "Klimt_grey.overlay.ppm");
365  vpImageIo::write(Ioverlay, filename);
366 
367  // If click is allowed, wait for a mouse click to close the display
368  if (opt_click_allowed) {
369  std::cout << "\nA click to close the windows..." << std::endl;
370  // Wait for a blocking mouse click
372  }
373 
374  // Close the display
375  vpDisplay::close(I);
376  }
377 
378  // Create a color image
379  vpImage<vpRGBa> Irgba;
380 
381  // Load a grey image from the disk and convert it to a color image
382  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
383  vpImageIo::read(Irgba, filename);
384 
385  // Create a new display
386  vpDisplayX displayRGBa;
387 
388  if (opt_display) {
389  // For this color image, open a X11 display at position 100,100
390  // in the screen, and with title "X11 color display"
391  displayRGBa.init(Irgba, 100, 100, "X11 color display");
392 
393  // Display the color image
394  vpDisplay::display(Irgba);
395  vpDisplay::flush(Irgba);
396 
397  // If click is allowed, wait for a blocking mouse click to display a
398  // cross at the clicked pixel position
399  if (opt_click_allowed) {
400  std::cout << "\nA click to display a cross..." << std::endl;
401  // Blocking wait for a click. Get the position of the selected pixel
402  // (i correspond to the row and j to the column coordinates in the
403  // image)
404  vpDisplay::getClick(Irgba, ip);
405  // Display a red cross on the click pixel position
406  std::cout << "Cross position: " << ip << std::endl;
407  vpDisplay::displayCross(Irgba, ip, 15, vpColor::red);
408  } else {
409  ip.set_i(10);
410  ip.set_j(20);
411  // Display a red cross at position i, j (i correspond to the row
412  // and j to the column coordinates in the image)
413  std::cout << "Cross position: " << ip << std::endl;
414  vpDisplay::displayCross(Irgba, ip, 15, vpColor::red);
415  }
416  // Flush the display. Sometimes the display content is
417  // bufferized. Force to display the content that has been bufferized.
418  vpDisplay::flush(Irgba);
419 
420  // Create a color image
421  vpImage<vpRGBa> Ioverlay;
422  // Updates the color image with the original loaded image and the
423  // overlay
424  vpDisplay::getImage(Irgba, Ioverlay);
425 
426  // Write the color image on the disk
427  filename = vpIoTools::createFilePath(odirname, "Klimt_color.overlay.ppm");
428  vpImageIo::write(Ioverlay, filename);
429 
430  // If click is allowed, wait for a blocking mouse click to exit.
431  if (opt_click_allowed) {
432  std::cout << "\nA click to exit the program..." << std::endl;
433  vpDisplay::getClick(Irgba);
434  std::cout << "Bye" << std::endl;
435  }
436  }
437  return EXIT_SUCCESS;
438  } catch (const vpException &e) {
439  std::cout << "Catch an exception: " << e << std::endl;
440  return EXIT_FAILURE;
441  }
442 }
443 #else
444 int main() {
445  std::cout << "You do not have X11 functionalities to display images..." << std::endl;
446  std::cout << "Tip if you are on a unix-like system:" << std::endl;
447  std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
448  return EXIT_SUCCESS;
449 }
450 #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
static void close(vpImage< unsigned char > &I)
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 const vpColor orange
Definition: vpColor.h:190
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 displayRectangle(const vpImage< unsigned char > &I, const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
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