Visual Servoing Platform  version 3.4.0
testMouseEvent.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 sequence from the disk and display it.
33  *
34  * Authors:
35  * Fabien Spindler
36  * Anthony Saunier
37  *
38  *****************************************************************************/
49 #include <visp3/core/vpConfig.h>
50 #include <visp3/core/vpDebug.h>
51 #include <visp3/core/vpIoTools.h>
52 #include <visp3/io/vpParseArgv.h>
53 
54 #include <iomanip>
55 #include <sstream>
56 #include <stdio.h>
57 #include <stdlib.h>
58 
59 #if (defined(VISP_HAVE_GTK) || defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_D3D9))
60 
61 #include <visp3/core/vpImage.h>
62 #include <visp3/io/vpImageIo.h>
63 
64 #include <visp3/core/vpMouseButton.h>
65 #include <visp3/gui/vpDisplayD3D.h>
66 #include <visp3/gui/vpDisplayGDI.h>
67 #include <visp3/gui/vpDisplayGTK.h>
68 #include <visp3/gui/vpDisplayX.h>
69 
70 #include <visp3/core/vpTime.h>
71 
82 // List of allowed command line options
83 #define GETOPTARGS "cdi:lp:ht:f:n:s:w"
84 typedef enum {
85  vpX11,
86  vpGTK,
87  vpGDI,
88  vpD3D,
89 } vpDisplayType;
90 
91 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
92  unsigned nimages, unsigned step, vpDisplayType &dtype);
93 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &nimages,
94  unsigned &step, vpDisplayType &dtype, bool &list, bool &display, bool &click, bool &wait);
95 
110 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
111  unsigned nimages, unsigned step, vpDisplayType &dtype)
112 {
113  fprintf(stdout, "\n\
114 Read an image sequence from the disk and display it.\n\
115 The sequence is made of separate images. Each image corresponds\n\
116 to a PGM file.\n\
117 \n\
118 SYNOPSIS\n\
119  %s [-i <test image path>] [-p <personal image path>]\n\
120  [-f <first image>] [-n <number of images>] [-s <step>] \n\
121  [-t <type of video device>] [-l] [-w] [-c] [-d] [-h]\n \
122  ", name);
123 
124  std::string display;
125  switch (dtype) {
126  case vpX11:
127  display = "X11";
128  break;
129  case vpGTK:
130  display = "GTK";
131  break;
132  case vpGDI:
133  display = "GDI";
134  break;
135  case vpD3D:
136  display = "D3D";
137  break;
138  }
139 
140  fprintf(stdout, "\n\
141  OPTIONS: Default\n\
142  -i <test image path> %s\n\
143  Set image input path.\n\
144  From this path read \"cube/image.%%04d.pgm\"\n\
145  images. These images come from ViSP-images-x.y.z.tar.gz\n\
146  available on the ViSP website.\n\
147  Setting the VISP_INPUT_IMAGE_PATH environment\n\
148  variable produces the same behaviour than using\n\
149  this option.\n\
150  \n\
151  -p <personal image path> %s\n\
152  Specify a personal sequence containing images \n\
153  to process.\n\
154  By image sequence, we mean one file per image.\n\
155  The following image file formats PNM (PGM P5, PPM P6)\n\
156  are supported. The format is selected by analysing \n\
157  the filename extension.\n\
158  Example : \"/Temp/ViSP-images/cube/image.%%04d.pgm\"\n\
159  %%04d is for the image numbering.\n\
160  \n\
161  -f <first image> %u\n\
162  First image number of the sequence.\n\
163  \n\
164  -n <number of images> %u\n\
165  Number of images to load from the sequence.\n\
166  \n\
167  -s <step> %u\n\
168  Step between two images.\n\
169 \n\
170  -t <type of video device> \"%s\"\n\
171  String specifying the video device to use.\n\
172  Possible values:\n\
173  \"X11\": only on UNIX platforms,\n\
174  \"GTK\": on all plaforms,\n\
175  \"GDI\": only on Windows platform (Graphics Device Interface),\n\
176  \"D3D\": only on Windows platform (Direct3D).\n\
177 \n\
178  -l\n\
179  Print the list of video-devices available and exit.\n\
180 \n\
181  -c\n\
182  Disable mouse click.\n\
183 \n\
184  -d\n\
185  Disable the image display. This can be useful \n\
186  for automatic tests using crontab under Unix or \n\
187  using the task manager under Windows.\n\
188 \n\
189  -w\n\
190  Wait for a mouse click between two images.\n\
191  If the image display is disabled (using -d)\n\
192  this option is without effect.\n\
193 \n\
194  -h\n\
195  Print the help.\n\n", ipath.c_str(), ppath.c_str(), first, nimages, step, display.c_str());
196 
197  if (badparam)
198  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
199 }
224 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &nimages,
225  unsigned &step, vpDisplayType &dtype, bool &list, bool &display, bool &click, bool &wait)
226 {
227  const char *optarg_;
228  int c;
229  std::string sDisplayType;
230  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
231 
232  switch (c) {
233  case 'c':
234  click = false;
235  break;
236  case 'd':
237  display = false;
238  break;
239  case 't':
240  sDisplayType = optarg_;
241  // Parse the display type option
242  if (sDisplayType.compare("X11") == 0) {
243  dtype = vpX11;
244  } else if (sDisplayType.compare("GTK") == 0) {
245  dtype = vpGTK;
246  } else if (sDisplayType.compare("GDI") == 0) {
247  dtype = vpGDI;
248  } else if (sDisplayType.compare("D3D") == 0) {
249  dtype = vpD3D;
250  }
251 
252  break;
253  case 'i':
254  ipath = optarg_;
255  break;
256  case 'l':
257  list = true;
258  break;
259  case 'p':
260  ppath = optarg_;
261  break;
262  case 'f':
263  first = (unsigned)atoi(optarg_);
264  break;
265  case 'n':
266  nimages = (unsigned)atoi(optarg_);
267  break;
268  case 's':
269  step = (unsigned)atoi(optarg_);
270  break;
271  case 'w':
272  wait = true;
273  break;
274  case 'h':
275  usage(argv[0], NULL, ipath, ppath, first, nimages, step, dtype);
276  return false;
277  break;
278 
279  default:
280  usage(argv[0], optarg_, ipath, ppath, first, nimages, step, dtype);
281  return false;
282  break;
283  }
284  }
285 
286  if ((c == 1) || (c == -1)) {
287  // standalone param or error
288  usage(argv[0], NULL, ipath, ppath, first, nimages, step, dtype);
289  std::cerr << "ERROR: " << std::endl;
290  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
291  return false;
292  }
293 
294  return true;
295 }
296 
297 int main(int argc, const char **argv)
298 {
299  std::string env_ipath;
300  std::string opt_ipath;
301  std::string ipath;
302  std::string opt_ppath;
303  std::string dirname;
304  std::string filename;
305  unsigned opt_first = 30;
306  unsigned opt_nimages = 10;
307  unsigned opt_step = 1;
308  vpDisplayType opt_dtype; // Type of display to use
309  bool opt_list = false; // To print the list of video devices
310  bool opt_display = true;
311  bool opt_click = true;
312  bool opt_click_blocking = false;
313 
314 // Default display is one available
315 #if defined VISP_HAVE_GTK
316  opt_dtype = vpGTK;
317 #elif defined VISP_HAVE_X11
318  opt_dtype = vpX11;
319 #elif defined VISP_HAVE_GDI
320  opt_dtype = vpGDI;
321 #elif defined VISP_HAVE_D3D9
322  opt_dtype = vpD3D;
323 #endif
324 
325  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
326  // environment variable value
327  env_ipath = vpIoTools::getViSPImagesDataPath();
328 
329  // Set the default input path
330  if (!env_ipath.empty())
331  ipath = env_ipath;
332 
333  // Read the command line options
334  if (getOptions(argc, argv, opt_ipath, opt_ppath, opt_first, opt_nimages, opt_step, opt_dtype, opt_list, opt_display,
335  opt_click, opt_click_blocking) == false) {
336  exit(-1);
337  }
338  // Print the list of video-devices available
339  if (opt_list) {
340  unsigned nbDevices = 0;
341  std::cout << "List of video-devices available: \n";
342 #if defined VISP_HAVE_GTK
343  std::cout << " GTK (use \"-t GTK\" option to use it)\n";
344  nbDevices++;
345 #endif
346 #if defined VISP_HAVE_X11
347  std::cout << " X11 (use \"-t X11\" option to use it)\n";
348  nbDevices++;
349 #endif
350 #if defined VISP_HAVE_GDI
351  std::cout << " GDI (use \"-t GDI\" option to use it)\n";
352  nbDevices++;
353 #endif
354 #if defined VISP_HAVE_D3D9
355  std::cout << " D3D (use \"-t D3D\" option to use it)\n";
356  nbDevices++;
357 #endif
358  if (!nbDevices) {
359  std::cout << " No display is available\n";
360  }
361  return (0);
362  }
363 
364  if (!opt_display)
365  opt_click_blocking = false; // turn off the waiting
366 
367  // Get the option values
368  if (!opt_ipath.empty())
369  ipath = opt_ipath;
370 
371  // Compare ipath and env_ipath. If they differ, we take into account
372  // the input path comming from the command line option
373  if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
374  if (ipath != env_ipath) {
375  std::cout << std::endl << "WARNING: " << std::endl;
376  std::cout << " Since -i <visp image path=" << ipath << "> "
377  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
378  << " we skip the environment variable." << std::endl;
379  }
380  }
381 
382  // Test if an input path is set
383  if (opt_ipath.empty() && env_ipath.empty() && opt_ppath.empty()) {
384  usage(argv[0], NULL, ipath, opt_ppath, opt_first, opt_nimages, opt_step, opt_dtype);
385  std::cerr << std::endl << "ERROR:" << std::endl;
386  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
387  << " environment variable to specify the location of the " << std::endl
388  << " image path where test images are located." << std::endl
389  << " Use -p <personal image path> option if you want to " << std::endl
390  << " use personal images." << std::endl
391  << std::endl;
392 
393  exit(-1);
394  }
395 
396  // Declare an image, this is a gray level image (unsigned char)
397  // it size is not defined yet, it will be defined when the image will
398  // read on the disk
400 
401  unsigned iter = opt_first;
402  std::ostringstream s;
403  char cfilename[FILENAME_MAX];
404 
405  if (opt_ppath.empty()) {
406 
407  // Warning :
408  // the image sequence is not provided with the ViSP package
409  // therefore the program will return you an error :
410  // !! vpImageIoPnm.cpp: readPGM(#210) :couldn't read file
411  // ViSP-images/cube/image.0001.pgm
412  // !! vpDotExample.cpp: main(#95) :Error while reading the image
413  // terminate called after throwing an instance of 'vpImageException'
414  //
415  // The sequence is available on the visp www site
416  // https://visp.inria.fr/download/
417  // in the download section. It is named "ViSP-images.tar.gz"
418 
419  // Set the path location of the image sequence
420  dirname = vpIoTools::createFilePath(ipath, "cube");
421 
422  // Build the name of the image file
423 
424  s.setf(std::ios::right, std::ios::adjustfield);
425  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
426  filename = vpIoTools::createFilePath(dirname, s.str());
427  } else {
428 
429  sprintf(cfilename, opt_ppath.c_str(), iter);
430  filename = cfilename;
431  }
432  // Read the PGM image named "filename" on the disk, and put the
433  // bitmap into the image structure I. I is initialized to the
434  // correct size
435  //
436  // exception readPGM may throw various exception if, for example,
437  // the file does not exist, or if the memory cannot be allocated
438  try {
439  vpImageIo::read(I, filename);
440  } catch (...) {
441  // an exception is throwned if an exception from readPGM has been catched
442  // here this will result in the end of the program
443  // Note that another error message has been printed from readPGM
444  // to give more information about the error
445  std::cerr << std::endl << "ERROR:" << std::endl;
446  std::cerr << " Cannot read " << filename << std::endl;
447  std::cerr << " Check your -i " << ipath << " option, " << std::endl
448  << " or your -p " << opt_ppath << " option " << std::endl
449  << " or VISP_INPUT_IMAGE_PATH environment variable" << std::endl;
450  exit(-1);
451  }
452  // Create a display for the image
453  vpDisplay *display = NULL;
454 
455  switch (opt_dtype) {
456  case vpX11:
457  std::cout << "Requested X11 display functionnalities..." << std::endl;
458 #if defined VISP_HAVE_X11
459  display = new vpDisplayX;
460 #else
461  std::cout << " Sorry, X11 video device is not available.\n";
462  std::cout << "Use \"" << argv[0] << " -l\" to print the list of available devices.\n";
463  return 0;
464 #endif
465  break;
466  case vpGTK:
467  std::cout << "Requested GTK display functionnalities..." << std::endl;
468 #if defined VISP_HAVE_GTK
469  display = new vpDisplayGTK;
470 #else
471  std::cout << " Sorry, GTK video device is not available.\n";
472  std::cout << "Use \"" << argv[0] << " -l\" to print the list of available devices.\n";
473  return 0;
474 #endif
475  break;
476  case vpGDI:
477  std::cout << "Requested GDI display functionnalities..." << std::endl;
478 #if defined VISP_HAVE_GDI
479  display = new vpDisplayGDI;
480 #else
481  std::cout << " Sorry, GDI video device is not available.\n";
482  std::cout << "Use \"" << argv[0] << " -l\" to print the list of available devices.\n";
483  return 0;
484 #endif
485  break;
486  case vpD3D:
487  std::cout << "Requested D3D display functionnalities..." << std::endl;
488 #if defined VISP_HAVE_D3D9
489  display = new vpDisplayD3D;
490 #else
491  std::cout << " Sorry, D3D video device is not available.\n";
492  std::cout << "Use \"" << argv[0] << " -l\" to print the list of available devices.\n";
493  return 0;
494 #endif
495  break;
496  }
497 
498  if (opt_display) {
499  try {
500  // We open a window using either X11 or GTK or GDI.
501  // Its size is automatically defined by the image (I) size
502  display->init(I, 100, 100, "Display...");
503 
504  // Display the image
505  // The image class has a member that specify a pointer toward
506  // the display that has been initialized in the display declaration
507  // therefore is is no longuer necessary to make a reference to the
508  // display variable.
510  vpDisplay::flush(I);
511  } catch (...) {
512  vpERROR_TRACE("Error while displaying the image");
513  delete display;
514  exit(-1);
515  }
516  }
517 
518  // double tms_1 = vpTime::measureTimeMs() ;
519  unsigned niter = 0;
520  // this is the loop over the image sequence
521  while (iter < opt_first + opt_nimages * opt_step) {
522  try {
523  double tms = vpTime::measureTimeMs();
524 
525  // set the new image name
526 
527  if (opt_ppath.empty()) {
528  s.str("");
529  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
530  filename = vpIoTools::createFilePath(dirname, s.str());
531  } else {
532  sprintf(cfilename, opt_ppath.c_str(), iter);
533  filename = cfilename;
534  }
535 
536  std::cout << "read : " << filename << std::endl;
537  // read the image
538  vpImageIo::read(I, filename);
539  if (opt_display) {
540  // Display the image
542  // Flush the display
543  vpDisplay::flush(I);
544 
545  if (opt_click_blocking) {
546  std::cout << "A click in the image to continue..." << std::endl;
547  }
548  vpImagePoint ip;
549 
550  if (opt_click) {
552  bool pressed = vpDisplay::getClick(I, ip, button, opt_click_blocking);
553  if (pressed) {
554  switch (button) {
556  std::cout << "Left button was pressed." << std::endl;
557  break;
559  std::cout << "Middle button was pressed." << std::endl;
560  break;
562  std::cout << "Right button was pressed. Bye. " << std::endl;
563  delete display;
564  return 0;
565  break;
566  case vpMouseButton::none:
567  break;
568  }
569  }
570  }
571 
572  vpTime::wait(tms, 1000);
573  }
574 
575  else {
576  // Synchronise the loop to 40 ms
577  vpTime::wait(tms, 40);
578  }
579  niter++;
580  } catch (...) {
581  delete display;
582  exit(-1);
583  }
584  iter += opt_step;
585  }
586  delete display;
587  // double tms_2 = vpTime::measureTimeMs() ;
588  // double tms_total = tms_2 - tms_1 ;
589  // std::cout << "Total Time : "<< tms_total<<std::endl;
590 }
591 #else
592 int main() { vpERROR_TRACE("You do not have X11 or GTK display functionalities..."); }
593 
594 #endif
VISP_EXPORT int wait(double t0, double t)
Definition: vpTime.cpp:173
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:177
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1202
#define vpERROR_TRACE
Definition: vpDebug.h:393
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:150
static void flush(const vpImage< unsigned char > &I)
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:126
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed...
Definition: vpDisplayD3D.h:106
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1446
static void display(const vpImage< unsigned char > &I)
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:134
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:244
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87