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