Visual Servoing Platform  version 3.6.1 under development (2024-03-28)
testPerformanceLUT.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 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  * Test performance between iteration and LUT.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <visp3/core/vpImage.h>
37 #include <visp3/core/vpIoTools.h>
38 #include <visp3/core/vpMath.h>
39 #include <visp3/io/vpImageIo.h>
40 #include <visp3/io/vpParseArgv.h>
41 
48 // List of allowed command line options
49 #define GETOPTARGS "cdi:o:t:h"
50 
51 /*
52  * Print the program options.
53  *
54  * \param name : Program name.
55  * \param badparam : Bad parameter name.
56  * \param ipath: Input image path.
57  * \param opath : Output image path.
58  * \param user : Username.
59  */
60 void usage(const char *name, const char *badparam, const std::string &ipath, const std::string &opath,
61  const std::string &user)
62 {
63  fprintf(stdout, "\n\
64 Test performance between methods to iterate over pixel image.\n\
65 \n\
66 SYNOPSIS\n\
67  %s [-i <input image path>] [-o <output image path>] [-t <nb threads>]\n\
68  [-h]\n\
69 ",
70 name);
71 
72  fprintf(stdout, "\n\
73 OPTIONS: Default\n\
74  -i <input image path> %s\n\
75  Set image input path.\n\
76  From this path read \"Klimt/Klimt.pgm\"\n\
77  image.\n\
78  Setting the VISP_INPUT_IMAGE_PATH environment\n\
79  variable produces the same behaviour than using\n\
80  this option.\n\
81 \n\
82  -o <output image path> %s\n\
83  Set image output path.\n\
84  From this directory, creates the \"%s\"\n\
85  subdirectory depending on the username, where \n\
86  Klimt_grey.pgm output image is written.\n\
87 \n\
88  -t <nb threads> \n\
89  Set the number of threads to use for the computation.\n\
90 \n\
91  -h\n\
92  Print the help.\n\n",
93  ipath.c_str(), opath.c_str(), user.c_str());
94 
95  if (badparam)
96  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
97 }
98 
110 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &opath, const std::string &user,
111  unsigned int &nbThreads)
112 {
113  const char *optarg_;
114  int c;
115  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
116 
117  switch (c) {
118  case 'i':
119  ipath = optarg_;
120  break;
121  case 'o':
122  opath = optarg_;
123  break;
124  case 't':
125  nbThreads = (unsigned int)atoi(optarg_);
126  break;
127  case 'h':
128  usage(argv[0], nullptr, ipath, opath, user);
129  return false;
130  break;
131 
132  case 'c':
133  case 'd':
134  break;
135 
136  default:
137  usage(argv[0], optarg_, ipath, opath, user);
138  return false;
139  break;
140  }
141  }
142 
143  if ((c == 1) || (c == -1)) {
144  // standalone param or error
145  usage(argv[0], nullptr, ipath, opath, user);
146  std::cerr << "ERROR: " << std::endl;
147  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
148  return false;
149  }
150 
151  return true;
152 }
153 
154 unsigned char getRandomValues(unsigned char min, unsigned char max)
155 {
156  return static_cast<unsigned char>((max - min) * static_cast<double>(rand()) / static_cast<double>(RAND_MAX) + min);
157 }
158 
159 void generateRandomImage(vpImage<unsigned char> &I, unsigned int min = 0, unsigned int max = 255)
160 {
161  for (unsigned int i = 0; i < I.getHeight(); ++i) {
162  for (unsigned int j = 0; j < I.getWidth(); ++j) {
163  I[i][j] = getRandomValues(min, max);
164  }
165  }
166 }
167 
168 void generateRandomImage(vpImage<vpRGBa> &I, unsigned int min = 0, unsigned int max = 255)
169 {
170  for (unsigned int i = 0; i < I.getHeight(); ++i) {
171  for (unsigned int j = 0; j < I.getWidth(); ++j) {
172  I[i][j].R = getRandomValues(min, max);
173  I[i][j].G = getRandomValues(min, max);
174  I[i][j].B = getRandomValues(min, max);
175  I[i][j].A = getRandomValues(min, max);
176  }
177  }
178 }
179 
188 void iterate_method1(vpImage<vpRGBa> &I, double alpha, double beta)
189 {
190  unsigned int size = I.getWidth() * I.getHeight();
191  unsigned char *ptrStart = (unsigned char *)I.bitmap;
192  unsigned char *ptrEnd = ptrStart + size * 4;
193  unsigned char *ptrCurrent = ptrStart;
194 
195  while (ptrCurrent != ptrEnd) {
196  *ptrCurrent = vpMath::saturate<unsigned char>((*ptrCurrent) * alpha + beta);
197  ++ptrCurrent;
198  }
199 }
200 
209 void iterate_method1(vpImage<unsigned char> &I, double alpha, double beta)
210 {
211  unsigned int size = I.getWidth() * I.getHeight();
212  unsigned char *ptrStart = (unsigned char *)I.bitmap;
213  unsigned char *ptrEnd = ptrStart + size;
214  unsigned char *ptrCurrent = ptrStart;
215 
216  while (ptrCurrent != ptrEnd) {
217  *ptrCurrent = vpMath::saturate<unsigned char>((*ptrCurrent) * alpha + beta);
218  ++ptrCurrent;
219  }
220 }
221 
230 void iterate_method2(vpImage<vpRGBa> &I, double alpha, double beta)
231 {
232  for (unsigned int i = 0; i < I.getHeight(); i++) {
233  for (unsigned int j = 0; j < I.getWidth(); j++) {
234  I[i][j].R = vpMath::saturate<unsigned char>(I[i][j].R * alpha + beta);
235  I[i][j].G = vpMath::saturate<unsigned char>(I[i][j].G * alpha + beta);
236  I[i][j].B = vpMath::saturate<unsigned char>(I[i][j].B * alpha + beta);
237  I[i][j].A = vpMath::saturate<unsigned char>(I[i][j].A * alpha + beta);
238  }
239  }
240 }
241 
242 int main(int argc, const char **argv)
243 {
244  try {
245  std::string env_ipath;
246  std::string opt_ipath;
247  std::string opt_opath;
248  std::string ipath;
249  std::string opath;
250  std::string filename;
251  std::string username;
252  unsigned int nbThreads = 4;
253 
254  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
255  // environment variable value
256  env_ipath = vpIoTools::getViSPImagesDataPath();
257 
258  // Set the default input path
259  if (!env_ipath.empty())
260  ipath = env_ipath;
261 
262 // Set the default output path
263 #if defined(_WIN32)
264  opt_opath = "C:/temp";
265 #else
266  opt_opath = "/tmp";
267 #endif
268 
269  // Get the user login name
270  vpIoTools::getUserName(username);
271 
272  // Read the command line options
273  if (getOptions(argc, argv, opt_ipath, opt_opath, username, nbThreads) == false) {
274  return EXIT_FAILURE;
275  }
276 
277  // Get the option values
278  if (!opt_ipath.empty())
279  ipath = opt_ipath;
280  if (!opt_opath.empty())
281  opath = opt_opath;
282 
283  // Append to the output path string, the login name of the user
284  opath = vpIoTools::createFilePath(opath, username);
285 
286  // Test if the output path exist. If no try to create it
287  if (vpIoTools::checkDirectory(opath) == false) {
288  try {
289  // Create the dirname
291  }
292  catch (...) {
293  usage(argv[0], nullptr, ipath, opt_opath, username);
294  std::cerr << std::endl << "ERROR:" << std::endl;
295  std::cerr << " Cannot create " << opath << std::endl;
296  std::cerr << " Check your -o " << opt_opath << " option " << std::endl;
297  return EXIT_FAILURE;
298  }
299  }
300 
301  // Compare ipath and env_ipath. If they differ, we take into account
302  // the input path coming from the command line option
303  if (!opt_ipath.empty() && !env_ipath.empty()) {
304  if (ipath != env_ipath) {
305  std::cout << std::endl << "WARNING: " << std::endl;
306  std::cout << " Since -i <visp image path=" << ipath << "> "
307  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
308  << " we skip the environment variable." << std::endl;
309  }
310  }
311 
312  // Test if an input path is set
313  if (opt_ipath.empty() && env_ipath.empty()) {
314  usage(argv[0], nullptr, ipath, opt_opath, username);
315  std::cerr << std::endl << "ERROR:" << std::endl;
316  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
317  << " environment variable to specify the location of the " << std::endl
318  << " image path where test images are located." << std::endl
319  << std::endl;
320  return EXIT_FAILURE;
321  }
322 
323  double alpha = 1.5, beta = -30.0;
324  unsigned int nbIterations = 10;
325 
326  //
327  // Here starts really the test
328  //
329  if (1) {
330  std::cout << "\n** Test LUT on color image" << std::endl;
331  // Create a color image
332  vpImage<vpRGBa> I_iterate1, I_iterate2, I_lut;
333 
334  // Load a color image from the disk
335  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
336  std::cout << "Read image: " << filename << std::endl;
337  vpImageIo::read(I_iterate1, filename);
338  vpImageIo::read(I_iterate2, filename);
339  vpImageIo::read(I_lut, filename);
340 
341  std::cout << "Image size: " << I_iterate1.getWidth() << "x" << I_iterate1.getHeight() << std::endl;
342 
343  // Iterate method 1
344  std::cout << "Run test n°1 " << nbIterations << " times" << std::endl;
345  double t_iterate1 = vpTime::measureTimeMs();
346  for (unsigned int cpt = 0; cpt < nbIterations; cpt++) {
347  iterate_method1(I_iterate1, alpha, beta);
348  }
349  t_iterate1 = vpTime::measureTimeMs() - t_iterate1;
350  std::cout << " Total time: " << t_iterate1 << " ms ; Mean time: "
351  << (t_iterate1 / nbIterations) << " ms" << std::endl;
352 
353  filename = vpIoTools::createFilePath(opath, "Klimt_performance_iterate1.ppm");
354  std::cout << " Save " << filename << std::endl;
355  vpImageIo::write(I_iterate1, filename);
356 
357  // Iterate method 2
358  std::cout << "Run test n°2 " << nbIterations << " times" << std::endl;
359  double t_iterate2 = vpTime::measureTimeMs();
360  for (unsigned int cpt = 0; cpt < nbIterations; cpt++) {
361  iterate_method2(I_iterate2, alpha, beta);
362  }
363  t_iterate2 = vpTime::measureTimeMs() - t_iterate2;
364  std::cout << " Total time: " << t_iterate2 << " ms ; Mean time: " << (t_iterate2 / nbIterations) << " ms" << std::endl;
365 
366  filename = vpIoTools::createFilePath(opath, "Klimt_performance_iterate2.ppm");
367  std::cout << " Save " << filename << std::endl;
368  vpImageIo::write(I_iterate2, filename);
369 
370  // Construct the LUT
371  vpRGBa lut[256];
372  for (unsigned int i = 0; i < 256; i++) {
373  lut[i].R = vpMath::saturate<unsigned char>(alpha * i + beta);
374  lut[i].G = vpMath::saturate<unsigned char>(alpha * i + beta);
375  lut[i].B = vpMath::saturate<unsigned char>(alpha * i + beta);
376  lut[i].A = vpMath::saturate<unsigned char>(alpha * i + beta);
377  }
378 
379  // LUT method
380  std::cout << "Run test n°3 " << nbIterations << " times" << std::endl;
381  double t_lut = vpTime::measureTimeMs();
382  for (unsigned int cpt = 0; cpt < nbIterations; cpt++) {
383  I_lut.performLut(lut, nbThreads);
384  }
385  t_lut = vpTime::measureTimeMs() - t_lut;
386  std::cout << " Total time: " << t_lut << " ms ; Mean time: " << (t_lut / nbIterations) << " ms" << std::endl;
387 
388  filename = vpIoTools::createFilePath(opath, "Klimt_performance_lut.ppm");
389  std::cout << " Save " << filename << std::endl;
390  vpImageIo::write(I_lut, filename);
391 
392  if ((I_iterate1 == I_iterate2) && (I_iterate1 == I_lut)) {
393  std::cerr << "Color images are the same" << std::endl;
394  }
395  else {
396  std::cerr << "Color images are different!" << std::endl;
397  std::cout << "Test failed" << std::endl;
398  return EXIT_FAILURE;
399  }
400  }
401  {
402  // Test LUT on grayscale image
403  std::cout << "\n** Test LUT on grayscale image" << std::endl;
404  vpImage<unsigned char> I_iterate_grayscale1, I_lut_grayscale;
405 
406  // Load a grayscale image from the disk
407  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
408  std::cout << "Read image: " << filename << std::endl;
409  vpImageIo::read(I_iterate_grayscale1, filename);
410  vpImageIo::read(I_lut_grayscale, filename);
411 
412  std::cout << "Image size: " << I_lut_grayscale.getWidth() << "x" << I_lut_grayscale.getHeight() << std::endl;
413 
414  // Iterate method 1 on grayscale
415  std::cout << "Run test n°1 " << nbIterations << " times" << std::endl;
416  double t_iterate_grayscale1 = vpTime::measureTimeMs();
417  for (unsigned int cpt = 0; cpt < nbIterations; cpt++) {
418  iterate_method1(I_iterate_grayscale1, alpha, beta);
419  }
420  t_iterate_grayscale1 = vpTime::measureTimeMs() - t_iterate_grayscale1;
421  std::cout << " Total time: " << t_iterate_grayscale1 << " ms ; Mean time: "
422  << (t_iterate_grayscale1 / nbIterations) << " ms" << std::endl;
423 
424  filename = vpIoTools::createFilePath(opath, "Klimt_performance_iterate1_grayscale.pgm");
425  std::cout << " Save result in " << filename << std::endl;
426  vpImageIo::write(I_iterate_grayscale1, filename);
427 
428  // Construct the LUT
429  unsigned char lut[256];
430  for (unsigned int i = 0; i < 256; i++) {
431  lut[i] = vpMath::saturate<unsigned char>(alpha * i + beta);
432  }
433 
434  // LUT method on grayscale
435  std::cout << "Run test n°2 " << nbIterations << " times with " << nbThreads << " threads" << std::endl;
436  double t_lut_grayscale = vpTime::measureTimeMs();
437  for (unsigned int cpt = 0; cpt < nbIterations; cpt++) {
438  I_lut_grayscale.performLut(lut, nbThreads);
439  }
440  t_lut_grayscale = vpTime::measureTimeMs() - t_lut_grayscale;
441  std::cout << " Total time: " << t_lut_grayscale << " ms ; Mean time: "
442  << (t_lut_grayscale / nbIterations) << " ms" << std::endl;
443 
444  filename = vpIoTools::createFilePath(opath, "Klimt_performance_lut_grayscale.pgm");
445  std::cout << " Save result in " << filename << std::endl;
446  vpImageIo::write(I_lut_grayscale, filename);
447 
448  // Check grayscale image
449  if (I_lut_grayscale == I_iterate_grayscale1) {
450  std::cout << "Grayscale images are same" << std::endl;
451  }
452  else {
453  std::cerr << "Grayscale images are different!" << std::endl;
454  std::cout << "Test failed" << std::endl;
455  return EXIT_FAILURE;
456  }
457  }
458  {
459  std::cout << "\n** Test multi-threaded LUT on color image" << std::endl;
460  vpImage<vpRGBa> I_lut_multi, I_lut_single;
461 
462  // Load a color image from the disk
463  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
464  std::cout << "Read image: " << filename << std::endl;
465  vpImageIo::read(I_lut_multi, filename);
466 
467  // Construct the LUT
468  vpRGBa lut[256];
469  for (unsigned int i = 0; i < 256; i++) {
470  lut[i].R = vpMath::saturate<unsigned char>(alpha * i + beta);
471  lut[i].G = vpMath::saturate<unsigned char>(alpha * i + beta);
472  lut[i].B = vpMath::saturate<unsigned char>(alpha * i + beta);
473  lut[i].A = vpMath::saturate<unsigned char>(alpha * i + beta);
474  }
475 
476  // Computation time on color image
477  std::cout << "Run test n°1 " << nbIterations* 10 << " times with " << nbThreads << " threads" << std::endl;
478  double t_lut_multithread = vpTime::measureTimeMs();
479  for (unsigned int cpt = 0; cpt < nbIterations * 10; cpt++) {
480  I_lut_multi.performLut(lut, nbThreads);
481  }
482  t_lut_multithread = vpTime::measureTimeMs() - t_lut_multithread;
483 
484  filename = vpIoTools::createFilePath(opath, "Klimt_performance_color_multi.ppm");
485  std::cout << " Save result in " << filename << std::endl;
486  vpImageIo::write(I_lut_multi, filename);
487 
488  vpImageIo::read(I_lut_single, filename);
489 
490  std::cout << "Run test n°2 " << nbIterations* 10 << " times in a single thread" << std::endl;
491  double t_lut_singlethread = vpTime::measureTimeMs();
492  for (unsigned int cpt = 0; cpt < nbIterations * 10; cpt++) {
493  I_lut_single.performLut(lut, 1);
494  }
495  t_lut_singlethread = vpTime::measureTimeMs() - t_lut_singlethread;
496 
497  filename = vpIoTools::createFilePath(opath, "Klimt_performance_color_single.ppm");
498  std::cout << " Save result in " << filename << std::endl;
499  vpImageIo::write(I_lut_single, filename);
500 
501  // Check color image
502  if (I_lut_multi == I_lut_single) {
503  std::cout << "Color images are the same" << std::endl;
504  std::cout << "Single-thread / multi-thread (color) gain: " << t_lut_singlethread / t_lut_multithread << std::endl;
505  }
506  else {
507  std::cerr << "Color images are different!" << std::endl;
508  std::cout << "Test failed" << std::endl;
509  return EXIT_FAILURE;
510  }
511  }
512  {
513  std::cout << "\n** Test multi-threaded LUT on gray image" << std::endl;
514  vpImage<unsigned char> I_lut_grayscale_multi, I_lut_grayscale_single;
515 
516  // Load a gray image from the disk
517  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
518 
519  std::cout << "Read image: " << filename << std::endl;
520  vpImageIo::read(I_lut_grayscale_multi, filename);
521 
522  // Construct the LUT
523  unsigned char lut[256];
524  for (unsigned int i = 0; i < 256; i++) {
525  lut[i] = vpMath::saturate<unsigned char>(alpha * i + beta);
526  }
527 
528  // Computation time on grayscale image
529  std::cout << "Run test n°1 " << nbIterations* 10 << " times with " << nbThreads << " threads" << std::endl;
530  double t_lut_multithread = vpTime::measureTimeMs();
531  for (unsigned int cpt = 0; cpt < nbIterations * 10; cpt++) {
532  I_lut_grayscale_multi.performLut(lut, nbThreads);
533  }
534  t_lut_multithread = vpTime::measureTimeMs() - t_lut_multithread;
535 
536  filename = vpIoTools::createFilePath(opath, "Klimt_performance_gray_multi.pgm");
537  std::cout << " Save result in " << filename << std::endl;
538  vpImageIo::write(I_lut_grayscale_multi, filename);
539 
540  vpImageIo::read(I_lut_grayscale_single, filename);
541 
542  std::cout << "Run test n°2 " << nbIterations* 10 << " times in a single thread" << std::endl;
543  double t_lut_singlethread = vpTime::measureTimeMs();
544  for (unsigned int cpt = 0; cpt < nbIterations * 10; cpt++) {
545  I_lut_grayscale_single.performLut(lut, 1);
546  }
547  t_lut_singlethread = vpTime::measureTimeMs() - t_lut_singlethread;
548 
549  filename = vpIoTools::createFilePath(opath, "Klimt_performance_gray_single.pgm");
550  std::cout << " Save result in " << filename << std::endl;
551  vpImageIo::write(I_lut_grayscale_single, filename);
552 
553  // Check color image
554  if (I_lut_grayscale_multi == I_lut_grayscale_single) {
555  std::cout << "Gray images are the same" << std::endl;
556  std::cout << "Single-thread / multi-thread (color) gain: " << t_lut_singlethread / t_lut_multithread << std::endl;
557  }
558  else {
559  std::cerr << "Color images are different!" << std::endl;
560  std::cout << "Test failed" << std::endl;
561  return EXIT_FAILURE;
562  }
563  }
564  {
565  std::cout << "\n** Test multi-threaded LUT on gray image which size is not divisible by 8" << std::endl;
566 
567  // Check performLut with multithreading and image size not divisible by 8
568  vpImage<unsigned char> I_test_grayscale_multi(49, 7), I_test_grayscale_single;
569  generateRandomImage(I_test_grayscale_multi);
570  I_test_grayscale_single = I_test_grayscale_multi;
571  // Construct the LUT
572  unsigned char lut_grayscale[256];
573  for (unsigned int i = 0; i < 256; i++) {
574  lut_grayscale[i] = vpMath::saturate<unsigned char>(alpha * i + beta);
575  }
576  std::cout << "Run test n°1 with " << nbThreads << " threads" << std::endl;
577  I_test_grayscale_multi.performLut(lut_grayscale, nbThreads);
578  std::cout << "Run test n°2 single threads" << std::endl;
579  I_test_grayscale_single.performLut(lut_grayscale, 1);
580 
581  // Check gray images
582  if (I_test_grayscale_multi == I_test_grayscale_single) {
583  std::cout << "Gray images are the same" << std::endl;
584  }
585  else {
586  std::cerr << "Gray images are different!" << std::endl;
587  std::cout << "Test failed" << std::endl;
588  return EXIT_FAILURE;
589  }
590  }
591  {
592  std::cout << "\n** Test multi-threaded LUT on color image which size is not divisible by 8" << std::endl;
593 
594  vpImage<vpRGBa> I_test_color_multi(49, 7), I_test_color_single;
595  generateRandomImage(I_test_color_multi);
596  I_test_color_single = I_test_color_multi;
597  // Construct the LUT
598  vpRGBa lut_color[256];
599  for (unsigned int i = 0; i < 256; i++) {
600  lut_color[i].R = vpMath::saturate<unsigned char>(alpha * i + beta);
601  lut_color[i].G = vpMath::saturate<unsigned char>(alpha * i + beta);
602  lut_color[i].B = vpMath::saturate<unsigned char>(alpha * i + beta);
603  lut_color[i].A = vpMath::saturate<unsigned char>(alpha * i + beta);
604  }
605  std::cout << "Run test n°1 with " << nbThreads << " threads" << std::endl;
606  I_test_color_multi.performLut(lut_color, nbThreads);
607  std::cout << "Run test n°2 single threads" << std::endl;
608  I_test_color_single.performLut(lut_color, 1);
609 
610  // Check color images
611  if (I_test_color_multi == I_test_color_single) {
612  std::cout << "Color images are the same" << std::endl;
613  }
614  else {
615  std::cerr << "Color images are different!" << std::endl;
616  std::cout << "Test failed" << std::endl;
617  return EXIT_FAILURE;
618  }
619  }
620  std::cout << "Test succeed" << std::endl;
621  return EXIT_SUCCESS;
622  }
623  catch (const vpException &e) {
624  std::cerr << "Catch an exception: " << e.what() << std::endl;
625  return EXIT_FAILURE;
626  }
627 }
error that can be emitted by ViSP classes.
Definition: vpException.h:59
const char * what() const
Definition: vpException.cpp:70
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:143
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:287
unsigned int getWidth() const
Definition: vpImage.h:245
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
Definition: vpImage.h:2277
Type * bitmap
points toward the bitmap
Definition: vpImage.h:139
unsigned int getHeight() const
Definition: vpImage.h:184
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1781
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:818
static std::string getUserName()
Definition: vpIoTools.cpp:711
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:2142
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:967
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
Definition: vpRGBa.h:61
unsigned char B
Blue component.
Definition: vpRGBa.h:139
unsigned char R
Red component.
Definition: vpRGBa.h:137
unsigned char G
Green component.
Definition: vpRGBa.h:138
unsigned char A
Additionnal component.
Definition: vpRGBa.h:140
VISP_EXPORT double measureTimeMs()