Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
vpImage.h
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Image handling.
33  *
34  * Authors:
35  * Eric Marchand
36  *
37  *****************************************************************************/
38 
44 #ifndef vpImage_H
45 #define vpImage_H
46 
47 #include <visp3/core/vpConfig.h>
48 #include <visp3/core/vpDebug.h>
49 #include <visp3/core/vpException.h>
50 #include <visp3/core/vpImageException.h>
51 #include <visp3/core/vpImagePoint.h>
52 #include <visp3/core/vpRGBa.h>
53 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
54 #include <visp3/core/vpThread.h>
55 #endif
56 
57 #include <fstream>
58 #include <iomanip> // std::setw
59 #include <iostream>
60 #include <math.h>
61 #include <string.h>
62 
63 class vpDisplay;
64 
115 // Ref: http://en.cppreference.com/w/cpp/language/friend#Template_friends
116 template <class Type> class vpImage; // forward declare to make function declaration possible
117 
118 // declarations
119 template <class Type> std::ostream &operator<<(std::ostream &, const vpImage<Type> &);
120 
121 std::ostream &operator<<(std::ostream &, const vpImage<unsigned char> &);
122 std::ostream &operator<<(std::ostream &, const vpImage<char> &);
123 std::ostream &operator<<(std::ostream &, const vpImage<float> &);
124 std::ostream &operator<<(std::ostream &, const vpImage<double> &);
125 
126 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second);
127 
128 template <class Type> class vpImage
129 {
130  friend class vpImageConvert;
131 
132 public:
133  Type *bitmap;
135 
137  vpImage();
139  vpImage(const vpImage<Type> &);
140 #ifdef VISP_HAVE_CPP11_COMPATIBILITY
143 #endif
144  vpImage(unsigned int height, unsigned int width);
147  vpImage(unsigned int height, unsigned int width, Type value);
149  vpImage(Type *const array, const unsigned int height, const unsigned int width, const bool copyData = false);
151  virtual ~vpImage();
152 
155 
156  // destructor
157  void destroy();
158 
159  // Returns a new image that's double size of the current image
160  void doubleSizeImage(vpImage<Type> &res);
161 
169  inline unsigned int getCols() const { return width; }
178  inline unsigned int getHeight() const { return height; }
179 
180  // Return the maximum value within the bitmap
181  Type getMaxValue() const;
182  // Return the mean value of the bitmap
183  Type getMeanValue() const;
184  // Return the minumum value within the bitmap
185  Type getMinValue() const;
186  // Look for the minumum and the maximum value within the bitmap
187  void getMinMaxValue(Type &min, Type &max) const;
188  // Look for the minumum and the maximum value within the bitmap and get their location
189  void getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal = NULL, Type *maxVal = NULL) const;
190 
201  inline unsigned int getNumberOfPixel() const { return npixels; }
202 
211  inline unsigned int getRows() const { return height; }
219  inline unsigned int getSize() const { return width * height; }
220 
221  // Gets the value of a pixel at a location.
222  Type getValue(unsigned int i, unsigned int j) const;
223  // Gets the value of a pixel at a location with bilinear interpolation.
224  Type getValue(double i, double j) const;
225  // Gets the value of a pixel at a location with bilinear interpolation.
226  Type getValue(vpImagePoint &ip) const;
227 
228  // Get image pixels sum
229  double getSum() const;
230 
239  inline unsigned int getWidth() const { return width; }
240 
241  // Returns a new image that's half size of the current image
242  void halfSizeImage(vpImage<Type> &res) const;
243 
245  void init(unsigned int height, unsigned int width);
247  void init(unsigned int height, unsigned int width, Type value);
249  void init(Type *const array, const unsigned int height, const unsigned int width, const bool copyData = false);
250  void insert(const vpImage<Type> &src, const vpImagePoint &topLeft);
251 
252  //------------------------------------------------------------------
253  // Acces to the image
254 
256  inline Type *operator[](const unsigned int i) { return row[i]; }
257  inline Type *operator[](const int i) { return row[i]; }
258 
260  inline const Type *operator[](unsigned int i) const { return row[i]; }
261  inline const Type *operator[](int i) const { return row[i]; }
262 
270  inline Type operator()(const unsigned int i, const unsigned int j) const { return bitmap[i * width + j]; }
276  inline void operator()(const unsigned int i, const unsigned int j, const Type &v) { bitmap[i * width + j] = v; }
288  inline Type operator()(const vpImagePoint &ip) const
289  {
290  unsigned int i = (unsigned int)ip.get_i();
291  unsigned int j = (unsigned int)ip.get_j();
292 
293  return bitmap[i * width + j];
294  }
304  inline void operator()(const vpImagePoint &ip, const Type &v)
305  {
306  unsigned int i = (unsigned int)ip.get_i();
307  unsigned int j = (unsigned int)ip.get_j();
308 
309  bitmap[i * width + j] = v;
310  }
311 
313 
316 
317  vpImage<Type> &operator=(const Type &v);
318  bool operator==(const vpImage<Type> &I);
319  bool operator!=(const vpImage<Type> &I);
320  friend std::ostream &operator<< <>(std::ostream &s, const vpImage<Type> &I);
321  friend std::ostream &operator<<(std::ostream &s, const vpImage<unsigned char> &I);
322  friend std::ostream &operator<<(std::ostream &s, const vpImage<char> &I);
323  friend std::ostream &operator<<(std::ostream &s, const vpImage<float> &I);
324  friend std::ostream &operator<<(std::ostream &s, const vpImage<double> &I);
325 
326  // Perform a look-up table transformation
327  void performLut(const Type (&lut)[256], const unsigned int nbThreads = 1);
328 
329  // Returns a new image that's a quarter size of the current image
330  void quarterSizeImage(vpImage<Type> &res) const;
331 
332  // set the size of the image without initializing it.
333  void resize(const unsigned int h, const unsigned int w);
334  // set the size of the image and initialize it.
335  void resize(const unsigned int h, const unsigned int w, const Type &val);
336 
337  void sub(const vpImage<Type> &B, vpImage<Type> &C);
338  void sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C);
339  void subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const;
340 
341  friend void swap<>(vpImage<Type> &first, vpImage<Type> &second);
342 
344 
345 private:
346  unsigned int npixels;
347  unsigned int width;
348  unsigned int height;
349  Type **row;
350 };
351 
352 template <class Type> std::ostream &operator<<(std::ostream &s, const vpImage<Type> &I)
353 {
354  if (I.bitmap == NULL) {
355  return s;
356  }
357 
358  for (unsigned int i = 0; i < I.getHeight(); i++) {
359  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
360  s << I[i][j] << " ";
361  }
362 
363  // We don't add " " after the last column element
364  s << I[i][I.getWidth() - 1];
365 
366  // We don't add a \n character at the end of the last row line
367  if (i < I.getHeight() - 1) {
368  s << std::endl;
369  }
370  }
371 
372  return s;
373 }
374 
375 inline std::ostream &operator<<(std::ostream &s, const vpImage<unsigned char> &I)
376 {
377  if (I.bitmap == NULL) {
378  return s;
379  }
380 
381  std::ios_base::fmtflags original_flags = s.flags();
382 
383  for (unsigned int i = 0; i < I.getHeight(); i++) {
384  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
385  s << std::setw(3) << static_cast<unsigned>(I[i][j]) << " ";
386  }
387 
388  // We don't add " " after the last column element
389  s << std::setw(3) << static_cast<unsigned>(I[i][I.getWidth() - 1]);
390 
391  // We don't add a \n character at the end of the last row line
392  if (i < I.getHeight() - 1) {
393  s << std::endl;
394  }
395  }
396 
397  s.flags(original_flags); // restore s to standard state
398  return s;
399 }
400 
401 inline std::ostream &operator<<(std::ostream &s, const vpImage<char> &I)
402 {
403  if (I.bitmap == NULL) {
404  return s;
405  }
406 
407  std::ios_base::fmtflags original_flags = s.flags();
408 
409  for (unsigned int i = 0; i < I.getHeight(); i++) {
410  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
411  s << std::setw(4) << static_cast<int>(I[i][j]) << " ";
412  }
413 
414  // We don't add " " after the last column element
415  s << std::setw(4) << static_cast<int>(I[i][I.getWidth() - 1]);
416 
417  // We don't add a \n character at the end of the last row line
418  if (i < I.getHeight() - 1) {
419  s << std::endl;
420  }
421  }
422 
423  s.flags(original_flags); // restore s to standard state
424  return s;
425 }
426 
427 inline std::ostream &operator<<(std::ostream &s, const vpImage<float> &I)
428 {
429  if (I.bitmap == NULL) {
430  return s;
431  }
432 
433  std::ios_base::fmtflags original_flags = s.flags();
434  s.precision(9); // http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
435 
436  for (unsigned int i = 0; i < I.getHeight(); i++) {
437  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
438  s << I[i][j] << " ";
439  }
440 
441  // We don't add " " after the last column element
442  s << I[i][I.getWidth() - 1];
443 
444  // We don't add a \n character at the end of the last row line
445  if (i < I.getHeight() - 1) {
446  s << std::endl;
447  }
448  }
449 
450  s.flags(original_flags); // restore s to standard state
451  return s;
452 }
453 
454 inline std::ostream &operator<<(std::ostream &s, const vpImage<double> &I)
455 {
456  if (I.bitmap == NULL) {
457  return s;
458  }
459 
460  std::ios_base::fmtflags original_flags = s.flags();
461  s.precision(17); // http://en.cppreference.com/w/cpp/types/numeric_limits/max_digits10
462 
463  for (unsigned int i = 0; i < I.getHeight(); i++) {
464  for (unsigned int j = 0; j < I.getWidth() - 1; j++) {
465  s << I[i][j] << " ";
466  }
467 
468  // We don't add " " after the last column element
469  s << I[i][I.getWidth() - 1];
470 
471  // We don't add a \n character at the end of the last row line
472  if (i < I.getHeight() - 1) {
473  s << std::endl;
474  }
475  }
476 
477  s.flags(original_flags); // restore s to standard state
478  return s;
479 }
480 
481 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
482 namespace
483 {
484 struct ImageLut_Param_t {
485  unsigned int m_start_index;
486  unsigned int m_end_index;
487 
488  unsigned char m_lut[256];
489  unsigned char *m_bitmap;
490 
491  ImageLut_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_bitmap(NULL) {}
492 
493  ImageLut_Param_t(const unsigned int start_index, const unsigned int end_index, unsigned char *bitmap)
494  : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
495  {
496  }
497 };
498 
499 vpThread::Return performLutThread(vpThread::Args args)
500 {
501  ImageLut_Param_t *imageLut_param = static_cast<ImageLut_Param_t *>(args);
502  unsigned int start_index = imageLut_param->m_start_index;
503  unsigned int end_index = imageLut_param->m_end_index;
504 
505  unsigned char *bitmap = imageLut_param->m_bitmap;
506 
507  unsigned char *ptrStart = bitmap + start_index;
508  unsigned char *ptrEnd = bitmap + end_index;
509  unsigned char *ptrCurrent = ptrStart;
510 
511  // while(ptrCurrent != ptrEnd) {
512  // *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
513  // ++ptrCurrent;
514  // }
515 
516  if (end_index - start_index >= 8) {
517  // Unroll loop version
518  for (; ptrCurrent <= ptrEnd - 8;) {
519  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
520  ++ptrCurrent;
521 
522  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
523  ++ptrCurrent;
524 
525  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
526  ++ptrCurrent;
527 
528  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
529  ++ptrCurrent;
530 
531  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
532  ++ptrCurrent;
533 
534  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
535  ++ptrCurrent;
536 
537  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
538  ++ptrCurrent;
539 
540  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
541  ++ptrCurrent;
542  }
543  }
544 
545  for (; ptrCurrent != ptrEnd; ++ptrCurrent) {
546  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent];
547  }
548 
549  return 0;
550 }
551 
552 struct ImageLutRGBa_Param_t {
553  unsigned int m_start_index;
554  unsigned int m_end_index;
555 
556  vpRGBa m_lut[256];
557  unsigned char *m_bitmap;
558 
559  ImageLutRGBa_Param_t() : m_start_index(0), m_end_index(0), m_lut(), m_bitmap(NULL) {}
560 
561  ImageLutRGBa_Param_t(const unsigned int start_index, const unsigned int end_index, unsigned char *bitmap)
562  : m_start_index(start_index), m_end_index(end_index), m_lut(), m_bitmap(bitmap)
563  {
564  }
565 };
566 
567 vpThread::Return performLutRGBaThread(vpThread::Args args)
568 {
569  ImageLutRGBa_Param_t *imageLut_param = static_cast<ImageLutRGBa_Param_t *>(args);
570  unsigned int start_index = imageLut_param->m_start_index;
571  unsigned int end_index = imageLut_param->m_end_index;
572 
573  unsigned char *bitmap = imageLut_param->m_bitmap;
574 
575  unsigned char *ptrStart = bitmap + start_index * 4;
576  unsigned char *ptrEnd = bitmap + end_index * 4;
577  unsigned char *ptrCurrent = ptrStart;
578 
579  if (end_index - start_index >= 4 * 2) {
580  // Unroll loop version
581  for (; ptrCurrent <= ptrEnd - 4 * 2;) {
582  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
583  ptrCurrent++;
584  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
585  ptrCurrent++;
586  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
587  ptrCurrent++;
588  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
589  ptrCurrent++;
590 
591  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
592  ptrCurrent++;
593  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
594  ptrCurrent++;
595  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
596  ptrCurrent++;
597  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
598  ptrCurrent++;
599  }
600  }
601 
602  while (ptrCurrent != ptrEnd) {
603  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].R;
604  ptrCurrent++;
605 
606  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].G;
607  ptrCurrent++;
608 
609  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].B;
610  ptrCurrent++;
611 
612  *ptrCurrent = imageLut_param->m_lut[*ptrCurrent].A;
613  ptrCurrent++;
614  }
615 
616  return 0;
617 }
618 }
619 #endif
620 
634 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w, Type value)
635 {
636  init(h, w);
637 
638  // for (unsigned int i = 0; i < npixels; i++)
639  // bitmap[i] = value;
640  std::fill(bitmap, bitmap + npixels, value);
641 }
642 
660 template <class Type> void vpImage<Type>::init(unsigned int h, unsigned int w)
661 {
662  if (h != this->height) {
663  if (row != NULL) {
664  vpDEBUG_TRACE(10, "Destruction row[]");
665  delete[] row;
666  row = NULL;
667  }
668  }
669 
670  if ((h != this->height) || (w != this->width)) {
671  if (bitmap != NULL) {
672  vpDEBUG_TRACE(10, "Destruction bitmap[]");
673  delete[] bitmap;
674  bitmap = NULL;
675  }
676  }
677 
678  this->width = w;
679  this->height = h;
680 
681  npixels = width * height;
682 
683  if (bitmap == NULL)
684  bitmap = new Type[npixels];
685 
686  if (bitmap == NULL) {
687  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
688  }
689 
690  if (row == NULL)
691  row = new Type *[height];
692  if (row == NULL) {
693  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
694  }
695 
696  for (unsigned int i = 0; i < height; i++)
697  row[i] = bitmap + i * width;
698 }
699 
713 template <class Type>
714 void vpImage<Type>::init(Type *const array, const unsigned int h, const unsigned int w, const bool copyData)
715 {
716  if (h != this->height) {
717  if (row != NULL) {
718  delete[] row;
719  row = NULL;
720  }
721  }
722 
723  // Delete bitmap if copyData==false, otherwise only if the dimension differs
724  if ((copyData && ((h != this->height) || (w != this->width))) || !copyData) {
725  if (bitmap != NULL) {
726  delete[] bitmap;
727  bitmap = NULL;
728  }
729  }
730 
731  this->width = w;
732  this->height = h;
733 
734  npixels = width * height;
735 
736  if (copyData) {
737  if (bitmap == NULL)
738  bitmap = new Type[npixels];
739 
740  if (bitmap == NULL) {
741  throw(vpException(vpException::memoryAllocationError, "cannot allocate bitmap "));
742  }
743 
744  // Copy the image data
745  memcpy(static_cast<void*>(bitmap), static_cast<void*>(array), (size_t)(npixels * sizeof(Type)));
746  } else {
747  // Copy the address of the array in the bitmap
748  bitmap = array;
749  }
750 
751  if (row == NULL)
752  row = new Type *[height];
753  if (row == NULL) {
754  throw(vpException(vpException::memoryAllocationError, "cannot allocate row "));
755  }
756 
757  for (unsigned int i = 0; i < height; i++) {
758  row[i] = bitmap + i * width;
759  }
760 }
761 
780 template <class Type>
781 vpImage<Type>::vpImage(unsigned int h, unsigned int w)
782  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL)
783 {
784  init(h, w, 0);
785 }
786 
804 template <class Type>
805 vpImage<Type>::vpImage(unsigned int h, unsigned int w, Type value)
806  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL)
807 {
808  init(h, w, value);
809 }
810 
826 template <class Type>
827 vpImage<Type>::vpImage(Type *const array, const unsigned int h, const unsigned int w, const bool copyData)
828  : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL)
829 {
830  init(array, h, w, copyData);
831 }
832 
842 template <class Type> vpImage<Type>::vpImage() : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL)
843 {
844 }
845 
866 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w) { init(h, w); }
867 
887 template <class Type> void vpImage<Type>::resize(unsigned int h, unsigned int w, const Type &val) { init(h, w, val); }
888 
895 template <class Type> void vpImage<Type>::destroy()
896 {
897  // vpERROR_TRACE("Deallocate ");
898 
899  if (bitmap != NULL) {
900  // vpERROR_TRACE("Deallocate bitmap memory %p",bitmap);
901  // vpDEBUG_TRACE(20,"Deallocate bitmap memory %p",bitmap);
902  delete[] bitmap;
903  bitmap = NULL;
904  }
905 
906  if (row != NULL) {
907  // vpERROR_TRACE("Deallocate row memory %p",row);
908  // vpDEBUG_TRACE(20,"Deallocate row memory %p",row);
909  delete[] row;
910  row = NULL;
911  }
912 }
913 
920 template <class Type> vpImage<Type>::~vpImage() { destroy(); }
921 
925 template <class Type>
926 vpImage<Type>::vpImage(const vpImage<Type> &I) : bitmap(NULL), display(NULL), npixels(0), width(0), height(0), row(NULL)
927 {
928  resize(I.getHeight(), I.getWidth());
929  memcpy(static_cast<void*>(bitmap), static_cast<void*>(I.bitmap), I.npixels * sizeof(Type));
930 }
931 
932 #ifdef VISP_HAVE_CPP11_COMPATIBILITY
933 
936 template <class Type>
938  : bitmap(I.bitmap), display(I.display), npixels(I.npixels), width(I.width), height(I.height), row(I.row)
939 {
940  I.bitmap = NULL;
941  I.display = NULL;
942  I.npixels = 0;
943  I.width = 0;
944  I.height = 0;
945  I.row = NULL;
946 }
947 #endif
948 
954 template <class Type> Type vpImage<Type>::getMaxValue() const
955 {
956  if (npixels == 0)
957  throw(vpException(vpException::fatalError, "Cannot compute maximum value of an empty image"));
958  Type m = bitmap[0];
959  for (unsigned int i = 0; i < npixels; i++) {
960  if (bitmap[i] > m)
961  m = bitmap[i];
962  }
963  return m;
964 }
965 
969 template <class Type> Type vpImage<Type>::getMeanValue() const
970 {
971  if ((height == 0) || (width == 0))
972  return 0.0;
973 
974  return getSum() / (height * width);
975 }
976 
982 template <class Type> Type vpImage<Type>::getMinValue() const
983 {
984  if (npixels == 0)
985  throw(vpException(vpException::fatalError, "Cannot compute minimum value of an empty image"));
986  Type m = bitmap[0];
987  for (unsigned int i = 0; i < npixels; i++)
988  if (bitmap[i] < m)
989  m = bitmap[i];
990  return m;
991 }
992 
1000 template <class Type> void vpImage<Type>::getMinMaxValue(Type &min, Type &max) const
1001 {
1002  if (npixels == 0)
1003  throw(vpException(vpException::fatalError, "Cannot get minimum/maximum values of an empty image"));
1004 
1005  min = max = bitmap[0];
1006  for (unsigned int i = 0; i < npixels; i++) {
1007  if (bitmap[i] < min)
1008  min = bitmap[i];
1009  if (bitmap[i] > max)
1010  max = bitmap[i];
1011  }
1012 }
1013 
1035 template <class Type>
1036 void vpImage<Type>::getMinMaxLoc(vpImagePoint *minLoc, vpImagePoint *maxLoc, Type *minVal, Type *maxVal) const
1037 {
1038  if (npixels == 0)
1039  throw(vpException(vpException::fatalError, "Cannot get location of minimum/maximum "
1040  "values of an empty image"));
1041 
1042  Type min = bitmap[0], max = bitmap[0];
1043  vpImagePoint minLoc_, maxLoc_;
1044  for (unsigned int i = 0; i < height; i++) {
1045  for (unsigned int j = 0; j < width; j++) {
1046  if (row[i][j] < min) {
1047  min = row[i][j];
1048  minLoc_.set_ij(i, j);
1049  }
1050 
1051  if (row[i][j] > max) {
1052  max = row[i][j];
1053  maxLoc_.set_ij(i, j);
1054  }
1055  }
1056  }
1057 
1058  if (minLoc != NULL)
1059  *minLoc = minLoc_;
1060 
1061  if (maxLoc != NULL)
1062  *maxLoc = maxLoc_;
1063 
1064  if (minVal != NULL)
1065  *minVal = min;
1066 
1067  if (maxVal != NULL)
1068  *maxVal = max;
1069 }
1070 
1075 {
1076  swap(*this, other);
1077  // Swap back display pointer if it was not null
1078  // vpImage<unsigned char> I2(480, 640);
1079  // vpDisplayX d(I2);
1080  // I2 = I1; //copy only the data
1081  if (other.display != NULL)
1082  display = other.display;
1083 
1084  return *this;
1085 }
1086 
1093 template <class Type> vpImage<Type> &vpImage<Type>::operator=(const Type &v)
1094 {
1095  for (unsigned int i = 0; i < npixels; i++)
1096  bitmap[i] = v;
1097 
1098  return *this;
1099 }
1100 
1106 template <class Type> bool vpImage<Type>::operator==(const vpImage<Type> &I)
1107 {
1108  if (this->width != I.getWidth())
1109  return false;
1110  if (this->height != I.getHeight())
1111  return false;
1112 
1113  // printf("wxh: %dx%d bitmap: %p I.bitmap %p\n", width, height, bitmap,
1114  // I.bitmap);
1115  for (unsigned int i = 0; i < npixels; i++) {
1116  if (bitmap[i] != I.bitmap[i]) {
1117  // std::cout << "differ for pixel " << i << " (" << i%this->height
1118  // << ", " << i - i%this->height << ")" << std::endl;
1119  return false;
1120  }
1121  }
1122  return true;
1123 }
1129 template <class Type> bool vpImage<Type>::operator!=(const vpImage<Type> &I)
1130 {
1131  // if (this->width != I.getWidth())
1132  // return true;
1133  // if (this->height != I.getHeight())
1134  // return true;
1135 
1136  // for (unsigned int i=0 ; i < npixels ; i++)
1137  // {
1138  // if (bitmap[i] != I.bitmap[i])
1139  // return true;
1140  // }
1141  // return false;
1142  return !(*this == I);
1143 }
1144 
1171 {
1172  vpImage<Type> C;
1173  sub(*this, B, C);
1174  return C;
1175 }
1176 
1188 template <class Type> void vpImage<Type>::insert(const vpImage<Type> &src, const vpImagePoint &topLeft)
1189 {
1190  int itl = (int)topLeft.get_i();
1191  int jtl = (int)topLeft.get_j();
1192 
1193  int dest_ibegin = 0;
1194  int dest_jbegin = 0;
1195  int src_ibegin = 0;
1196  int src_jbegin = 0;
1197  int dest_w = (int)this->getWidth();
1198  int dest_h = (int)this->getHeight();
1199  int src_w = (int)src.getWidth();
1200  int src_h = (int)src.getHeight();
1201  int wsize = (int)src.getWidth();
1202  int hsize = (int)src.getHeight();
1203 
1204  if (itl >= dest_h || jtl >= dest_w)
1205  return;
1206 
1207  if (itl < 0)
1208  src_ibegin = -itl;
1209  else
1210  dest_ibegin = itl;
1211 
1212  if (jtl < 0)
1213  src_jbegin = -jtl;
1214  else
1215  dest_jbegin = jtl;
1216 
1217  if (src_w - src_jbegin > dest_w - dest_jbegin)
1218  wsize = dest_w - dest_jbegin;
1219  else
1220  wsize = src_w - src_jbegin;
1221 
1222  if (src_h - src_ibegin > dest_h - dest_ibegin)
1223  hsize = dest_h - dest_ibegin;
1224  else
1225  hsize = src_h - src_ibegin;
1226 
1227  for (int i = 0; i < hsize; i++) {
1228  Type *srcBitmap = src.bitmap + ((src_ibegin + i) * src_w + src_jbegin);
1229  Type *destBitmap = this->bitmap + ((dest_ibegin + i) * dest_w + dest_jbegin);
1230 
1231  memcpy(static_cast<void*>(destBitmap), static_cast<void*>(srcBitmap), (size_t)wsize * sizeof(Type));
1232  }
1233 }
1234 
1265 template <class Type> void vpImage<Type>::halfSizeImage(vpImage<Type> &res) const
1266 {
1267  unsigned int h = height / 2;
1268  unsigned int w = width / 2;
1269  res.resize(h, w);
1270  for (unsigned int i = 0; i < h; i++)
1271  for (unsigned int j = 0; j < w; j++)
1272  res[i][j] = (*this)[i << 1][j << 1];
1273 }
1274 
1292 template <class Type>
1293 void vpImage<Type>::subsample(unsigned int v_scale, unsigned int h_scale, vpImage<Type> &sampled) const
1294 {
1295  unsigned int h = height / v_scale;
1296  unsigned int w = width / h_scale;
1297  sampled.resize(h, w);
1298  for (unsigned int i = 0; i < h; i++)
1299  for (unsigned int j = 0; j < w; j++)
1300  sampled[i][j] = (*this)[i * v_scale][j * h_scale];
1301 }
1302 
1327 template <class Type> void vpImage<Type>::quarterSizeImage(vpImage<Type> &res) const
1328 {
1329  unsigned int h = height / 4;
1330  unsigned int w = width / 4;
1331  res.resize(h, w);
1332  for (unsigned int i = 0; i < h; i++)
1333  for (unsigned int j = 0; j < w; j++)
1334  res[i][j] = (*this)[i << 2][j << 2];
1335 }
1336 
1370 template <class Type> void vpImage<Type>::doubleSizeImage(vpImage<Type> &res)
1371 {
1372  int h = height * 2;
1373  int w = width * 2;
1374 
1375  res.resize(h, w);
1376 
1377  for (int i = 0; i < h; i++)
1378  for (int j = 0; j < w; j++)
1379  res[i][j] = (*this)[i >> 1][j >> 1];
1380 
1381  /*
1382  A B C
1383  E F G
1384  H I J
1385  A C H J are pixels from original image
1386  B E G I are interpolated pixels
1387  */
1388 
1389  // interpolate pixels B and I
1390  for (int i = 0; i < h; i += 2)
1391  for (int j = 1; j < w - 1; j += 2)
1392  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1]));
1393 
1394  // interpolate pixels E and G
1395  for (int i = 1; i < h - 1; i += 2)
1396  for (int j = 0; j < w; j += 2)
1397  res[i][j] = (Type)(0.5 * ((*this)[i >> 1][j >> 1] + (*this)[(i >> 1) + 1][j >> 1]));
1398 
1399  // interpolate pixel F
1400  for (int i = 1; i < h - 1; i += 2)
1401  for (int j = 1; j < w - 1; j += 2)
1402  res[i][j] = (Type)(0.25 * ((*this)[i >> 1][j >> 1] + (*this)[i >> 1][(j >> 1) + 1] +
1403  (*this)[(i >> 1) + 1][j >> 1] + (*this)[(i >> 1) + 1][(j >> 1) + 1]));
1404 }
1405 
1420 template <class Type> inline Type vpImage<Type>::getValue(unsigned int i, unsigned int j) const
1421 {
1422  if (i >= height || j >= width) {
1423  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1424  }
1425 
1426  return row[i][j];
1427 }
1428 
1449 template <class Type> Type vpImage<Type>::getValue(double i, double j) const
1450 {
1451  unsigned int iround, jround;
1452  double rfrac, cfrac;
1453 
1454  iround = (unsigned int)floor(i);
1455  jround = (unsigned int)floor(j);
1456 
1457  if (iround >= height || jround >= width) {
1458  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1459  }
1460 
1461  if (i > height - 1)
1462  i = (double)(height - 1);
1463 
1464  if (j > width - 1)
1465  j = (double)(width - 1);
1466 
1467  double rratio = i - (double)iround;
1468  if (rratio < 0)
1469  rratio = -rratio;
1470  double cratio = j - (double)jround;
1471  if (cratio < 0)
1472  cratio = -cratio;
1473 
1474  rfrac = 1.0f - rratio;
1475  cfrac = 1.0f - cratio;
1476 
1477  double value = ((double)row[iround][jround] * rfrac + (double)row[iround + 1][jround] * rratio) * cfrac +
1478  ((double)row[iround][jround + 1] * rfrac + (double)row[iround + 1][jround + 1] * rratio) * cratio;
1479  return (Type)vpMath::round(value);
1480 }
1481 
1501 template <> inline double vpImage<double>::getValue(double i, double j) const
1502 {
1503  unsigned int iround, jround;
1504  double rfrac, cfrac;
1505 
1506  iround = (unsigned int)floor(i);
1507  jround = (unsigned int)floor(j);
1508 
1509  if (iround >= height || jround >= width) {
1510  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1511  }
1512 
1513  if (i > height - 1)
1514  i = (double)(height - 1);
1515 
1516  if (j > width - 1)
1517  j = (double)(width - 1);
1518 
1519  double rratio = i - (double)iround;
1520  if (rratio < 0)
1521  rratio = -rratio;
1522  double cratio = j - (double)jround;
1523  if (cratio < 0)
1524  cratio = -cratio;
1525 
1526  rfrac = 1.0f - rratio;
1527  cfrac = 1.0f - cratio;
1528 
1529  double value = ((double)row[iround][jround] * rfrac + (double)row[iround + 1][jround] * rratio) * cfrac +
1530  ((double)row[iround][jround + 1] * rfrac + (double)row[iround + 1][jround + 1] * rratio) * cratio;
1531  return value;
1532 }
1533 
1534 template <> inline vpRGBa vpImage<vpRGBa>::getValue(double i, double j) const
1535 {
1536  unsigned int iround, jround;
1537  double rfrac, cfrac;
1538 
1539  iround = (unsigned int)floor(i);
1540  jround = (unsigned int)floor(j);
1541 
1542  if (iround >= height || jround >= width) {
1543  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1544  }
1545 
1546  if (i > height - 1)
1547  i = (double)(height - 1);
1548 
1549  if (j > width - 1)
1550  j = (double)(width - 1);
1551 
1552  double rratio = i - (double)iround;
1553  if (rratio < 0)
1554  rratio = -rratio;
1555  double cratio = j - (double)jround;
1556  if (cratio < 0)
1557  cratio = -cratio;
1558 
1559  rfrac = 1.0f - rratio;
1560  cfrac = 1.0f - cratio;
1561 
1562  double valueR = ((double)row[iround][jround].R * rfrac + (double)row[iround + 1][jround].R * rratio) * cfrac +
1563  ((double)row[iround][jround + 1].R * rfrac + (double)row[iround + 1][jround + 1].R * rratio) * cratio;
1564  double valueG = ((double)row[iround][jround].G * rfrac + (double)row[iround + 1][jround].G * rratio) * cfrac +
1565  ((double)row[iround][jround + 1].G * rfrac + (double)row[iround + 1][jround + 1].G * rratio) * cratio;
1566  double valueB = ((double)row[iround][jround].B * rfrac + (double)row[iround + 1][jround].B * rratio) * cfrac +
1567  ((double)row[iround][jround + 1].B * rfrac + (double)row[iround + 1][jround + 1].B * rratio) * cratio;
1568  return vpRGBa((unsigned char)vpMath::round(valueR), (unsigned char)vpMath::round(valueG),
1569  (unsigned char)vpMath::round(valueB));
1570 }
1571 
1591 template <class Type> inline Type vpImage<Type>::getValue(vpImagePoint &ip) const
1592 {
1593  unsigned int iround, jround;
1594  double rfrac, cfrac;
1595 
1596  iround = (unsigned int)floor(ip.get_i());
1597  jround = (unsigned int)floor(ip.get_j());
1598 
1599  if (iround >= height || jround >= width) {
1600  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1601  }
1602 
1603  if (ip.get_i() > height - 1)
1604  ip.set_i((double)(height - 1));
1605 
1606  if (ip.get_j() > width - 1)
1607  ip.set_j((double)(width - 1));
1608 
1609  double rratio = ip.get_i() - (double)iround;
1610  if (rratio < 0)
1611  rratio = -rratio;
1612  double cratio = ip.get_j() - (double)jround;
1613  if (cratio < 0)
1614  cratio = -cratio;
1615 
1616  rfrac = 1.0f - rratio;
1617  cfrac = 1.0f - cratio;
1618 
1619  double value = ((double)row[iround][jround] * rfrac + (double)row[iround + 1][jround] * rratio) * cfrac +
1620  ((double)row[iround][jround + 1] * rfrac + (double)row[iround + 1][jround + 1] * rratio) * cratio;
1621  return (Type)vpMath::round(value);
1622 }
1623 
1624 template <> inline double vpImage<double>::getValue(vpImagePoint &ip) const
1625 {
1626  unsigned int iround, jround;
1627  double rfrac, cfrac;
1628 
1629  iround = (unsigned int)floor(ip.get_i());
1630  jround = (unsigned int)floor(ip.get_j());
1631 
1632  if (iround >= height || jround >= width) {
1633  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1634  }
1635 
1636  if (ip.get_i() > height - 1)
1637  ip.set_i((double)(height - 1));
1638 
1639  if (ip.get_j() > width - 1)
1640  ip.set_j((double)(width - 1));
1641 
1642  double rratio = ip.get_i() - (double)iround;
1643  if (rratio < 0)
1644  rratio = -rratio;
1645  double cratio = ip.get_j() - (double)jround;
1646  if (cratio < 0)
1647  cratio = -cratio;
1648 
1649  rfrac = 1.0f - rratio;
1650  cfrac = 1.0f - cratio;
1651 
1652  double value = ((double)row[iround][jround] * rfrac + (double)row[iround + 1][jround] * rratio) * cfrac +
1653  ((double)row[iround][jround + 1] * rfrac + (double)row[iround + 1][jround + 1] * rratio) * cratio;
1654  return value;
1655 }
1656 
1657 template <> inline vpRGBa vpImage<vpRGBa>::getValue(vpImagePoint &ip) const
1658 {
1659  unsigned int iround, jround;
1660  double rfrac, cfrac;
1661 
1662  iround = (unsigned int)floor(ip.get_i());
1663  jround = (unsigned int)floor(ip.get_j());
1664 
1665  if (iround >= height || jround >= width) {
1666  throw(vpException(vpImageException::notInTheImage, "Pixel outside the image"));
1667  }
1668 
1669  if (ip.get_i() > height - 1)
1670  ip.set_i((double)(height - 1));
1671 
1672  if (ip.get_j() > width - 1)
1673  ip.set_j((double)(width - 1));
1674 
1675  double rratio = ip.get_i() - (double)iround;
1676  if (rratio < 0)
1677  rratio = -rratio;
1678  double cratio = ip.get_j() - (double)jround;
1679  if (cratio < 0)
1680  cratio = -cratio;
1681 
1682  rfrac = 1.0f - rratio;
1683  cfrac = 1.0f - cratio;
1684 
1685  double valueR = ((double)row[iround][jround].R * rfrac + (double)row[iround + 1][jround].R * rratio) * cfrac +
1686  ((double)row[iround][jround + 1].R * rfrac + (double)row[iround + 1][jround + 1].R * rratio) * cratio;
1687  double valueG = ((double)row[iround][jround].G * rfrac + (double)row[iround + 1][jround].G * rratio) * cfrac +
1688  ((double)row[iround][jround + 1].G * rfrac + (double)row[iround + 1][jround + 1].G * rratio) * cratio;
1689  double valueB = ((double)row[iround][jround].B * rfrac + (double)row[iround + 1][jround].B * rratio) * cfrac +
1690  ((double)row[iround][jround + 1].B * rfrac + (double)row[iround + 1][jround + 1].B * rratio) * cratio;
1691  return vpRGBa((unsigned char)vpMath::round(valueR), (unsigned char)vpMath::round(valueG),
1692  (unsigned char)vpMath::round(valueB));
1693 }
1694 
1698 template <class Type> inline double vpImage<Type>::getSum() const
1699 {
1700  if ((height == 0) || (width == 0))
1701  return 0.0;
1702 
1703  double res = 0.0;
1704  for (unsigned int i = 0; i < height * width; ++i) {
1705  res += static_cast<double>(bitmap[i]);
1706  }
1707  return res;
1708 }
1709 
1739 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &B, vpImage<Type> &C)
1740 {
1741 
1742  try {
1743  if ((this->getHeight() != C.getHeight()) || (this->getWidth() != C.getWidth()))
1744  C.resize(this->getHeight(), this->getWidth());
1745  } catch (const vpException &me) {
1746  std::cout << me << std::endl;
1747  throw;
1748  }
1749 
1750  if ((this->getWidth() != B.getWidth()) || (this->getHeight() != B.getHeight())) {
1751  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage substraction "));
1752  }
1753 
1754  for (unsigned int i = 0; i < this->getWidth() * this->getHeight(); i++) {
1755  *(C.bitmap + i) = *(bitmap + i) - *(B.bitmap + i);
1756  }
1757 }
1758 
1770 template <class Type> void vpImage<Type>::sub(const vpImage<Type> &A, const vpImage<Type> &B, vpImage<Type> &C)
1771 {
1772 
1773  try {
1774  if ((A.getHeight() != C.getHeight()) || (A.getWidth() != C.getWidth()))
1775  C.resize(A.getHeight(), A.getWidth());
1776  } catch (const vpException &me) {
1777  std::cout << me << std::endl;
1778  throw;
1779  }
1780 
1781  if ((A.getWidth() != B.getWidth()) || (A.getHeight() != B.getHeight())) {
1782  throw(vpException(vpException::memoryAllocationError, "vpImage mismatch in vpImage/vpImage substraction "));
1783  }
1784 
1785  for (unsigned int i = 0; i < A.getWidth() * A.getHeight(); i++) {
1786  *(C.bitmap + i) = *(A.bitmap + i) - *(B.bitmap + i);
1787  }
1788 }
1789 
1800 template <class Type> void vpImage<Type>::performLut(const Type (&)[256], const unsigned int)
1801 {
1802  std::cerr << "Not implemented !" << std::endl;
1803 }
1804 
1813 template <>
1814 inline void vpImage<unsigned char>::performLut(const unsigned char (&lut)[256], const unsigned int nbThreads)
1815 {
1816  unsigned int size = getWidth() * getHeight();
1817  unsigned char *ptrStart = (unsigned char *)bitmap;
1818  unsigned char *ptrEnd = ptrStart + size;
1819  unsigned char *ptrCurrent = ptrStart;
1820 
1821  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
1822 #if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
1823  use_single_thread = true;
1824 #endif
1825 
1826  if (!use_single_thread && getSize() <= nbThreads) {
1827  use_single_thread = true;
1828  }
1829 
1830  if (use_single_thread) {
1831  // Single thread
1832 
1833  while (ptrCurrent != ptrEnd) {
1834  *ptrCurrent = lut[*ptrCurrent];
1835  ++ptrCurrent;
1836  }
1837  } else {
1838 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
1839  // Multi-threads
1840 
1841  std::vector<vpThread *> threadpool;
1842  std::vector<ImageLut_Param_t *> imageLutParams;
1843 
1844  unsigned int image_size = getSize();
1845  unsigned int step = image_size / nbThreads;
1846  unsigned int last_step = image_size - step * (nbThreads - 1);
1847 
1848  for (unsigned int index = 0; index < nbThreads; index++) {
1849  unsigned int start_index = index * step;
1850  unsigned int end_index = (index + 1) * step;
1851 
1852  if (index == nbThreads - 1) {
1853  end_index = start_index + last_step;
1854  }
1855 
1856  ImageLut_Param_t *imageLut_param = new ImageLut_Param_t(start_index, end_index, bitmap);
1857  memcpy(imageLut_param->m_lut, lut, 256 * sizeof(unsigned char));
1858 
1859  imageLutParams.push_back(imageLut_param);
1860 
1861  // Start the threads
1862  vpThread *imageLut_thread = new vpThread((vpThread::Fn)performLutThread, (vpThread::Args)imageLut_param);
1863  threadpool.push_back(imageLut_thread);
1864  }
1865 
1866  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1867  // Wait until thread ends up
1868  threadpool[cpt]->join();
1869  }
1870 
1871  // Delete
1872  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1873  delete threadpool[cpt];
1874  }
1875 
1876  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
1877  delete imageLutParams[cpt];
1878  }
1879 #endif
1880  }
1881 }
1882 
1891 template <> inline void vpImage<vpRGBa>::performLut(const vpRGBa (&lut)[256], const unsigned int nbThreads)
1892 {
1893  unsigned int size = getWidth() * getHeight();
1894  unsigned char *ptrStart = (unsigned char *)bitmap;
1895  unsigned char *ptrEnd = ptrStart + size * 4;
1896  unsigned char *ptrCurrent = ptrStart;
1897 
1898  bool use_single_thread = (nbThreads == 0 || nbThreads == 1);
1899 #if !defined(VISP_HAVE_PTHREAD) && !defined(_WIN32)
1900  use_single_thread = true;
1901 #endif
1902 
1903  if (!use_single_thread && getSize() <= nbThreads) {
1904  use_single_thread = true;
1905  }
1906 
1907  if (use_single_thread) {
1908  // Single thread
1909  while (ptrCurrent != ptrEnd) {
1910  *ptrCurrent = lut[*ptrCurrent].R;
1911  ++ptrCurrent;
1912 
1913  *ptrCurrent = lut[*ptrCurrent].G;
1914  ++ptrCurrent;
1915 
1916  *ptrCurrent = lut[*ptrCurrent].B;
1917  ++ptrCurrent;
1918 
1919  *ptrCurrent = lut[*ptrCurrent].A;
1920  ++ptrCurrent;
1921  }
1922  } else {
1923 #if defined(VISP_HAVE_PTHREAD) || (defined(_WIN32) && !defined(WINRT_8_0))
1924  // Multi-threads
1925  std::vector<vpThread *> threadpool;
1926  std::vector<ImageLutRGBa_Param_t *> imageLutParams;
1927 
1928  unsigned int image_size = getSize();
1929  unsigned int step = image_size / nbThreads;
1930  unsigned int last_step = image_size - step * (nbThreads - 1);
1931 
1932  for (unsigned int index = 0; index < nbThreads; index++) {
1933  unsigned int start_index = index * step;
1934  unsigned int end_index = (index + 1) * step;
1935 
1936  if (index == nbThreads - 1) {
1937  end_index = start_index + last_step;
1938  }
1939 
1940  ImageLutRGBa_Param_t *imageLut_param = new ImageLutRGBa_Param_t(start_index, end_index, (unsigned char *)bitmap);
1941  memcpy(imageLut_param->m_lut, lut, 256 * sizeof(vpRGBa));
1942 
1943  imageLutParams.push_back(imageLut_param);
1944 
1945  // Start the threads
1946  vpThread *imageLut_thread = new vpThread((vpThread::Fn)performLutRGBaThread, (vpThread::Args)imageLut_param);
1947  threadpool.push_back(imageLut_thread);
1948  }
1949 
1950  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1951  // Wait until thread ends up
1952  threadpool[cpt]->join();
1953  }
1954 
1955  // Delete
1956  for (size_t cpt = 0; cpt < threadpool.size(); cpt++) {
1957  delete threadpool[cpt];
1958  }
1959 
1960  for (size_t cpt = 0; cpt < imageLutParams.size(); cpt++) {
1961  delete imageLutParams[cpt];
1962  }
1963 #endif
1964  }
1965 }
1966 
1967 template <class Type> void swap(vpImage<Type> &first, vpImage<Type> &second)
1968 {
1969  using std::swap;
1970  swap(first.bitmap, second.bitmap);
1971  swap(first.display, second.display);
1972  swap(first.npixels, second.npixels);
1973  swap(first.width, second.width);
1974  swap(first.height, second.height);
1975  swap(first.row, second.row);
1976 }
1977 
1978 #endif
void quarterSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1327
unsigned int getCols() const
Definition: vpImage.h:169
vpDisplay * display
Definition: vpImage.h:134
void doubleSizeImage(vpImage< Type > &res)
Definition: vpImage.h:1370
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:171
void * Return
Definition: vpThread.h:78
double get_i() const
Definition: vpImagePoint.h:204
unsigned int getWidth() const
Definition: vpImage.h:239
void init(unsigned int height, unsigned int width)
Set the size of the image.
Definition: vpImage.h:660
Type operator()(const unsigned int i, const unsigned int j) const
Definition: vpImage.h:270
void getMinMaxValue(Type &min, Type &max) const
Look for the minimum and the maximum value within the bitmap.
Definition: vpImage.h:1000
Type * bitmap
points toward the bitmap
Definition: vpImage.h:133
Type operator()(const vpImagePoint &ip) const
Definition: vpImage.h:288
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:982
Type * operator[](const unsigned int i)
operator[] allows operation like I[i] = x.
Definition: vpImage.h:256
virtual ~vpImage()
destructor
Definition: vpImage.h:920
static int round(const double x)
Definition: vpMath.h:235
double get_j() const
Definition: vpImagePoint.h:215
vpImage< Type > & operator=(vpImage< Type > other)
Copy operator.
Definition: vpImage.h:1074
Definition: vpRGBa.h:66
double getSum() const
Definition: vpImage.h:1698
unsigned int getRows() const
Definition: vpImage.h:211
void set_i(const double ii)
Definition: vpImagePoint.h:167
Type getValue(unsigned int i, unsigned int j) const
Definition: vpImage.h:1420
friend void swap(vpImage< Type > &first, vpImage< Type > &second)
Definition: vpImage.h:1967
void *(* Fn)(Args)
Definition: vpThread.h:79
unsigned int getSize() const
Definition: vpImage.h:219
bool operator!=(const vpImage< Type > &I)
Definition: vpImage.h:1129
void * Args
Definition: vpThread.h:77
Memory allocation error.
Definition: vpException.h:88
void operator()(const vpImagePoint &ip, const Type &v)
Definition: vpImage.h:304
Type getMaxValue() const
Return the maximum value within the bitmap.
Definition: vpImage.h:954
const Type * operator[](int i) const
Definition: vpImage.h:261
unsigned int getNumberOfPixel() const
Definition: vpImage.h:201
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:866
void insert(const vpImage< Type > &src, const vpImagePoint &topLeft)
Definition: vpImage.h:1188
void destroy()
Destructor : Memory de-allocation.
Definition: vpImage.h:895
const Type * operator[](unsigned int i) const
operator[] allows operation like x = I[i]
Definition: vpImage.h:260
void set_j(const double jj)
Definition: vpImagePoint.h:178
void subsample(unsigned int v_scale, unsigned int h_scale, vpImage< Type > &sampled) const
Definition: vpImage.h:1293
void halfSizeImage(vpImage< Type > &res) const
Definition: vpImage.h:1265
Type * operator[](const int i)
Definition: vpImage.h:257
vpImage< Type > operator-(const vpImage< Type > &B)
Definition: vpImage.h:1170
Type getMeanValue() const
Return the mean value of the bitmap.
Definition: vpImage.h:969
#define vpDEBUG_TRACE
Definition: vpDebug.h:487
unsigned int getHeight() const
Definition: vpImage.h:178
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:1036
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
void operator()(const unsigned int i, const unsigned int j, const Type &v)
Definition: vpImage.h:276
void performLut(const Type(&lut)[256], const unsigned int nbThreads=1)
Definition: vpImage.h:1800
vpImage()
constructor
Definition: vpImage.h:842
Definition of the vpImage class member functions.
Definition: vpImage.h:116
bool operator==(const vpImage< Type > &I)
Definition: vpImage.h:1106
void sub(const vpImage< Type > &B, vpImage< Type > &C)
Definition: vpImage.h:1739
void set_ij(const double ii, const double jj)
Definition: vpImagePoint.h:189