Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
displayGTK.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Read an image on the disk and display it using GTK.
32 */
41
42#include <iostream>
43
44#include <visp3/core/vpConfig.h>
45#include <visp3/core/vpDebug.h>
46
47#ifdef VISP_HAVE_GTK
48
49#include <stdio.h>
50#include <stdlib.h>
51
52#include <visp3/core/vpImage.h>
53#include <visp3/core/vpImagePoint.h>
54#include <visp3/core/vpIoTools.h>
55#include <visp3/gui/vpDisplayGTK.h>
56#include <visp3/io/vpImageIo.h>
57#include <visp3/io/vpParseArgv.h>
58
67
68// List of allowed command line options
69#define GETOPTARGS "cdi:o:h"
70
71#ifdef ENABLE_VISP_NAMESPACE
72using namespace VISP_NAMESPACE_NAME;
73#endif
74
86void usage(const char *name, const char *badparam, const std::string &ipath, const std::string &opath, const std::string &user)
87{
88 fprintf(stdout, "\n\
89Read an image on the disk, display it using GTK, display some\n\
90features (line, circle, characters) in overlay and finally write \n\
91the image and the overlayed features in an image on the disk\n\
92\n\
93SYNOPSIS\n\
94 %s [-i <input image path>] [-o <output image path>]\n\
95 [-c] [-d] [-h]\n \
96",
97name);
98
99 fprintf(stdout, "\n\
100OPTIONS: Default\n\
101 -i <input image path> %s\n\
102 Set image input path.\n\
103 From this path read \"Klimt/Klimt.pgm\"\n\
104 image.\n\
105 Setting the VISP_INPUT_IMAGE_PATH environment\n\
106 variable produces the same behaviour than using\n\
107 this option.\n\
108\n\
109 -o <output image path> %s\n\
110 Set image output path.\n\
111 From this directory, creates the \"%s\"\n\
112 subdirectory depending on the username, where \n\
113 Klimt_grey.overlay.ppm output image is written.\n\
114\n\
115 -c\n\
116 Disable the mouse click. Useful to automate the \n\
117 execution of this program without human intervention.\n\
118\n\
119 -d \n\
120 Disable the image display. This can be useful \n\
121 for automatic tests using crontab under Unix or \n\
122 using the task manager under Windows.\n\
123\n\
124 -h\n\
125 Print the help.\n\n",
126 ipath.c_str(), opath.c_str(), user.c_str());
127
128 if (badparam)
129 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
130}
131
149bool 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], nullptr, ipath, opath, user);
171 return false;
172
173 default:
174 usage(argv[0], optarg, ipath, opath, user);
175 return false;
176 }
177 }
178
179 if ((c == 1) || (c == -1)) {
180 // standalone param or error
181 usage(argv[0], nullptr, ipath, opath, user);
182 std::cerr << "ERROR: " << std::endl;
183 std::cerr << " Bad argument " << optarg << std::endl << std::endl;
184 return false;
185 }
186
187 return true;
188}
189
190int main(int argc, const char **argv)
191{
192 try {
193 std::string env_ipath;
194 std::string opt_ipath;
195 std::string opt_opath;
196 std::string ipath;
197 std::string opath;
198 std::string filename;
199 std::string username;
200 bool opt_click_allowed = true;
201 bool opt_display = true;
202
203 // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
204 // environment variable value
206
207 // Set the default input path
208 if (!env_ipath.empty())
209 ipath = env_ipath;
210
211 // Set the default output path
212#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
213 opt_opath = "/tmp";
214#elif defined(_WIN32)
215 opt_opath = "C:\\temp";
216#endif
217
218 // Get the user login name
219 vpIoTools::getUserName(username);
220
221 // Read the command line options
222 if (getOptions(argc, argv, opt_ipath, opt_opath, opt_click_allowed, username, opt_display) == false) {
223 return EXIT_FAILURE;
224 }
225
226 // Get the option values
227 if (!opt_ipath.empty())
228 ipath = opt_ipath;
229 if (!opt_opath.empty())
230 opath = opt_opath;
231
232 // Append to the output path string, the login name of the user
233 std::string odirname = vpIoTools::createFilePath(opath, username);
234
235 // Test if the output path exist. If no try to create it
236 if (vpIoTools::checkDirectory(odirname) == false) {
237 try {
238 // Create the dirname
239 vpIoTools::makeDirectory(odirname);
240 }
241 catch (...) {
242 usage(argv[0], nullptr, ipath, opath, username);
243 std::cerr << std::endl << "ERROR:" << std::endl;
244 std::cerr << " Cannot create " << odirname << std::endl;
245 std::cerr << " Check your -o " << opath << " option " << std::endl;
246 return EXIT_FAILURE;
247 }
248 }
249
250 // Compare ipath and env_ipath. If they differ, we take into account
251 // the input path coming from the command line option
252 if (!opt_ipath.empty() && !env_ipath.empty()) {
253 if (ipath != env_ipath) {
254 std::cout << std::endl << "WARNING: " << std::endl;
255 std::cout << " Since -i <visp image path=" << ipath << "> "
256 << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
257 << " we skip the environment variable." << std::endl;
258 }
259 }
260
261 // Test if an input path is set
262 if (opt_ipath.empty() && env_ipath.empty()) {
263 usage(argv[0], nullptr, ipath, opath, username);
264 std::cerr << std::endl << "ERROR:" << std::endl;
265 std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
266 << " environment variable to specify the location of the " << std::endl
267 << " image path where test images are located." << std::endl
268 << std::endl;
269 return EXIT_FAILURE;
270 }
271
272 // Create a grey level image
274 vpImagePoint ip, ip1, ip2;
275
276 // Load a grey image from the disk
277 filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
278 vpImageIo::read(I, filename);
279
280 // Create a display using X11
281 vpDisplayGTK display;
282
283 if (opt_display) {
284 // For this grey level image, open a X11 display at position 100,100
285 // in the screen, and with title "X11 display"
286 display.init(I, 100, 100, "X11 display");
287
288 // Display the image
290
291 // Display in overlay a red cross at position 10,10 in the
292 // image. The lines are 10 pixels long
293 ip.set_i(100);
294 ip.set_j(10);
295
297
298 // Display in overlay horizontal red lines
299 for (unsigned i = 0; i < I.getHeight(); i += 20) {
300 ip1.set_i(i);
301 ip1.set_j(0);
302 ip2.set_i(i);
303 ip2.set_j(I.getWidth());
305 }
306
307 // Display a ligne in the diagonal
308 ip1.set_i(-10);
309 ip1.set_j(-10);
310 ip2.set_i(I.getHeight() + 10);
311 ip2.set_j(I.getWidth() + 10);
312
314
315 // Display in overlay vertical green dot lines
316 for (unsigned i = 0; i < I.getWidth(); i += 20) {
317 ip1.set_i(0);
318 ip1.set_j(i);
319 ip2.set_i(I.getWidth());
320 ip2.set_j(i);
322 }
323
324 // Display a rectangle
325 ip.set_i(I.getHeight() - 45);
326 ip.set_j(-10);
328
329 // Display in overlay a blue arrow
330 ip1.set_i(0);
331 ip1.set_j(0);
332 ip2.set_i(100);
333 ip2.set_j(100);
335
336 // Display in overlay some circles. The position of the center is 200,
337 // 200 the radius is increased by 20 pixels for each circle
338
339 for (unsigned int i = 0; i < 100; i += 20) {
340 ip.set_i(80);
341 ip.set_j(80);
343 }
344
345 ip.set_i(-10);
346 ip.set_j(300);
348
349 // Display in overlay a yellow string
350 ip.set_i(85);
351 ip.set_j(100);
352 vpDisplay::displayText(I, ip, "ViSP is a marvelous software", vpColor::yellow);
353 // Flush the display
355
356 // Create a color image
357 vpImage<vpRGBa> Ioverlay;
358 // Updates the color image with the original loaded image and the
359 // overlay
360 vpDisplay::getImage(I, Ioverlay);
361
362 // Write the color image on the disk
363 filename = vpIoTools::createFilePath(odirname, "Klimt_grey.overlay.ppm");
364 vpImageIo::write(Ioverlay, filename);
365
366 // If click is allowed, wait for a mouse click to close the display
367 if (opt_click_allowed) {
368 std::cout << "\nA click to close the windows..." << std::endl;
369 // Wait for a blocking mouse click
371 }
372
373 // Close the display
375 }
376
377 // Create a color image
378 vpImage<vpRGBa> Irgba;
379
380 // Load a grey image from the disk and convert it to a color image
381 filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
382 vpImageIo::read(Irgba, filename);
383
384 // Create a new display
385 vpDisplayGTK displayRGBa;
386
387 if (opt_display) {
388 // For this color image, open a X11 display at position 100,100
389 // in the screen, and with title "X11 color display"
390 displayRGBa.init(Irgba, 100, 100, "X11 color display");
391
392 // Display the color image
393 vpDisplay::display(Irgba);
394 vpDisplay::flush(Irgba);
395
396 // If click is allowed, wait for a blocking mouse click to display a
397 // cross at the clicked pixel position
398 if (opt_click_allowed) {
399 std::cout << "\nA click to display a cross..." << std::endl;
400 // Blocking wait for a click. Get the position of the selected pixel
401 // (i correspond to the row and j to the column coordinates in the
402 // image)
403 vpDisplay::getClick(Irgba, ip);
404 // Display a red cross on the click pixel position
405 std::cout << "Cross position: " << ip << std::endl;
407 }
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;
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 }
439 catch (const vpException &e) {
440 std::cout << "Catch an exception: " << e << std::endl;
441 return EXIT_FAILURE;
442 }
443}
444#else
445int main()
446{
447 std::cout << "You do not have GTK functionalities to display images..." << std::endl;
448 std::cout << "Tip:" << std::endl;
449 std::cout << "- Install GTK, configure again ViSP using cmake and build again this example" << std::endl;
450 return EXIT_SUCCESS;
451}
452#endif
static const vpColor red
Definition vpColor.h:198
static const vpColor orange
Definition vpColor.h:208
static const vpColor blue
Definition vpColor.h:204
static const vpColor yellow
Definition vpColor.h:206
static const vpColor green
Definition vpColor.h:201
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
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)
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)
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void set_j(double jj)
void set_i(double ii)
Definition of the vpImage class member functions.
Definition vpImage.h:131
static std::string getViSPImagesDataPath()
static bool checkDirectory(const std::string &dirname)
static std::string getUserName()
static std::string createFilePath(const std::string &parent, const std::string &child)
static void makeDirectory(const std::string &dirname)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)