Visual Servoing Platform  version 3.3.1 under development (2020-05-29)
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 
641 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w, Type value)
642 {
643  init(h, w);
644 
645  // for (unsigned int i = 0; i < npixels; i++)
646  // bitmap[i] = value;
647  std::fill(bitmap, bitmap + npixels, value);
648 }
649 
667 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w)
668 {
669  if (h != this->height) {
670  if (row != NULL) {
671  vpDEBUG_TRACE(10, "Destruction row[]");
672  delete[] row;
673  row = NULL;
674  }
675  }
676 
677  if ((h != this->height) || (w != this->width)) {
678  if (bitmap != NULL) {
679  vpDEBUG_TRACE(10, "Destruction bitmap[]");
680  if (hasOwnership) {
681  delete[] bitmap;
682  }
683  bitmap = NULL;
684  }
685  }
686 
687  this->width = w;
688  this->height = h;
689 
690  npixels = width * height;
691 
692  if (bitmap == NULL) {
693  bitmap = new Type[npixels];
694  hasOwnership = true;
695  }
696 
697  if (bitmap == NULL) {
698  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
699  }
700 
701  if (row == NULL)
702  row = new Type *[height];
703  if (row == NULL) {
704  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
705  }
706 
707  for (unsigned int i = 0; i < height; i++)
708  row[i] = bitmap + i * width;
709 }
710 
724 template <class Type>
725 void vpImage<Type>::init(Type *const array, unsigned int h, unsigned int w, bool copyData)
726 {
727  if (h != this->height) {
728  if (row != NULL) {
729  delete[] row;
730  row = NULL;
731  }
732  }
733 
734  // Delete bitmap if copyData==false, otherwise only if the dimension differs
735  if ((copyData && ((h != this->height) || (w != this->width))) || !copyData) {
736  if (bitmap != NULL) {
737  if (hasOwnership) {
738  delete[] bitmap;
739  }
740  bitmap = NULL;
741  }
742  }
743 
744  hasOwnership = copyData;
745  this->width = w;
746  this->height = h;
747 
748  npixels = width * height;
749 
750  if (copyData) {
751  if (bitmap == NULL)
752  bitmap = new Type[npixels];
753 
754  if (bitmap == NULL) {
755  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
756  }
757 
758  // Copy the image data
759  memcpy(static_cast<void*>(bitmap), static_cast<void*>(array), (size_t)(npixels * sizeof(Type)));
760  } else {
761  // Copy the address of the array in the bitmap
762  bitmap = array;
763  }
764 
765  if (row == NULL)
766  row = new Type *[height];
767  if (row == NULL) {
768  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
769  }
770 
771  for (unsigned int i = 0; i < height; i++) {
772  row[i] = bitmap + i * width;
773  }
774 }
775 
794 template <class Type>
795 vpImage<Type>::vpImage(unsigned int h, unsigned int w)
796  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
797 {
798  init(h, w, 0);
799 }
800 
818 template <class Type>
819 vpImage<Type>::vpImage(unsigned int h, unsigned int w, Type value)
820  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
821 {
822  init(h, w, value);
823 }
824 
840 template <class Type>
841 vpImage<Type>::vpImage(Type *const array, unsigned int h, unsigned int w, bool copyData)
842  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
843 {
844  init(array, h, w, copyData);
845 }
846 
856 template <class Type> vpImage<Type>::vpImage() :
857  bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
858 {
859 }
860 
881 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w) { init(h, w); }
882 
902 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w, const Type &val) { init(h, w, val); }
903 
910 template <class Type> void vpImage<Type>::destroy()
911 {
912  // vpERROR_TRACE("Deallocate ");
913 
914  if (bitmap != NULL) {
915  // vpERROR_TRACE("Deallocate bitmap memory %p",bitmap);
916  // vpDEBUG_TRACE(20,"Deallocate bitmap memory %p",bitmap);
917  if (hasOwnership) {
918  delete[] bitmap;
919  }
920  bitmap = NULL;
921  }
922 
923  if (row != NULL) {
924  // vpERROR_TRACE("Deallocate row memory %p",row);
925  // vpDEBUG_TRACE(20,"Deallocate row memory %p",row);
926  delete[] row;
927  row = NULL;
928  }
929 }
930 
937 template <class Type> vpImage<Type>::~vpImage() { destroy(); }
938 
942 template <class Type>
944  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL), hasOwnership(true)
945 {
946  resize(I.getHeight(), I.getWidth());
947  memcpy(static_cast<void*>(bitmap), static_cast<void*>(I.bitmap), I.npixels * sizeof(Type));
948 }
949 
950 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
951 
954 template <class Type>
956  : bitmap(I.bitmap), display(I.display), npixels(I.npixels), width(I.width), height(I.height), row(I.row), hasOwnership(I.hasOwnership)
957 {
958  I.bitmap = NULL;
959  I.display = NULL;
960  I.npixels = 0;
961  I.width = 0;
962  I.height = 0;
963  I.row = NULL;
964  I.hasOwnership = false;
965 }
966 #endif
967 
973 template <class Type> Type vpImage<Type>::getMaxValue() const
974 {
975  if (npixels == 0)
976  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
977  Type m = bitmap[0];
978  for (unsigned int i = 0; i < npixels; i++) {
979  if (bitmap[i] > m)
980  m = bitmap[i];
981  }
982  return m;
983 }
984 
988 template <class Type> Type vpImage<Type>::getMeanValue() const
989 {
990  if ((height == 0) || (width == 0))
991  return 0.0;
992 
993  return getSum() / (height * width);
994 }
995 
1001 template <class Type> Type vpImage<Type>::getMinValue() const
1002 {
1003  if (npixels == 0)
1004  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
1005  Type m = bitmap[0];
1006  for (unsigned int i = 0; i < npixels; i++)
1007  if (bitmap[i] < m)
1008  m = bitmap[i];
1009  return m;
1010 }
1011 
1019 template <class Type> void vpImage<Type>::getMinMaxValue(Type &min, Type &max) const
1020 {
1021  if (npixels == 0)
1022  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1023 
1024  min = max = bitmap[0];
1025  for (unsigned int i = 0; i < npixels; i++) {
1026  if (bitmap[i] < min)
1027  min = bitmap[i];
1028  if (bitmap[i] > max)
1029  max = bitmap[i];
1030  }
1031 }
1032 
1054 template <class Type>
1055 void vpImage<Type>::getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal, Type *maxVal) const
1056 {
1057  if (npixels == 0)
1058  throw(vpException(vpException::fatalError, "Cannot get location of minimum/maximum "
1059  "values of an empty image"));
1060 
1061  Type min = bitmap[0], max = bitmap[0];
1062  vpImagePoint minLoc_, maxLoc_;
1063  for (unsigned int i = 0; i < height; i++) {
1064  for (unsigned int j = 0; j < width; j++) {
1065  if (row[i][j] < min) {
1066  min = row[i][j];
1067  minLoc_.set_ij(i, j);
1068  }
1069 
1070  if (row[i][j] > max) {
1071  max = row[i][j];
1072  maxLoc_.set_ij(i, j);
1073  }
1074  }
1075  }
1076 
1077  if (minLoc != NULL)
1078  *minLoc = minLoc_;
1079 
1080  if (maxLoc != NULL)
1081  *maxLoc = maxLoc_;
1082 
1083  if (minVal != NULL)
1084  *minVal = min;
1085 
1086  if (maxVal != NULL)
1087  *maxVal = max;
1088 }
1089 
1094 {
1095  swap(*this, other);
1096  // Swap back display pointer if it was not null
1097  // vpImage<unsigned char> I2(480, 640);
1098  // vpDisplayX d(I2);
1099  // I2 = I1; //copy only the data
1100  if (other.display != NULL)
1101  display = other.display;
1102 
1103  return *this;
1104 }
1105 
1112 template <class Type> vpImage<Type> &vpImage<Type>::operator=(const Type &v)
1113 {
1114  for (unsigned int i = 0; i < npixels; i++)
1115  bitmap[i] = v;
1116 
1117  return *this;
1118 }
1119 
1125 template <class Type> bool vpImage<Type>::operator==(const vpImage<Type> &I)
1126 {
1127  if (this->width != I.getWidth())
1128  return false;
1129  if (this->height != I.getHeight())
1130  return false;
1131 
1132  // printf("wxh: %dx%d bitmap: %p I.bitmap %p\n", width, height, bitmap,
1133  // I.bitmap);
1134  for (unsigned int i = 0; i < npixels; i++) {
1135  if (bitmap[i] != I.bitmap[i]) {
1136  // std::cout << "differ for pixel " << i << " (" << i%this->height
1137  // << ", " << i - i%this->height << ")" << std::endl;
1138  return false;
1139  }
1140  }
1141  return true;
1142 }
1148 template <class Type> bool vpImage<Type>::operator!=(const vpImage<Type> &I)
1149 {
1150  return !(*this == I);
1151 }
1152 
1179 {
1180  vpImage<Type> C;
1181  sub(*this, B, C);
1182  return C;
1183 }
1184 
1196 template <class Type> void vpImage<Type>::insert(const vpImage<Type> &src, const vpImagePoint &topLeft)
1197 {
1198  int itl = (int)topLeft.get_i();
1199  int jtl = (int)topLeft.get_j();
1200 
1201  int dest_ibegin = 0;
1202  int dest_jbegin = 0;
1203  int src_ibegin = 0;
1204  int src_jbegin = 0;
1205  int dest_w = (int)this->getWidth();
1206  int dest_h = (int)this->getHeight();
1207  int src_w = (int)src.getWidth();
1208  int src_h = (int)src.getHeight();
1209  int wsize = (int)src.getWidth();
1210  int hsize = (int)src.getHeight();
1211 
1212  if (itl >= dest_h || jtl >= dest_w)
1213  return;
1214 
1215  if (itl < 0)
1216  src_ibegin = -itl;
1217  else
1218  dest_ibegin = itl;
1219 
1220  if (jtl < 0)
1221  src_jbegin = -jtl;
1222  else
1223  dest_jbegin = jtl;
1224 
1225  if (src_w - src_jbegin > dest_w - dest_jbegin)
1226  wsize = dest_w - dest_jbegin;
1227  else
1228  wsize = src_w - src_jbegin;
1229 
1230  if (src_h - src_ibegin > dest_h - dest_ibegin)
1231  hsize = dest_h - dest_ibegin;
1232  else
1233  hsize = src_h - src_ibegin;
1234 
1235  for (int i = 0; i < hsize; i++) {
1236  Type *srcBitmap = src.bitmap + ((src_ibegin + i) * src_w + src_jbegin);
1237  Type *destBitmap = this->bitmap + ((dest_ibegin + i) * dest_w + dest_jbegin);
1238 
1239  memcpy(static_cast<void*>(destBitmap), static_cast<void*>(srcBitmap), (size_t)wsize * sizeof(Type));
1240  }
1241 }
1242 
1273 template <class Type> void vpImage<Type>::halfSizeImage(vpImage<Type> &res) const
1274 {
1275  unsigned int h = height / 2;
1276  unsigned int w = width / 2;
1277  res.resize(h, w);
1278  for (unsigned int i = 0; i < h; i++)
1279  for (unsigned int j = 0; j < w; j++)
1280  res[i][j] = (*this)[i << 1][j << 1];
1281 }
1282 
1300 template <class Type>
1301 void vpImage<Type>::subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const
1302 {
1303  if (v_scale == 1 && h_scale == 1) {
1304  sampled = (*this);
1305  return;
1306  }
1307  unsigned int h = height / v_scale;
1308  unsigned int w = width / h_scale;
1309  sampled.resize(h, w);
1310  for (unsigned int i = 0; i < h; i++)
1311  for (unsigned int j = 0; j < w; j++)
1312  sampled[i][j] = (*this)[i * v_scale][j * h_scale];
1313 }
1314 
1337 template <class Type> void vpImage<Type>::quarterSizeImage(vpImage<Type> &res) const
1338 {
1339  unsigned int h = height / 4;
1340  unsigned int w = width / 4;
1341  res.resize(h, w);
1342  for (unsigned int i = 0; i < h; i++)
1343  for (unsigned int j = 0; j < w; j++)
1344  res[i][j] = (*this)[i << 2][j << 2];
1345 }
1346 
1379 template <class Type> void vpImage<Type>::doubleSizeImage(vpImage<Type> &res)
1380 {
1381  int h = height * 2;
1382  int w = width * 2;
1383 
1384  res.resize(h, w);
1385 
1386  for (int i = 0; i < h; i++)
1387  for (int j = 0; j < w; j++)
1388  res[i][j] = (*this)[i >> 1][j >> 1];
1389 
1390  /*
1391  A B C
1392  E F G
1393  H I J
1394  A C H J are pixels from original image
1395  B E G I are interpolated pixels
1396  */
1397 
1398  // interpolate pixels B and I
1399  for (int i = 0; i < h; i += 2)
1400  for (int j = 1; j < w - 1; j += 2)
1401  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1]));
1402 
1403  // interpolate pixels E and G
1404  for (int i = 1; i < h - 1; i += 2)
1405  for (int j = 0; j < w; j += 2)
1406  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[(i >> 1) + 1][j >> 1]));
1407 
1408  // interpolate pixel F
1409  for (int i = 1; i < h - 1; i += 2)
1410  for (int j = 1; j < w - 1; j += 2)
1411  res[i][j] = (Type)(0.25 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1] +
1412  (*this)[(i >> 1) + 1][j >> 1] + (*this)[(i >> 1) + 1][(j >> 1) + 1]));
1413 }
1414 
1427 template <class Type> inline Type vpImage<Type>::getValue(unsigned int i, unsigned int j) const
1428 {
1429  if (i >= height || j >= width) {
1430  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1431  }
1432 
1433  return row[i][j];
1434 }
1435 
1452 template <class Type> Type vpImage<Type>::getValue(double i, double j) const
1453 {
1454  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1455  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1456  }
1457  if (height * width == 0) {
1458  throw vpException(vpImageException::notInitializedError, "Empty image!");
1459  }
1460 
1461  unsigned int iround = static_cast<unsigned int>(floor(i));
1462  unsigned int jround = static_cast<unsigned int>(floor(j));
1463 
1464  double rratio = i - static_cast<double>(iround);
1465  double cratio = j - static_cast<double>(jround);
1466 
1467  double rfrac = 1.0 - rratio;
1468  double cfrac = 1.0 - cratio;
1469 
1470  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1471  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1472 
1473  double value = (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
1474  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) * cratio;
1475 
1476  return static_cast<Type>(vpMath::round(value));
1477 }
1478 
1482 template <> inline double vpImage<double>::getValue(double i, double j) const
1483 {
1484  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1485  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1486  }
1487  if (height * width == 0) {
1488  throw vpException(vpImageException::notInitializedError, "Empty image!");
1489  }
1490 
1491  unsigned int iround = static_cast<unsigned int>(floor(i));
1492  unsigned int jround = static_cast<unsigned int>(floor(j));
1493 
1494  double rratio = i - static_cast<double>(iround);
1495  double cratio = j - static_cast<double>(jround);
1496 
1497  double rfrac = 1.0 - rratio;
1498  double cfrac = 1.0 - cratio;
1499 
1500  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1501  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1502 
1503  return (row[iround][jround] * rfrac + row[iround_1][jround] * rratio) * cfrac +
1504  (row[iround][jround_1] * rfrac + row[iround_1][jround_1] * rratio) * cratio;
1505 }
1506 
1510 template <> inline unsigned char vpImage<unsigned char>::getValue(double i, double j) const {
1511  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1512  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1513  }
1514  if (height * width == 0) {
1515  throw vpException(vpImageException::notInitializedError, "Empty image!");
1516  }
1517 
1518 #if (defined(VISP_LITTLE_ENDIAN) || defined(VISP_BIG_ENDIAN))
1519  //Fixed-point arithmetic
1520  const int32_t precision = 1 << 16;
1521  int64_t y = static_cast<int64_t>(i * precision);
1522  int64_t x = static_cast<int64_t>(j * precision);
1523 
1524  int64_t iround = y & (~0xFFFF);
1525  int64_t jround = x & (~0xFFFF);
1526 
1527  int64_t rratio = y - iround;
1528  int64_t cratio = x - jround;
1529 
1530  int64_t rfrac = precision - rratio;
1531  int64_t cfrac = precision - cratio;
1532 
1533  int64_t x_ = x >> 16;
1534  int64_t y_ = y >> 16;
1535 
1536  if (y_ + 1 < height && x_ + 1 < width) {
1537  uint16_t up = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + y_ * width + x_);
1538  uint16_t down = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + (y_ + 1) * width + x_);
1539 
1540  return static_cast<unsigned char>((((up & 0x00FF) * rfrac + (down & 0x00FF) * rratio) * cfrac +
1541  ((up >> 8) * rfrac + (down >> 8) * rratio) * cratio) >> 32);
1542  } else if (y_ + 1 < height) {
1543  return static_cast<unsigned char>(((row[y_][x_] * rfrac + row[y_ + 1][x_] * rratio)) >> 16);
1544  } else if (x_ + 1 < width) {
1545  uint16_t up = vpEndian::reinterpret_cast_uchar_to_uint16_LE(bitmap + y_ * width + x_);
1546  return static_cast<unsigned char>(((up & 0x00FF) * cfrac + (up >> 8) * cratio) >> 16);
1547  } else {
1548  return row[y_][x_];
1549  }
1550 #else
1551  unsigned int iround = static_cast<unsigned int>(floor(i));
1552  unsigned int jround = static_cast<unsigned int>(floor(j));
1553 
1554  if (iround >= height || jround >= width) {
1555  vpERROR_TRACE("Pixel outside the image") ;
1557  "Pixel outside the image"));
1558  }
1559 
1560  double rratio = i - static_cast<double>(iround);
1561  double cratio = j - static_cast<double>(jround);
1562 
1563  double rfrac = 1.0 - rratio;
1564  double cfrac = 1.0 - cratio;
1565 
1566  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1567  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1568 
1569  double value = (static_cast<double>(row[iround][jround]) * rfrac + static_cast<double>(row[iround_1][jround]) * rratio) * cfrac +
1570  (static_cast<double>(row[iround][jround_1]) * rfrac + static_cast<double>(row[iround_1][jround_1]) * rratio) * cratio;
1571  return static_cast<unsigned char>(vpMath::round(value));
1572 #endif
1573 }
1574 
1578 template <> inline vpRGBa vpImage<vpRGBa>::getValue(double i, double j) const
1579 {
1580  if (i < 0 || j < 0 || i+1 > height || j+1 > width) {
1581  throw(vpException(vpImageException::notInTheImage, "Pixel outside of the image"));
1582  }
1583  if (height * width == 0) {
1584  throw vpException(vpImageException::notInitializedError, "Empty image!");
1585  }
1586 
1587  unsigned int iround = static_cast<unsigned int>(floor(i));
1588  unsigned int jround = static_cast<unsigned int>(floor(j));
1589 
1590  double rratio = i - static_cast<double>(iround);
1591  double cratio = j - static_cast<double>(jround);
1592 
1593  double rfrac = 1.0 - rratio;
1594  double cfrac = 1.0 - cratio;
1595 
1596  unsigned int iround_1 = (std::min)(height - 1, iround + 1);
1597  unsigned int jround_1 = (std::min)(width - 1, jround + 1);
1598 
1599  double valueR = (static_cast<double>(row[iround][jround].R) * rfrac + static_cast<double>(row[iround_1][jround].R) * rratio) * cfrac +
1600  (static_cast<double>(row[iround][jround_1].R) * rfrac + static_cast<double>(row[iround_1][jround_1].R) * rratio) * cratio;
1601  double valueG = (static_cast<double>(row[iround][jround].G) * rfrac + static_cast<double>(row[iround_1][jround].G) * rratio) * cfrac +
1602  (static_cast<double>(row[iround][jround_1].G) * rfrac + static_cast<double>(row[iround_1][jround_1].G) * rratio) * cratio;
1603  double valueB = (static_cast<double>(row[iround][jround].B) * rfrac + static_cast<double>(row[iround_1][jround].B) * rratio) * cfrac +
1604  (static_cast<double>(row[iround][jround_1].B) * rfrac + static_cast<double>(row[iround_1][jround_1].B) * rratio) * cratio;
1605 
1606  return vpRGBa(static_cast<unsigned char>(vpMath::round(valueR)),
1607  static_cast<unsigned char>(vpMath::round(valueG)),
1608  static_cast<unsigned char>(vpMath::round(valueB)));
1609 }
1610 
1627 template <class Type> inline Type vpImage<Type>::getValue(const vpImagePoint &ip) const
1628 {
1629  return getValue(ip.get_i(), ip.get_j());
1630 }
1631 
1635 template <> inline double vpImage<double>::getValue(const vpImagePoint &ip) const
1636 {
1637  return getValue(ip.get_i(), ip.get_j());
1638 }
1639 
1643 template <> inline unsigned char vpImage<unsigned char>::getValue(const vpImagePoint &ip) const
1644 {
1645  return getValue(ip.get_i(), ip.get_j());
1646 }
1647 
1651 template <> inline vpRGBa vpImage<vpRGBa>::getValue(const vpImagePoint &ip) const
1652 {
1653  return getValue(ip.get_i(), ip.get_j());
1654 }
1655 
1659 template <class Type> inline double vpImage<Type>::getSum() const
1660 {
1661  if ((height == 0) || (width == 0))
1662  return 0.0;
1663 
1664  double res = 0.0;
1665  for (unsigned int i = 0; i < height * width; ++i) {
1666  res += static_cast<double>(bitmap[i]);
1667  }
1668  return res;
1669 }
1670 
1700 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &B, vpImage<Type> &C)
1701 {
1702 
1703  try {
1704  if ((this->getHeight() != C.getHeight()) || (this->getWidth() != C.getWidth()))
1705  C.resize(this->getHeight(), this->getWidth());
1706  } catch (const vpException &me) {
1707  std::cout << me << std::endl;
1708  throw;
1709  }
1710 
1711  if ((this->getWidth() != B.getWidth()) || (this->getHeight() != B.getHeight())) {
1712  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage substraction "));
1713  }
1714 
1715  for (unsigned int i = 0; i < this->getWidth() * this->getHeight(); i++) {
1716  *(C.bitmap + i) = *(bitmap + i) - *(B.bitmap + i);
1717  }
1718 }
1719 
1731 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C)
1732 {
1733 
1734  try {
1735  if ((A.getHeight() != C.getHeight()) || (A.getWidth() != C.getWidth()))
1736  C.resize(A.getHeight(), A.getWidth());
1737  } catch (const vpException &me) {
1738  std::cout << me << std::endl;
1739  throw;
1740  }
1741 
1742  if ((A.getWidth() != B.getWidth()) || (A.getHeight() != B.getHeight())) {
1743  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage substraction "));
1744  }
1745 
1746  for (unsigned int i = 0; i < A.getWidth() * A.getHeight(); i++) {
1747  *(C.bitmap + i) = *(A.bitmap + i) - *(B.bitmap + i);
1748  }
1749 }
1750 
1759 template <class Type> void vpImage<Type>::performLut(const Type (&)[256], unsigned int)
1760 {
1761  std::cerr << "Not implemented !" << std::endl;
1762 }
1763 
1774 template <> inline void vpImage<unsigned char>::performLut(const unsigned char (&lut)[256], unsigned int nbThreads)
1775 {
1776  unsigned int size = getWidth() * getHeight();
1777  unsigned char *ptrStart = (unsigned char *)bitmap;
1778  unsigned char *ptrEnd = ptrStart + size;
1779  unsigned char *ptrCurrent = ptrStart;
1780 
1781  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
1782 #if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
1783  use_single_thread = true;
1784 #endif
1785 
1786  if (!use_single_thread && getSize() <= nbThreads) {
1787  use_single_thread = true;
1788  }
1789 
1790  if (use_single_thread) {
1791  // Single thread
1792 
1793  while (ptrCurrent != ptrEnd) {
1794  *ptrCurrent = lut[*ptrCurrent];
1795  ++ptrCurrent;
1796  }
1797  } else {
1798 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
1799  // Multi-threads
1800 
1801  std::vector<vpThread *> threadpool;
1802  std::vector<ImageLut_Param_t *> imageLutParams;
1803 
1804  unsigned int image_size = getSize();
1805  unsigned int step = image_size / nbThreads;
1806  unsigned int last_step = image_size - step * (nbThreads - 1);
1807 
1808  for (unsigned int index = 0; index < nbThreads; index++) {
1809  unsigned int start_index = index * step;
1810  unsigned int end_index = (index + 1) * step;
1811 
1812  if (index == nbThreads - 1) {
1813  end_index = start_index + last_step;
1814  }
1815 
1816  ImageLut_Param_t *imageLut_param = new ImageLut_Param_t(start_index, end_index, bitmap);
1817  memcpy(imageLut_param->m_lut, lut, 256 * sizeof(unsigned char));
1818 
1819  imageLutParams.push_back(imageLut_param);
1820 
1821  // Start the threads
1822  vpThread *imageLut_thread = new vpThread((vpThread::Fn)performLutThread, (vpThread::Args)imageLut_param);
1823  threadpool.push_back(imageLut_thread);
1824  }
1825 
1826  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1827  // Wait until thread ends up
1828  threadpool[cpt]->join();
1829  }
1830 
1831  // Delete
1832  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1833  delete threadpool[cpt];
1834  }
1835 
1836  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
1837  delete imageLutParams[cpt];
1838  }
1839 #endif
1840  }
1841 }
1842 
1853 template <> inline void vpImage<vpRGBa>::performLut(const vpRGBa (&lut)[256], unsigned int nbThreads)
1854 {
1855  unsigned int size = getWidth() * getHeight();
1856  unsigned char *ptrStart = (unsigned char *)bitmap;
1857  unsigned char *ptrEnd = ptrStart + size * 4;
1858  unsigned char *ptrCurrent = ptrStart;
1859 
1860  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
1861 #if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
1862  use_single_thread = true;
1863 #endif
1864 
1865  if (!use_single_thread && getSize() <= nbThreads) {
1866  use_single_thread = true;
1867  }
1868 
1869  if (use_single_thread) {
1870  // Single thread
1871  while (ptrCurrent != ptrEnd) {
1872  *ptrCurrent = lut[*ptrCurrent].R;
1873  ++ptrCurrent;
1874 
1875  *ptrCurrent = lut[*ptrCurrent].G;
1876  ++ptrCurrent;
1877 
1878  *ptrCurrent = lut[*ptrCurrent].B;
1879  ++ptrCurrent;
1880 
1881  *ptrCurrent = lut[*ptrCurrent].A;
1882  ++ptrCurrent;
1883  }
1884  } else {
1885 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
1886  // Multi-threads
1887  std::vector<vpThread *> threadpool;
1888  std::vector<ImageLutRGBa_Param_t *> imageLutParams;
1889 
1890  unsigned int image_size = getSize();
1891  unsigned int step = image_size / nbThreads;
1892  unsigned int last_step = image_size - step * (nbThreads - 1);
1893 
1894  for (unsigned int index = 0; index < nbThreads; index++) {
1895  unsigned int start_index = index * step;
1896  unsigned int end_index = (index + 1) * step;
1897 
1898  if (index == nbThreads - 1) {
1899  end_index = start_index + last_step;
1900  }
1901 
1902  ImageLutRGBa_Param_t *imageLut_param = new ImageLutRGBa_Param_t(start_index, end_index, (unsigned char *)bitmap);
1903  memcpy(imageLut_param->m_lut, lut, 256 * sizeof(vpRGBa));
1904 
1905  imageLutParams.push_back(imageLut_param);
1906 
1907  // Start the threads
1908  vpThread *imageLut_thread = new vpThread((vpThread::Fn)performLutRGBaThread, (vpThread::Args)imageLut_param);
1909  threadpool.push_back(imageLut_thread);
1910  }
1911 
1912  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1913  // Wait until thread ends up
1914  threadpool[cpt]->join();
1915  }
1916 
1917  // Delete
1918  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1919  delete threadpool[cpt];
1920  }
1921 
1922  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
1923  delete imageLutParams[cpt];
1924  }
1925 #endif
1926  }
1927 }
1928 
1929 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second)
1930 {
1931  using std::swap;
1932  swap(first.bitmap, second.bitmap);
1933  swap(first.display, second.display);
1934  swap(first.npixels, second.npixels);
1935  swap(first.width, second.width);
1936  swap(first.height, second.height);
1937  swap(first.row, second.row);
1938 }
1939 
1940 #endif
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:1759
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:1379
double get_i() const
Definition: vpImagePoint.h:203
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:177
void halfSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1273
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:1055
Type getMinValue() const
Return the minimum value within the bitmap.
Definition: vpImage.h:1001
void * Return
Definition: vpThread.h:78
void init(unsigned int height, unsigned int width)
Set the size of the image.
Definition: vpImage.h:667
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:881
Type getValue(unsigned int i, unsigned int j) const
Definition: vpImage.h:1427
unsigned int getRows() const
Definition: vpImage.h:218
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:1301
#define vpERROR_TRACE
Definition: vpDebug.h:393
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 operator()(const vpImagePoint &ip) const
Definition: vpImage.h:294
double getSum() const
Definition: vpImage.h:1659
virtual ~vpImage()
destructor
Definition: vpImage.h:937
vpImage< Type > & operator=(vpImage< Type > other)
Copy operator.
Definition: vpImage.h:1093
Definition: vpRGBa.h:66
const Type * operator[](unsigned int i) const
operator[] allows operation like x = I[i]
Definition: vpImage.h:267
friend void swap(vpImage< Type > &first, vpImage< Type > &second)
Definition: vpImage.h:1929
void *(* Fn)(Args)
Definition: vpThread.h:79
bool operator!=(const vpImage< Type > &I)
Definition: vpImage.h:1148
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
double get_j() const
Definition: vpImagePoint.h:214
unsigned int getCols() const
Definition: vpImage.h:179
Type operator()(unsigned int i, unsigned int j) const
Definition: vpImage.h:276
Type getMaxValue() const
Return the maximum value within the bitmap.
Definition: vpImage.h:973
void insert(const vpImage< Type > &src, const vpImagePoint &topLeft)
Definition: vpImage.h:1196
void destroy()
Destructor : Memory de-allocation.
Definition: vpImage.h:910
const Type * operator[](int i) const
Definition: vpImage.h:268
void quarterSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1337
Type * operator[](unsigned int i)
operator[] allows operation like I[i] = x.
Definition: vpImage.h:263
unsigned int getNumberOfPixel() const
Definition: vpImage.h:209
Type getMeanValue() const
Return the mean value of the bitmap.
Definition: vpImage.h:988
static int round(double x)
Definition: vpMath.h:245
void set_ij(double ii, double jj)
Definition: vpImagePoint.h:188
unsigned int getHeight() const
Definition: vpImage.h:188
unsigned int getSize() const
Definition: vpImage.h:227
vpImage< Type > operator-(const vpImage< Type > &B)
Definition: vpImage.h:1178
#define vpDEBUG_TRACE
Definition: vpDebug.h:487
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
vpImage()
constructor
Definition: vpImage.h:856
unsigned int getWidth() const
Definition: vpImage.h:246
Definition of the vpImage class member functions.
Definition: vpImage.h:126
bool operator==(const vpImage< Type > &I)
Definition: vpImage.h:1125
void getMinMaxValue(Type &min, Type &max) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:1019
void sub(const vpImage< Type > &B, vpImage< Type > &C)
Definition: vpImage.h:1700