Visual Servoing Platform  version 3.4.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/vpEndian.h>
50 #include <visp3/core/vpException.h>
51 #include <visp3/core/vpImageException.h>
52 #include <visp3/core/vpImagePoint.h>
53 #include <visp3/core/vpRGBa.h>
54 
55 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
56 #include <visp3/core/vpThread.h>
57 #endif
58 
59 #include <fstream>
60 #include <iomanip> // std::setw
61 #include <iostream>
62 #include <math.h>
63 #include <string.h>
64 
65 // Visual Studio 2010 or previous is missing inttypes.h
66 #if defined(_MSC_VER) && (_MSC_VER < 1700)
67 typedef long long int64_t;
68 typedef unsigned short uint16_t;
69 #else
70 # include <inttypes.h>
71 #endif
72 
73 class vpDisplay;
74 
125 // Ref: http://en.cppreference.com/w/cpp/language/friend#Template_friends
126 template <class Type> class vpImage; // forward declare to make function declaration possible
127 
128 // declarations
129 template <class Type> std::ostream &operator<<(std::ostream &, const vpImage<Type> &);
130 
131 std::ostream &operator<<(std::ostream &, const vpImage<unsigned char> &);
132 std::ostream &operator<<(std::ostream &, const vpImage<char> &);
133 std::ostream &operator<<(std::ostream &, const vpImage<float> &);
134 std::ostream &operator<<(std::ostream &, const vpImage<double> &);
135 
136 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second);
137 
138 template <class Type> class vpImage
139 {
140  friend class vpImageConvert;
141 
142 public:
143  Type *bitmap;
145 
147  vpImage();
149  vpImage(const vpImage<Type> &);
150 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
153 #endif
154  vpImage(unsigned int height, unsigned int width);
157  vpImage(unsigned int height, unsigned int width, Type value);
159  vpImage(Type *const array, unsigned int height, unsigned int width, bool copyData = false);
161  virtual ~vpImage();
162 
165 
166  // destructor
167  void destroy();
168 
169  // Returns a new image that's double size of the current image
170  void doubleSizeImage(vpImage<Type> &res);
171 
179  inline unsigned int getCols() const { return width; }
188  inline unsigned int getHeight() const { return height; }
189 
190  // Return the maximum value within the bitmap
191  Type getMaxValue() const;
192  // Return the mean value of the bitmap
193  Type getMeanValue() const;
194  // Return the minumum value within the bitmap
195  Type getMinValue() const;
196  // Look for the minumum and the maximum value within the bitmap
197  void getMinMaxValue(Type &min, Type &max) const;
198  // Look for the minumum and the maximum value within the bitmap and get their location
199  void getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal = NULL, Type *maxVal = NULL) const;
200 
209  inline unsigned int getNumberOfPixel() const { return npixels; }
210 
218  inline unsigned int getRows() const { return height; }
219 
227  inline unsigned int getSize() const { return width * height; }
228 
229  // Gets the value of a pixel at a location.
230  Type getValue(unsigned int i, unsigned int j) const;
231  // Gets the value of a pixel at a location with bilinear interpolation.
232  Type getValue(double i, double j) const;
233  // Gets the value of a pixel at a location with bilinear interpolation.
234  Type getValue(const vpImagePoint &ip) const;
235 
236  // Get image pixels sum
237  double getSum() const;
238 
246  inline unsigned int getWidth() const { return width; }
247 
248  // Returns a new image that's half size of the current image
249  void halfSizeImage(vpImage<Type> &res) const;
250 
252  void init(unsigned int height, unsigned int width);
254  void init(unsigned int height, unsigned int width, Type value);
256  void init(Type *const array, unsigned int height, unsigned int width, bool copyData = false);
257  void insert(const vpImage<Type> &src, const vpImagePoint &topLeft);
258 
259  //------------------------------------------------------------------
260  // Acces to the image
261 
263  inline Type *operator[](unsigned int i) { return row[i]; }
264  inline Type *operator[](int i) { return row[i]; }
265 
267  inline const Type *operator[](unsigned int i) const { return row[i]; }
268  inline const Type *operator[](int i) const { return row[i]; }
269 
276  inline Type operator()(unsigned int i, unsigned int j) const { return bitmap[i * width + j]; }
277 
282  inline void operator()(unsigned int i, unsigned int j, const Type &v) { bitmap[i * width + j] = v; }
283 
294  inline Type operator()(const vpImagePoint &ip) const
295  {
296  unsigned int i = (unsigned int)ip.get_i();
297  unsigned int j = (unsigned int)ip.get_j();
298 
299  return bitmap[i * width + j];
300  }
301 
310  inline void operator()(const vpImagePoint &ip, const Type &v)
311  {
312  unsigned int i = (unsigned int)ip.get_i();
313  unsigned int j = (unsigned int)ip.get_j();
314 
315  bitmap[i * width + j] = v;
316  }
317 
319 
322 
323  vpImage<Type> &operator=(const Type &v);
324  bool operator==(const vpImage<Type> &I);
325  bool operator!=(const vpImage<Type> &I);
326  friend std::ostream &operator<< <>(std::ostream &s, const vpImage<Type> &I);
327  friend std::ostream &operator<<(std::ostream &s, const vpImage<unsigned char> &I);
328  friend std::ostream &operator<<(std::ostream &s, const vpImage<char> &I);
329  friend std::ostream &operator<<(std::ostream &s, const vpImage<float> &I);
330  friend std::ostream &operator<<(std::ostream &s, const vpImage<double> &I);
331 
332  // Perform a look-up table transformation
333  void performLut(const Type (&lut)[256], unsigned int nbThreads = 1);
334 
335  // Returns a new image that's a quarter size of the current image
336  void quarterSizeImage(vpImage<Type> &res) const;
337 
338  // set the size of the image without initializing it.
339  void resize(unsigned int h, unsigned int w);
340  // set the size of the image and initialize it.
341  void resize(unsigned int h, unsigned int w, const Type &val);
342 
343  void sub(const vpImage<Type> &B, vpImage<Type> &C);
344  void sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C);
345  void subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const;
346 
347  friend void swap<>(vpImage<Type> &first, vpImage<Type> &second);
348 
350 
351 private:
352  unsigned int npixels;
353  unsigned int width;
354  unsigned int height;
355  Type **row;
356  bool hasOwnership;
357 };
358 
359 template <class Type> std::ostream &operator<<(std::ostream &s, const vpImage<Type> &I)
360 {
361  if (I.bitmap == NULL) {
362  return s;
363  }
364 
365  for (unsigned int i = 0; i < I.getHeight(); i++) {
366  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
367  s << I[i][j] << " ";
368  }
369 
370  // We don't add " " after the last column element
371  s << I[i][I.getWidth() - 1];
372 
373  // We don't add a \n character at the end of the last row line
374  if (i < I.getHeight() - 1) {
375  s << std::endl;
376  }
377  }
378 
379  return s;
380 }
381 
382 inline std::ostream &operator<<(std::ostream &s, const vpImage<unsigned char> &I)
383 {
384  if (I.bitmap == NULL) {
385  return s;
386  }
387 
388  std::ios_base::fmtflags original_flags = s.flags();
389 
390  for (unsigned int i = 0; i < I.getHeight(); i++) {
391  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
392  s << std::setw(3) << static_cast<unsigned>(I[i][j]) << " ";
393  }
394 
395  // We don't add " " after the last column element
396  s << std::setw(3) << static_cast<unsigned>(I[i][I.getWidth() - 1]);
397 
398  // We don't add a \n character at the end of the last row line
399  if (i < I.getHeight() - 1) {
400  s << std::endl;
401  }
402  }
403 
404  s.flags(original_flags); // restore s to standard state
405  return s;
406 }
407 
408 inline std::ostream &operator<<(std::ostream &s, const vpImage<char> &I)
409 {
410  if (I.bitmap == NULL) {
411  return s;
412  }
413 
414  std::ios_base::fmtflags original_flags = s.flags();
415 
416  for (unsigned int i = 0; i < I.getHeight(); i++) {
417  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
418  s << std::setw(4) << static_cast<int>(I[i][j]) << " ";
419  }
420 
421  // We don't add " " after the last column element
422  s << std::setw(4) << static_cast<int>(I[i][I.getWidth() - 1]);
423 
424  // We don't add a \n character at the end of the last row line
425  if (i < I.getHeight() - 1) {
426  s << std::endl;
427  }
428  }
429 
430  s.flags(original_flags); // restore s to standard state
431  return s;
432 }
433 
434 inline std::ostream &operator<<(std::ostream &s, const vpImage<float> &I)
435 {
436  if (I.bitmap == NULL) {
437  return s;
438  }
439 
440  std::ios_base::fmtflags original_flags = s.flags();
441  s.precision(9); // http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
442 
443  for (unsigned int i = 0; i < I.getHeight(); i++) {
444  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
445  s << I[i][j] << " ";
446  }
447 
448  // We don't add " " after the last column element
449  s << I[i][I.getWidth() - 1];
450 
451  // We don't add a \n character at the end of the last row line
452  if (i < I.getHeight() - 1) {
453  s << std::endl;
454  }
455  }
456 
457  s.flags(original_flags); // restore s to standard state
458  return s;
459 }
460 
461 inline std::ostream &operator<<(std::ostream &s, const vpImage<double> &I)
462 {
463  if (I.bitmap == NULL) {
464  return s;
465  }
466 
467  std::ios_base::fmtflags original_flags = s.flags();
468  s.precision(17); // http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
469 
470  for (unsigned int i = 0; i < I.getHeight(); i++) {
471  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
472  s << I[i][j] << " ";
473  }
474 
475  // We don't add " " after the last column element
476  s << I[i][I.getWidth() - 1];
477 
478  // We don't add a \n character at the end of the last row line
479  if (i < I.getHeight() - 1) {
480  s << std::endl;
481  }
482  }
483 
484  s.flags(original_flags); // restore s to standard state
485  return s;
486 }
487 
488 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
489 namespace
490 {
491 struct ImageLut_Param_t {
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  ImageLut_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_bitmap(NULL) {}
499 
500  ImageLut_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 
506 vpThread::Return performLutThread(vpThread::Args args)
507 {
508  ImageLut_Param_t *imageLut_param = static_cast<ImageLut_Param_t *>(args);
509  unsigned int start_index = imageLut_param->m_start_index;
510  unsigned int end_index = imageLut_param->m_end_index;
511 
512  unsigned char *bitmap = imageLut_param->m_bitmap;
513 
514  unsigned char *ptrStart = bitmap + start_index;
515  unsigned char *ptrEnd = bitmap + end_index;
516  unsigned char *ptrCurrent = ptrStart;
517 
518  // while(ptrCurrent != ptrEnd) {
519  // *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
520  // ++ptrCurrent;
521  // }
522 
523  if (end_index - start_index >= 8) {
524  // Unroll loop version
525  for (; ptrCurrent <= ptrEnd - 8;) {
526  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
527  ++ptrCurrent;
528 
529  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
530  ++ptrCurrent;
531 
532  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
533  ++ptrCurrent;
534 
535  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
536  ++ptrCurrent;
537 
538  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
539  ++ptrCurrent;
540 
541  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
542  ++ptrCurrent;
543 
544  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
545  ++ptrCurrent;
546 
547  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
548  ++ptrCurrent;
549  }
550  }
551 
552  for (; ptrCurrent != ptrEnd; ++ptrCurrent) {
553  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
554  }
555 
556  return 0;
557 }
558 
559 struct ImageLutRGBa_Param_t {
560  unsigned int m_start_index;
561  unsigned int m_end_index;
562 
563  vpRGBa m_lut[256];
564  unsigned char *m_bitmap;
565 
566  ImageLutRGBa_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_bitmap(NULL) {}
567 
568  ImageLutRGBa_Param_t(unsigned int start_index, unsigned int end_index, unsigned char *bitmap)
569  : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
570  {
571  }
572 };
573 
574 vpThread::Return performLutRGBaThread(vpThread::Args args)
575 {
576  ImageLutRGBa_Param_t *imageLut_param = static_cast<ImageLutRGBa_Param_t *>(args);
577  unsigned int start_index = imageLut_param->m_start_index;
578  unsigned int end_index = imageLut_param->m_end_index;
579 
580  unsigned char *bitmap = imageLut_param->m_bitmap;
581 
582  unsigned char *ptrStart = bitmap + start_index * 4;
583  unsigned char *ptrEnd = bitmap + end_index * 4;
584  unsigned char *ptrCurrent = ptrStart;
585 
586  if (end_index - start_index >= 4 * 2) {
587  // Unroll loop version
588  for (; ptrCurrent <= ptrEnd - 4 * 2;) {
589  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
590  ptrCurrent++;
591  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
592  ptrCurrent++;
593  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
594  ptrCurrent++;
595  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
596  ptrCurrent++;
597 
598  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
599  ptrCurrent++;
600  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
601  ptrCurrent++;
602  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
603  ptrCurrent++;
604  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
605  ptrCurrent++;
606  }
607  }
608 
609  while (ptrCurrent != ptrEnd) {
610  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
611  ptrCurrent++;
612 
613  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
614  ptrCurrent++;
615 
616  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
617  ptrCurrent++;
618 
619  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
620  ptrCurrent++;
621  }
622 
623  return 0;
624 }
625 }
626 #endif
627 
631 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w, Type value)
632 {
633  init(h, w);
634 
635  // for (unsigned int i = 0; i < npixels; i++)
636  // bitmap[i] = value;
637  std::fill(bitmap, bitmap + npixels, value);
638 }
639 
643 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w)
644 {
645  if (h != this->height) {
646  if (row != NULL) {
647  vpDEBUG_TRACE(10, "Destruction row[]");
648  delete[] row;
649  row = NULL;
650  }
651  }
652 
653  if ((h != this->height) || (w != this->width)) {
654  if (bitmap != NULL) {
655  vpDEBUG_TRACE(10, "Destruction bitmap[]");
656  if (hasOwnership) {
657  delete[] bitmap;
658  }
659  bitmap = NULL;
660  }
661  }
662 
663  this->width = w;
664  this->height = h;
665 
666  npixels = width * height;
667 
668  if (bitmap == NULL) {
669  bitmap = new Type[npixels];
670  hasOwnership = true;
671  }
672 
673  if (bitmap == NULL) {
674  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
675  }
676 
677  if (row == NULL)
678  row = new Type *[height];
679  if (row == NULL) {
680  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
681  }
682 
683  for (unsigned int i = 0; i < height; i++)
684  row[i] = bitmap + i * width;
685 }
686 
690 template <class Type>
691 void vpImage<Type>::init(Type *const array, unsigned int h, unsigned int w, bool copyData)
692 {
693  if (h != this->height) {
694  if (row != NULL) {
695  delete[] row;
696  row = NULL;
697  }
698  }
699 
700  // Delete bitmap if copyData==false, otherwise only if the dimension differs
701  if ((copyData && ((h != this->height) || (w != this->width))) || !copyData) {
702  if (bitmap != NULL) {
703  if (hasOwnership) {
704  delete[] bitmap;
705  }
706  bitmap = NULL;
707  }
708  }
709 
710  hasOwnership = copyData;
711  this->width = w;
712  this->height = h;
713 
714  npixels = width * height;
715 
716  if (copyData) {
717  if (bitmap == NULL)
718  bitmap = new Type[npixels];
719 
720  if (bitmap == NULL) {
721  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
722  }
723 
724  // Copy the image data
725  memcpy(static_cast<void*>(bitmap), static_cast<void*>(array), (size_t)(npixels * sizeof(Type)));
726  } else {
727  // Copy the address of the array in the bitmap
728  bitmap = array;
729  }
730 
731  if (row == NULL)
732  row = new Type *[height];
733  if (row == NULL) {
734  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
735  }
736 
737  for (unsigned int i = 0; i < height; i++) {
738  row[i] = bitmap + i * width;
739  }
740 }
741 
745 template <class Type>
746 vpImage<Type>::vpImage(unsigned int h, unsigned int w)
747  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
748 {
749  init(h, w, 0);
750 }
751 
755 template <class Type>
756 vpImage<Type>::vpImage(unsigned int h, unsigned int w, Type value)
757  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
758 {
759  init(h, w, value);
760 }
761 
765 template <class Type>
766 vpImage<Type>::vpImage(Type *const array, unsigned int h, unsigned int w, bool copyData)
767  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
768 {
769  init(array, h, w, copyData);
770 }
771 
775 template <class Type> vpImage<Type>::vpImage() :
776  bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
777 {
778 }
779 
800 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w) { init(h, w); }
801 
821 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w, const Type &val) { init(h, w, val); }
822 
829 template <class Type> void vpImage<Type>::destroy()
830 {
831  // vpERROR_TRACE("Deallocate ");
832 
833  if (bitmap != NULL) {
834  // vpERROR_TRACE("Deallocate bitmap memory %p",bitmap);
835  // vpDEBUG_TRACE(20,"Deallocate bitmap memory %p",bitmap);
836  if (hasOwnership) {
837  delete[] bitmap;
838  }
839  bitmap = NULL;
840  }
841 
842  if (row != NULL) {
843  // vpERROR_TRACE("Deallocate row memory %p",row);
844  // vpDEBUG_TRACE(20,"Deallocate row memory %p",row);
845  delete[] row;
846  row = NULL;
847  }
848 }
849 
856 template <class Type> vpImage<Type>::~vpImage() { destroy(); }
857 
861 template <class Type>
863  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
864 {
865  resize(I.getHeight(), I.getWidth());
866  memcpy(static_cast<void*>(bitmap), static_cast<void*>(I.bitmap), I.npixels * sizeof(Type));
867 }
868 
869 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
870 
873 template <class Type>
875  : bitmap(I.bitmap), display(I.display), npixels(I.npixels), width(I.width), height(I.height), row(I.row), hasOwnership(I.hasOwnership)
876 {
877  I.bitmap = NULL;
878  I.display = NULL;
879  I.npixels = 0;
880  I.width = 0;
881  I.height = 0;
882  I.row = NULL;
883  I.hasOwnership = false;
884 }
885 #endif
886 
892 template <class Type> Type vpImage<Type>::getMaxValue() const
893 {
894  if (npixels == 0)
895  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
896  Type m = bitmap[0];
897  for (unsigned int i = 0; i < npixels; i++) {
898  if (bitmap[i] > m)
899  m = bitmap[i];
900  }
901  return m;
902 }
903 
907 template <class Type> Type vpImage<Type>::getMeanValue() const
908 {
909  if ((height == 0) || (width == 0))
910  return 0.0;
911 
912  return getSum() / (height * width);
913 }
914 
920 template <class Type> Type vpImage<Type>::getMinValue() const
921 {
922  if (npixels == 0)
923  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
924  Type m = bitmap[0];
925  for (unsigned int i = 0; i < npixels; i++)
926  if (bitmap[i] < m)
927  m = bitmap[i];
928  return m;
929 }
930 
938 template <class Type> void vpImage<Type>::getMinMaxValue(Type &min, Type &max) const
939 {
940  if (npixels == 0)
941  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
942 
943  min = max = bitmap[0];
944  for (unsigned int i = 0; i < npixels; i++) {
945  if (bitmap[i] < min)
946  min = bitmap[i];
947  if (bitmap[i] > max)
948  max = bitmap[i];
949  }
950 }
951 
973 template <class Type>
974 void vpImage<Type>::getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal, Type *maxVal) const
975 {
976  if (npixels == 0)
977  throw(vpException(vpException::fatalError, "Cannot get location of minimum/maximum "
978  "values of an empty image"));
979 
980  Type min = bitmap[0], max = bitmap[0];
981  vpImagePoint minLoc_, maxLoc_;
982  for (unsigned int i = 0; i < height; i++) {
983  for (unsigned int j = 0; j < width; j++) {
984  if (row[i][j] < min) {
985  min = row[i][j];
986  minLoc_.set_ij(i, j);
987  }
988 
989  if (row[i][j] > max) {
990  max = row[i][j];
991  maxLoc_.set_ij(i, j);
992  }
993  }
994  }
995 
996  if (minLoc != NULL)
997  *minLoc = minLoc_;
998 
999  if (maxLoc != NULL)
1000  *maxLoc = maxLoc_;
1001 
1002  if (minVal != NULL)
1003  *minVal = min;
1004 
1005  if (maxVal != NULL)
1006  *maxVal = max;
1007 }
1008 
1013 {
1014  swap(*this, other);
1015  // Swap back display pointer if it was not null
1016  // vpImage<unsigned char> I2(480, 640);
1017  // vpDisplayX d(I2);
1018  // I2 = I1; //copy only the data
1019  if (other.display != NULL)
1020  display = other.display;
1021 
1022  return *this;
1023 }
1024 
1031 template <class Type> vpImage<Type> &vpImage<Type>::operator=(const Type &v)
1032 {
1033  for (unsigned int i = 0; i < npixels; i++)
1034  bitmap[i] = v;
1035 
1036  return *this;
1037 }
1038 
1044 template <class Type> bool vpImage<Type>::operator==(const vpImage<Type> &I)
1045 {
1046  if (this->width != I.getWidth())
1047  return false;
1048  if (this->height != I.getHeight())
1049  return false;
1050 
1051  // printf("wxh: %dx%d bitmap: %p I.bitmap %p\n", width, height, bitmap,
1052  // I.bitmap);
1053  for (unsigned int i = 0; i < npixels; i++) {
1054  if (bitmap[i] != I.bitmap[i]) {
1055  // std::cout << "differ for pixel " << i << " (" << i%this->height
1056  // << ", " << i - i%this->height << ")" << std::endl;
1057  return false;
1058  }
1059  }
1060  return true;
1061 }
1067 template <class Type> bool vpImage<Type>::operator!=(const vpImage<Type> &I)
1068 {
1069  return !(*this == I);
1070 }
1071 
1098 {
1099  vpImage<Type> C;
1100  sub(*this, B, C);
1101  return C;
1102 }
1103 
1115 template <class Type> void vpImage<Type>::insert(const vpImage<Type> &src, const vpImagePoint &topLeft)
1116 {
1117  int itl = (int)topLeft.get_i();
1118  int jtl = (int)topLeft.get_j();
1119 
1120  int dest_ibegin = 0;
1121  int dest_jbegin = 0;
1122  int src_ibegin = 0;
1123  int src_jbegin = 0;
1124  int dest_w = (int)this->getWidth();
1125  int dest_h = (int)this->getHeight();
1126  int src_w = (int)src.getWidth();
1127  int src_h = (int)src.getHeight();
1128  int wsize = (int)src.getWidth();
1129  int hsize = (int)src.getHeight();
1130 
1131  if (itl >= dest_h || jtl >= dest_w)
1132  return;
1133 
1134  if (itl < 0)
1135  src_ibegin = -itl;
1136  else
1137  dest_ibegin = itl;
1138 
1139  if (jtl < 0)
1140  src_jbegin = -jtl;
1141  else
1142  dest_jbegin = jtl;
1143 
1144  if (src_w - src_jbegin > dest_w - dest_jbegin)
1145  wsize = dest_w - dest_jbegin;
1146  else
1147  wsize = src_w - src_jbegin;
1148 
1149  if (src_h - src_ibegin > dest_h - dest_ibegin)
1150  hsize = dest_h - dest_ibegin;
1151  else
1152  hsize = src_h - src_ibegin;
1153 
1154  for (int i = 0; i < hsize; i++) {
1155  Type *srcBitmap = src.bitmap + ((src_ibegin + i) * src_w + src_jbegin);
1156  Type *destBitmap = this->bitmap + ((dest_ibegin + i) * dest_w + dest_jbegin);
1157 
1158  memcpy(static_cast<void*>(destBitmap), static_cast<void*>(srcBitmap), (size_t)wsize * sizeof(Type));
1159  }
1160 }
1161 
1192 template <class Type> void vpImage<Type>::halfSizeImage(vpImage<Type> &res) const
1193 {
1194  unsigned int h = height / 2;
1195  unsigned int w = width / 2;
1196  res.resize(h, w);
1197  for (unsigned int i = 0; i < h; i++)
1198  for (unsigned int j = 0; j < w; j++)
1199  res[i][j] = (*this)[i << 1][j << 1];
1200 }
1201 
1219 template <class Type>
1220 void vpImage<Type>::subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const
1221 {
1222  if (v_scale == 1 && h_scale == 1) {
1223  sampled = (*this);
1224  return;
1225  }
1226  unsigned int h = height / v_scale;
1227  unsigned int w = width / h_scale;
1228  sampled.resize(h, w);
1229  for (unsigned int i = 0; i < h; i++)
1230  for (unsigned int j = 0; j < w; j++)
1231  sampled[i][j] = (*this)[i * v_scale][j * h_scale];
1232 }
1233 
1256 template <class Type> void vpImage<Type>::quarterSizeImage(vpImage<Type> &res) const
1257 {
1258  unsigned int h = height / 4;
1259  unsigned int w = width / 4;
1260  res.resize(h, w);
1261  for (unsigned int i = 0; i < h; i++)
1262  for (unsigned int j = 0; j < w; j++)
1263  res[i][j] = (*this)[i << 2][j << 2];
1264 }
1265 
1298 template <class Type> void vpImage<Type>::doubleSizeImage(vpImage<Type> &res)
1299 {
1300  int h = height * 2;
1301  int w = width * 2;
1302 
1303  res.resize(h, w);
1304 
1305  for (int i = 0; i < h; i++)
1306  for (int j = 0; j < w; j++)
1307  res[i][j] = (*this)[i >> 1][j >> 1];
1308 
1309  /*
1310  A B C
1311  E F G
1312  H I J
1313  A C H J are pixels from original image
1314  B E G I are interpolated pixels
1315  */
1316 
1317  // interpolate pixels B and I
1318  for (int i = 0; i < h; i += 2)
1319  for (int j = 1; j < w - 1; j += 2)
1320  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1]));
1321 
1322  // interpolate pixels E and G
1323  for (int i = 1; i < h - 1; i += 2)
1324  for (int j = 0; j < w; j += 2)
1325  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[(i >> 1) + 1][j >> 1]));
1326 
1327  // interpolate pixel F
1328  for (int i = 1; i < h - 1; i += 2)
1329  for (int j = 1; j < w - 1; j += 2)
1330  res[i][j] = (Type)(0.25 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1] +
1331  (*this)[(i >> 1) + 1][j >> 1] + (*this)[(i >> 1) + 1][(j >> 1) + 1]));
1332 }
1333 
1346 template <class Type> inline Type vpImage<Type>::getValue(unsigned int i, unsigned int j) const
1347 {
1348  if (i >= height || j >= width) {
1349  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1350  }
1351 
1352  return row[i][j];
1353 }
1354 
1371 template <class Type> Type vpImage<Type>::getValue(double i, double j) const
1372 {
1373  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1374  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1375  }
1376  if (height * width == 0) {
1377  throw vpException(vpImageException::notInitializedError, "Empty image!");
1378  }
1379 
1380  unsigned int iround = static_cast<unsigned int>(floor(i));
1381  unsigned int jround = static_cast<unsigned int>(floor(j));
1382 
1383  double rratio = i - static_cast<double>(iround);
1384  double cratio = j - static_cast<double>(jround);
1385 
1386  double rfrac = 1.0 - rratio;
1387  double cfrac = 1.0 - cratio;
1388 
1389  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1390  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1391 
1392  double value = (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
1393  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) * cratio;
1394 
1395  return static_cast<Type>(vpMath::round(value));
1396 }
1397 
1401 template <> inline double vpImage<double>::getValue(double i, double j) const
1402 {
1403  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1404  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1405  }
1406  if (height * width == 0) {
1407  throw vpException(vpImageException::notInitializedError, "Empty image!");
1408  }
1409 
1410  unsigned int iround = static_cast<unsigned int>(floor(i));
1411  unsigned int jround = static_cast<unsigned int>(floor(j));
1412 
1413  double rratio = i - static_cast<double>(iround);
1414  double cratio = j - static_cast<double>(jround);
1415 
1416  double rfrac = 1.0 - rratio;
1417  double cfrac = 1.0 - cratio;
1418 
1419  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1420  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1421 
1422  return (row[iround][jround] * rfrac + row[iround_1][jround] * rratio) * cfrac +
1423  (row[iround][jround_1] * rfrac + row[iround_1][jround_1] * rratio) * cratio;
1424 }
1425 
1429 template <> inline unsigned char vpImage<unsigned char>::getValue(double i, double j) const {
1430  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1431  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1432  }
1433  if (height * width == 0) {
1434  throw vpException(vpImageException::notInitializedError, "Empty image!");
1435  }
1436 
1437  // alpha architecture is bi-endianness. The following optimization makes testImageGetValue failing
1438 #if (defined(VISP_LITTLE_ENDIAN) || defined(VISP_BIG_ENDIAN)) && !(defined(__alpha__) || defined(_M_ALPHA))
1439  //Fixed-point arithmetic
1440  const int32_t precision = 1 << 16;
1441  int64_t y = static_cast<int64_t>(i * precision);
1442  int64_t x = static_cast<int64_t>(j * precision);
1443 
1444  int64_t iround = y & (~0xFFFF);
1445  int64_t jround = x & (~0xFFFF);
1446 
1447  int64_t rratio = y - iround;
1448  int64_t cratio = x - jround;
1449 
1450  int64_t rfrac = precision - rratio;
1451  int64_t cfrac = precision - cratio;
1452 
1453  int64_t x_ = x >> 16;
1454  int64_t y_ = y >> 16;
1455 
1456  if (y_ + 1 < height && x_ + 1 < width) {
1457  uint16_t up = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + y_ * width + x_);
1458  uint16_t down = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + (y_ + 1) * width + x_);
1459 
1460  return static_cast<unsigned char>((((up & 0x00FF) * rfrac + (down & 0x00FF) * rratio) * cfrac +
1461  ((up >> 8) * rfrac + (down >> 8) * rratio) * cratio) >> 32);
1462  } else if (y_ + 1 < height) {
1463  return static_cast<unsigned char>(((row[y_][x_] * rfrac + row[y_ + 1][x_] * rratio)) >> 16);
1464  } else if (x_ + 1 < width) {
1465  uint16_t up = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + y_ * width + x_);
1466  return static_cast<unsigned char>(((up & 0x00FF) * cfrac + (up >> 8) * cratio) >> 16);
1467  } else {
1468  return row[y_][x_];
1469  }
1470 #else
1471  unsigned int iround = static_cast<unsigned int>(floor(i));
1472  unsigned int jround = static_cast<unsigned int>(floor(j));
1473 
1474  if (iround >= height || jround >= width) {
1475  vpERROR_TRACE("Pixel outside the image") ;
1477  "Pixel outside the image"));
1478  }
1479 
1480  double rratio = i - static_cast<double>(iround);
1481  double cratio = j - static_cast<double>(jround);
1482 
1483  double rfrac = 1.0 - rratio;
1484  double cfrac = 1.0 - cratio;
1485 
1486  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1487  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1488 
1489  double value = (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
1490  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) * cratio;
1491  return static_cast<unsigned char>(vpMath::round(value));
1492 #endif
1493 }
1494 
1498 template <> inline vpRGBa vpImage<vpRGBa>::getValue(double i, double j) const
1499 {
1500  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1501  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1502  }
1503  if (height * width == 0) {
1504  throw vpException(vpImageException::notInitializedError, "Empty image!");
1505  }
1506 
1507  unsigned int iround = static_cast<unsigned int>(floor(i));
1508  unsigned int jround = static_cast<unsigned int>(floor(j));
1509 
1510  double rratio = i - static_cast<double>(iround);
1511  double cratio = j - static_cast<double>(jround);
1512 
1513  double rfrac = 1.0 - rratio;
1514  double cfrac = 1.0 - cratio;
1515 
1516  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1517  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1518 
1519  double valueR = (static_cast<double>(row[iround][jround].R) * rfrac + static_cast<double>(row[iround_1][jround].R) * rratio) * cfrac +
1520  (static_cast<double>(row[iround][jround_1].R) * rfrac + static_cast<double>(row[iround_1][jround_1].R) * rratio) * cratio;
1521  double valueG = (static_cast<double>(row[iround][jround].G) * rfrac + static_cast<double>(row[iround_1][jround].G) * rratio) * cfrac +
1522  (static_cast<double>(row[iround][jround_1].G) * rfrac + static_cast<double>(row[iround_1][jround_1].G) * rratio) * cratio;
1523  double valueB = (static_cast<double>(row[iround][jround].B) * rfrac + static_cast<double>(row[iround_1][jround].B) * rratio) * cfrac +
1524  (static_cast<double>(row[iround][jround_1].B) * rfrac + static_cast<double>(row[iround_1][jround_1].B) * rratio) * cratio;
1525 
1526  return vpRGBa(static_cast<unsigned char>(vpMath::round(valueR)),
1527  static_cast<unsigned char>(vpMath::round(valueG)),
1528  static_cast<unsigned char>(vpMath::round(valueB)));
1529 }
1530 
1547 template <class Type> inline Type vpImage<Type>::getValue(const vpImagePoint &ip) const
1548 {
1549  return getValue(ip.get_i(), ip.get_j());
1550 }
1551 
1555 template <> inline double vpImage<double>::getValue(const vpImagePoint &ip) const
1556 {
1557  return getValue(ip.get_i(), ip.get_j());
1558 }
1559 
1563 template <> inline unsigned char vpImage<unsigned char>::getValue(const vpImagePoint &ip) const
1564 {
1565  return getValue(ip.get_i(), ip.get_j());
1566 }
1567 
1571 template <> inline vpRGBa vpImage<vpRGBa>::getValue(const vpImagePoint &ip) const
1572 {
1573  return getValue(ip.get_i(), ip.get_j());
1574 }
1575 
1579 template <class Type> inline double vpImage<Type>::getSum() const
1580 {
1581  if ((height == 0) || (width == 0))
1582  return 0.0;
1583 
1584  double res = 0.0;
1585  for (unsigned int i = 0; i < height * width; ++i) {
1586  res += static_cast<double>(bitmap[i]);
1587  }
1588  return res;
1589 }
1590 
1620 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &B, vpImage<Type> &C)
1621 {
1622 
1623  try {
1624  if ((this->getHeight() != C.getHeight()) || (this->getWidth() != C.getWidth()))
1625  C.resize(this->getHeight(), this->getWidth());
1626  } catch (const vpException &me) {
1627  std::cout << me << std::endl;
1628  throw;
1629  }
1630 
1631  if ((this->getWidth() != B.getWidth()) || (this->getHeight() != B.getHeight())) {
1632  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage substraction "));
1633  }
1634 
1635  for (unsigned int i = 0; i < this->getWidth() * this->getHeight(); i++) {
1636  *(C.bitmap + i) = *(bitmap + i) - *(B.bitmap + i);
1637  }
1638 }
1639 
1651 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C)
1652 {
1653 
1654  try {
1655  if ((A.getHeight() != C.getHeight()) || (A.getWidth() != C.getWidth()))
1656  C.resize(A.getHeight(), A.getWidth());
1657  } catch (const vpException &me) {
1658  std::cout << me << std::endl;
1659  throw;
1660  }
1661 
1662  if ((A.getWidth() != B.getWidth()) || (A.getHeight() != B.getHeight())) {
1663  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage substraction "));
1664  }
1665 
1666  for (unsigned int i = 0; i < A.getWidth() * A.getHeight(); i++) {
1667  *(C.bitmap + i) = *(A.bitmap + i) - *(B.bitmap + i);
1668  }
1669 }
1670 
1679 template <class Type> void vpImage<Type>::performLut(const Type (&)[256], unsigned int)
1680 {
1681  std::cerr << "Not implemented !" << std::endl;
1682 }
1683 
1694 template <> inline void vpImage<unsigned char>::performLut(const unsigned char (&lut)[256], unsigned int nbThreads)
1695 {
1696  unsigned int size = getWidth() * getHeight();
1697  unsigned char *ptrStart = (unsigned char *)bitmap;
1698  unsigned char *ptrEnd = ptrStart + size;
1699  unsigned char *ptrCurrent = ptrStart;
1700 
1701  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
1702 #if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
1703  use_single_thread = true;
1704 #endif
1705 
1706  if (!use_single_thread && getSize() <= nbThreads) {
1707  use_single_thread = true;
1708  }
1709 
1710  if (use_single_thread) {
1711  // Single thread
1712 
1713  while (ptrCurrent != ptrEnd) {
1714  *ptrCurrent = lut[*ptrCurrent];
1715  ++ptrCurrent;
1716  }
1717  } else {
1718 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
1719  // Multi-threads
1720 
1721  std::vector<vpThread *> threadpool;
1722  std::vector<ImageLut_Param_t *> imageLutParams;
1723 
1724  unsigned int image_size = getSize();
1725  unsigned int step = image_size / nbThreads;
1726  unsigned int last_step = image_size - step * (nbThreads - 1);
1727 
1728  for (unsigned int index = 0; index < nbThreads; index++) {
1729  unsigned int start_index = index * step;
1730  unsigned int end_index = (index + 1) * step;
1731 
1732  if (index == nbThreads - 1) {
1733  end_index = start_index + last_step;
1734  }
1735 
1736  ImageLut_Param_t *imageLut_param = new ImageLut_Param_t(start_index, end_index, bitmap);
1737  memcpy(imageLut_param->m_lut, lut, 256 * sizeof(unsigned char));
1738 
1739  imageLutParams.push_back(imageLut_param);
1740 
1741  // Start the threads
1742  vpThread *imageLut_thread = new vpThread((vpThread::Fn)performLutThread, (vpThread::Args)imageLut_param);
1743  threadpool.push_back(imageLut_thread);
1744  }
1745 
1746  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1747  // Wait until thread ends up
1748  threadpool[cpt]->join();
1749  }
1750 
1751  // Delete
1752  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1753  delete threadpool[cpt];
1754  }
1755 
1756  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
1757  delete imageLutParams[cpt];
1758  }
1759 #endif
1760  }
1761 }
1762 
1773 template <> inline void vpImage<vpRGBa>::performLut(const vpRGBa (&lut)[256], unsigned int nbThreads)
1774 {
1775  unsigned int size = getWidth() * getHeight();
1776  unsigned char *ptrStart = (unsigned char *)bitmap;
1777  unsigned char *ptrEnd = ptrStart + size * 4;
1778  unsigned char *ptrCurrent = ptrStart;
1779 
1780  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
1781 #if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
1782  use_single_thread = true;
1783 #endif
1784 
1785  if (!use_single_thread && getSize() <= nbThreads) {
1786  use_single_thread = true;
1787  }
1788 
1789  if (use_single_thread) {
1790  // Single thread
1791  while (ptrCurrent != ptrEnd) {
1792  *ptrCurrent = lut[*ptrCurrent].R;
1793  ++ptrCurrent;
1794 
1795  *ptrCurrent = lut[*ptrCurrent].G;
1796  ++ptrCurrent;
1797 
1798  *ptrCurrent = lut[*ptrCurrent].B;
1799  ++ptrCurrent;
1800 
1801  *ptrCurrent = lut[*ptrCurrent].A;
1802  ++ptrCurrent;
1803  }
1804  } else {
1805 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
1806  // Multi-threads
1807  std::vector<vpThread *> threadpool;
1808  std::vector<ImageLutRGBa_Param_t *> imageLutParams;
1809 
1810  unsigned int image_size = getSize();
1811  unsigned int step = image_size / nbThreads;
1812  unsigned int last_step = image_size - step * (nbThreads - 1);
1813 
1814  for (unsigned int index = 0; index < nbThreads; index++) {
1815  unsigned int start_index = index * step;
1816  unsigned int end_index = (index + 1) * step;
1817 
1818  if (index == nbThreads - 1) {
1819  end_index = start_index + last_step;
1820  }
1821 
1822  ImageLutRGBa_Param_t *imageLut_param = new ImageLutRGBa_Param_t(start_index, end_index, (unsigned char *)bitmap);
1823  memcpy(static_cast<void*>(imageLut_param->m_lut), lut, 256 * sizeof(vpRGBa));
1824 
1825  imageLutParams.push_back(imageLut_param);
1826 
1827  // Start the threads
1828  vpThread *imageLut_thread = new vpThread((vpThread::Fn)performLutRGBaThread, (vpThread::Args)imageLut_param);
1829  threadpool.push_back(imageLut_thread);
1830  }
1831 
1832  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1833  // Wait until thread ends up
1834  threadpool[cpt]->join();
1835  }
1836 
1837  // Delete
1838  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1839  delete threadpool[cpt];
1840  }
1841 
1842  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
1843  delete imageLutParams[cpt];
1844  }
1845 #endif
1846  }
1847 }
1848 
1849 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second)
1850 {
1851  using std::swap;
1852  swap(first.bitmap, second.bitmap);
1853  swap(first.display, second.display);
1854  swap(first.npixels, second.npixels);
1855  swap(first.width, second.width);
1856  swap(first.height, second.height);
1857  swap(first.row, second.row);
1858 }
1859 
1860 #endif
void quarterSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1256
unsigned int getCols() const
Definition: vpImage.h:179
Type * operator[](int i)
Definition: vpImage.h:264
vpDisplay * display
Definition: vpImage.h:144
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
Definition: vpImage.h:1679
VISP_EXPORT uint16_t reinterpret_cast_uchar_to_uint16_LE(unsigned char *const ptr)
Definition: vpEndian.cpp:111
void doubleSizeImage(vpImage< Type > &res)
Definition: vpImage.h:1298
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:177
void * Return
Definition: vpThread.h:78
double get_i() const
Definition: vpImagePoint.h:203
unsigned int getWidth() const
Definition: vpImage.h:246
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:800
void getMinMaxValue(Type &min, Type &max) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:938
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
#define vpERROR_TRACE
Definition: vpDebug.h:393
Type operator()(const vpImagePoint &ip) const
Definition: vpImage.h:294
void operator()(unsigned int i, unsigned int j, const Type &v)
Definition: vpImage.h:282
error that can be emited by ViSP classes.
Definition: vpException.h:71
Type getMinValue() const
Return the minimum value within the bitmap.
Definition: vpImage.h:920
virtual ~vpImage()
destructor
Definition: vpImage.h:856
double get_j() const
Definition: vpImagePoint.h:214
vpImage< Type > & operator=(vpImage< Type > other)
Copy operator.
Definition: vpImage.h:1012
Definition: vpRGBa.h:66
double getSum() const
Definition: vpImage.h:1579
unsigned int getRows() const
Definition: vpImage.h:218
Type getValue(unsigned int i, unsigned int j) const
Definition: vpImage.h:1346
friend void swap(vpImage< Type > &first, vpImage< Type > &second)
Definition: vpImage.h:1849
void *(* Fn)(Args)
Definition: vpThread.h:79
unsigned int getSize() const
Definition: vpImage.h:227
bool operator!=(const vpImage< Type > &I)
Definition: vpImage.h:1067
void * Args
Definition: vpThread.h:77
Memory allocation error.
Definition: vpException.h:88
void operator()(const vpImagePoint &ip, const Type &v)
Definition: vpImage.h:310
Type getMaxValue() const
Return the maximum value within the bitmap.
Definition: vpImage.h:892
const Type * operator[](int i) const
Definition: vpImage.h:268
unsigned int getNumberOfPixel() const
Definition: vpImage.h:209
void init(unsigned int height, unsigned int width)
Set the size of the image.
Definition: vpImage.h:643
void insert(const vpImage< Type > &src, const vpImagePoint &topLeft)
Definition: vpImage.h:1115
void destroy()
Destructor : Memory de-allocation.
Definition: vpImage.h:829
const Type * operator[](unsigned int i) const
operator[] allows operation like x = I[i]
Definition: vpImage.h:267
Type * operator[](unsigned int i)
operator[] allows operation like I[i] = x.
Definition: vpImage.h:263
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:1220
static int round(double x)
Definition: vpMath.h:245
void halfSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1192
void set_ij(double ii, double jj)
Definition: vpImagePoint.h:188
vpImage()
constructor
Definition: vpImage.h:775
Type operator()(unsigned int i, unsigned int j) const
Definition: vpImage.h:276
vpImage< Type > operator-(const vpImage< Type > &B)
Definition: vpImage.h:1097
Type getMeanValue() const
Return the mean value of the bitmap.
Definition: vpImage.h:907
#define vpDEBUG_TRACE
Definition: vpDebug.h:487
unsigned int getHeight() const
Definition: vpImage.h:188
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:974
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
Definition of the vpImage class member functions.
Definition: vpImage.h:126
bool operator==(const vpImage< Type > &I)
Definition: vpImage.h:1044
void sub(const vpImage< Type > &B, vpImage< Type > &C)
Definition: vpImage.h:1620