Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
grabDisk.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 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 https://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 *****************************************************************************/
35 
46 #include <stdlib.h>
47 #include <visp3/core/vpConfig.h>
48 #include <visp3/core/vpDebug.h>
49 #if (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI))
50 
51 #include <visp3/core/vpDisplay.h>
52 #include <visp3/core/vpImage.h>
53 #include <visp3/core/vpIoTools.h>
54 #include <visp3/core/vpTime.h>
55 #include <visp3/gui/vpDisplayGDI.h>
56 #include <visp3/gui/vpDisplayX.h>
57 #include <visp3/io/vpDiskGrabber.h>
58 #include <visp3/io/vpParseArgv.h>
59 
60 // List of allowed command line options
61 #define GETOPTARGS "b:de:f:hi:l:s:z:"
62 
63 #ifdef ENABLE_VISP_NAMESPACE
64 using namespace VISP_NAMESPACE_NAME;
65 #endif
66 
67 /*
68 
69  Print the program options.
70 
71  \param name : Program name.
72  \param badparam : Bad parameter name.
73  \param ipath : Input image path.
74  \param basename : Input image base name.
75  \param ext : Input image extension.
76  \param first : First image number to read.
77  \param last : Number of images to read.
78  \param step : Step between two successive images to read.
79  \param nzero : Number of zero for the image number coding.
80 
81  */
82 void usage(const char *name, const char *badparam, std::string ipath, std::string basename, std::string ext, long first,
83  long last, long step, unsigned int nzero)
84 {
85  fprintf(stdout, "\n\
86 Read an image sequence from the disk. Display it using X11 or GTK.\n\
87 The sequence is made of separate images. Each image corresponds\n\
88 to a PGM file.\n\
89 \n\
90 SYNOPSIS\n\
91  %s [-i <input image path>] [-b <base name>] [-e <extension>] \n\
92  [-f <first frame>] [-l <last image> [-s <step>] \n\
93  [-z <number of zero>] [-d] [-h]\n",
94  name);
95 
96  fprintf(stdout, "\n\
97 OPTIONS: Default\n\
98  -i <input image path> %s\n\
99  Set image input path.\n\
100  From this path read \"cube/image.%%04d.%s\"\n\
101  images.\n\
102  Setting the VISP_INPUT_IMAGE_PATH environment\n\
103  variable produces the same behaviour than using\n\
104  this option.\n\
105 \n\
106  -b <base name> %s\n\
107  Specify the base name of the files of the sequence\n\
108  containing the images to process. \n\
109  By image sequence, we mean one file per image.\n\
110  The format is selected by analysing the filename extension.\n\
111 \n\
112  -e <extension> %s\n\
113  Specify the extension of the files.\n\
114  Not taken into account for the moment. Will be a\n\
115  future feature...\n\
116 \n\
117  -f <first frame> %ld\n\
118  First frame number of the sequence.\n\
119 \n\
120  -l <last image > %ld\n\
121  Last frame number of the sequence.\n\
122 \n\
123  -s <step> %ld\n\
124  Step between two images.\n\
125 \n\
126  -z <number of zero> %u\n\
127  Number of digits to encode the image number.\n\
128 \n\
129  -d \n\
130  Turn off the display.\n\
131 \n\
132  -h \n\
133  Print the help.\n\n",
134  ipath.c_str(), ext.c_str(), basename.c_str(), ext.c_str(), first, last, step, nzero);
135 
136  if (badparam)
137  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
138 }
157 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &basename, std::string &ext, long &first,
158  long &last, long &step, unsigned int &nzero, bool &display)
159 {
160  const char *optarg_;
161  int c;
162  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
163 
164  switch (c) {
165  case 'b':
166  basename = optarg_;
167  break;
168  case 'd':
169  display = false;
170  break;
171  case 'e':
172  ext = optarg_;
173  break;
174  case 'f':
175  first = atol(optarg_);
176  break;
177  case 'i':
178  ipath = optarg_;
179  break;
180  case 'l':
181  last = std::atol(optarg_);
182  break;
183  case 's':
184  step = atol(optarg_);
185  break;
186  case 'z':
187  nzero = (unsigned)atoi(optarg_);
188  break;
189  case 'h':
190  usage(argv[0], nullptr, ipath, basename, ext, first, last, step, nzero);
191  return false;
192  break;
193 
194  default:
195  usage(argv[0], optarg_, ipath, basename, ext, first, last, step, nzero);
196  return false;
197  break;
198  }
199  }
200 
201  if ((c == 1) || (c == -1)) {
202  // standalone param or error
203  usage(argv[0], nullptr, ipath, basename, ext, first, last, step, nzero);
204  std::cerr << "ERROR: " << std::endl;
205  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
206  return false;
207  }
208 
209  return true;
210 }
211 
221 int main(int argc, const char **argv)
222 {
223  try {
224  std::string env_ipath;
225  std::string opt_ipath;
226  std::string ipath;
227  std::string opt_basename = "cube/image.";
228 #if VISP_HAVE_DATASET_VERSION >= 0x030600
229  std::string opt_ext("png");
230 #else
231  std::string opt_ext("pgm");
232 #endif
233 
234  bool opt_display = true;
235 
236  long opt_first = 5;
237  long opt_last = 70;
238  long opt_step = 1;
239  unsigned int opt_nzero = 4;
240 
241  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
242  // environment variable value
243  env_ipath = vpIoTools::getViSPImagesDataPath();
244 
245  // Set the default input path
246  if (!env_ipath.empty())
247  ipath = env_ipath;
248 
249  // Read the command line options
250  if (getOptions(argc, argv, opt_ipath, opt_basename, opt_ext, opt_first, opt_last, opt_step, opt_nzero,
251  opt_display) == false) {
252  return EXIT_FAILURE;
253  }
254 
255  // Get the option values
256  if (!opt_ipath.empty())
257  ipath = opt_ipath;
258 
259  // Compare ipath and env_ipath. If they differ, we take into account
260  // the input path coming from the command line option
261  if (!opt_ipath.empty() && !env_ipath.empty()) {
262  if (ipath != env_ipath) {
263  std::cout << std::endl << "WARNING: " << std::endl;
264  std::cout << " Since -i <visp image path=" << ipath << "> "
265  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
266  << " we skip the environment variable." << std::endl;
267  }
268  }
269 
270  // Test if an input path is set
271  if (opt_ipath.empty() && env_ipath.empty()) {
272  usage(argv[0], nullptr, ipath, opt_basename, opt_ext, opt_first, opt_last, opt_step, opt_nzero);
273  std::cerr << std::endl << "ERROR:" << std::endl;
274  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
275  << " environment variable to specify the location of the " << std::endl
276  << " image path where test images are located." << std::endl
277  << std::endl;
278  return EXIT_FAILURE;
279  }
280 
281  // Declare an image, this is a gray level image (unsigned char)
282  // it size is not defined yet, it will be defined when the image will
283  // read on the disk
285 
286  // Declare a framegrabber able to read a sequence of successive
287  // images from the disk
288  vpDiskGrabber g;
289 
290  // Set the path to the directory containing the sequence
291  g.setDirectory(ipath.c_str());
292  // Set the image base name. The directory and the base name constitute
293  // the constant part of the full filename
294  g.setBaseName(opt_basename.c_str());
295  // Set the step between two images of the sequence
296  g.setStep(opt_step);
297  // Set the number of digits to build the image number
298  g.setNumberOfZero(opt_nzero);
299  // Set the first frame number of the sequence
300  g.setImageNumber(opt_first);
301  // Set the image extension
302  g.setExtension(opt_ext.c_str());
303 
304  // Open the framegrabber by loading the first image of the sequence
305  g.open(I);
306 
307  std::cout << "Image size: width : " << I.getWidth() << " height: " << I.getHeight() << std::endl;
308 
309  // We open a window using either X11 or GDI.
310  // Its size is automatically defined by the image (I) size
311 #if defined(VISP_HAVE_X11)
312  vpDisplayX display(I);
313 #elif defined(VISP_HAVE_GDI)
314  vpDisplayGDI display(I);
315 #else
316  std::cout << "No image viewer is available..." << std::endl;
317 #endif
318 
319  if (opt_display) {
320  display.init(I, 100, 100, "Disk Framegrabber");
321 
322  // display the image
323  // The image class has a member that specify a pointer toward
324  // the display that has been initialized in the display declaration
325  // therefore is is no longer necessary to make a reference to the
326  // display variable.
328  vpDisplay::flush(I);
329  }
330 
331  // this is the loop over the image sequence
332  while (g.getImageNumber() < opt_last) {
333  double tms = vpTime::measureTimeMs();
334  // read the image and then increment the image counter so that the next
335  // call to acquire(I) will get the next image
336  g.acquire(I);
337  if (opt_display) {
338  // Display the image
340  // Flush the display
341  vpDisplay::flush(I);
342  }
343  // Synchronise the loop to 40 ms
344  vpTime::wait(tms, 40);
345  }
346  return EXIT_SUCCESS;
347  }
348  catch (const vpException &e) {
349  std::cout << "Catch an exception: " << e << std::endl;
350  return EXIT_FAILURE;
351  }
352 }
353 
354 #else
355 int main()
356 {
357  std::cout << "You do not have X11, or GDI (Graphical Device Interface) functionalities to display images..."
358  << std::endl;
359  std::cout << "Tip if you are on a unix-like system:" << std::endl;
360  std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
361  std::cout << "Tip if you are on a windows-like system:" << std::endl;
362  std::cout << "- Install GDI, configure again ViSP using cmake and build again this example" << std::endl;
363  return EXIT_SUCCESS;
364  }
365 #endif
Class to grab (ie. read) images from the disk.
void setStep(long step)
void setDirectory(const std::string &dir)
void setExtension(const std::string &ext)
void open(vpImage< unsigned char > &I)
void setImageNumber(long number)
void setNumberOfZero(unsigned int noz)
void setBaseName(const std::string &name)
long getImageNumber() const
void acquire(vpImage< unsigned char > &I)
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:130
static void display(const vpImage< unsigned char > &I)
static void flush(const vpImage< unsigned char > &I)
error that can be emitted by ViSP classes.
Definition: vpException.h:60
unsigned int getWidth() const
Definition: vpImage.h:242
unsigned int getHeight() const
Definition: vpImage.h:181
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1053
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:70
VISP_EXPORT int wait(double t0, double t)
VISP_EXPORT double measureTimeMs()