Visual Servoing Platform  version 3.3.0
vpImage.h
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Image handling.
33  *
34  * Authors:
35  * Eric Marchand
36  *
37  *****************************************************************************/
38 
44 #ifndef vpImage_H
45 #define vpImage_H
46 
47 #include <visp3/core/vpConfig.h>
48 #include <visp3/core/vpDebug.h>
49 #include <visp3/core/vpException.h>
50 #include <visp3/core/vpImageException.h>
51 #include <visp3/core/vpImagePoint.h>
52 #include <visp3/core/vpRGBa.h>
53 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
54 #include <visp3/core/vpThread.h>
55 #endif
56 
57 #include <fstream>
58 #include <iomanip> // std::setw
59 #include <iostream>
60 #include <math.h>
61 #include <string.h>
62 
63 // Visual Studio 2010 or previous is missing inttypes.h
64 #if defined(_MSC_VER) && (_MSC_VER < 1700)
65 typedef long long int64_t;
66 typedef unsigned short uint16_t;
67 #else
68 # include <inttypes.h>
69 #endif
70 
71 // Detect endianness of the host machine
72 // Reference: http://www.boost.org/doc/libs/1_36_0/boost/detail/endian.hpp
73 #if defined(__GLIBC__) || (defined(__GNUC__) && !defined(__llvm__) && !defined(__MINGW32__) && !defined(__FreeBSD__) && defined(__BYTE_ORDER__))
74 #include <endian.h>
75 #if (__BYTE_ORDER == __LITTLE_ENDIAN)
76 #define VISP_LITTLE_ENDIAN
77 #elif (__BYTE_ORDER == __BIG_ENDIAN)
78 #define VISP_BIG_ENDIAN
79 #elif (__BYTE_ORDER == __PDP_ENDIAN)
80 // Currently not supported when reading / writing binary file
81 #define VISP_PDP_ENDIAN
82 //#error PDP endian is not supported. //Uncomment if needed/happens
83 #else
84 #error Unknown machine endianness detected.
85 #endif
86 #elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) || defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
87 #define VISP_BIG_ENDIAN
88 #elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) || defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
89 #define VISP_LITTLE_ENDIAN
90 #elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || \
91  defined(__hpux) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
92 
93 #define VISP_BIG_ENDIAN
94 #elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || \
95  defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || \
96  defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__ANDROID__)
97  // It appears that all Android systems are little endian.
98  // Refer https://stackoverflow.com/questions/6212951/endianness-of-android-ndk
99 #define VISP_LITTLE_ENDIAN
100 #elif defined(WINRT) // For UWP
101 // Refer https://social.msdn.microsoft.com/Forums/en-US/04c92ef9-e38e-415f-8958-ec9f7c196fd3/arm-endianess-under-windows-mobile?forum=windowsmobiledev
102 #define VISP_LITTLE_ENDIAN
103 #else
104 #error Cannot detect host machine endianness.
105 #endif
106 
107 class vpDisplay;
108 
159 // Ref: http://en.cppreference.com/w/cpp/language/friend#Template_friends
160 template <class Type> class vpImage; // forward declare to make function declaration possible
161 
162 // declarations
163 template <class Type> std::ostream &operator<<(std::ostream &, const vpImage<Type> &);
164 
165 std::ostream &operator<<(std::ostream &, const vpImage<unsigned char> &);
166 std::ostream &operator<<(std::ostream &, const vpImage<char> &);
167 std::ostream &operator<<(std::ostream &, const vpImage<float> &);
168 std::ostream &operator<<(std::ostream &, const vpImage<double> &);
169 
170 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second);
171 
172 template <class Type> class vpImage
173 {
174  friend class vpImageConvert;
175 
176 public:
177  Type *bitmap;
179 
184 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
187 #endif
188  vpImage(unsigned int height, unsigned int width);
191  vpImage(unsigned int height, unsigned int width, Type value);
193  vpImage(Type *const array, unsigned int height, unsigned int width, bool copyData = false);
195  virtual ~vpImage();
196 
199 
200  // destructor
201  void destroy();
202 
203  // Returns a new image that's double size of the current image
205 
213  inline unsigned int getCols() const { return width; }
222  inline unsigned int getHeight() const { return height; }
223 
224  // Return the maximum value within the bitmap
225  Type getMaxValue() const;
226  // Return the mean value of the bitmap
227  Type getMeanValue() const;
228  // Return the minumum value within the bitmap
229  Type getMinValue() const;
230  // Look for the minumum and the maximum value within the bitmap
231  void getMinMaxValue(Type &min, Type &max) const;
232  // Look for the minumum and the maximum value within the bitmap and get their location
233  void getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal = NULL, Type *maxVal = NULL) const;
234 
243  inline unsigned int getNumberOfPixel() const { return npixels; }
244 
252  inline unsigned int getRows() const { return height; }
253 
261  inline unsigned int getSize() const { return width * height; }
262 
263  // Gets the value of a pixel at a location.
264  Type getValue(unsigned int i, unsigned int j) const;
265  // Gets the value of a pixel at a location with bilinear interpolation.
266  Type getValue(double i, double j) const;
267  // Gets the value of a pixel at a location with bilinear interpolation.
268  Type getValue(const vpImagePoint &ip) const;
269 
270  // Get image pixels sum
271  double getSum() const;
272 
280  inline unsigned int getWidth() const { return width; }
281 
282  // Returns a new image that's half size of the current image
283  void halfSizeImage(vpImage<Type> &res) const;
284 
286  void init(unsigned int height, unsigned int width);
288  void init(unsigned int height, unsigned int width, Type value);
290  void init(Type *const array, unsigned int height, unsigned int width, bool copyData = false);
291  void insert(const vpImage<Type> &src, const vpImagePoint &topLeft);
292 
293  //------------------------------------------------------------------
294  // Acces to the image
295 
297  inline Type *operator[](unsigned int i) { return row[i]; }
298  inline Type *operator[](int i) { return row[i]; }
299 
301  inline const Type *operator[](unsigned int i) const { return row[i]; }
302  inline const Type *operator[](int i) const { return row[i]; }
303 
310  inline Type operator()(unsigned int i, unsigned int j) const { return bitmap[i * width + j]; }
311 
316  inline void operator()(unsigned int i, unsigned int j, const Type &v) { bitmap[i * width + j] = v; }
317 
328  inline Type operator()(const vpImagePoint &ip) const
329  {
330  unsigned int i = (unsigned int)ip.get_i();
331  unsigned int j = (unsigned int)ip.get_j();
332 
333  return bitmap[i * width + j];
334  }
335 
344  inline void operator()(const vpImagePoint &ip, const Type &v)
345  {
346  unsigned int i = (unsigned int)ip.get_i();
347  unsigned int j = (unsigned int)ip.get_j();
348 
349  bitmap[i * width + j] = v;
350  }
351 
353 
356 
357  vpImage<Type> &operator=(const Type &v);
358  bool operator==(const vpImage<Type> &I);
359  bool operator!=(const vpImage<Type> &I);
360  friend std::ostream &operator<< <>(std::ostream &s, const vpImage<Type> &I);
361  friend std::ostream &operator<<(std::ostream &s, const vpImage<unsigned char> &I);
362  friend std::ostream &operator<<(std::ostream &s, const vpImage<char> &I);
363  friend std::ostream &operator<<(std::ostream &s, const vpImage<float> &I);
364  friend std::ostream &operator<<(std::ostream &s, const vpImage<double> &I);
365 
366  // Perform a look-up table transformation
367  void performLut(const Type (&lut)[256], unsigned int nbThreads = 1);
368 
369  // Returns a new image that's a quarter size of the current image
370  void quarterSizeImage(vpImage<Type> &res) const;
371 
372  // set the size of the image without initializing it.
373  void resize(unsigned int h, unsigned int w);
374  // set the size of the image and initialize it.
375  void resize(unsigned int h, unsigned int w, const Type &val);
376 
377  void sub(const vpImage<Type> &B, vpImage<Type> &C);
378  void sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C);
379  void subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const;
380 
381  friend void swap<>(vpImage<Type> &first, vpImage<Type> &second);
382 
384 
385 private:
386  unsigned int npixels;
387  unsigned int width;
388  unsigned int height;
389  Type **row;
390  bool hasOwnership;
391 };
392 
393 template <class Type> std::ostream &operator<<(std::ostream &s, const vpImage<Type> &I)
394 {
395  if (I.bitmap == NULL) {
396  return s;
397  }
398 
399  for (unsigned int i = 0; i < I.getHeight(); i++) {
400  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
401  s << I[i][j] << " ";
402  }
403 
404  // We don't add " " after the last column element
405  s << I[i][I.getWidth() - 1];
406 
407  // We don't add a \n character at the end of the last row line
408  if (i < I.getHeight() - 1) {
409  s << std::endl;
410  }
411  }
412 
413  return s;
414 }
415 
416 inline std::ostream &operator<<(std::ostream &s, const vpImage<unsigned char> &I)
417 {
418  if (I.bitmap == NULL) {
419  return s;
420  }
421 
422  std::ios_base::fmtflags original_flags = s.flags();
423 
424  for (unsigned int i = 0; i < I.getHeight(); i++) {
425  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
426  s << std::setw(3) << static_cast<unsigned>(I[i][j]) << " ";
427  }
428 
429  // We don't add " " after the last column element
430  s << std::setw(3) << static_cast<unsigned>(I[i][I.getWidth() - 1]);
431 
432  // We don't add a \n character at the end of the last row line
433  if (i < I.getHeight() - 1) {
434  s << std::endl;
435  }
436  }
437 
438  s.flags(original_flags); // restore s to standard state
439  return s;
440 }
441 
442 inline std::ostream &operator<<(std::ostream &s, const vpImage<char> &I)
443 {
444  if (I.bitmap == NULL) {
445  return s;
446  }
447 
448  std::ios_base::fmtflags original_flags = s.flags();
449 
450  for (unsigned int i = 0; i < I.getHeight(); i++) {
451  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
452  s << std::setw(4) << static_cast<int>(I[i][j]) << " ";
453  }
454 
455  // We don't add " " after the last column element
456  s << std::setw(4) << static_cast<int>(I[i][I.getWidth() - 1]);
457 
458  // We don't add a \n character at the end of the last row line
459  if (i < I.getHeight() - 1) {
460  s << std::endl;
461  }
462  }
463 
464  s.flags(original_flags); // restore s to standard state
465  return s;
466 }
467 
468 inline std::ostream &operator<<(std::ostream &s, const vpImage<float> &I)
469 {
470  if (I.bitmap == NULL) {
471  return s;
472  }
473 
474  std::ios_base::fmtflags original_flags = s.flags();
475  s.precision(9); // http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
476 
477  for (unsigned int i = 0; i < I.getHeight(); i++) {
478  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
479  s << I[i][j] << " ";
480  }
481 
482  // We don't add " " after the last column element
483  s << I[i][I.getWidth() - 1];
484 
485  // We don't add a \n character at the end of the last row line
486  if (i < I.getHeight() - 1) {
487  s << std::endl;
488  }
489  }
490 
491  s.flags(original_flags); // restore s to standard state
492  return s;
493 }
494 
495 inline std::ostream &operator<<(std::ostream &s, const vpImage<double> &I)
496 {
497  if (I.bitmap == NULL) {
498  return s;
499  }
500 
501  std::ios_base::fmtflags original_flags = s.flags();
502  s.precision(17); // http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
503 
504  for (unsigned int i = 0; i < I.getHeight(); i++) {
505  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
506  s << I[i][j] << " ";
507  }
508 
509  // We don't add " " after the last column element
510  s << I[i][I.getWidth() - 1];
511 
512  // We don't add a \n character at the end of the last row line
513  if (i < I.getHeight() - 1) {
514  s << std::endl;
515  }
516  }
517 
518  s.flags(original_flags); // restore s to standard state
519  return s;
520 }
521 
522 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
523 namespace
524 {
525 struct ImageLut_Param_t {
526  unsigned int m_start_index;
527  unsigned int m_end_index;
528 
529  unsigned char m_lut[256];
530  unsigned char *m_bitmap;
531 
532  ImageLut_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_bitmap(NULL) {}
533 
534  ImageLut_Param_t(unsigned int start_index, unsigned int end_index, unsigned char *bitmap)
535  : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
536  {
537  }
538 };
539 
540 vpThread::Return performLutThread(vpThread::Args args)
541 {
542  ImageLut_Param_t *imageLut_param = static_cast<ImageLut_Param_t *>(args);
543  unsigned int start_index = imageLut_param->m_start_index;
544  unsigned int end_index = imageLut_param->m_end_index;
545 
546  unsigned char *bitmap = imageLut_param->m_bitmap;
547 
548  unsigned char *ptrStart = bitmap + start_index;
549  unsigned char *ptrEnd = bitmap + end_index;
550  unsigned char *ptrCurrent = ptrStart;
551 
552  // while(ptrCurrent != ptrEnd) {
553  // *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
554  // ++ptrCurrent;
555  // }
556 
557  if (end_index - start_index >= 8) {
558  // Unroll loop version
559  for (; ptrCurrent <= ptrEnd - 8;) {
560  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
561  ++ptrCurrent;
562 
563  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
564  ++ptrCurrent;
565 
566  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
567  ++ptrCurrent;
568 
569  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
570  ++ptrCurrent;
571 
572  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
573  ++ptrCurrent;
574 
575  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
576  ++ptrCurrent;
577 
578  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
579  ++ptrCurrent;
580 
581  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
582  ++ptrCurrent;
583  }
584  }
585 
586  for (; ptrCurrent != ptrEnd; ++ptrCurrent) {
587  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
588  }
589 
590  return 0;
591 }
592 
593 struct ImageLutRGBa_Param_t {
594  unsigned int m_start_index;
595  unsigned int m_end_index;
596 
597  vpRGBa m_lut[256];
598  unsigned char *m_bitmap;
599 
600  ImageLutRGBa_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_bitmap(NULL) {}
601 
602  ImageLutRGBa_Param_t(unsigned int start_index, unsigned int end_index, unsigned char *bitmap)
603  : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
604  {
605  }
606 };
607 
608 vpThread::Return performLutRGBaThread(vpThread::Args args)
609 {
610  ImageLutRGBa_Param_t *imageLut_param = static_cast<ImageLutRGBa_Param_t *>(args);
611  unsigned int start_index = imageLut_param->m_start_index;
612  unsigned int end_index = imageLut_param->m_end_index;
613 
614  unsigned char *bitmap = imageLut_param->m_bitmap;
615 
616  unsigned char *ptrStart = bitmap + start_index * 4;
617  unsigned char *ptrEnd = bitmap + end_index * 4;
618  unsigned char *ptrCurrent = ptrStart;
619 
620  if (end_index - start_index >= 4 * 2) {
621  // Unroll loop version
622  for (; ptrCurrent <= ptrEnd - 4 * 2;) {
623  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
624  ptrCurrent++;
625  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
626  ptrCurrent++;
627  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
628  ptrCurrent++;
629  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
630  ptrCurrent++;
631 
632  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
633  ptrCurrent++;
634  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
635  ptrCurrent++;
636  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
637  ptrCurrent++;
638  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
639  ptrCurrent++;
640  }
641  }
642 
643  while (ptrCurrent != ptrEnd) {
644  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
645  ptrCurrent++;
646 
647  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
648  ptrCurrent++;
649 
650  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
651  ptrCurrent++;
652 
653  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
654  ptrCurrent++;
655  }
656 
657  return 0;
658 }
659 }
660 #endif
661 
675 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w, Type value)
676 {
677  init(h, w);
678 
679  // for (unsigned int i = 0; i < npixels; i++)
680  // bitmap[i] = value;
681  std::fill(bitmap, bitmap + npixels, value);
682 }
683 
701 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w)
702 {
703  if (h != this->height) {
704  if (row != NULL) {
705  vpDEBUG_TRACE(10, "Destruction row[]");
706  delete[] row;
707  row = NULL;
708  }
709  }
710 
711  if ((h != this->height) || (w != this->width)) {
712  if (bitmap != NULL) {
713  vpDEBUG_TRACE(10, "Destruction bitmap[]");
714  if (hasOwnership) {
715  delete[] bitmap;
716  }
717  bitmap = NULL;
718  }
719  }
720 
721  this->width = w;
722  this->height = h;
723 
724  npixels = width * height;
725 
726  if (bitmap == NULL) {
727  bitmap = new Type[npixels];
728  hasOwnership = true;
729  }
730 
731  if (bitmap == NULL) {
732  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
733  }
734 
735  if (row == NULL)
736  row = new Type *[height];
737  if (row == NULL) {
738  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
739  }
740 
741  for (unsigned int i = 0; i < height; i++)
742  row[i] = bitmap + i * width;
743 }
744 
758 template <class Type>
759 void vpImage<Type>::init(Type *const array, unsigned int h, unsigned int w, bool copyData)
760 {
761  if (h != this->height) {
762  if (row != NULL) {
763  delete[] row;
764  row = NULL;
765  }
766  }
767 
768  // Delete bitmap if copyData==false, otherwise only if the dimension differs
769  if ((copyData && ((h != this->height) || (w != this->width))) || !copyData) {
770  if (bitmap != NULL) {
771  if (hasOwnership) {
772  delete[] bitmap;
773  }
774  bitmap = NULL;
775  }
776  }
777 
778  hasOwnership = copyData;
779  this->width = w;
780  this->height = h;
781 
782  npixels = width * height;
783 
784  if (copyData) {
785  if (bitmap == NULL)
786  bitmap = new Type[npixels];
787 
788  if (bitmap == NULL) {
789  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
790  }
791 
792  // Copy the image data
793  memcpy(static_cast<void*>(bitmap), static_cast<void*>(array), (size_t)(npixels * sizeof(Type)));
794  } else {
795  // Copy the address of the array in the bitmap
796  bitmap = array;
797  }
798 
799  if (row == NULL)
800  row = new Type *[height];
801  if (row == NULL) {
802  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
803  }
804 
805  for (unsigned int i = 0; i < height; i++) {
806  row[i] = bitmap + i * width;
807  }
808 }
809 
828 template <class Type>
829 vpImage<Type>::vpImage(unsigned int h, unsigned int w)
830  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
831 {
832  init(h, w, 0);
833 }
834 
852 template <class Type>
853 vpImage<Type>::vpImage(unsigned int h, unsigned int w, Type value)
854  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
855 {
856  init(h, w, value);
857 }
858 
874 template <class Type>
875 vpImage<Type>::vpImage(Type *const array, unsigned int h, unsigned int w, bool copyData)
876  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
877 {
878  init(array, h, w, copyData);
879 }
880 
890 template <class Type> vpImage<Type>::vpImage() :
891  bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
892 {
893 }
894 
915 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w) { init(h, w); }
916 
936 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w, const Type &val) { init(h, w, val); }
937 
944 template <class Type> void vpImage<Type>::destroy()
945 {
946  // vpERROR_TRACE("Deallocate ");
947 
948  if (bitmap != NULL) {
949  // vpERROR_TRACE("Deallocate bitmap memory %p",bitmap);
950  // vpDEBUG_TRACE(20,"Deallocate bitmap memory %p",bitmap);
951  if (hasOwnership) {
952  delete[] bitmap;
953  }
954  bitmap = NULL;
955  }
956 
957  if (row != NULL) {
958  // vpERROR_TRACE("Deallocate row memory %p",row);
959  // vpDEBUG_TRACE(20,"Deallocate row memory %p",row);
960  delete[] row;
961  row = NULL;
962  }
963 }
964 
971 template <class Type> vpImage<Type>::~vpImage() { destroy(); }
972 
976 template <class Type>
978  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
979 {
980  resize(I.getHeight(), I.getWidth());
981  memcpy(static_cast<void*>(bitmap), static_cast<void*>(I.bitmap), I.npixels * sizeof(Type));
982 }
983 
984 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
985 
988 template <class Type>
990  : bitmap(I.bitmap), display(I.display), npixels(I.npixels), width(I.width), height(I.height), row(I.row), hasOwnership(I.hasOwnership)
991 {
992  I.bitmap = NULL;
993  I.display = NULL;
994  I.npixels = 0;
995  I.width = 0;
996  I.height = 0;
997  I.row = NULL;
998  I.hasOwnership = false;
999 }
1000 #endif
1001 
1007 template <class Type> Type vpImage<Type>::getMaxValue() const
1008 {
1009  if (npixels == 0)
1010  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
1011  Type m = bitmap[0];
1012  for (unsigned int i = 0; i < npixels; i++) {
1013  if (bitmap[i] > m)
1014  m = bitmap[i];
1015  }
1016  return m;
1017 }
1018 
1022 template <class Type> Type vpImage<Type>::getMeanValue() const
1023 {
1024  if ((height == 0) || (width == 0))
1025  return 0.0;
1026 
1027  return getSum() / (height * width);
1028 }
1029 
1035 template <class Type> Type vpImage<Type>::getMinValue() const
1036 {
1037  if (npixels == 0)
1038  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
1039  Type m = bitmap[0];
1040  for (unsigned int i = 0; i < npixels; i++)
1041  if (bitmap[i] < m)
1042  m = bitmap[i];
1043  return m;
1044 }
1045 
1053 template <class Type> void vpImage<Type>::getMinMaxValue(Type &min, Type &max) const
1054 {
1055  if (npixels == 0)
1056  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1057 
1058  min = max = bitmap[0];
1059  for (unsigned int i = 0; i < npixels; i++) {
1060  if (bitmap[i] < min)
1061  min = bitmap[i];
1062  if (bitmap[i] > max)
1063  max = bitmap[i];
1064  }
1065 }
1066 
1088 template <class Type>
1089 void vpImage<Type>::getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal, Type *maxVal) const
1090 {
1091  if (npixels == 0)
1092  throw(vpException(vpException::fatalError, "Cannot get location of minimum/maximum "
1093  "values of an empty image"));
1094 
1095  Type min = bitmap[0], max = bitmap[0];
1096  vpImagePoint minLoc_, maxLoc_;
1097  for (unsigned int i = 0; i < height; i++) {
1098  for (unsigned int j = 0; j < width; j++) {
1099  if (row[i][j] < min) {
1100  min = row[i][j];
1101  minLoc_.set_ij(i, j);
1102  }
1103 
1104  if (row[i][j] > max) {
1105  max = row[i][j];
1106  maxLoc_.set_ij(i, j);
1107  }
1108  }
1109  }
1110 
1111  if (minLoc != NULL)
1112  *minLoc = minLoc_;
1113 
1114  if (maxLoc != NULL)
1115  *maxLoc = maxLoc_;
1116 
1117  if (minVal != NULL)
1118  *minVal = min;
1119 
1120  if (maxVal != NULL)
1121  *maxVal = max;
1122 }
1123 
1128 {
1129  swap(*this, other);
1130  // Swap back display pointer if it was not null
1131  // vpImage<unsigned char> I2(480, 640);
1132  // vpDisplayX d(I2);
1133  // I2 = I1; //copy only the data
1134  if (other.display != NULL)
1135  display = other.display;
1136 
1137  return *this;
1138 }
1139 
1146 template <class Type> vpImage<Type> &vpImage<Type>::operator=(const Type &v)
1147 {
1148  for (unsigned int i = 0; i < npixels; i++)
1149  bitmap[i] = v;
1150 
1151  return *this;
1152 }
1153 
1159 template <class Type> bool vpImage<Type>::operator==(const vpImage<Type> &I)
1160 {
1161  if (this->width != I.getWidth())
1162  return false;
1163  if (this->height != I.getHeight())
1164  return false;
1165 
1166  // printf("wxh: %dx%d bitmap: %p I.bitmap %p\n", width, height, bitmap,
1167  // I.bitmap);
1168  for (unsigned int i = 0; i < npixels; i++) {
1169  if (bitmap[i] != I.bitmap[i]) {
1170  // std::cout << "differ for pixel " << i << " (" << i%this->height
1171  // << ", " << i - i%this->height << ")" << std::endl;
1172  return false;
1173  }
1174  }
1175  return true;
1176 }
1182 template <class Type> bool vpImage<Type>::operator!=(const vpImage<Type> &I)
1183 {
1184  return !(*this == I);
1185 }
1186 
1213 {
1214  vpImage<Type> C;
1215  sub(*this, B, C);
1216  return C;
1217 }
1218 
1230 template <class Type> void vpImage<Type>::insert(const vpImage<Type> &src, const vpImagePoint &topLeft)
1231 {
1232  int itl = (int)topLeft.get_i();
1233  int jtl = (int)topLeft.get_j();
1234 
1235  int dest_ibegin = 0;
1236  int dest_jbegin = 0;
1237  int src_ibegin = 0;
1238  int src_jbegin = 0;
1239  int dest_w = (int)this->getWidth();
1240  int dest_h = (int)this->getHeight();
1241  int src_w = (int)src.getWidth();
1242  int src_h = (int)src.getHeight();
1243  int wsize = (int)src.getWidth();
1244  int hsize = (int)src.getHeight();
1245 
1246  if (itl >= dest_h || jtl >= dest_w)
1247  return;
1248 
1249  if (itl < 0)
1250  src_ibegin = -itl;
1251  else
1252  dest_ibegin = itl;
1253 
1254  if (jtl < 0)
1255  src_jbegin = -jtl;
1256  else
1257  dest_jbegin = jtl;
1258 
1259  if (src_w - src_jbegin > dest_w - dest_jbegin)
1260  wsize = dest_w - dest_jbegin;
1261  else
1262  wsize = src_w - src_jbegin;
1263 
1264  if (src_h - src_ibegin > dest_h - dest_ibegin)
1265  hsize = dest_h - dest_ibegin;
1266  else
1267  hsize = src_h - src_ibegin;
1268 
1269  for (int i = 0; i < hsize; i++) {
1270  Type *srcBitmap = src.bitmap + ((src_ibegin + i) * src_w + src_jbegin);
1271  Type *destBitmap = this->bitmap + ((dest_ibegin + i) * dest_w + dest_jbegin);
1272 
1273  memcpy(static_cast<void*>(destBitmap), static_cast<void*>(srcBitmap), (size_t)wsize * sizeof(Type));
1274  }
1275 }
1276 
1307 template <class Type> void vpImage<Type>::halfSizeImage(vpImage<Type> &res) const
1308 {
1309  unsigned int h = height / 2;
1310  unsigned int w = width / 2;
1311  res.resize(h, w);
1312  for (unsigned int i = 0; i < h; i++)
1313  for (unsigned int j = 0; j < w; j++)
1314  res[i][j] = (*this)[i << 1][j << 1];
1315 }
1316 
1334 template <class Type>
1335 void vpImage<Type>::subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const
1336 {
1337  unsigned int h = height / v_scale;
1338  unsigned int w = width / h_scale;
1339  sampled.resize(h, w);
1340  for (unsigned int i = 0; i < h; i++)
1341  for (unsigned int j = 0; j < w; j++)
1342  sampled[i][j] = (*this)[i * v_scale][j * h_scale];
1343 }
1344 
1367 template <class Type> void vpImage<Type>::quarterSizeImage(vpImage<Type> &res) const
1368 {
1369  unsigned int h = height / 4;
1370  unsigned int w = width / 4;
1371  res.resize(h, w);
1372  for (unsigned int i = 0; i < h; i++)
1373  for (unsigned int j = 0; j < w; j++)
1374  res[i][j] = (*this)[i << 2][j << 2];
1375 }
1376 
1409 template <class Type> void vpImage<Type>::doubleSizeImage(vpImage<Type> &res)
1410 {
1411  int h = height * 2;
1412  int w = width * 2;
1413 
1414  res.resize(h, w);
1415 
1416  for (int i = 0; i < h; i++)
1417  for (int j = 0; j < w; j++)
1418  res[i][j] = (*this)[i >> 1][j >> 1];
1419 
1420  /*
1421  A B C
1422  E F G
1423  H I J
1424  A C H J are pixels from original image
1425  B E G I are interpolated pixels
1426  */
1427 
1428  // interpolate pixels B and I
1429  for (int i = 0; i < h; i += 2)
1430  for (int j = 1; j < w - 1; j += 2)
1431  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1]));
1432 
1433  // interpolate pixels E and G
1434  for (int i = 1; i < h - 1; i += 2)
1435  for (int j = 0; j < w; j += 2)
1436  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[(i >> 1) + 1][j >> 1]));
1437 
1438  // interpolate pixel F
1439  for (int i = 1; i < h - 1; i += 2)
1440  for (int j = 1; j < w - 1; j += 2)
1441  res[i][j] = (Type)(0.25 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1] +
1442  (*this)[(i >> 1) + 1][j >> 1] + (*this)[(i >> 1) + 1][(j >> 1) + 1]));
1443 }
1444 
1458 template <class Type> inline Type vpImage<Type>::getValue(unsigned int i, unsigned int j) const
1459 {
1460  if (i >= height || j >= width) {
1461  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1462  }
1463 
1464  return row[i][j];
1465 }
1466 
1484 template <class Type> Type vpImage<Type>::getValue(double i, double j) const
1485 {
1486  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1487  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1488  }
1489  if (height * width == 0) {
1490  throw vpException(vpImageException::notInitializedError, "Empty image!");
1491  }
1492 
1493  unsigned int iround = static_cast<unsigned int>(floor(i));
1494  unsigned int jround = static_cast<unsigned int>(floor(j));
1495 
1496  double rratio = i - static_cast<double>(iround);
1497  double cratio = j - static_cast<double>(jround);
1498 
1499  double rfrac = 1.0 - rratio;
1500  double cfrac = 1.0 - cratio;
1501 
1502  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1503  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1504 
1505  double value = (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
1506  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) * cratio;
1507 
1508  return static_cast<Type>(vpMath::round(value));
1509 }
1510 
1527 template <> inline double vpImage<double>::getValue(double i, double j) const
1528 {
1529  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1530  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1531  }
1532  if (height * width == 0) {
1533  throw vpException(vpImageException::notInitializedError, "Empty image!");
1534  }
1535 
1536  unsigned int iround = static_cast<unsigned int>(floor(i));
1537  unsigned int jround = static_cast<unsigned int>(floor(j));
1538 
1539  double rratio = i - static_cast<double>(iround);
1540  double cratio = j - static_cast<double>(jround);
1541 
1542  double rfrac = 1.0 - rratio;
1543  double cfrac = 1.0 - cratio;
1544 
1545  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1546  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1547 
1548  return (row[iround][jround] * rfrac + row[iround_1][jround] * rratio) * cfrac +
1549  (row[iround][jround_1] * rfrac + row[iround_1][jround_1] * rratio) * cratio;
1550 }
1551 
1552 template <> inline unsigned char vpImage<unsigned char>::getValue(double i, double j) const {
1553  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1554  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1555  }
1556  if (height * width == 0) {
1557  throw vpException(vpImageException::notInitializedError, "Empty image!");
1558  }
1559 
1560 #if defined(VISP_LITTLE_ENDIAN)
1561  //Fixed-point arithmetic
1562  const int precision = 1 << 16;
1563  int64_t y = static_cast<int64_t>(i * precision);
1564  int64_t x = static_cast<int64_t>(j * precision);
1565 
1566  int64_t iround = y & (~0xFFFF);
1567  int64_t jround = x & (~0xFFFF);
1568 
1569  int64_t rratio = y - iround;
1570  int64_t cratio = x - jround;
1571 
1572  int64_t rfrac = precision - rratio;
1573  int64_t cfrac = precision - cratio;
1574 
1575  int64_t x_ = x >> 16;
1576  int64_t y_ = y >> 16;
1577 
1578  if (y_ + 1 < height && x_ + 1 < width) {
1579  uint16_t up = *reinterpret_cast<uint16_t *>(bitmap + y_ * width + x_);
1580  uint16_t down = *reinterpret_cast<uint16_t *>(bitmap + (y_ + 1) * width + x_);
1581 
1582  return static_cast<unsigned char>((((up & 0x00FF) * rfrac + (down & 0x00FF) * rratio) * cfrac +
1583  ((up >> 8) * rfrac + (down >> 8) * rratio) * cratio) >> 32);
1584  } else if (y_ + 1 < height) {
1585  return static_cast<unsigned char>(((row[y_][x_] * rfrac + row[y_ + 1][x_] * rratio)) >> 16);
1586  } else if (x_ + 1 < width) {
1587  uint16_t up = *reinterpret_cast<uint16_t *>(bitmap + y_ * width + x_);
1588  return static_cast<unsigned char>(((up & 0x00FF) * cfrac + (up >> 8) * cratio) >> 16);
1589  } else {
1590  return row[y_][x_];
1591  }
1592 #elif defined(VISP_BIG_ENDIAN)
1593  //Fixed-point arithmetic
1594  const int precision = 1 << 16;
1595  int64_t y = static_cast<int64_t>(i * precision);
1596  int64_t x = static_cast<int64_t>(j * precision);
1597 
1598  int64_t iround = y & (~0xFFFF);
1599  int64_t jround = x & (~0xFFFF);
1600 
1601  int64_t rratio = y - iround;
1602  int64_t cratio = x - jround;
1603 
1604  int64_t rfrac = precision - rratio;
1605  int64_t cfrac = precision - cratio;
1606 
1607  int64_t x_ = x >> 16;
1608  int64_t y_ = y >> 16;
1609 
1610  if (y_ + 1 < height && x_ + 1 < width) {
1611  uint16_t up = *reinterpret_cast<uint16_t *>(bitmap + y_ * width + x_);
1612  uint16_t down = *reinterpret_cast<uint16_t *>(bitmap + (y_ + 1) * width + x_);
1613 
1614  return static_cast<unsigned char>((((up >> 8) * rfrac + (down >> 8) * rratio) * cfrac +
1615  ((up & 0x00FF) * rfrac + (down & 0x00FF) * rratio) * cratio) >> 32);
1616  } else if (y_ + 1 < height) {
1617  return static_cast<unsigned char>(((row[y_][x_] * rfrac + row[y_ + 1][x_] * rratio)) >> 16);
1618  } else if (x_ + 1 < width) {
1619  uint16_t up = *reinterpret_cast<uint16_t *>(bitmap + y_ * width + x_);
1620  return static_cast<unsigned char>(((up >> 8) * cfrac + (up & 0x00FF) * cratio) >> 16);
1621  } else {
1622  return row[y_][x_];
1623  }
1624 #else
1625  unsigned int iround = static_cast<unsigned int>(floor(i));
1626  unsigned int jround = static_cast<unsigned int>(floor(j));
1627 
1628  if (iround >= height || jround >= width) {
1629  vpERROR_TRACE("Pixel outside the image") ;
1631  "Pixel outside the image"));
1632  }
1633 
1634  double rratio = i - static_cast<double>(iround);
1635  double cratio = j - static_cast<double>(jround);
1636 
1637  double rfrac = 1.0 - rratio;
1638  double cfrac = 1.0 - cratio;
1639 
1640  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1641  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1642 
1643  double value = (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
1644  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) * cratio;
1645  return static_cast<unsigned char>(vpMath::round(value));
1646 #endif
1647 }
1648 
1649 template <> inline vpRGBa vpImage<vpRGBa>::getValue(double i, double j) const
1650 {
1651  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1652  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1653  }
1654  if (height * width == 0) {
1655  throw vpException(vpImageException::notInitializedError, "Empty image!");
1656  }
1657 
1658  unsigned int iround = static_cast<unsigned int>(floor(i));
1659  unsigned int jround = static_cast<unsigned int>(floor(j));
1660 
1661  double rratio = i - static_cast<double>(iround);
1662  double cratio = j - static_cast<double>(jround);
1663 
1664  double rfrac = 1.0 - rratio;
1665  double cfrac = 1.0 - cratio;
1666 
1667  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1668  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1669 
1670  double valueR = (static_cast<double>(row[iround][jround].R) * rfrac + static_cast<double>(row[iround_1][jround].R) * rratio) * cfrac +
1671  (static_cast<double>(row[iround][jround_1].R) * rfrac + static_cast<double>(row[iround_1][jround_1].R) * rratio) * cratio;
1672  double valueG = (static_cast<double>(row[iround][jround].G) * rfrac + static_cast<double>(row[iround_1][jround].G) * rratio) * cfrac +
1673  (static_cast<double>(row[iround][jround_1].G) * rfrac + static_cast<double>(row[iround_1][jround_1].G) * rratio) * cratio;
1674  double valueB = (static_cast<double>(row[iround][jround].B) * rfrac + static_cast<double>(row[iround_1][jround].B) * rratio) * cfrac +
1675  (static_cast<double>(row[iround][jround_1].B) * rfrac + static_cast<double>(row[iround_1][jround_1].B) * rratio) * cratio;
1676 
1677  return vpRGBa(static_cast<unsigned char>(vpMath::round(valueR)),
1678  static_cast<unsigned char>(vpMath::round(valueG)),
1679  static_cast<unsigned char>(vpMath::round(valueB)));
1680 }
1681 
1698 template <class Type> inline Type vpImage<Type>::getValue(const vpImagePoint &ip) const
1699 {
1700  return getValue(ip.get_i(), ip.get_j());
1701 }
1702 
1703 template <> inline double vpImage<double>::getValue(const vpImagePoint &ip) const
1704 {
1705  return getValue(ip.get_i(), ip.get_j());
1706 }
1707 
1708 template <> inline unsigned char vpImage<unsigned char>::getValue(const vpImagePoint &ip) const
1709 {
1710  return getValue(ip.get_i(), ip.get_j());
1711 }
1712 
1713 template <> inline vpRGBa vpImage<vpRGBa>::getValue(const vpImagePoint &ip) const
1714 {
1715  return getValue(ip.get_i(), ip.get_j());
1716 }
1717 
1721 template <class Type> inline double vpImage<Type>::getSum() const
1722 {
1723  if ((height == 0) || (width == 0))
1724  return 0.0;
1725 
1726  double res = 0.0;
1727  for (unsigned int i = 0; i < height * width; ++i) {
1728  res += static_cast<double>(bitmap[i]);
1729  }
1730  return res;
1731 }
1732 
1762 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &B, vpImage<Type> &C)
1763 {
1764 
1765  try {
1766  if ((this->getHeight() != C.getHeight()) || (this->getWidth() != C.getWidth()))
1767  C.resize(this->getHeight(), this->getWidth());
1768  } catch (const vpException &me) {
1769  std::cout << me << std::endl;
1770  throw;
1771  }
1772 
1773  if ((this->getWidth() != B.getWidth()) || (this->getHeight() != B.getHeight())) {
1774  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage subtraction "));
1775  }
1776 
1777  for (unsigned int i = 0; i < this->getWidth() * this->getHeight(); i++) {
1778  *(C.bitmap + i) = *(bitmap + i) - *(B.bitmap + i);
1779  }
1780 }
1781 
1793 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C)
1794 {
1795 
1796  try {
1797  if ((A.getHeight() != C.getHeight()) || (A.getWidth() != C.getWidth()))
1798  C.resize(A.getHeight(), A.getWidth());
1799  } catch (const vpException &me) {
1800  std::cout << me << std::endl;
1801  throw;
1802  }
1803 
1804  if ((A.getWidth() != B.getWidth()) || (A.getHeight() != B.getHeight())) {
1805  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage subtraction "));
1806  }
1807 
1808  for (unsigned int i = 0; i < A.getWidth() * A.getHeight(); i++) {
1809  *(C.bitmap + i) = *(A.bitmap + i) - *(B.bitmap + i);
1810  }
1811 }
1812 
1823 template <class Type> void vpImage<Type>::performLut(const Type (&)[256], const unsigned int)
1824 {
1825  std::cerr << "Not implemented !" << std::endl;
1826 }
1827 
1836 template <>
1837 inline void vpImage<unsigned char>::performLut(const unsigned char (&lut)[256], unsigned int nbThreads)
1838 {
1839  unsigned int size = getWidth() * getHeight();
1840  unsigned char *ptrStart = (unsigned char *)bitmap;
1841  unsigned char *ptrEnd = ptrStart + size;
1842  unsigned char *ptrCurrent = ptrStart;
1843 
1844  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
1845 #if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
1846  use_single_thread = true;
1847 #endif
1848 
1849  if (!use_single_thread && getSize() <= nbThreads) {
1850  use_single_thread = true;
1851  }
1852 
1853  if (use_single_thread) {
1854  // Single thread
1855 
1856  while (ptrCurrent != ptrEnd) {
1857  *ptrCurrent = lut[*ptrCurrent];
1858  ++ptrCurrent;
1859  }
1860  } else {
1861 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
1862  // Multi-threads
1863 
1864  std::vector<vpThread *> threadpool;
1865  std::vector<ImageLut_Param_t *> imageLutParams;
1866 
1867  unsigned int image_size = getSize();
1868  unsigned int step = image_size / nbThreads;
1869  unsigned int last_step = image_size - step * (nbThreads - 1);
1870 
1871  for (unsigned int index = 0; index < nbThreads; index++) {
1872  unsigned int start_index = index * step;
1873  unsigned int end_index = (index + 1) * step;
1874 
1875  if (index == nbThreads - 1) {
1876  end_index = start_index + last_step;
1877  }
1878 
1879  ImageLut_Param_t *imageLut_param = new ImageLut_Param_t(start_index, end_index, bitmap);
1880  memcpy(imageLut_param->m_lut, lut, 256 * sizeof(unsigned char));
1881 
1882  imageLutParams.push_back(imageLut_param);
1883 
1884  // Start the threads
1885  vpThread *imageLut_thread = new vpThread((vpThread::Fn)performLutThread, (vpThread::Args)imageLut_param);
1886  threadpool.push_back(imageLut_thread);
1887  }
1888 
1889  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1890  // Wait until thread ends up
1891  threadpool[cpt]->join();
1892  }
1893 
1894  // Delete
1895  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1896  delete threadpool[cpt];
1897  }
1898 
1899  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
1900  delete imageLutParams[cpt];
1901  }
1902 #endif
1903  }
1904 }
1905 
1914 template <> inline void vpImage<vpRGBa>::performLut(const vpRGBa (&lut)[256], unsigned int nbThreads)
1915 {
1916  unsigned int size = getWidth() * getHeight();
1917  unsigned char *ptrStart = (unsigned char *)bitmap;
1918  unsigned char *ptrEnd = ptrStart + size * 4;
1919  unsigned char *ptrCurrent = ptrStart;
1920 
1921  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
1922 #if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
1923  use_single_thread = true;
1924 #endif
1925 
1926  if (!use_single_thread && getSize() <= nbThreads) {
1927  use_single_thread = true;
1928  }
1929 
1930  if (use_single_thread) {
1931  // Single thread
1932  while (ptrCurrent != ptrEnd) {
1933  *ptrCurrent = lut[*ptrCurrent].R;
1934  ++ptrCurrent;
1935 
1936  *ptrCurrent = lut[*ptrCurrent].G;
1937  ++ptrCurrent;
1938 
1939  *ptrCurrent = lut[*ptrCurrent].B;
1940  ++ptrCurrent;
1941 
1942  *ptrCurrent = lut[*ptrCurrent].A;
1943  ++ptrCurrent;
1944  }
1945  } else {
1946 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
1947  // Multi-threads
1948  std::vector<vpThread *> threadpool;
1949  std::vector<ImageLutRGBa_Param_t *> imageLutParams;
1950 
1951  unsigned int image_size = getSize();
1952  unsigned int step = image_size / nbThreads;
1953  unsigned int last_step = image_size - step * (nbThreads - 1);
1954 
1955  for (unsigned int index = 0; index < nbThreads; index++) {
1956  unsigned int start_index = index * step;
1957  unsigned int end_index = (index + 1) * step;
1958 
1959  if (index == nbThreads - 1) {
1960  end_index = start_index + last_step;
1961  }
1962 
1963  ImageLutRGBa_Param_t *imageLut_param = new ImageLutRGBa_Param_t(start_index, end_index, (unsigned char *)bitmap);
1964  memcpy(imageLut_param->m_lut, lut, 256 * sizeof(vpRGBa));
1965 
1966  imageLutParams.push_back(imageLut_param);
1967 
1968  // Start the threads
1969  vpThread *imageLut_thread = new vpThread((vpThread::Fn)performLutRGBaThread, (vpThread::Args)imageLut_param);
1970  threadpool.push_back(imageLut_thread);
1971  }
1972 
1973  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1974  // Wait until thread ends up
1975  threadpool[cpt]->join();
1976  }
1977 
1978  // Delete
1979  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1980  delete threadpool[cpt];
1981  }
1982 
1983  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
1984  delete imageLutParams[cpt];
1985  }
1986 #endif
1987  }
1988 }
1989 
1990 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second)
1991 {
1992  using std::swap;
1993  swap(first.bitmap, second.bitmap);
1994  swap(first.display, second.display);
1995  swap(first.npixels, second.npixels);
1996  swap(first.width, second.width);
1997  swap(first.height, second.height);
1998  swap(first.row, second.row);
1999 }
2000 
2001 #endif
vpImage::getNumberOfPixel
unsigned int getNumberOfPixel() const
Definition: vpImage.h:243
vpImage::operator<<
friend std::ostream & operator<<(std::ostream &s, const vpImage< unsigned char > &I)
Definition: vpImage.h:416
vpImage::resize
void resize(unsigned int h, unsigned int w, const Type &val)
resize the image : Image initialization
Definition: vpImage.h:936
vpThread::Return
void * Return
Definition: vpThread.h:78
vpImage::getValue
Type getValue(unsigned int i, unsigned int j) const
Definition: vpImage.h:1458
vpImage::operator[]
const Type * operator[](unsigned int i) const
operator[] allows operation like x = I[i]
Definition: vpImage.h:301
vpImage::operator[]
Type * operator[](int i)
Definition: vpImage.h:298
vpImage::halfSizeImage
void halfSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1307
vpImage::sub
void sub(const vpImage< Type > &A, const vpImage< Type > &B, vpImage< Type > &C)
Definition: vpImage.h:1793
vpImage::getMeanValue
Type getMeanValue() const
Return the mean value of the bitmap.
Definition: vpImage.h:1022
vpImage::getMinMaxLoc
void getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal=NULL, Type *maxVal=NULL) const
Get the position of the minimum and/or the maximum pixel value within the bitmap and the correspondin...
Definition: vpImage.h:1089
vpImage::resize
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:915
vpImage::operator=
vpImage< Type > & operator=(vpImage< Type > other)
Copy operator.
Definition: vpImage.h:1127
vpImage::getCols
unsigned int getCols() const
Definition: vpImage.h:213
vpException::fatalError
@ fatalError
Fatal error.
Definition: vpException.h:96
vpImage::getMaxValue
Type getMaxValue() const
Return the maximum value within the bitmap.
Definition: vpImage.h:1007
vpThread
Definition: vpThread.h:74
vpImage::operator()
Type operator()(unsigned int i, unsigned int j) const
Definition: vpImage.h:310
vpThread::Fn
void *(* Fn)(Args)
Definition: vpThread.h:79
vpImage::getSize
unsigned int getSize() const
Definition: vpImage.h:261
vpImage::insert
void insert(const vpImage< Type > &src, const vpImagePoint &topLeft)
Definition: vpImage.h:1230
vpImagePoint::set_ij
void set_ij(double ii, double jj)
Definition: vpImagePoint.h:189
vpRGBa
Definition: vpRGBa.h:67
vpImage::getValue
Type getValue(const vpImagePoint &ip) const
Definition: vpImage.h:1698
vpImage::init
void init(unsigned int height, unsigned int width, Type value)
Set the size of the image.
Definition: vpImage.h:675
vpImage::operator!=
bool operator!=(const vpImage< Type > &I)
Definition: vpImage.h:1182
vpImage::quarterSizeImage
void quarterSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1367
vpImage::operator[]
Type * operator[](unsigned int i)
operator[] allows operation like I[i] = x.
Definition: vpImage.h:297
vpThread::Args
void * Args
Definition: vpThread.h:77
vpImage::~vpImage
virtual ~vpImage()
destructor
Definition: vpImage.h:971
vpImagePoint::get_i
double get_i() const
Definition: vpImagePoint.h:204
vpImage::bitmap
Type * bitmap
points toward the bitmap
Definition: vpImage.h:177
vpImage::getRows
unsigned int getRows() const
Definition: vpImage.h:252
vpImage::subsample
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:1335
vpImage::operator<<
friend std::ostream & operator<<(std::ostream &s, const vpImage< double > &I)
Definition: vpImage.h:495
vpImage::getValue
Type getValue(double i, double j) const
Definition: vpImage.h:1484
vpImage::doubleSizeImage
void doubleSizeImage(vpImage< Type > &res)
Definition: vpImage.h:1409
vpImage::getMinValue
Type getMinValue() const
Return the minimum value within the bitmap.
Definition: vpImage.h:1035
vpImage::vpImage
vpImage()
constructor
Definition: vpImage.h:890
vpImageException::notInitializedError
@ notInitializedError
Definition: vpImageException.h:83
vpImage::vpImage
vpImage(unsigned int height, unsigned int width, Type value)
constructor set the size of the image and init all the pixel
Definition: vpImage.h:853
vpImage::init
void init(unsigned int height, unsigned int width)
Set the size of the image.
Definition: vpImage.h:701
vpImage::getSum
double getSum() const
Definition: vpImage.h:1721
vpImage::getHeight
unsigned int getHeight() const
Definition: vpImage.h:222
vpImage::operator==
bool operator==(const vpImage< Type > &I)
Definition: vpImage.h:1159
vpImage::operator=
vpImage< Type > & operator=(const Type &v)
= operator : Set all the element of the bitmap to a given value v.
Definition: vpImage.h:1146
vpException::memoryAllocationError
@ memoryAllocationError
Memory allocation error.
Definition: vpException.h:88
vpImage::operator-
vpImage< Type > operator-(const vpImage< Type > &B)
Definition: vpImage.h:1212
vpImagePoint
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:89
vpImageException::notInTheImage
@ notInTheImage
Definition: vpImageException.h:85
vpImageConvert
Definition: vpImageConvert.h:106
vpImage::operator()
Type operator()(const vpImagePoint &ip) const
Definition: vpImage.h:328
vpERROR_TRACE
#define vpERROR_TRACE
Definition: vpDebug.h:393
vpImage::operator<<
friend std::ostream & operator<<(std::ostream &s, const vpImage< char > &I)
Definition: vpImage.h:442
vpImage::operator<<
friend std::ostream & operator<<(std::ostream &s, const vpImage< float > &I)
Definition: vpImage.h:468
vpMath::round
static int round(double x)
Definition: vpMath.h:241
vpImage::getMinMaxValue
void getMinMaxValue(Type &min, Type &max) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:1053
vpImage::sub
void sub(const vpImage< Type > &B, vpImage< Type > &C)
Definition: vpImage.h:1762
vpImage
Definition of the vpImage class member functions.
Definition: vpImage.h:107
vpImage::operator()
void operator()(const vpImagePoint &ip, const Type &v)
Definition: vpImage.h:344
vpImage::init
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:759
vpImage::vpImage
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:875
vpImage::operator()
void operator()(unsigned int i, unsigned int j, const Type &v)
Definition: vpImage.h:316
vpImage::display
vpDisplay * display
Definition: vpImage.h:178
vpImage::performLut
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
Definition: vpImage.h:1823
vpDisplay
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:172
vpException
error that can be emited by ViSP classes.
Definition: vpException.h:72
vpImage::swap
friend void swap(vpImage< Type > &first, vpImage< Type > &second)
Definition: vpImage.h:1990
vpImage::operator[]
const Type * operator[](int i) const
Definition: vpImage.h:302
vpArray2D::operator<<
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Definition: vpArray2D.h:494
vpImagePoint::get_j
double get_j() const
Definition: vpImagePoint.h:215
vpImage::vpImage
vpImage(const vpImage< Type > &)
copy constructor
Definition: vpImage.h:977
vpImage::getWidth
unsigned int getWidth() const
Definition: vpImage.h:280
vpImage::destroy
void destroy()
Destructor : Memory de-allocation.
Definition: vpImage.h:944
vpDEBUG_TRACE
#define vpDEBUG_TRACE
Definition: vpDebug.h:487