Visual Servoing Platform  version 3.6.1 under development (2024-03-29)
vpImage.h
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  * Image handling.
32  */
33 
39 #ifndef vpImage_H
40 #define vpImage_H
41 
42 #include <visp3/core/vpConfig.h>
43 #include <visp3/core/vpDebug.h>
44 #include <visp3/core/vpEndian.h>
45 #include <visp3/core/vpException.h>
46 #include <visp3/core/vpImageException.h>
47 #include <visp3/core/vpImagePoint.h>
48 #include <visp3/core/vpRGBa.h>
49 #include <visp3/core/vpRGBf.h>
50 
51 #if defined(VISP_HAVE_THREADS)
52 #include <thread>
53 #endif
54 
55 #include <fstream>
56 #include <iomanip> // std::setw
57 #include <iostream>
58 #include <math.h>
59 #include <string.h>
60 
61 // Visual Studio 2010 or previous is missing inttypes.h
62 #if defined(_MSC_VER) && (_MSC_VER < 1700)
63 typedef long long int64_t;
64 typedef unsigned short uint16_t;
65 #else
66 #include <inttypes.h>
67 #endif
68 
69 class vpDisplay;
70 
121 // Ref: http://en.cppreference.com/w/cpp/language/friend#Template_friends
122 template <class Type> class vpImage; // forward declare to make function declaration possible
123 
124 // declarations
125 template <class Type> std::ostream &operator<<(std::ostream &, const vpImage<Type> &);
126 
127 std::ostream &operator<<(std::ostream &, const vpImage<unsigned char> &);
128 std::ostream &operator<<(std::ostream &, const vpImage<char> &);
129 std::ostream &operator<<(std::ostream &, const vpImage<float> &);
130 std::ostream &operator<<(std::ostream &, const vpImage<double> &);
131 
132 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second);
133 
134 template <class Type> class vpImage
135 {
136  friend class vpImageConvert;
137 
138 public:
139  Type *bitmap;
141 
146 #if ((__cplusplus >= 201103L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L))) // Check if cxx11 or higher
148  vpImage(vpImage<Type> &&);
149 #endif
151  vpImage(unsigned int height, unsigned int width);
153  vpImage(unsigned int height, unsigned int width, Type value);
155  vpImage(Type *const array, unsigned int height, unsigned int width, bool copyData = false);
157  virtual ~vpImage();
158 
161 
162  // destructor
163  void destroy();
164 
165  // Returns a new image that's double size of the current image
167 
175  inline unsigned int getCols() const { return width; }
184  inline unsigned int getHeight() const { return height; }
185 
186  // Return the maximum value within the bitmap
187  Type getMaxValue(bool onlyFiniteVal = true) const;
188  // Return the mean value of the bitmap
189  double getMeanValue(const vpImage<bool> *p_mask = nullptr, unsigned int *nbValidPoints = nullptr) const;
190 
191  // Return the minumum value within the bitmap
192  Type getMinValue(bool onlyFiniteVal = true) const;
193  // Look for the minumum and the maximum value within the bitmap
194  void getMinMaxValue(Type &min, Type &max, bool onlyFiniteVal = true) const;
195  // Look for the minumum and the maximum value within the bitmap and get their location
196  void getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal = nullptr, Type *maxVal = nullptr) const;
197 
206  inline unsigned int getNumberOfPixel() const { return npixels; }
207 
215  inline unsigned int getRows() const { return height; }
216 
224  inline unsigned int getSize() const { return width * height; }
225 
226  double getStdev(const vpImage<bool> *p_mask = nullptr, unsigned int *nbValidPoints = nullptr) const;
227  double getStdev(const double &mean, const vpImage<bool> *p_mask = nullptr, unsigned int *nbValidPoints = nullptr) const;
228 
229  double getSum(const vpImage<bool> *p_mask = nullptr, unsigned int *nbValidPoints = nullptr) const;
230 
231  // Gets the value of a pixel at a location.
232  Type getValue(unsigned int i, unsigned int j) const;
233  // Gets the value of a pixel at a location with bilinear interpolation.
234  Type getValue(double i, double j) const;
235  // Gets the value of a pixel at a location with bilinear interpolation.
236  Type getValue(const vpImagePoint &ip) const;
237 
245  inline unsigned int getWidth() const { return width; }
246 
247  // Returns a new image that's half size of the current image
248  void halfSizeImage(vpImage<Type> &res) const;
249 
251  void init(unsigned int height, unsigned int width);
253  void init(unsigned int height, unsigned int width, Type value);
255  void init(Type *const array, unsigned int height, unsigned int width, bool copyData = false);
256  void insert(const vpImage<Type> &src, const vpImagePoint &topLeft);
257 
258  //------------------------------------------------------------------
259  // Access to the image
260 
262  inline Type *operator[](unsigned int i) { return row[i]; }
263  inline Type *operator[](int i) { return row[i]; }
264 
266  inline const Type *operator[](unsigned int i) const { return row[i]; }
267  inline const Type *operator[](int i) const { return row[i]; }
268 
275  inline Type operator()(unsigned int i, unsigned int j) const { return bitmap[i * width + j]; }
276 
281  inline void operator()(unsigned int i, unsigned int j, const Type &v) { bitmap[i * width + j] = v; }
282 
293  inline Type operator()(const vpImagePoint &ip) const
294  {
295  unsigned int i = (unsigned int)ip.get_i();
296  unsigned int j = (unsigned int)ip.get_j();
297 
298  return bitmap[i * width + j];
299  }
300 
309  inline void operator()(const vpImagePoint &ip, const Type &v)
310  {
311  unsigned int i = (unsigned int)ip.get_i();
312  unsigned int j = (unsigned int)ip.get_j();
313 
314  bitmap[i * width + j] = v;
315  }
316 
318 
321 
322  vpImage<Type> &operator=(const Type &v);
323  bool operator==(const vpImage<Type> &I) const;
324  bool operator!=(const vpImage<Type> &I) const;
325  friend std::ostream &operator<< <>(std::ostream &s, const vpImage<Type> &I);
326  friend std::ostream &operator<<(std::ostream &s, const vpImage<unsigned char> &I);
327  friend std::ostream &operator<<(std::ostream &s, const vpImage<char> &I);
328  friend std::ostream &operator<<(std::ostream &s, const vpImage<float> &I);
329  friend std::ostream &operator<<(std::ostream &s, const vpImage<double> &I);
330 
331  // Perform a look-up table transformation
332  void performLut(const Type(&lut)[256], unsigned int nbThreads = 1);
333 
334  // Returns a new image that's a quarter size of the current image
335  void quarterSizeImage(vpImage<Type> &res) const;
336 
337  // set the size of the image without initializing it.
338  void resize(unsigned int h, unsigned int w);
339  // set the size of the image and initialize it.
340  void resize(unsigned int h, unsigned int w, const Type &val);
341 
342  void sub(const vpImage<Type> &B, vpImage<Type> &C) const;
343  void sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C) const;
344  void subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const;
345 
346  friend void swap<>(vpImage<Type> &first, vpImage<Type> &second);
347 
349 
350 private:
351  unsigned int npixels;
352  unsigned int width;
353  unsigned int height;
354  Type **row;
355  bool hasOwnership;
356 };
357 
358 template <class Type> std::ostream &operator<<(std::ostream &s, const vpImage<Type> &I)
359 {
360  if (I.bitmap == nullptr) {
361  return s;
362  }
363 
364  for (unsigned int i = 0; i < I.getHeight(); i++) {
365  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
366  s << I[i][j] << " ";
367  }
368 
369  // We don't add " " after the last column element
370  s << I[i][I.getWidth() - 1];
371 
372  // We don't add a \n character at the end of the last row line
373  if (i < I.getHeight() - 1) {
374  s << std::endl;
375  }
376  }
377 
378  return s;
379 }
380 
381 inline std::ostream &operator<<(std::ostream &s, const vpImage<unsigned char> &I)
382 {
383  if (I.bitmap == nullptr) {
384  return s;
385  }
386 
387  std::ios_base::fmtflags original_flags = s.flags();
388 
389  for (unsigned int i = 0; i < I.getHeight(); i++) {
390  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
391  s << std::setw(3) << static_cast<unsigned>(I[i][j]) << " ";
392  }
393 
394  // We don't add " " after the last column element
395  s << std::setw(3) << static_cast<unsigned>(I[i][I.getWidth() - 1]);
396 
397  // We don't add a \n character at the end of the last row line
398  if (i < I.getHeight() - 1) {
399  s << std::endl;
400  }
401  }
402 
403  s.flags(original_flags); // restore s to standard state
404  return s;
405 }
406 
407 inline std::ostream &operator<<(std::ostream &s, const vpImage<char> &I)
408 {
409  if (I.bitmap == nullptr) {
410  return s;
411  }
412 
413  std::ios_base::fmtflags original_flags = s.flags();
414 
415  for (unsigned int i = 0; i < I.getHeight(); i++) {
416  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
417  s << std::setw(4) << static_cast<int>(I[i][j]) << " ";
418  }
419 
420  // We don't add " " after the last column element
421  s << std::setw(4) << static_cast<int>(I[i][I.getWidth() - 1]);
422 
423  // We don't add a \n character at the end of the last row line
424  if (i < I.getHeight() - 1) {
425  s << std::endl;
426  }
427  }
428 
429  s.flags(original_flags); // restore s to standard state
430  return s;
431 }
432 
433 inline std::ostream &operator<<(std::ostream &s, const vpImage<float> &I)
434 {
435  if (I.bitmap == nullptr) {
436  return s;
437  }
438 
439  std::ios_base::fmtflags original_flags = s.flags();
440  s.precision(9); // http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
441 
442  for (unsigned int i = 0; i < I.getHeight(); i++) {
443  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
444  s << I[i][j] << " ";
445  }
446 
447  // We don't add " " after the last column element
448  s << I[i][I.getWidth() - 1];
449 
450  // We don't add a \n character at the end of the last row line
451  if (i < I.getHeight() - 1) {
452  s << std::endl;
453  }
454  }
455 
456  s.flags(original_flags); // restore s to standard state
457  return s;
458 }
459 
460 inline std::ostream &operator<<(std::ostream &s, const vpImage<double> &I)
461 {
462  if (I.bitmap == nullptr) {
463  return s;
464  }
465 
466  std::ios_base::fmtflags original_flags = s.flags();
467  s.precision(17); // http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
468 
469  for (unsigned int i = 0; i < I.getHeight(); i++) {
470  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
471  s << I[i][j] << " ";
472  }
473 
474  // We don't add " " after the last column element
475  s << I[i][I.getWidth() - 1];
476 
477  // We don't add a \n character at the end of the last row line
478  if (i < I.getHeight() - 1) {
479  s << std::endl;
480  }
481  }
482 
483  s.flags(original_flags); // restore s to standard state
484  return s;
485 }
486 
487 #if defined(VISP_HAVE_THREADS)
488 namespace
489 {
490 struct vpImageLut_Param_t
491 {
492  unsigned int m_start_index;
493  unsigned int m_end_index;
494 
495  unsigned char m_lut[256];
496  unsigned char *m_bitmap;
497 
498  vpImageLut_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_bitmap(nullptr) { }
499 
500  vpImageLut_Param_t(unsigned int start_index, unsigned int end_index, unsigned char *bitmap)
501  : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
502  { }
503 };
504 
505 void performLutThread(vpImageLut_Param_t *imageLut_param)
506 {
507  unsigned int start_index = imageLut_param->m_start_index;
508  unsigned int end_index = imageLut_param->m_end_index;
509 
510  unsigned char *bitmap = imageLut_param->m_bitmap;
511 
512  unsigned char *ptrStart = bitmap + start_index;
513  unsigned char *ptrEnd = bitmap + end_index;
514  unsigned char *ptrCurrent = ptrStart;
515 
516  if (end_index - start_index >= 8) {
517  // Unroll loop version
518  for (; ptrCurrent <= ptrEnd - 8;) {
519  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
520  ++ptrCurrent;
521 
522  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
523  ++ptrCurrent;
524 
525  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
526  ++ptrCurrent;
527 
528  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
529  ++ptrCurrent;
530 
531  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
532  ++ptrCurrent;
533 
534  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
535  ++ptrCurrent;
536 
537  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
538  ++ptrCurrent;
539 
540  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
541  ++ptrCurrent;
542  }
543  }
544 
545  for (; ptrCurrent != ptrEnd; ++ptrCurrent) {
546  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
547  }
548 }
549 
550 struct vpImageLutRGBa_Param_t
551 {
552  unsigned int m_start_index;
553  unsigned int m_end_index;
554 
555  vpRGBa m_lut[256];
556  unsigned char *m_bitmap;
557 
558  vpImageLutRGBa_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_bitmap(nullptr) { }
559 
560  vpImageLutRGBa_Param_t(unsigned int start_index, unsigned int end_index, unsigned char *bitmap)
561  : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
562  { }
563 };
564 
565 void performLutRGBaThread(vpImageLutRGBa_Param_t *imageLut_param)
566 {
567  unsigned int start_index = imageLut_param->m_start_index;
568  unsigned int end_index = imageLut_param->m_end_index;
569 
570  unsigned char *bitmap = imageLut_param->m_bitmap;
571 
572  unsigned char *ptrStart = bitmap + start_index * 4;
573  unsigned char *ptrEnd = bitmap + end_index * 4;
574  unsigned char *ptrCurrent = ptrStart;
575 
576  if (end_index - start_index >= 4 * 2) {
577  // Unroll loop version
578  for (; ptrCurrent <= ptrEnd - 4 * 2;) {
579  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
580  ptrCurrent++;
581  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
582  ptrCurrent++;
583  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
584  ptrCurrent++;
585  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
586  ptrCurrent++;
587 
588  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
589  ptrCurrent++;
590  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
591  ptrCurrent++;
592  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
593  ptrCurrent++;
594  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
595  ptrCurrent++;
596  }
597  }
598 
599  while (ptrCurrent != ptrEnd) {
600  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
601  ptrCurrent++;
602 
603  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
604  ptrCurrent++;
605 
606  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
607  ptrCurrent++;
608 
609  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
610  ptrCurrent++;
611  }
612 }
613 } // namespace
614 #endif
615 
619 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w, Type value)
620 {
621  init(h, w);
622 
623  // for (unsigned int i = 0; i < npixels; i++)
624  // bitmap[i] = value;
625  std::fill(bitmap, bitmap + npixels, value);
626 }
627 
631 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w)
632 {
633  if (h != this->height) {
634  if (row != nullptr) {
635  delete[] row;
636  row = nullptr;
637  }
638  }
639 
640  if ((h != this->height) || (w != this->width)) {
641  if (bitmap != nullptr) {
642  if (hasOwnership) {
643  delete[] bitmap;
644  }
645  bitmap = nullptr;
646  }
647  }
648 
649  this->width = w;
650  this->height = h;
651 
652  npixels = width * height;
653 
654  if (bitmap == nullptr) {
655  bitmap = new Type[npixels];
656  hasOwnership = true;
657  }
658  if (bitmap == nullptr) {
659  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
660  }
661  if (row == nullptr)
662  row = new Type *[height];
663  if (row == nullptr) {
664  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
665  }
666 
667  for (unsigned int i = 0; i < height; i++)
668  row[i] = bitmap + i * width;
669 }
670 
674 template <class Type> void vpImage<Type>::init(Type *const array, unsigned int h, unsigned int w, bool copyData)
675 {
676  if (h != this->height) {
677  if (row != nullptr) {
678  delete[] row;
679  row = nullptr;
680  }
681  }
682 
683  // Delete bitmap if copyData==false, otherwise only if the dimension differs
684  if ((copyData && ((h != this->height) || (w != this->width))) || !copyData) {
685  if (bitmap != nullptr) {
686  if (hasOwnership) {
687  delete[] bitmap;
688  }
689  bitmap = nullptr;
690  }
691  }
692 
693  hasOwnership = copyData;
694  this->width = w;
695  this->height = h;
696 
697  npixels = width * height;
698 
699  if (copyData) {
700  if (bitmap == nullptr)
701  bitmap = new Type[npixels];
702 
703  if (bitmap == nullptr) {
704  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
705  }
706 
707  // Copy the image data
708  memcpy(static_cast<void *>(bitmap), static_cast<void *>(array), (size_t)(npixels * sizeof(Type)));
709  }
710  else {
711  // Copy the address of the array in the bitmap
712  bitmap = array;
713  }
714 
715  if (row == nullptr)
716  row = new Type *[height];
717  if (row == nullptr) {
718  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
719  }
720 
721  for (unsigned int i = 0; i < height; i++) {
722  row[i] = bitmap + i * width;
723  }
724 }
725 
729 template <class Type>
730 vpImage<Type>::vpImage(unsigned int h, unsigned int w)
731  : bitmap(nullptr), display(nullptr), npixels(0), width(0), height(0), row(nullptr), hasOwnership(true)
732 {
733  init(h, w, 0);
734 }
735 
739 template <class Type>
740 vpImage<Type>::vpImage(unsigned int h, unsigned int w, Type value)
741  : bitmap(nullptr), display(nullptr), npixels(0), width(0), height(0), row(nullptr), hasOwnership(true)
742 {
743  init(h, w, value);
744 }
745 
749 template <class Type>
750 vpImage<Type>::vpImage(Type *const array, unsigned int h, unsigned int w, bool copyData)
751  : bitmap(nullptr), display(nullptr), npixels(0), width(0), height(0), row(nullptr), hasOwnership(true)
752 {
753  init(array, h, w, copyData);
754 }
755 
759 template <class Type>
760 vpImage<Type>::vpImage() : bitmap(nullptr), display(nullptr), npixels(0), width(0), height(0), row(nullptr), hasOwnership(true)
761 { }
762 
783 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w) { init(h, w); }
784 
804 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w, const Type &val) { init(h, w, val); }
805 
812 template <class Type> void vpImage<Type>::destroy()
813 {
814  if (bitmap != nullptr) {
815  if (hasOwnership) {
816  delete[] bitmap;
817  }
818  bitmap = nullptr;
819  }
820 
821  if (row != nullptr) {
822  delete[] row;
823  row = nullptr;
824  }
825 }
826 
833 template <class Type> vpImage<Type>::~vpImage() { destroy(); }
834 
838 template <class Type>
840  : bitmap(nullptr), display(nullptr), npixels(0), width(0), height(0), row(nullptr), hasOwnership(true)
841 {
842  resize(I.getHeight(), I.getWidth());
843  if (bitmap) {
844  memcpy(static_cast<void *>(bitmap), static_cast<void *>(I.bitmap), I.npixels * sizeof(Type));
845  }
846 }
847 
848 #if ((__cplusplus >= 201103L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L))) // Check if cxx11 or higher
852 template <class Type>
854  : bitmap(I.bitmap), display(I.display), npixels(I.npixels), width(I.width), height(I.height), row(I.row),
855  hasOwnership(I.hasOwnership)
856 {
857  I.bitmap = nullptr;
858  I.display = nullptr;
859  I.npixels = 0;
860  I.width = 0;
861  I.height = 0;
862  I.row = nullptr;
863  I.hasOwnership = false;
864 }
865 #endif
866 
874 template <class Type> Type vpImage<Type>::getMaxValue(bool onlyFiniteVal) const
875 {
876  if (npixels == 0)
877  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
878  Type m = bitmap[0];
879  for (unsigned int i = 0; i < npixels; i++) {
880  if (bitmap[i] > m) {
881  m = bitmap[i];
882  }
883  }
884  (void)onlyFiniteVal;
885  return m;
886 }
887 
896 template <> inline double vpImage<double>::getMaxValue(bool onlyFiniteVal) const
897 {
898  if (npixels == 0)
899  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
900  double m = bitmap[0];
901  if (onlyFiniteVal) {
902  for (unsigned int i = 0; i < npixels; i++) {
903  if (bitmap[i] > m && vpMath::isFinite(bitmap[i]))
904  m = bitmap[i];
905  }
906  }
907  else {
908  for (unsigned int i = 0; i < npixels; i++) {
909  if (bitmap[i] > m)
910  m = bitmap[i];
911  }
912  }
913  return m;
914 }
915 
924 template <> inline float vpImage<float>::getMaxValue(bool onlyFiniteVal) const
925 {
926  if (npixels == 0)
927  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
928  float m = bitmap[0];
929  if (onlyFiniteVal) {
930  for (unsigned int i = 0; i < npixels; i++) {
931  if (bitmap[i] > m && vpMath::isFinite(bitmap[i]))
932  m = bitmap[i];
933  }
934  }
935  else {
936  for (unsigned int i = 0; i < npixels; i++) {
937  if (bitmap[i] > m)
938  m = bitmap[i];
939  }
940  }
941  return m;
942 }
943 
954 template <class Type> double vpImage<Type>::getMeanValue(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
955 {
956  if ((height == 0) || (width == 0)) {
957  return 0.0;
958  }
959  unsigned int nbPointsInMask = 0;
960  double sum = getSum(p_mask, &nbPointsInMask);
961  if (nbPointsInMask == 0) {
962  throw(vpException(vpException::divideByZeroError, "Division by zero in vpImage::getMeanValue()"));
963  }
964  if (nbValidPoints) {
965  *nbValidPoints = nbPointsInMask;
966  }
967  return sum / nbPointsInMask;
968 }
969 
985 template <class Type> double vpImage<Type>::getStdev(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
986 {
987  double mean = getMeanValue(p_mask, nbValidPoints);
988  return getStdev(mean, p_mask);
989 }
990 
1009 template <class Type> double vpImage<Type>::getStdev(const double &mean, const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
1010 {
1011  if ((height == 0) || (width == 0)) {
1012  return 0.0;
1013  }
1014  const unsigned int size = width * height;
1015  double sum = 0.;
1016  unsigned int nbPointsInMask = 0;
1017  if (p_mask) {
1018  if (p_mask->getWidth() != width || p_mask->getHeight() != height) {
1019  throw(vpException(vpException::fatalError, "Cannot compute standard deviation: image and mask size differ"));
1020  }
1021  for (unsigned int i = 0; i < size; ++i) {
1022  if (p_mask->bitmap[i]) {
1023  sum += (bitmap[i] - mean) * (bitmap[i] - mean);
1024  ++nbPointsInMask;
1025  }
1026  }
1027  }
1028  else {
1029  for (unsigned int i = 0; i < size; ++i) {
1030  sum += (bitmap[i] - mean) * (bitmap[i] - mean);
1031  }
1032  nbPointsInMask = size;
1033  }
1034  sum /= static_cast<double>(nbPointsInMask);
1035  if (nbValidPoints) {
1036  *nbValidPoints = nbPointsInMask;
1037  }
1038  return std::sqrt(sum);
1039 }
1040 
1041 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1060 template <> inline double vpImage<vpRGBa>::getStdev(const double &mean, const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
1061 {
1062  if ((height == 0) || (width == 0)) {
1063  return 0.0;
1064  }
1065  const unsigned int size = width * height;
1066  double sum = 0.;
1067  unsigned int nbPointsInMask = 0;
1068  if (p_mask) {
1069  if (p_mask->getWidth() != width || p_mask->getHeight() != height) {
1070  throw(vpException(vpException::fatalError, "Cannot compute standard deviation: image and mask size differ"));
1071  }
1072  for (unsigned int i = 0; i < size; ++i) {
1073  if (p_mask->bitmap[i]) {
1074  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1075  sum += (val - mean) * (val - mean);
1076  ++nbPointsInMask;
1077  }
1078  }
1079  }
1080  else {
1081  for (unsigned int i = 0; i < size; ++i) {
1082  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1083  sum += (val - mean) * (val - mean);
1084  }
1085  nbPointsInMask = size;
1086  }
1087  sum /= static_cast<double>(nbPointsInMask);
1088  if (nbValidPoints) {
1089  *nbValidPoints = nbPointsInMask;
1090  }
1091  return std::sqrt(sum);
1092 }
1093 
1112 template <> inline double vpImage<vpRGBf>::getStdev(const double &mean, const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
1113 {
1114  if ((height == 0) || (width == 0)) {
1115  return 0.0;
1116  }
1117  const unsigned int size = width * height;
1118  double sum = 0.;
1119  unsigned int nbPointsInMask = 0;
1120  if (p_mask) {
1121  if (p_mask->getWidth() != width || p_mask->getHeight() != height) {
1122  throw(vpException(vpException::fatalError, "Cannot compute standard deviation: image and mask size differ"));
1123  }
1124  for (unsigned int i = 0; i < size; ++i) {
1125  if (p_mask->bitmap[i]) {
1126  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1127  sum += (val - mean) * (val - mean);
1128  ++nbPointsInMask;
1129  }
1130  }
1131  }
1132  else {
1133  for (unsigned int i = 0; i < size; ++i) {
1134  double val = static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
1135  sum += (val - mean) * (val - mean);
1136  }
1137  nbPointsInMask = size;
1138  }
1139  sum /= static_cast<double>(nbPointsInMask);
1140  if (nbValidPoints) {
1141  *nbValidPoints = nbPointsInMask;
1142  }
1143  return std::sqrt(sum);
1144 }
1145 #endif // DOXYGEN_SHOULD_SKIP_THIS
1146 
1154 template <class Type> Type vpImage<Type>::getMinValue(bool onlyFiniteVal) const
1155 {
1156  if (npixels == 0)
1157  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
1158  Type m = bitmap[0];
1159  for (unsigned int i = 0; i < npixels; i++) {
1160  if (bitmap[i] < m) {
1161  m = bitmap[i];
1162  }
1163  }
1164  (void)onlyFiniteVal;
1165  return m;
1166 }
1167 
1176 template <> inline double vpImage<double>::getMinValue(bool onlyFiniteVal) const
1177 {
1178  if (npixels == 0)
1179  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
1180  double m = bitmap[0];
1181  if (onlyFiniteVal) {
1182  for (unsigned int i = 0; i < npixels; i++)
1183  if (bitmap[i] < m && vpMath::isFinite(bitmap[i]))
1184  m = bitmap[i];
1185  }
1186  else {
1187  for (unsigned int i = 0; i < npixels; i++)
1188  if (bitmap[i] < m)
1189  m = bitmap[i];
1190  }
1191  return m;
1192 }
1193 
1202 template <> inline float vpImage<float>::getMinValue(bool onlyFiniteVal) const
1203 {
1204  if (npixels == 0)
1205  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
1206  float m = bitmap[0];
1207  if (onlyFiniteVal) {
1208  for (unsigned int i = 0; i < npixels; i++)
1209  if (bitmap[i] < m && vpMath::isFinite(bitmap[i]))
1210  m = bitmap[i];
1211  }
1212  else {
1213  for (unsigned int i = 0; i < npixels; i++)
1214  if (bitmap[i] < m)
1215  m = bitmap[i];
1216  }
1217  return m;
1218 }
1219 
1230 template <class Type> void vpImage<Type>::getMinMaxValue(Type &min, Type &max, bool onlyFiniteVal) const
1231 {
1232  if (npixels == 0)
1233  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1234 
1235  min = max = bitmap[0];
1236  for (unsigned int i = 0; i < npixels; i++) {
1237  if (bitmap[i] < min)
1238  min = bitmap[i];
1239  if (bitmap[i] > max)
1240  max = bitmap[i];
1241  }
1242  (void)onlyFiniteVal;
1243 }
1244 
1256 template <> inline void vpImage<double>::getMinMaxValue(double &min, double &max, bool onlyFiniteVal) const
1257 {
1258  if (npixels == 0)
1259  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1260 
1261  min = max = bitmap[0];
1262  if (onlyFiniteVal) {
1263  for (unsigned int i = 0; i < npixels; i++) {
1264  if (vpMath::isFinite(bitmap[i])) {
1265  if (bitmap[i] < min)
1266  min = bitmap[i];
1267  if (bitmap[i] > max)
1268  max = bitmap[i];
1269  }
1270  }
1271  }
1272  else {
1273  for (unsigned int i = 0; i < npixels; i++) {
1274  if (bitmap[i] < min)
1275  min = bitmap[i];
1276  if (bitmap[i] > max)
1277  max = bitmap[i];
1278  }
1279  }
1280 }
1281 
1293 template <> inline void vpImage<float>::getMinMaxValue(float &min, float &max, bool onlyFiniteVal) const
1294 {
1295  if (npixels == 0)
1296  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1297 
1298  min = max = bitmap[0];
1299  if (onlyFiniteVal) {
1300  for (unsigned int i = 0; i < npixels; i++) {
1301  if (vpMath::isFinite(bitmap[i])) {
1302  if (bitmap[i] < min)
1303  min = bitmap[i];
1304  if (bitmap[i] > max)
1305  max = bitmap[i];
1306  }
1307  }
1308  }
1309  else {
1310  for (unsigned int i = 0; i < npixels; i++) {
1311  if (bitmap[i] < min)
1312  min = bitmap[i];
1313  if (bitmap[i] > max)
1314  max = bitmap[i];
1315  }
1316  }
1317 }
1318 
1329 template <> inline void vpImage<vpRGBf>::getMinMaxValue(vpRGBf &min, vpRGBf &max, bool onlyFiniteVal) const
1330 {
1331  if (npixels == 0)
1332  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1333 
1334  min = max = bitmap[0];
1335  if (onlyFiniteVal) {
1336  for (unsigned int i = 0; i < npixels; i++) {
1337  if (vpMath::isFinite(bitmap[i].R)) {
1338  if (bitmap[i].R < min.R)
1339  min.R = bitmap[i].R;
1340  if (bitmap[i].R > max.R)
1341  max.R = bitmap[i].R;
1342  }
1343  if (vpMath::isFinite(bitmap[i].G)) {
1344  if (bitmap[i].G < min.G)
1345  min.G = bitmap[i].G;
1346  if (bitmap[i].G > max.G)
1347  max.G = bitmap[i].G;
1348  }
1349  if (vpMath::isFinite(bitmap[i].B)) {
1350  if (bitmap[i].B < min.B)
1351  min.B = bitmap[i].B;
1352  if (bitmap[i].B > max.B)
1353  max.B = bitmap[i].B;
1354  }
1355  }
1356  }
1357  else {
1358  for (unsigned int i = 0; i < npixels; i++) {
1359  if (bitmap[i].R < min.R)
1360  min.R = bitmap[i].R;
1361  if (bitmap[i].R > max.R)
1362  max.R = bitmap[i].R;
1363 
1364  if (bitmap[i].G < min.G)
1365  min.G = bitmap[i].G;
1366  if (bitmap[i].G > max.G)
1367  max.G = bitmap[i].G;
1368 
1369  if (bitmap[i].B < min.B)
1370  min.B = bitmap[i].B;
1371  if (bitmap[i].B > max.B)
1372  max.B = bitmap[i].B;
1373  }
1374  }
1375 }
1376 
1398 template <class Type>
1399 void vpImage<Type>::getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal, Type *maxVal) const
1400 {
1401  if (npixels == 0)
1402  throw(vpException(vpException::fatalError, "Cannot get location of minimum/maximum "
1403  "values of an empty image"));
1404 
1405  Type min = bitmap[0], max = bitmap[0];
1406  vpImagePoint minLoc_, maxLoc_;
1407  for (unsigned int i = 0; i < height; i++) {
1408  for (unsigned int j = 0; j < width; j++) {
1409  if (row[i][j] < min) {
1410  min = row[i][j];
1411  minLoc_.set_ij(i, j);
1412  }
1413 
1414  if (row[i][j] > max) {
1415  max = row[i][j];
1416  maxLoc_.set_ij(i, j);
1417  }
1418  }
1419  }
1420 
1421  if (minLoc != nullptr)
1422  *minLoc = minLoc_;
1423 
1424  if (maxLoc != nullptr)
1425  *maxLoc = maxLoc_;
1426 
1427  if (minVal != nullptr)
1428  *minVal = min;
1429 
1430  if (maxVal != nullptr)
1431  *maxVal = max;
1432 }
1433 
1438 {
1439  swap(*this, other);
1440  if (other.display != nullptr)
1441  display = other.display;
1442 
1443  return *this;
1444 }
1445 
1452 template <class Type> vpImage<Type> &vpImage<Type>::operator=(const Type &v)
1453 {
1454  for (unsigned int i = 0; i < npixels; i++)
1455  bitmap[i] = v;
1456 
1457  return *this;
1458 }
1459 
1465 template <class Type> bool vpImage<Type>::operator==(const vpImage<Type> &I) const
1466 {
1467  if (this->width != I.getWidth())
1468  return false;
1469  if (this->height != I.getHeight())
1470  return false;
1471 
1472  // printf("wxh: %dx%d bitmap: %p I.bitmap %p\n", width, height, bitmap,
1473  // I.bitmap);
1474  for (unsigned int i = 0; i < npixels; i++) {
1475  if (bitmap[i] != I.bitmap[i]) {
1476  // std::cout << "differ for pixel " << i << " (" << i%this->height
1477  // << ", " << i - i%this->height << ")" << std::endl;
1478  return false;
1479  }
1480  }
1481  return true;
1482 }
1488 template <class Type> bool vpImage<Type>::operator!=(const vpImage<Type> &I) const { return !(*this == I); }
1489 
1515 template <class Type> vpImage<Type> vpImage<Type>::operator-(const vpImage<Type> &B) const
1516 {
1517  vpImage<Type> C;
1518  sub(*this, B, C);
1519  return C;
1520 }
1521 
1533 template <class Type> void vpImage<Type>::insert(const vpImage<Type> &src, const vpImagePoint &topLeft)
1534 {
1535  int itl = (int)topLeft.get_i();
1536  int jtl = (int)topLeft.get_j();
1537 
1538  int dest_ibegin = 0;
1539  int dest_jbegin = 0;
1540  int src_ibegin = 0;
1541  int src_jbegin = 0;
1542  int dest_w = (int)this->getWidth();
1543  int dest_h = (int)this->getHeight();
1544  int src_w = (int)src.getWidth();
1545  int src_h = (int)src.getHeight();
1546  int wsize = (int)src.getWidth();
1547  int hsize = (int)src.getHeight();
1548 
1549  if (itl >= dest_h || jtl >= dest_w)
1550  return;
1551 
1552  if (itl < 0)
1553  src_ibegin = -itl;
1554  else
1555  dest_ibegin = itl;
1556 
1557  if (jtl < 0)
1558  src_jbegin = -jtl;
1559  else
1560  dest_jbegin = jtl;
1561 
1562  if (src_w - src_jbegin > dest_w - dest_jbegin)
1563  wsize = dest_w - dest_jbegin;
1564  else
1565  wsize = src_w - src_jbegin;
1566 
1567  if (src_h - src_ibegin > dest_h - dest_ibegin)
1568  hsize = dest_h - dest_ibegin;
1569  else
1570  hsize = src_h - src_ibegin;
1571 
1572  for (int i = 0; i < hsize; i++) {
1573  Type *srcBitmap = src.bitmap + ((src_ibegin + i) * src_w + src_jbegin);
1574  Type *destBitmap = this->bitmap + ((dest_ibegin + i) * dest_w + dest_jbegin);
1575 
1576  memcpy(static_cast<void *>(destBitmap), static_cast<void *>(srcBitmap), (size_t)wsize * sizeof(Type));
1577  }
1578 }
1579 
1610 template <class Type> void vpImage<Type>::halfSizeImage(vpImage<Type> &res) const
1611 {
1612  unsigned int h = height / 2;
1613  unsigned int w = width / 2;
1614  res.resize(h, w);
1615  for (unsigned int i = 0; i < h; i++)
1616  for (unsigned int j = 0; j < w; j++)
1617  res[i][j] = (*this)[i << 1][j << 1];
1618 }
1619 
1637 template <class Type>
1638 void vpImage<Type>::subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const
1639 {
1640  if (v_scale == 1 && h_scale == 1) {
1641  sampled = (*this);
1642  return;
1643  }
1644  unsigned int h = height / v_scale;
1645  unsigned int w = width / h_scale;
1646  sampled.resize(h, w);
1647  for (unsigned int i = 0; i < h; i++)
1648  for (unsigned int j = 0; j < w; j++)
1649  sampled[i][j] = (*this)[i * v_scale][j * h_scale];
1650 }
1651 
1674 template <class Type> void vpImage<Type>::quarterSizeImage(vpImage<Type> &res) const
1675 {
1676  unsigned int h = height / 4;
1677  unsigned int w = width / 4;
1678  res.resize(h, w);
1679  for (unsigned int i = 0; i < h; i++)
1680  for (unsigned int j = 0; j < w; j++)
1681  res[i][j] = (*this)[i << 2][j << 2];
1682 }
1683 
1716 template <class Type> void vpImage<Type>::doubleSizeImage(vpImage<Type> &res)
1717 {
1718  int h = height * 2;
1719  int w = width * 2;
1720 
1721  res.resize(h, w);
1722 
1723  for (int i = 0; i < h; i++)
1724  for (int j = 0; j < w; j++)
1725  res[i][j] = (*this)[i >> 1][j >> 1];
1726 
1727  /*
1728  A B C
1729  E F G
1730  H I J
1731  A C H J are pixels from original image
1732  B E G I are interpolated pixels
1733  */
1734 
1735  // interpolate pixels B and I
1736  for (int i = 0; i < h; i += 2)
1737  for (int j = 1; j < w - 1; j += 2)
1738  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1]));
1739 
1740  // interpolate pixels E and G
1741  for (int i = 1; i < h - 1; i += 2)
1742  for (int j = 0; j < w; j += 2)
1743  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[(i >> 1) + 1][j >> 1]));
1744 
1745  // interpolate pixel F
1746  for (int i = 1; i < h - 1; i += 2)
1747  for (int j = 1; j < w - 1; j += 2)
1748  res[i][j] = (Type)(0.25 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1] +
1749  (*this)[(i >> 1) + 1][j >> 1] + (*this)[(i >> 1) + 1][(j >> 1) + 1]));
1750 }
1751 
1764 template <class Type> inline Type vpImage<Type>::getValue(unsigned int i, unsigned int j) const
1765 {
1766  if (i >= height || j >= width) {
1767  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1768  }
1769 
1770  return row[i][j];
1771 }
1772 
1789 template <class Type> Type vpImage<Type>::getValue(double i, double j) const
1790 {
1791  if (i < 0 || j < 0 || i + 1 > height || j + 1 > width) {
1792  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1793  }
1794  if (height * width == 0) {
1795  throw vpException(vpImageException::notInitializedError, "Empty image!");
1796  }
1797 
1798  unsigned int iround = static_cast<unsigned int>(floor(i));
1799  unsigned int jround = static_cast<unsigned int>(floor(j));
1800 
1801  double rratio = i - static_cast<double>(iround);
1802  double cratio = j - static_cast<double>(jround);
1803 
1804  double rfrac = 1.0 - rratio;
1805  double cfrac = 1.0 - cratio;
1806 
1807  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
1808  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
1809 
1810  double value =
1811  (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
1812  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) *
1813  cratio;
1814 
1815  return static_cast<Type>(vpMath::round(value));
1816 }
1817 
1821 template <> inline double vpImage<double>::getValue(double i, double j) const
1822 {
1823  if (i < 0 || j < 0 || i + 1 > height || j + 1 > width) {
1824  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1825  }
1826  if (height * width == 0) {
1827  throw vpException(vpImageException::notInitializedError, "Empty image!");
1828  }
1829 
1830  unsigned int iround = static_cast<unsigned int>(floor(i));
1831  unsigned int jround = static_cast<unsigned int>(floor(j));
1832 
1833  double rratio = i - static_cast<double>(iround);
1834  double cratio = j - static_cast<double>(jround);
1835 
1836  double rfrac = 1.0 - rratio;
1837  double cfrac = 1.0 - cratio;
1838 
1839  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
1840  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
1841 
1842  return (row[iround][jround] * rfrac + row[iround_1][jround] * rratio) * cfrac +
1843  (row[iround][jround_1] * rfrac + row[iround_1][jround_1] * rratio) * cratio;
1844 }
1845 
1849 template <> inline unsigned char vpImage<unsigned char>::getValue(double i, double j) const
1850 {
1851  if (i < 0 || j < 0 || i + 1 > height || j + 1 > width) {
1852  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1853  }
1854  if (height * width == 0) {
1855  throw vpException(vpImageException::notInitializedError, "Empty image!");
1856  }
1857 
1858  // alpha architecture is bi-endianness. The following optimization makes testImageGetValue failing
1859 #if (defined(VISP_LITTLE_ENDIAN) || defined(VISP_BIG_ENDIAN)) && !(defined(__alpha__) || defined(_M_ALPHA))
1860  // Fixed-point arithmetic
1861  const int32_t precision = 1 << 16;
1862  int64_t y = static_cast<int64_t>(i * precision);
1863  int64_t x = static_cast<int64_t>(j * precision);
1864 
1865  int64_t iround = y & (~0xFFFF);
1866  int64_t jround = x & (~0xFFFF);
1867 
1868  int64_t rratio = y - iround;
1869  int64_t cratio = x - jround;
1870 
1871  int64_t rfrac = precision - rratio;
1872  int64_t cfrac = precision - cratio;
1873 
1874  int64_t x_ = x >> 16;
1875  int64_t y_ = y >> 16;
1876 
1877  if (y_ + 1 < height && x_ + 1 < width) {
1878  uint16_t up = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + y_ * width + x_);
1879  uint16_t down = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + (y_ + 1) * width + x_);
1880 
1881  return static_cast<unsigned char>((((up & 0x00FF) * rfrac + (down & 0x00FF) * rratio) * cfrac +
1882  ((up >> 8) * rfrac + (down >> 8) * rratio) * cratio) >>
1883  32);
1884  }
1885  else if (y_ + 1 < height) {
1886  return static_cast<unsigned char>(((row[y_][x_] * rfrac + row[y_ + 1][x_] * rratio)) >> 16);
1887  }
1888  else if (x_ + 1 < width) {
1889  uint16_t up = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + y_ * width + x_);
1890  return static_cast<unsigned char>(((up & 0x00FF) * cfrac + (up >> 8) * cratio) >> 16);
1891  }
1892  else {
1893  return row[y_][x_];
1894  }
1895 #else
1896  unsigned int iround = static_cast<unsigned int>(floor(i));
1897  unsigned int jround = static_cast<unsigned int>(floor(j));
1898 
1899  if (iround >= height || jround >= width) {
1900  vpERROR_TRACE("Pixel outside the image");
1901  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1902  }
1903 
1904  double rratio = i - static_cast<double>(iround);
1905  double cratio = j - static_cast<double>(jround);
1906 
1907  double rfrac = 1.0 - rratio;
1908  double cfrac = 1.0 - cratio;
1909 
1910  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
1911  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
1912 
1913  double value =
1914  (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
1915  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) *
1916  cratio;
1917  return static_cast<unsigned char>(vpMath::round(value));
1918 #endif
1919 }
1920 
1924 template <> inline vpRGBa vpImage<vpRGBa>::getValue(double i, double j) const
1925 {
1926  if (i < 0 || j < 0 || i + 1 > height || j + 1 > width) {
1927  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1928  }
1929  if (height * width == 0) {
1930  throw vpException(vpImageException::notInitializedError, "Empty image!");
1931  }
1932 
1933  unsigned int iround = static_cast<unsigned int>(floor(i));
1934  unsigned int jround = static_cast<unsigned int>(floor(j));
1935 
1936  double rratio = i - static_cast<double>(iround);
1937  double cratio = j - static_cast<double>(jround);
1938 
1939  double rfrac = 1.0 - rratio;
1940  double cfrac = 1.0 - cratio;
1941 
1942  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
1943  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
1944 
1945  double valueR =
1946  (static_cast<double>(row[iround][jround].R) * rfrac + static_cast<double>(row[iround_1][jround].R) * rratio) *
1947  cfrac +
1948  (static_cast<double>(row[iround][jround_1].R) * rfrac + static_cast<double>(row[iround_1][jround_1].R) * rratio) *
1949  cratio;
1950  double valueG =
1951  (static_cast<double>(row[iround][jround].G) * rfrac + static_cast<double>(row[iround_1][jround].G) * rratio) *
1952  cfrac +
1953  (static_cast<double>(row[iround][jround_1].G) * rfrac + static_cast<double>(row[iround_1][jround_1].G) * rratio) *
1954  cratio;
1955  double valueB =
1956  (static_cast<double>(row[iround][jround].B) * rfrac + static_cast<double>(row[iround_1][jround].B) * rratio) *
1957  cfrac +
1958  (static_cast<double>(row[iround][jround_1].B) * rfrac + static_cast<double>(row[iround_1][jround_1].B) * rratio) *
1959  cratio;
1960 
1961  return vpRGBa(static_cast<unsigned char>(vpMath::round(valueR)), static_cast<unsigned char>(vpMath::round(valueG)),
1962  static_cast<unsigned char>(vpMath::round(valueB)));
1963 }
1964 
1968 template <> inline vpRGBf vpImage<vpRGBf>::getValue(double i, double j) const
1969 {
1970  if (i < 0 || j < 0 || i + 1 > height || j + 1 > width) {
1971  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1972  }
1973  if (height * width == 0) {
1974  throw vpException(vpImageException::notInitializedError, "Empty image!");
1975  }
1976 
1977  unsigned int iround = static_cast<unsigned int>(floor(i));
1978  unsigned int jround = static_cast<unsigned int>(floor(j));
1979 
1980  double rratio = i - static_cast<double>(iround);
1981  double cratio = j - static_cast<double>(jround);
1982 
1983  double rfrac = 1.0 - rratio;
1984  double cfrac = 1.0 - cratio;
1985 
1986  unsigned int iround_1 = std::min<unsigned int>(height - 1, iround + 1);
1987  unsigned int jround_1 = std::min<unsigned int>(width - 1, jround + 1);
1988 
1989  double valueR =
1990  (static_cast<double>(row[iround][jround].R) * rfrac + static_cast<double>(row[iround_1][jround].R) * rratio) *
1991  cfrac +
1992  (static_cast<double>(row[iround][jround_1].R) * rfrac + static_cast<double>(row[iround_1][jround_1].R) * rratio) *
1993  cratio;
1994  double valueG =
1995  (static_cast<double>(row[iround][jround].G) * rfrac + static_cast<double>(row[iround_1][jround].G) * rratio) *
1996  cfrac +
1997  (static_cast<double>(row[iround][jround_1].G) * rfrac + static_cast<double>(row[iround_1][jround_1].G) * rratio) *
1998  cratio;
1999  double valueB =
2000  (static_cast<double>(row[iround][jround].B) * rfrac + static_cast<double>(row[iround_1][jround].B) * rratio) *
2001  cfrac +
2002  (static_cast<double>(row[iround][jround_1].B) * rfrac + static_cast<double>(row[iround_1][jround_1].B) * rratio) *
2003  cratio;
2004 
2005  return vpRGBf(static_cast<float>(valueR), static_cast<float>(valueG), static_cast<float>(valueB));
2006 }
2007 
2024 template <class Type> inline Type vpImage<Type>::getValue(const vpImagePoint &ip) const
2025 {
2026  return getValue(ip.get_i(), ip.get_j());
2027 }
2028 
2032 template <> inline double vpImage<double>::getValue(const vpImagePoint &ip) const
2033 {
2034  return getValue(ip.get_i(), ip.get_j());
2035 }
2036 
2040 template <> inline unsigned char vpImage<unsigned char>::getValue(const vpImagePoint &ip) const
2041 {
2042  return getValue(ip.get_i(), ip.get_j());
2043 }
2044 
2048 template <> inline vpRGBa vpImage<vpRGBa>::getValue(const vpImagePoint &ip) const
2049 {
2050  return getValue(ip.get_i(), ip.get_j());
2051 }
2052 
2064 template <class Type> inline double vpImage<Type>::getSum(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
2065 {
2066  if ((height == 0) || (width == 0)) {
2067  if (nbValidPoints) {
2068  *nbValidPoints = 0;
2069  }
2070  return 0.0;
2071  }
2072  if (p_mask) {
2073  if (p_mask->getWidth() != width || p_mask->getHeight() != height) {
2074  throw(vpException(vpException::fatalError, "Cannot compute sum: image and mask size differ"));
2075  }
2076  }
2077  double res = 0.0;
2078  unsigned int nbPointsInMask = 0;
2079  unsigned int size = height * width;
2080  if (p_mask) {
2081  for (unsigned int i = 0; i < size; ++i) {
2082  if (p_mask->bitmap[i]) {
2083  res += static_cast<double>(bitmap[i]);
2084  ++nbPointsInMask;
2085  }
2086  }
2087  }
2088  else {
2089  for (unsigned int i = 0; i < size; ++i) {
2090  res += static_cast<double>(bitmap[i]);
2091  }
2092  nbPointsInMask = size;
2093  }
2094  if (nbValidPoints) {
2095  *nbValidPoints = nbPointsInMask;
2096  }
2097 
2098  return res;
2099 }
2100 
2101 #ifndef DOXYGEN_SHOULD_SKIP_THIS
2113 template <> inline double vpImage<vpRGBa>::getSum(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
2114 {
2115  if ((height == 0) || (width == 0)) {
2116  return 0.0;
2117  }
2118  double res = 0.0;
2119  unsigned int nbPointsInMask = 0;
2120  unsigned int size = height * width;
2121  if (p_mask) {
2122  if (p_mask->getWidth() != width || p_mask->getHeight() != height) {
2123  throw(vpException(vpException::fatalError, "Cannot compute sum: image and mask size differ"));
2124  }
2125  for (unsigned int i = 0; i < size; ++i) {
2126  if (p_mask->bitmap[i]) {
2127  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
2128  ++nbPointsInMask;
2129  }
2130  }
2131  }
2132  else {
2133  for (unsigned int i = 0; i < height * width; ++i) {
2134  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
2135  }
2136  nbPointsInMask = size;
2137  }
2138  if (nbValidPoints) {
2139  *nbValidPoints = nbPointsInMask;
2140  }
2141  return res;
2142 }
2143 
2155 template <> inline double vpImage<vpRGBf>::getSum(const vpImage<bool> *p_mask, unsigned int *nbValidPoints) const
2156 {
2157  if ((height == 0) || (width == 0)) {
2158  return 0.0;
2159  }
2160  double res = 0.0;
2161  unsigned int nbPointsInMask = 0;
2162  unsigned int size = height * width;
2163  if (p_mask) {
2164  if (p_mask->getWidth() != width || p_mask->getHeight() != height) {
2165  throw(vpException(vpException::fatalError, "Cannot compute sum: image and mask size differ"));
2166  }
2167  for (unsigned int i = 0; i < size; ++i) {
2168  if (p_mask->bitmap[i]) {
2169  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
2170  ++nbPointsInMask;
2171  }
2172  }
2173  }
2174  else {
2175  for (unsigned int i = 0; i < height * width; ++i) {
2176  res += static_cast<double>(bitmap[i].R) + static_cast<double>(bitmap[i].G) + static_cast<double>(bitmap[i].B);
2177  }
2178  nbPointsInMask = size;
2179  }
2180  if (nbValidPoints) {
2181  *nbValidPoints = nbPointsInMask;
2182  }
2183  return res;
2184 }
2185 #endif // DOXYGEN_SHOULD_SKIP_THIS
2186 
2216 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &B, vpImage<Type> &C) const
2217 {
2218 
2219  try {
2220  if ((this->getHeight() != C.getHeight()) || (this->getWidth() != C.getWidth()))
2221  C.resize(this->getHeight(), this->getWidth());
2222  }
2223  catch (const vpException &me) {
2224  std::cout << me << std::endl;
2225  throw;
2226  }
2227 
2228  if ((this->getWidth() != B.getWidth()) || (this->getHeight() != B.getHeight())) {
2229  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage subtraction"));
2230  }
2231 
2232  for (unsigned int i = 0; i < this->getWidth() * this->getHeight(); i++) {
2233  *(C.bitmap + i) = *(bitmap + i) - *(B.bitmap + i);
2234  }
2235 }
2236 
2248 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C) const
2249 {
2250 
2251  try {
2252  if ((A.getHeight() != C.getHeight()) || (A.getWidth() != C.getWidth()))
2253  C.resize(A.getHeight(), A.getWidth());
2254  }
2255  catch (const vpException &me) {
2256  std::cout << me << std::endl;
2257  throw;
2258  }
2259 
2260  if ((A.getWidth() != B.getWidth()) || (A.getHeight() != B.getHeight())) {
2261  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage subtraction "));
2262  }
2263 
2264  for (unsigned int i = 0; i < A.getWidth() * A.getHeight(); i++) {
2265  *(C.bitmap + i) = *(A.bitmap + i) - *(B.bitmap + i);
2266  }
2267 }
2268 
2277 template <class Type> void vpImage<Type>::performLut(const Type(&)[256], unsigned int)
2278 {
2279  std::cerr << "Not implemented !" << std::endl;
2280 }
2281 
2292 template <> inline void vpImage<unsigned char>::performLut(const unsigned char(&lut)[256], unsigned int nbThreads)
2293 {
2294  unsigned int size = getWidth() * getHeight();
2295  unsigned char *ptrStart = (unsigned char *)bitmap;
2296  unsigned char *ptrEnd = ptrStart + size;
2297  unsigned char *ptrCurrent = ptrStart;
2298 
2299  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
2300 #if !defined(VISP_HAVE_THREADS)
2301  use_single_thread = true;
2302 #endif
2303 
2304  if (!use_single_thread && getSize() <= nbThreads) {
2305  use_single_thread = true;
2306  }
2307 
2308  if (use_single_thread) {
2309  // Single thread
2310 
2311  while (ptrCurrent != ptrEnd) {
2312  *ptrCurrent = lut[*ptrCurrent];
2313  ++ptrCurrent;
2314  }
2315  }
2316  else {
2317 #if defined(VISP_HAVE_THREADS)
2318  // Multi-threads
2319  std::vector<std::thread *> threadpool;
2320  std::vector<vpImageLut_Param_t *> imageLutParams;
2321 
2322  unsigned int image_size = getSize();
2323  unsigned int step = image_size / nbThreads;
2324  unsigned int last_step = image_size - step * (nbThreads - 1);
2325 
2326  for (unsigned int index = 0; index < nbThreads; index++) {
2327  unsigned int start_index = index * step;
2328  unsigned int end_index = (index + 1) * step;
2329 
2330  if (index == nbThreads - 1) {
2331  end_index = start_index + last_step;
2332  }
2333 
2334  vpImageLut_Param_t *imageLut_param = new vpImageLut_Param_t(start_index, end_index, bitmap);
2335  memcpy(imageLut_param->m_lut, lut, 256 * sizeof(unsigned char));
2336 
2337  imageLutParams.push_back(imageLut_param);
2338 
2339  // Start the threads
2340  std::thread *imageLut_thread = new std::thread(&performLutThread, imageLut_param);
2341  threadpool.push_back(imageLut_thread);
2342  }
2343 
2344  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
2345  // Wait until thread ends up
2346  threadpool[cpt]->join();
2347  }
2348 
2349  // Delete
2350  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
2351  delete threadpool[cpt];
2352  }
2353 
2354  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
2355  delete imageLutParams[cpt];
2356  }
2357 #endif
2358  }
2359 }
2360 
2371 template <> inline void vpImage<vpRGBa>::performLut(const vpRGBa(&lut)[256], unsigned int nbThreads)
2372 {
2373  unsigned int size = getWidth() * getHeight();
2374  unsigned char *ptrStart = (unsigned char *)bitmap;
2375  unsigned char *ptrEnd = ptrStart + size * 4;
2376  unsigned char *ptrCurrent = ptrStart;
2377 
2378  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
2379 #if !defined(VISP_HAVE_THREADS)
2380  use_single_thread = true;
2381 #endif
2382 
2383  if (!use_single_thread && getSize() <= nbThreads) {
2384  use_single_thread = true;
2385  }
2386 
2387  if (use_single_thread) {
2388  // Single thread
2389  while (ptrCurrent != ptrEnd) {
2390  *ptrCurrent = lut[*ptrCurrent].R;
2391  ++ptrCurrent;
2392 
2393  *ptrCurrent = lut[*ptrCurrent].G;
2394  ++ptrCurrent;
2395 
2396  *ptrCurrent = lut[*ptrCurrent].B;
2397  ++ptrCurrent;
2398 
2399  *ptrCurrent = lut[*ptrCurrent].A;
2400  ++ptrCurrent;
2401  }
2402  }
2403  else {
2404 #if defined(VISP_HAVE_THREADS)
2405  // Multi-threads
2406  std::vector<std::thread *> threadpool;
2407  std::vector<vpImageLutRGBa_Param_t *> imageLutParams;
2408 
2409  unsigned int image_size = getSize();
2410  unsigned int step = image_size / nbThreads;
2411  unsigned int last_step = image_size - step * (nbThreads - 1);
2412 
2413  for (unsigned int index = 0; index < nbThreads; index++) {
2414  unsigned int start_index = index * step;
2415  unsigned int end_index = (index + 1) * step;
2416 
2417  if (index == nbThreads - 1) {
2418  end_index = start_index + last_step;
2419  }
2420 
2421  vpImageLutRGBa_Param_t *imageLut_param = new vpImageLutRGBa_Param_t(start_index, end_index, (unsigned char *)bitmap);
2422  memcpy(static_cast<void *>(imageLut_param->m_lut), lut, 256 * sizeof(vpRGBa));
2423 
2424  imageLutParams.push_back(imageLut_param);
2425 
2426  // Start the threads
2427  std::thread *imageLut_thread = new std::thread(&performLutRGBaThread, imageLut_param);
2428  threadpool.push_back(imageLut_thread);
2429  }
2430 
2431  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
2432  // Wait until thread ends up
2433  threadpool[cpt]->join();
2434  }
2435 
2436  // Delete
2437  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
2438  delete threadpool[cpt];
2439  }
2440 
2441  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
2442  delete imageLutParams[cpt];
2443  }
2444 #endif
2445  }
2446 }
2447 
2448 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second)
2449 {
2450  using std::swap;
2451  swap(first.bitmap, second.bitmap);
2452  swap(first.display, second.display);
2453  swap(first.npixels, second.npixels);
2454  swap(first.width, second.width);
2455  swap(first.height, second.height);
2456  swap(first.row, second.row);
2457 }
2458 
2459 #endif
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Definition: vpArray2D.h:547
Class that defines generic functionalities for display.
Definition: vpDisplay.h:173
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ memoryAllocationError
Memory allocation error.
Definition: vpException.h:76
@ fatalError
Fatal error.
Definition: vpException.h:84
@ divideByZeroError
Division by zero.
Definition: vpException.h:82
@ notInitializedError
Image not initialized.
@ notInTheImage
Pixel not in the image.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
double get_j() const
Definition: vpImagePoint.h:125
void set_ij(double ii, double jj)
Definition: vpImagePoint.h:315
double get_i() const
Definition: vpImagePoint.h:114
Definition of the vpImage class member functions.
Definition: vpImage.h:69
Type operator()(const vpImagePoint &ip) const
Definition: vpImage.h:293
void destroy()
Destructor : Memory de-allocation.
Definition: vpImage.h:812
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:1638
void halfSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1610
vpImage< Type > & operator=(vpImage< Type > other)
Copy operator.
Definition: vpImage.h:1437
Type * operator[](int i)
Definition: vpImage.h:263
double getSum(const vpImage< bool > *p_mask=nullptr, unsigned int *nbValidPoints=nullptr) const
Compute the sum of image intensities.
Definition: vpImage.h:2064
Type getMinValue(bool onlyFiniteVal=true) const
Return the minimum value within the bitmap.
Definition: vpImage.h:1154
void quarterSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1674
void getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal=nullptr, Type *maxVal=nullptr) const
Get the position of the minimum and/or the maximum pixel value within the bitmap and the correspondin...
Definition: vpImage.h:1399
void init(unsigned int height, unsigned int width)
Set the size of the image.
Definition: vpImage.h:631
Type * operator[](unsigned int i)
operator[] allows operation like I[i] = x.
Definition: vpImage.h:262
void resize(unsigned int h, unsigned int w, const Type &val)
resize the image : Image initialization
Definition: vpImage.h:804
unsigned int getWidth() const
Definition: vpImage.h:245
friend std::ostream & operator<<(std::ostream &s, const vpImage< unsigned char > &I)
Definition: vpImage.h:381
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:783
unsigned int getNumberOfPixel() const
Definition: vpImage.h:206
Type getValue(double i, double j) const
Definition: vpImage.h:1789
void doubleSizeImage(vpImage< Type > &res)
Definition: vpImage.h:1716
vpImage(unsigned int height, unsigned int width, Type value)
constructor set the size of the image and init all the pixel
Definition: vpImage.h:740
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
Definition: vpImage.h:2277
const Type * operator[](int i) const
Definition: vpImage.h:267
friend std::ostream & operator<<(std::ostream &s, const vpImage< float > &I)
Definition: vpImage.h:433
bool operator==(const vpImage< Type > &I) const
Definition: vpImage.h:1465
void insert(const vpImage< Type > &src, const vpImagePoint &topLeft)
Definition: vpImage.h:1533
void sub(const vpImage< Type > &A, const vpImage< Type > &B, vpImage< Type > &C) const
Definition: vpImage.h:2248
Type getValue(unsigned int i, unsigned int j) const
Definition: vpImage.h:1764
double getValue(double i, double j) const
Definition: vpImage.h:1821
vpImage< Type > operator-(const vpImage< Type > &B) const
Definition: vpImage.h:1515
void init(unsigned int height, unsigned int width, Type value)
Set the size of the image.
Definition: vpImage.h:619
unsigned int getSize() const
Definition: vpImage.h:224
friend void swap(vpImage< Type > &first, vpImage< Type > &second)
Definition: vpImage.h:2448
unsigned int getCols() const
Definition: vpImage.h:175
Type * bitmap
points toward the bitmap
Definition: vpImage.h:139
const Type * operator[](unsigned int i) const
operator[] allows operation like x = I[i]
Definition: vpImage.h:266
double getStdev(const vpImage< bool > *p_mask=nullptr, unsigned int *nbValidPoints=nullptr) const
Return the standard deviation of the bitmap.
Definition: vpImage.h:985
Type getValue(const vpImagePoint &ip) const
Definition: vpImage.h:2024
void sub(const vpImage< Type > &B, vpImage< Type > &C) const
Definition: vpImage.h:2216
vpImage(Type *const array, unsigned int height, unsigned int width, bool copyData=false)
constructor from an image stored as a continuous array in memory
Definition: vpImage.h:750
void init(Type *const array, unsigned int height, unsigned int width, bool copyData=false)
init from an image stored as a continuous array in memory
Definition: vpImage.h:674
double getStdev(const double &mean, const vpImage< bool > *p_mask=nullptr, unsigned int *nbValidPoints=nullptr) const
Return the standard deviation of the bitmap.
Definition: vpImage.h:1009
Type getMaxValue(bool onlyFiniteVal=true) const
Return the maximum value within the bitmap.
Definition: vpImage.h:874
virtual ~vpImage()
destructor
Definition: vpImage.h:833
unsigned int getHeight() const
Definition: vpImage.h:184
unsigned int getRows() const
Definition: vpImage.h:215
friend std::ostream & operator<<(std::ostream &s, const vpImage< double > &I)
Definition: vpImage.h:460
void getMinMaxValue(Type &min, Type &max, bool onlyFiniteVal=true) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:1230
vpImage< Type > & operator=(const Type &v)
= operator : Set all the element of the bitmap to a given value v.
Definition: vpImage.h:1452
vpDisplay * display
Definition: vpImage.h:140
vpImage()
constructor
Definition: vpImage.h:760
friend std::ostream & operator<<(std::ostream &s, const vpImage< char > &I)
Definition: vpImage.h:407
void operator()(const vpImagePoint &ip, const Type &v)
Definition: vpImage.h:309
Type operator()(unsigned int i, unsigned int j) const
Definition: vpImage.h:275
bool operator!=(const vpImage< Type > &I) const
Definition: vpImage.h:1488
double getMeanValue(const vpImage< bool > *p_mask=nullptr, unsigned int *nbValidPoints=nullptr) const
Return the mean value of the bitmap.
Definition: vpImage.h:954
void init(unsigned int h, unsigned int w, Type value)
Definition: vpImage.h:619
vpImage(const vpImage< Type > &)
copy constructor
Definition: vpImage.h:839
vpImage(unsigned int height, unsigned int width)
constructor set the size of the image
Definition: vpImage.h:730
void operator()(unsigned int i, unsigned int j, const Type &v)
Definition: vpImage.h:281
static int round(double x)
Definition: vpMath.h:403
static bool isFinite(double value)
Definition: vpMath.cpp:178
Definition: vpRGBa.h:61
Definition: vpRGBf.h:57
float B
Blue component.
Definition: vpRGBf.h:126
float G
Green component.
Definition: vpRGBf.h:125
float R
Red component.
Definition: vpRGBf.h:124
#define vpERROR_TRACE
Definition: vpDebug.h:382
VISP_EXPORT uint16_t reinterpret_cast_uchar_to_uint16_LE(unsigned char *const ptr)
Definition: vpEndian.cpp:108