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