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