Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Image.cpp
1 /* This file is part of the BIAS library (Basic ImageAlgorithmS).
2 
3  Copyright (C) 2003-2009 (see file CONTACT for details)
4  Multimediale Systeme der Informationsverarbeitung
5  Institut fuer Informatik
6  Christian-Albrechts-Universitaet Kiel
7 
8 
9  BIAS is free software; you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation; either version 2.1 of the License, or
12  (at your option) any later version.
13 
14  BIAS is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with BIAS; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
22 #include "Image.hh"
23 // tell WIN32 to define math-constants
24 //--- math.h is included by <complex>
25 #include <Base/Common/W32Compat.hh>
26 #include <typeinfo>
27 
28 #include <assert.h>
29 #include <stdio.h>
30 #include <limits.h>
31 #include <typeinfo>
32 #include <string>
33 #include <Base/Common/BIASpragma.hh>
34 #include <Base/Debug/Error.hh>
35 
36 //disables warning C4756: overflow in constant arithmetic in line 1132, function: InvertValues
37 #ifdef WIN32
38 #pragma warning (disable: 4756)
39 #endif
40 
41 using namespace BIAS;
42 using namespace std;
43 
44 namespace BIAS {
45 
46 template<class StorageType>
49 {}
50 
51 template<>
54 {
55 #ifdef BIAS_DEBUG
56  BIASGDOUT(D_IMAGE_TRACE, "called Image<unsigned char>::Image()");
57 #endif
59  Depth_ = sizeof(unsigned char);
60  BitDepth_ = 8 * Depth_;
61 }
62 
63 
64 template<>
67 {
68 #ifdef BIAS_DEBUG
69  BIASGDOUT(D_IMAGE_TRACE, "called Image<float>::Image()");
70 #endif
72  Depth_ = sizeof(float);
73  BitDepth_ = 8 * Depth_;
74 }
75 
76 
77 #ifdef BUILD_IMAGE_SHORT
78 template<>
81 {
83  Depth_ = sizeof(short int);
84  BitDepth_ = 8 * Depth_;
85 }
86 #endif // BUILD_IMAGE_SHORT
87 
88 
89 template<class StorageType>
92 {
93  BIASERR("invalid StorageType, necessary instance of image not compiled:"
94  <<PRINTTYPE(StorageType));
95  //BIASABORT
96 }
97 
98 template<>
100 Image(const ImageBase& im) : ImageBase()
101 {
102 #ifdef BIAS_DEBUG
103  BIASGDOUT(D_IMAGE_TRACE,
104  "called Image<uchar>::Image(const ImageBase& Source)");
105 #endif
107  Depth_ = sizeof(unsigned char);
108  BitDepth_ = 8 * Depth_;
109  if (GetStorageType() != StorageType_)
110  {
111  BIASERR("You tried to construct Image<unsigned char> from "
112  <<" ImageBase with StorageType "<<im.GetStorageType()
113  <<". Aborting.");
114  BIASABORT;
115  }
116  this->ImageBase::operator=(im);
117 }
118 
119 template<>
121 Image(const ImageBase& im) : ImageBase()
122 {
123 #ifdef BIAS_DEBUG
124  BIASGDOUT(D_IMAGE_TRACE,
125  "called Image<float>::Image(const ImageBase& Source)");
126 #endif
128  Depth_ = sizeof(float);
129  BitDepth_ = 8 * Depth_;
130  if (GetStorageType() != StorageType_)
131  {
132  BIASERR("You tried to construct Image<float> from "
133  <<" ImageBase with StorageType "<<im.GetStorageType()
134  <<". Aborting.");
135  BIASABORT;
136  }
137  this->ImageBase::operator=(im);
138 }
139 
140 template<class StorageType>
142 Image(const ImageBase& im) : ImageBase()
143 {
144  // this is the generic implementation which must NEVER be called !
145  BIASERR("You tried to construct Image<"<<PRINTTYPE(StorageType)<<"> from "
146  <<" ImageBase with StorageType "<<im.GetStorageType()
147  <<". Not implemented for that type. Aborting.");
148  BIASABORT;
149 }
150 
151 
152 template<class StorageType>
154 Image(unsigned int Width, unsigned int Height,
155  unsigned int channels, bool interleaved)
156 {
157  BIASERR("invalid StorageType="<<PRINTTYPE(StorageType));
158  BIASABORT;
159 }
160 
161 
162 template<>
164 Image(unsigned int Width, unsigned int Height,
165  unsigned int Channels, bool interleaved)
166 {
167 #ifdef BIAS_DEBUG
168  BIASGDOUT(D_IMAGE_TRACE,
169  "called Image<uchar>::Image(width,height,channels,interl)");
170 #endif
171  StorageType_ = ST_unsignedchar;
172  ImageBase::Init(Width, Height, Channels, StorageType_, interleaved);
173 }
174 
175 
176 template<>
178 Image(unsigned int Width, unsigned int Height,
179  unsigned int Channels, bool interleaved)
180 {
181 #ifdef BIAS_DEBUG
182  BIASGDOUT(D_IMAGE_TRACE,
183  "called Image<float>::Image(width,height,channels,interl)");
184 #endif
185  StorageType_ = ST_float;
186  ImageBase::Init(Width, Height, Channels, StorageType_, interleaved);
187 }
188 
189 
190 #ifdef BUILD_IMAGE_CHAR
191 template<>
194 {
196  Depth_ = sizeof(char);
197  BitDepth_ = 8 * Depth_;
198 }
199 
200 
201 template<>
203 Image(const ImageBase& im) : ImageBase()
204 {
206  Depth_ = sizeof(char);
207  BitDepth_ = 8 * Depth_;
208  if (GetStorageType() != StorageType_)
209  {
210  BIASERR("You tried to construct Image<char> from "
211  <<" ImageBase with StorageType "<<im.GetStorageType()
212  <<". Aborting.");
213  BIASABORT;
214  }
215  this->ImageBase::operator=(im);
216 }
217 
218 
219 template<>
221 Image(unsigned int Width, unsigned int Height,
222  unsigned int Channels, bool interleaved)
223 {
224  StorageType_ = ST_char;
225  ImageBase::Init(Width, Height, Channels, StorageType_, interleaved);
226 }
227 #endif
228 
229 
230 #ifdef BUILD_IMAGE_USHORT
231 template<>
234 {
236  Depth_ = sizeof(unsigned short int);
237  BitDepth_ = 8 * Depth_;
238 }
239 
240 
241 template<>
243 Image(const ImageBase& im) : ImageBase()
244 {
246  Depth_ = sizeof(unsigned short int);
247  BitDepth_ = 8 * Depth_;
248  if (GetStorageType() != StorageType_)
249  {
250  BIASERR("You tried to construct Image<unsigned short int> from "
251  <<" ImageBase with StorageType "<<im.GetStorageType()
252  <<". Aborting.");
253  BIASABORT;
254  }
255  this->ImageBase::operator=(im);
256 }
257 
258 
259 template<>
261 Image(unsigned int Width, unsigned int Height,
262  unsigned int Channels, bool interleaved)
263 {
264  StorageType_ = ST_unsignedshortint;
265  ImageBase::Init(Width, Height, Channels, StorageType_, interleaved);
266 }
267 #endif // BUILD_IMAGE_USHORT
268 
269 
270 #ifdef BUILD_IMAGE_SHORT
271 template<>
273 Image(const ImageBase& im) : ImageBase()
274 {
276  Depth_ = sizeof(short int);
277  BitDepth_ = 8 * Depth_;
278  if (GetStorageType() != StorageType_)
279  {
280  BIASERR("You tried to construct Image<short int> from "
281  <<" ImageBase with StorageType "<<im.GetStorageType()
282  <<". Aborting.");
283  BIASABORT;
284  }
285  this->ImageBase::operator=(im);
286 }
287 
288 
289 template<>
291 Image(unsigned int Width, unsigned int Height,
292  unsigned int Channels, bool interleaved)
293 {
294  StorageType_ = ST_shortint;
295  ImageBase::Init(Width, Height, Channels, StorageType_, interleaved);
296 }
297 #endif
298 
299 
300 #ifdef BUILD_IMAGE_UINT
301 template<>
304 {
306  Depth_ = sizeof(unsigned int);
307  BitDepth_ = 8 * Depth_;
308 }
309 
310 
311 template<>
313 Image(const ImageBase& im) : ImageBase()
314 {
316  Depth_ = sizeof(unsigned int);
317  BitDepth_ = 8 * Depth_;
318  if (GetStorageType() != StorageType_)
319  {
320  BIASERR("You tried to construct Image<unsigned int> from "
321  <<" ImageBase with StorageType "<<im.GetStorageType()
322  <<". Aborting.");
323  BIASABORT;
324  }
325  this->ImageBase::operator=(im);
326 }
327 
328 
329 template<>
331 Image(unsigned int Width, unsigned int Height,
332  unsigned int Channels, bool interleaved)
333 {
334  StorageType_ = ST_unsignedint;
335  ImageBase::Init(Width, Height, Channels, StorageType_, interleaved);
336 }
337 #endif
338 
339 #ifdef BUILD_IMAGE_INT
340 template<>
343 {
345  Depth_ = sizeof(int);
346  BitDepth_ = 8 * Depth_;
347 }
348 
349 
350 template<>
352 Image(const ImageBase& im) : ImageBase()
353 {
355  Depth_ = sizeof(int);
356  BitDepth_ = 8 * Depth_;
357  if (GetStorageType() != StorageType_)
358  {
359  BIASERR("You tried to construct Image<int> from "
360  <<" ImageBase with StorageType "<<im.GetStorageType()
361  <<". Aborting.");
362  BIASABORT;
363  }
364  this->ImageBase::operator=(im);
365 }
366 
367 
368 template<>
370 Image(unsigned int Width, unsigned int Height,
371  unsigned int Channels, bool interleaved)
372 {
373  StorageType_ = ST_int;
374  ImageBase::Init(Width, Height, Channels, StorageType_, interleaved);
375 }
376 #endif
377 
378 
379 #ifdef BUILD_IMAGE_DOUBLE
380 template<>
383 {
385  Depth_ = sizeof(double);
386  BitDepth_ = 8 * Depth_;
387 }
388 
389 
390 template<>
392 Image(const ImageBase& im) : ImageBase()
393 {
395  Depth_ = sizeof(double);
396  BitDepth_ = 8 * Depth_;
397  if (GetStorageType() != StorageType_)
398  {
399  BIASERR("You tried to construct Image<double> from "
400  <<" ImageBase with StorageType "<<im.GetStorageType()
401  <<". Aborting.");
402  BIASABORT;
403  }
404  this->ImageBase::operator=(im);
405 }
406 
407 
408 template<>
410 Image(unsigned int Width, unsigned int Height,
411  unsigned int Channels, bool interleaved)
412 {
413  StorageType_ = ST_double;
414  ImageBase::Init(Width, Height, Channels, StorageType_, interleaved);
415 }
416 #endif
417 
418 
419 template<class StorageType>
421 Init(unsigned int Width, unsigned int Height,
422  unsigned int Channels, enum EStorageType storType, bool interleaved)
423 {
424  // StorageType_ is set from constructor
425  ImageBase::Init(Width, Height, Channels, StorageType_, interleaved);
426 }
427 
428 
429 template<class StorageType>
430 std::ostream &Image<StorageType>::
431 PrintPointer(std::ostream& os) const
432 {
433  BIASASSERT(ImageData_ != NULL);BIASASSERT(ImageDataArray_ != NULL);
434  os << "\nImageData_: \t\t" << (void *) GetImageData()
435  << "\nimageDataArray_: \t" << (void *) (GetImageDataArray()[0]);
436  return os;
437 }
438 
439 
440 template<class StorageType>
441 std::ostream& Image<StorageType>::
442 PrintData(std::ostream& os) const
443 {
444  BIASASSERT(ImageData_ != NULL);
445  os << "\nImageData_: \t\t" << GetImageData() << endl;
446  for (unsigned long int i = 0; i < GetPixelCount(); i++)
447  os << ((StorageType *) GetImageData())[i] << " ";
448  // << (int)GetImageData()[i] << " ";
449  os << endl;
450  return os;
451 }
452 
453 
454 template<class StorageType>
456 FillImageWithConstValue(StorageType Value)
457 {
458  int minx, miny, maxx, maxy, cc = GetChannelCount();
459  GetROI()->GetCorners(minx, miny, maxx, maxy);
460  minx *= cc;
461  maxx *= cc;
462  register int width = (int) GetWidth() * cc, step = width - maxx + minx;
463  // beginning of ROI
464  register StorageType *p = GetImageData() + width * miny + minx;
465  // end of first row of ROI
466  register StorageType *le = GetImageData() + width * miny + maxx;
467  // end of last row of ROI
468  register StorageType *e = GetImageData() + width * (maxy - 1) + maxx;
469  // int x=0, y=0;
470  while (p < e)
471  {
472  while (p < le)
473  { // walk width of ROI in one line
474  *p++ = Value;
475  //x++;
476  }
477  //y++; x=0;
478  le += width; // set line end pointer one line further down
479  p += step; // skip to beginning of ROI in next line
480  }
481 }
482 
483 
484 template<class StorageType>
486 FillImageWithConstValue(StorageType Value[])
487 {
488  int minx, miny, maxx, maxy, i;
489  register int cc = GetChannelCount();
490  GetROI()->GetCorners(minx, miny, maxx, maxy);
491  if (IsInterleaved())
492  {
493  minx *= cc;
494  maxx *= cc;
495  register int width = (int) GetWidth() * cc, step = width - maxx
496  + minx;
497  // beginning of ROI
498  register StorageType *p = GetImageData() + width * miny + minx;
499  // end of first row of ROI
500  register StorageType *le = GetImageData() + width * miny + maxx;
501  // end of last row of ROI
502  register StorageType *e = GetImageData() + width * (maxy - 1) + maxx;
503  // int x=0, y=0;
504  while (p < e)
505  {
506  while (p < le)
507  { // walk width of ROI in one line
508  for (i = 0; i < cc; i++)
509  *p++ = Value[i];
510  }
511  //y++; x=0;
512  le+=width; // set line end pointer one line further down
513  p+=step; // skip to beginning of ROI in next line
514  }
515  }
516  else
517  {
518  for (int i = 0; i < cc; i++)
519  {
520  register int width = (int) GetWidth(), step = width - maxx + minx;
521  // beginning of ROI
522  register StorageType *p = GetImageData() + i * GetPixelCount()
523  + width * miny + minx;
524  // end of first row of ROI
525  register StorageType *le = GetImageData() + i * GetPixelCount()
526  + width * miny + maxx;
527  // end of last row of ROI
528  register StorageType *e = GetImageData() + i * GetPixelCount()
529  + width * (maxy - 1) + maxx;
530  // int x=0, y=0;
531  while (p < e)
532  {
533  while (p < le)
534  { // walk width of ROI in one line
535  *p++ = Value[i];
536  }
537  //y++; x=0;
538  le += width; // set line end pointer one line further down
539  p += step; // skip to beginning of ROI in next line
540  }
541  }
542  }
543  }
544 
545 template<class StorageType>
547 ClearChannel(const unsigned int channel, const StorageType value)
548 {
549  int minx=0, miny=0, maxx=0, maxy=0, i=0;
550  register int cc = GetChannelCount();
551  GetROI()->GetCorners(minx, miny, maxx, maxy);
552  if (IsInterleaved())
553  {
554  minx *= cc;
555  maxx *= cc;
556  register int width = (int) GetWidth() * cc, step = width - maxx + minx;
557  // beginning of ROI
558  register StorageType *p = GetImageData() + width * miny + minx + channel;
559  // end of first row of ROI
560  register StorageType *le = GetImageData() + width * miny + maxx;
561  // end of last row of ROI
562  register StorageType *e = GetImageData() + width * (maxy - 1) + maxx;
563  // int x=0, y=0;
564  while (p < e)
565  {
566  while (p < le)
567  { // walk width of ROI in one line
568  //for (i = 0; i < cc; i++)
569  *p = value;
570  p+=cc;
571  }
572  //y++; x=0;
573  le+=width; // set line end pointer one line further down
574  p+=step; // skip to beginning of ROI in next line
575  }
576  }
577  else
578  {
579 
580  register int width = (int) GetWidth(), step = width - maxx + minx;
581  // beginning of ROI
582  register StorageType *p = GetImageData() + i * GetPixelCount()
583  + width * miny + minx;
584  // end of first row of ROI
585  register StorageType *le = GetImageData() + i * GetPixelCount()
586  + width * miny + maxx;
587  // end of last row of ROI
588  register StorageType *e = GetImageData() + i * GetPixelCount()
589  + width * (maxy - 1) + maxx;
590  // int x=0, y=0;
591  while (p < e)
592  {
593  while (p < le)
594  { // walk width of ROI in one line
595  *p++ = value;
596  }
597  //y++; x=0;
598  le += width; // set line end pointer one line further down
599  p += step; // skip to beginning of ROI in next line
600  }
601 
602  }
603 }
604 
605 
606  template<class StorageType>
607  void
609  {
610  StorageType *p = GetImageData();
611 
612  for (unsigned int y = 0; y < GetHeight(); y++)
613  {
614  for (unsigned int x = 0; x < GetWidth(); x++)
615  {
616  p[y * GetWidth() + x] = StorageType(x);
617  }
618  }
619  }
620 
621  template<class StorageType>
622  void
624  {
625  if (IsInterleaved())
626  {
627  register const unsigned cc = GetChannelCount();
628  register unsigned int i;
629  double *sum = new double[cc];
630  for (i = 0; i < cc; i++)
631  sum[i] = 0.0;
632  int minx, miny, maxx, maxy;
633  GetROI()->GetCorners(minx, miny, maxx, maxy);
634  register double pc = (double) ((maxx - minx) * (maxy - miny));
635  minx *= cc;
636  maxx *= cc;
637  register int width = (int) GetWidth() * cc, step = width - maxx
638  + minx;
639  // beginning of ROI
640  register StorageType *p = GetImageData() + width * miny + minx;
641  // end of first row of ROI
642  register StorageType *le = GetImageData() + width * miny + maxx;
643  // end of last row of ROI
644  register StorageType *e = GetImageData() + width * (maxy - 1) + maxx;
645  // int x=0, y=0;
646  while (p < e)
647  {
648  while (p < le)
649  { // walk width of ROI in one line
650  for (i = 0; i < cc; i++)
651  sum[i] += (double) p[i];
652  p += cc;
653  }
654  le += width; // set line end pointer one line further down
655  p += step; // skip to beginning of ROI in next line
656  }
657 
658  for (i = 0; i < cc; i++)
659  mean[i] = (StorageType)(sum[i] / pc);
660  delete[] sum;
661  }
662  else
663  {
664  BIASERR("GetMeanPixelValue not implemented for planar images ");
665  }
666  }
667 
668  /////////////////////////////////////////////////////////////////////////////////
669  template<class StorageType>
670  void
672  const StorageType ignoreStart, const StorageType ignoreEnd) const
673  {
674  if (IsInterleaved())
675  {
676  register const unsigned cc = GetChannelCount();
677  register unsigned int i;
678  double *sum = new double[cc];
679  double *pc = new double[cc];
680  for (i = 0; i < cc; i++){
681  sum[i] = 0.0;
682  pc[i] = 0.0;
683  }
684 
685  int minx, miny, maxx, maxy;
686  GetROI()->GetCorners(minx, miny, maxx, maxy);
687  minx *= cc;
688  maxx *= cc;
689  register int width = (int) GetWidth() * cc, step = width - maxx + minx;
690  // beginning of ROI
691  const register StorageType *p = GetImageData() + width * miny + minx;
692  // end of first row of ROI
693  const register StorageType *le = GetImageData() + width * miny + maxx;
694  // end of last row of ROI
695  const register StorageType *e = GetImageData() + width * (maxy - 1) + maxx;
696  // int x=0, y=0;
697  while (p < e)
698  {
699  while (p < le)
700  { // walk width of ROI in one line
701  for (i = 0; i < cc; i++){
702  if(p[i] < ignoreStart || p[i] > ignoreEnd){
703  sum[i] += (double) p[i];
704  pc[i]++;
705  }
706  }
707  p += cc;
708  }
709  le += width; // set line end pointer one line further down
710  p += step; // skip to beginning of ROI in next line
711  }
712 
713  for (i = 0; i < cc; i++)
714  mean[i] = (StorageType)(sum[i] / pc[i]);
715  delete[] sum;
716  }
717  else
718  {
719  BIASERR("GetMeanPixelValue not implemented for planar images ");
720  }
721  }
722 
723  /////////////////////////////////////////////////////////////////////////////////
724  // JW 01/2003
725  template<class StorageType>
726  bool
728  StorageType& max, const StorageType ignoreStart,
729  const StorageType ignoreEnd, const unsigned short int channel) const
730  {
731 #ifdef BIAS_DEBUG
732  // test if this implementation is suitable...
733  if (IsEmpty())
734  BIASERR("Image<StorageType>::GetMinMaxPixelValueIgnoreZero() image is empty");
735 
736  if (channel> (GetChannelCount() - 1))
737  BIASERR("Image<StorageType>::GetMinMaxPixelValueIgnoreZero() invalid channel");
738 
739  if ((!IsPlanar()) )
740  {
741  if (GetChannelCount()!=1)
742  {
743  BIASERR("Image<StorageType>::GetMinMaxPixelValueIgnoreZero() not yet implemented for interleaved multi channel images");
744  BIASERR("ChannelCount: "<<GetChannelCount());
745  BIASERR("IsPlanar: "<<IsPlanar() );
746  };
747  };
748  unsigned minx, miny, maxx, maxy;
749  GetROI()->GetCorners(minx, miny, maxx, maxy);
750  if (minx!=0 || miny!=0 || maxx!=GetWidth() || maxy!=GetHeight())
751  BIASERR("Image<StorageType>::GetMinMaxPixelValueIgnoreZero() not implemented for ROI!");
752 #endif
753 
754  // OK, work...
755  // Planar implementation:
756 
757  const StorageType *p_act, *p_end; // pointer to actual and end position in image data.
758 
759  p_act = GetImageData() + channel * GetPixelCount(); // pointer to start of data
760  p_end = p_act + GetPixelCount(); // pointer to end of data
761  min = 0;
762  max = 0;
763  bool foundInRange = false;
764  while ((!foundInRange) && (p_act != p_end))
765  { // while no legal value found and pixels left..
766  if((*p_act < ignoreStart) || (*p_act > ignoreEnd))
767  {
768  // found value out of ignore range, use it as initial min/max
769  min = *p_act;
770  max = *p_act;
771  foundInRange = true;
772  };
773  p_act++;
774  };
775  if(!foundInRange) return foundInRange;
776 
777  // initial valid min and max are set, find 'better' in the rest of the plane:
778  for (; p_act != p_end; p_act++)
779  {
780  // check if new min found:
781  // min and max can't be changed at once!
782  if (*p_act < min)
783  {
784  if ((*p_act < ignoreStart) || (*p_act > ignoreEnd))
785  {
786  min = *p_act; // found
787  };
788  }
789  else if (*p_act > max)
790  {
791  if((*p_act < ignoreStart) || (*p_act > ignoreEnd))
792  {
793  max = *p_act; // found
794  };
795  };
796  }; // found min and max for planar image
797  return foundInRange; // return if any value within range was found
798  }
799 
800  template<class StorageType>
801  void
802  Image<StorageType>::GetMinMaxPixelValue(StorageType& min, StorageType& max,
803  unsigned short int channel, unsigned int *mincoo, unsigned int *maxcoo) const
804  {
805  register int ChannelCount = GetChannelCount();
806  // register StorageType *ImageDataPointer, *EndImageData;
807  // register unsigned int x, y;
808 #ifdef BIAS_DEBUG
809  if (IsEmpty())
810  BIASERR("Image<StorageType>::GetMinMaxPixelValue() image is empty");
811  if (channel> (ChannelCount - 1))
812  BIASERR("Image<StorageType>::GetMinMaxPixelValue() inavlid channel");
813  if ( (GetColorModel() != CM_RGB) && (GetColorModel() != CM_BGR) &&
814  (GetColorModel() != CM_Grey) && (GetColorModel() != CM_HSV) &&
815  (GetColorModel() != CM_RGBA) &&
816  (GetColorModel() != CM_Bayer_RGGB) &&
817  (GetColorModel() != CM_Bayer_GBRG) &&
818  (GetColorModel() != CM_Bayer_GRBG) &&
819  (GetColorModel() != CM_Bayer_BGGR) &&
820  (GetColorModel() != CM_Depth) &&
821  (GetColorModel() != CM_DepthAndVariance) &&
822  (GetColorModel() != CM_Disparity))
823  BIASERR("Image<StorageType>::GetMinMaxPixelValue() not implemented"
824  <<" for this colormodel");
825 #endif
826  unsigned minx, miny, maxx, maxy;
827  GetROI()->GetCorners(minx, miny, maxx, maxy);
828  const StorageType **ida = GetImageDataArray();
829 
830  if (IsInterleaved())
831  {
832  BIASCDOUT(D_IMAGE_MINMAXCOO," interleaved ("<<minx<<", "<<miny<<") <--> ("
833  <<maxx<<", "<<maxy<<")\n");
834  unsigned cc = ChannelCount;
835  BIASASSERT(ida[miny]!=NULL);
836  min = max = ida[miny][minx * cc + channel];
837  const unsigned mmaxx = maxx * cc;
838  if (mincoo != NULL || maxcoo != NULL)
839  { // remember coordinates
840  BIASCDOUT(D_IMAGE_MINMAXCOO, "remember coordinates\n");
841  if (mincoo)
842  {
843  mincoo[0] = minx;
844  mincoo[1] = miny;
845  }
846  if (maxcoo)
847  {
848  maxcoo[0] = minx;
849  maxcoo[1] = miny;
850  }
851  for (unsigned y = miny; y < maxy; y++)
852  {
853  for (unsigned x = minx * cc + channel; x < mmaxx; x += cc)
854  {
855  if (ida[y][x] > max)
856  {
857  max = ida[y][x];
858  if (maxcoo)
859  {
860  maxcoo[0] = (x - channel) / cc;
861  maxcoo[1] = y;
862  }
863  }
864  else if (ida[y][x] < min)
865  {
866  min = ida[y][x];
867  if (mincoo)
868  {
869  mincoo[0] = (x - channel) / cc;
870  mincoo[1] = y;
871  }
872  }
873  }
874  }
875  }
876  else
877  { // no need to remeber coordinates
878  BIASCDOUT(D_IMAGE_MINMAXCOO, "don't remember coordinates\n");
879  for (unsigned y = miny; y < maxy; y++)
880  {
881  BIASASSERT(ida[y]!=NULL);
882  for (unsigned x = minx * cc + channel; x < mmaxx; x += cc)
883  {
884  //cout<<" ("<<(x-channel)/cc<<", "<<y<<"):" <<(int)(ida[y][x])<<flush;
885  /// @bug NULL pointer exception occurs, here (e.g. in fuse) JW
886  if (ida[y][x] > max)
887  max = ida[y][x];
888  if (ida[y][x] < min)
889  min = ida[y][x];
890  }
891  }
892  }
893  }
894  else
895  { // planar image
896  BIASCDOUT(D_IMAGE_MINMAXCOO," planar ("<<minx<<", "<<miny<<") <--> ("
897  <<maxx<<", "<<maxy<<")\n");
898  const StorageType *start = GetImageData() + channel * GetPixelCount()
899  + miny * GetWidth() + minx;
900  const StorageType *mendl = start + maxx - minx;
901  const StorageType *end = GetImageData() + channel * GetPixelCount()
902  + (maxy - 1) * GetWidth() + maxx;
903  int step = (int) GetWidth() - (int) maxx + (int) minx;
904  int x = minx;
905  int y = miny;
906  const int width = (int) GetWidth();
907  max = min = *start;
908  BIASCDOUT(D_IMAGE_MINMAXCOO, "starting with min: "<< (int)min <<"\tmax: "
909  << (int)max <<endl);
910  if (mincoo != NULL || maxcoo != NULL)
911  { // remember coordinates
912  BIASCDOUT(D_IMAGE_MINMAXCOO, "remember coordinates\n");
913  if (mincoo)
914  {
915  mincoo[0] = minx;
916  mincoo[1] = miny;
917  }
918  if (maxcoo)
919  {
920  maxcoo[0] = minx;
921  maxcoo[1] = miny;
922  }
923  while (start < end)
924  {
925  while (start < mendl)
926  {
927  //cerr << " ("<<x<<", "<<y<<") " << (int)(*start) << endl;
928  if (*start > max)
929  {
930  max = *start;
931  if (maxcoo)
932  {
933  maxcoo[0] = x;
934  maxcoo[1] = y;
935  }
936  }
937  else if (*start < min)
938  {
939  min = *start;
940  if (mincoo)
941  {
942  mincoo[0] = x;
943  mincoo[1] = y;
944  }
945  }
946  start++;
947  x++;
948  }
949  start += step;
950  mendl += width;
951  y++;
952  x = minx;
953  }
954  }
955  else
956  { // no need to remeber coordinates
957  BIASCDOUT(D_IMAGE_MINMAXCOO, "don't remember coordinates\n");
958  while (start < end)
959  {
960  while (start < mendl)
961  {
962  if (*start > max)
963  max = *start;
964  else if (*start < min)
965  min = *start;
966  start++;
967  }
968  start += step;
969  mendl += width;
970  }
971  }
972  }
973  }
974 
975  template<class StorageType>
976  StorageType
977  Image<StorageType>::GetMinPixelValue(unsigned short int channel,
978  unsigned int *coo) const
979  {
980  StorageType min, max;
981  if (coo == NULL)
982  {
983  GetMinMaxPixelValue(min, max, channel);
984  }
985  else
986  {
987  unsigned int maxcoo[2];
988  GetMinMaxPixelValue(min, max, channel, coo, maxcoo);
989  }
990  return min;
991  }
992 
993  template<class StorageType>
994  StorageType
995  Image<StorageType>::GetMaxPixelValue(unsigned short int channel,
996  unsigned int *coo) const
997  {
998  StorageType min, max;
999  if (coo == NULL)
1000  {
1001  GetMinMaxPixelValue(min, max, channel);
1002  }
1003  else
1004  {
1005  unsigned int mincoo[2];
1006  GetMinMaxPixelValue(min, max, channel, mincoo, coo);
1007  }
1008  return max;
1009  }
1010 
1011  template<class StorageType>
1012  int
1014  StorageType Value)
1015  {
1016  StorageType *p = GetImageData();
1017  unsigned int count = GetPixelCount() * GetChannelCount();
1018  for (register int i = count; i > 0; i--)
1019  {
1020  *p = (*p > Threshold) ? *p : Value;
1021  p++;
1022  }
1023  return 0;
1024  }
1025 
1026  template<class StorageType>
1027  int
1029  StorageType Value)
1030  {
1031  StorageType *p = GetImageData();
1032  unsigned int count = GetPixelCount() * GetChannelCount();
1033  for (register int i = count; i > 0; i--)
1034  {
1035  *p = (*p < Threshold) ? *p : Value;
1036  p++;
1037  }
1038  return 0;
1039  }
1040 
1041  template<class StorageType>
1042  void
1043  Image<StorageType>::Binarize(StorageType threshold)
1044  {
1045  StorageType *ptr, *end;
1046  ptr = end = GetImageData();
1047  end += GetPixelCount();
1048  while (ptr < end)
1049  {
1050  *ptr = (*ptr > threshold) ? (MaxSTValue()) : (MinSTValue());
1051  ptr++;
1052  }
1053  }
1054 
1055  template<class StorageType>
1056  void
1057  Image<StorageType>::Binarise(StorageType threshold)
1058  {
1059  this->Binarize(threshold);
1060  }
1061 
1062  template<class StorageType>
1063  int
1064  Image<StorageType>::ScaleShift(double Scale, double Shift)
1065  {
1066  register StorageType *ImageData = GetImageData();
1067  register StorageType *ImageDataEnd = ImageData + GetPixelCount()
1068  * GetChannelCount();
1069  while (ImageData < ImageDataEnd)
1070  {
1071  *ImageData = (StorageType)(((double) (*ImageData) + Shift) * Scale);
1072  ImageData++;
1073  }
1074  return 0;
1075  }
1076 
1077  template<class StorageType>
1078  int
1079  Image<StorageType>::ScaleShiftChannel(double Scale, double Shift,
1080  unsigned int channel)
1081  {
1082  StorageType *ImageData = GetImageData();
1083  StorageType *ImageDataEnd = ImageData + GetPixelCount()
1084  * GetChannelCount();
1085 
1086  if (channel >= GetChannelCount())
1087  {
1088  BIASERR("Not enough channels.");
1089  return -1;
1090  }
1091 
1092  if (IsPlanar())
1093  {
1094  ImageData += GetPixelCount() * channel;
1095  while (ImageData < ImageData + GetPixelCount() * (channel + 1))
1096  {
1097  *ImageData = (StorageType)(((double) (*ImageData) + Shift)
1098  * Scale);
1099  ImageData++;
1100  }
1101  }
1102  else
1103  {
1104  ImageData += channel;
1105  while (ImageData < ImageDataEnd)
1106  {
1107  *ImageData = (StorageType)(((double) (*ImageData) + Shift)
1108  * Scale);
1109  ImageData += GetChannelCount();
1110  }
1111  }
1112 
1113  return 0;
1114  }
1115 
1116  template<class StorageType>
1117  int
1119  {
1120  register double Scale, Shift;
1121  int res = CalcScaleShift(Min, Max, Scale, Shift);
1122  if (res != 0)
1123  {
1124  BIASWARNONCE("Cannot scale-shift, error in determining numbers.");
1125  return res;
1126  }
1127  res = ScaleShift(Scale, Shift);
1128  return res;
1129  }
1130 
1131  template<class StorageType>
1132  int
1134  {
1135 
1136  int width = GetWidth();
1137  int height = GetHeight();
1138  int channels = GetChannelCount();
1139 
1140  if ((int) result.GetWidth() != height && (int) result.GetHeight()
1141  != width && (int) result.GetChannelCount() != channels)
1142  {
1143  result.Init(height, width, channels);
1144  }
1145 
1146  for (int x = 0; x < width; x++)
1147  {
1148  for (int y = 0; y < height; y++)
1149  {
1150  for (unsigned short ch = 0; ch < channels; ch++)
1151  {
1152  StorageType val = PixelValue(x, y, ch);
1153  result.SetPixel(val, y, x, ch);
1154  }
1155  }
1156  }
1157 
1158  return 0;
1159  }
1160 /////////////////////////////////////////////////////////////////////////
1161 template<class StorageType>
1163 InvertValues(BIAS::Image<StorageType>& inverted, StorageType* newMax)
1164 {
1165  unsigned width = GetWidth();
1166  unsigned height = GetHeight();
1167  unsigned channels = GetChannelCount();
1168  StorageType max=0;
1169  if(newMax != NULL)
1170  max = *newMax;
1171  else if (typeid(StorageType) == typeid(unsigned char))
1172  max = (StorageType)(UCHAR_MAX);
1173  else if(typeid(StorageType) == typeid(float))
1174  max = StorageType(FLT_MAX);
1175  #ifdef BUILD_IMAGE_INT
1176  else if(typeid(StorageType) == typeid(int))
1177  max = StorageType(INT_MAX);
1178  #endif
1179  #ifdef BUILD_IMAGE_CHAR
1180  else if(typeid(StorageType) == typeid(char))
1181  max = StorageType(CHAR_MAX);
1182  #endif
1183  #ifdef BUILD_IMAGE_SHORT
1184  else if(typeid(StorageType) == typeid(short))
1185  max = (StorageType)(SHRT_MAX);
1186  #endif
1187  #if defined(BUILD_IMAGE_USHORT)
1188  else if(typeid(StorageType) == typeid(unsigned short))
1189  max = (StorageType)(USHRT_MAX);
1190  #endif
1191  #ifdef BUILD_IMAGE_DOUBLE
1192  else if(typeid(StorageType) == typeid(double))
1193  max = (StorageType)(DBL_MAX);
1194  #endif
1195  #ifdef BUILD_IMAGE_UINT
1196  else if(typeid(StorageType) == typeid(unsigned int))
1197  max = (StorageType)(UINT_MAX);
1198  #endif
1199 
1200 
1201 
1202 
1203  if (inverted.GetWidth() != height &&inverted.GetHeight()
1204  != width && inverted.GetChannelCount() != channels)
1205  {
1206  inverted.Init(height, width, channels);
1207  }
1208  StorageType ** ida = GetImageDataArray();
1209  StorageType **idaRes = inverted.GetImageDataArray();
1210  for (unsigned int y = 0; y < height; y++){
1211  for (unsigned int x = 0; x < width; x++){
1212  for (unsigned int c = 0; c < channels; c++){
1213  idaRes[y][x] = max - ida[y][x];
1214  }
1215  }
1216  }
1217  return 0;
1218 }
1219  /////////////////////////////////////////////////////////////////////////
1220  template<class StorageType>
1221  int
1222  Image<StorageType>::CalcScaleShift(double Min, double Max, double& Scale,
1223  double &Shift) const
1224  {
1225  StorageType min = 0, max = 0, MinVal = 0, MaxVal = 0;
1226  GetMinMaxPixelValue(MinVal, MaxVal, 0);
1227  for (unsigned int i = 1; i < GetChannelCount(); i++)
1228  {
1229  GetMinMaxPixelValue(min, max, (unsigned short) i);
1230  // unsigned int mincoo[2],maxcoo[2];
1231  // GetMinMaxPixelValue(min, max, (unsigned short)i,mincoo,maxcoo );
1232  // cout <<"Channel "<<i<<" Max: "<<max<<" at: ("<<maxcoo[0]<<","<<maxcoo[1]<<") Min: "<<min<<" at: ("<<mincoo[0]<<","<<mincoo[1]<<")"<<endl;
1233 
1234  if (max > MaxVal)
1235  MaxVal = max;
1236  if (min < MinVal)
1237  MinVal = min;
1238  }
1239 
1240  if ((MaxVal - MinVal) == 0)
1241  {
1242  BIASWARNONCE("Image<StorageType>::CalcScaleShift(): minimum pixelvalue is"
1243  <<" equal to maximum pixel value -> no scaling possible");
1244  return -1;
1245  }
1246  Scale = (double) (Max - Min) / (double) (MaxVal - MinVal);
1247  Shift = (double) (Min - MinVal);
1248 
1249  return 0;
1250  }
1251 
1252  template<class StorageType>
1253  int
1255  StorageType MinValue, StorageType MaxValue)
1256  {
1257  if (GetChannelCount() != 1)
1258  {
1259 #ifdef BIAS_DEBUG
1260  BIASERR("Image<StorageType>::BinaryThreshold(): only greyscale images supported");
1261 #endif
1262  return -1;
1263  }
1264  StorageType** dat = GetImageDataArray();
1265  //unsigned h = GetHeight();
1266  //unsigned w = GetWidth();
1267  unsigned minY = GetROIUpperLeftY();
1268  unsigned uppboundY = GetROILowerRightY();
1269  unsigned minX = GetROIUpperLeftX();
1270  unsigned uppboundX = GetROILowerRightX();
1271  for (unsigned y = minY; y < uppboundY; y++)
1272  {
1273  for (unsigned x = minX; x < uppboundX; x++)
1274  {
1275  dat[y][x] = (dat[y][x] >= Threshold) ? MaxValue : MinValue;
1276  }
1277  }
1278 
1279  /*
1280  //fixed but still not so easy to understand...
1281  //and it is questionable that this asm-like code is still so much faster:
1282 
1283  register StorageType* ImageData = GetImageData() + (GetROILowerRightY()-1) *
1284  GetWidth()*sizeof(StorageType) + GetROIUpperLeftX ();
1285  register StorageType* ImageDataStop = GetImageData() +
1286  (GetROILowerRightY()-1) * GetWidth()*sizeof(StorageType) + GetROILowerRightX();
1287  register int ROIBreite = GetROILowerRightX() - GetROIUpperLeftX() ;
1288  for(int i = (GetROILowerRightY() - GetROIUpperLeftY()); i > 0; i--) {
1289  for(;ImageData < ImageDataStop; ImageData+=sizeof(StorageType)) {
1290  *ImageData =*ImageData >= Threshold ? MaxValue : MinValue;
1291  }
1292  // Decrease the counter to proceed with above line
1293  ImageDataStop -= GetWidth()*sizeof(StorageType);
1294  ImageData = ImageDataStop - ROIBreite;
1295  }
1296  */
1297  return 0;
1298  }
1299 
1300  template<class StorageType>
1301  void
1302  Image<StorageType>::MaskValues(StorageType Threshold,
1303  Image<unsigned char>& binaryImage)
1304  {
1305  unsigned int width = GetWidth();
1306  unsigned int height = GetHeight();
1307  unsigned int channels = GetChannelCount();
1308 
1309  if (binaryImage.GetWidth() != width || binaryImage.GetHeight() != height
1310  || binaryImage.GetChannelCount() != 1)
1311  {
1312  binaryImage.ReInit(width, height, 1);
1313  }
1314 
1315  for (unsigned int x = 0; x < width; x++)
1316  {
1317  for (unsigned int y = 0; y < height; y++)
1318  {
1319  bool flag = true;
1320  for (unsigned short ch = 0; ch < channels; ch++)
1321  {
1322  StorageType val = PixelValue(x, y, ch);
1323  if (val > Threshold)
1324  {
1325  flag = false;
1326  break;
1327  }
1328  }
1329  if (flag) {
1330  binaryImage.SetPixel(255,x,y);
1331  } else {
1332  binaryImage.SetPixel(0,x,y);
1333  }
1334  }
1335  }
1336  }
1337 
1338  ///////////////////////////////////////////////////////////////////////////
1339  template<class StorageType>
1340  double
1341  Image<StorageType>::BilinearInterpolation(const double x, const double y,
1342  const unsigned short int channel) const
1343  {
1344 #ifdef BIAS_DEBUG
1345  if (!CheckBilinearInterpolation(x, y)) {
1346  BIASERR("BilinearInterpolation() coordinates out of bounds: x = "
1347  << x << ", y = " << y << ", width = " <<GetWidth()
1348  << ", height = " << GetHeight());
1349  }
1350 #endif
1351  double res = -1;
1352 
1353  switch (GetColorModel())
1354  {
1355  case CM_Grey:
1356  res = BilinearInterpolationGrey(x, y);
1357  break;
1358  case CM_RGB:
1359  case CM_BGR:
1360  case CM_RGBA:
1361  if (IsPlanar())
1362  {
1363  res = BilinearInterpolationRGBPlanar(x, y, channel);
1364  }
1365  else
1366  {
1367  res = BilinearInterpolationRGBInterleaved(x, y, channel);
1368  }
1369  ;
1370  break;
1371  default:
1372  if (IsInterleaved())
1373  {
1374  StorageType **ida = (StorageType**) GetImageDataArray();
1375  BIASASSERT(ida!=NULL);
1376  unsigned int x_floor = (unsigned int) floor(x);
1377  unsigned int y_floor = (unsigned int) floor(y);
1378  unsigned int x_ceil = (unsigned int) ceil(x);
1379  unsigned int y_ceil = (unsigned int) ceil(y);
1380  StorageType ul =
1381  ida[y_floor][x_floor * GetChannelCount() + channel];
1382  StorageType ur = ida[y_floor][x_ceil * GetChannelCount() + channel];
1383  StorageType ll = ida[y_ceil][x_floor * GetChannelCount() + channel];
1384  StorageType lr = ida[y_ceil][x_ceil * GetChannelCount() + channel];
1385  double dy = y - y_floor;
1386  double dx = x - x_floor;
1387 
1388  return ul + dy * (ll - ul) + dx * (ur - ul) + dy * dx * (ul + lr
1389  - ll - ur);
1390  }
1391  else
1392  {
1393  BIASERR("BilinearInterpolation() not implemented for planar "
1394  "non-RGB images");
1395  break;
1396  }
1397  }
1398  return res;
1399  }
1400 
1401  template<class StorageType>
1402  double
1403  Image<StorageType>::BicubicInterpolation(const double& x, const double& y,
1404  const unsigned short int channel) const
1405  {
1406 #ifdef BIAS_DEBUG
1407  if (!CheckBicubicInterpolation(x, y)) {
1408  BIASERR("BicubicInterpolation() coordinates out of bounds: x = "
1409  << x << ", y = " << y << ", width = " <<GetWidth()
1410  << ", height = " << GetHeight());
1411  }
1412 #endif
1413 
1414  // always use smaller int to find "next" grid position
1415  const int x_int = floor(x);
1416  const int y_int = floor(y);
1417 
1418  // compute offset from regular grid
1419  const double offsetx = x - x_int;
1420  const double offsety = y - y_int;
1421 
1422  // y weights
1423  const double wy0 = 0.25 * (((2.0 - offsety) * offsety - 1.0) * offsety);
1424  const double wy1 = 0.25 * ((3.0 * offsety - 5.0) * offsety * offsety
1425  + 2.0);
1426  const double wy2 = 0.25 * (((4.0 - 3.0 * offsety) * offsety + 1.0)
1427  * offsety);
1428  const double wy3 = 0.25 * ((offsety - 1.0) * offsety * offsety);
1429 
1430  // x weights
1431  const double wx0 = ((2.0 - offsetx) * offsetx - 1.0) * offsetx;
1432  const double wx1 = (3.0 * offsetx - 5.0) * offsetx * offsetx + 2.0;
1433  const double wx2 = ((4.0 - 3.0 * offsetx) * offsetx + 1.0) * offsetx;
1434  const double wx3 = (offsetx - 1.0) * offsetx * offsetx;
1435 
1436  const StorageType** pD = (const StorageType**) GetImageDataArray();
1437  return ((wx0 * pD[y_int - 1][(x_int - 1) * ChannelCount_ + channel] + wx1
1438  * pD[y_int - 1][x_int * ChannelCount_ + channel] + wx2
1439  * pD[y_int - 1][(x_int + 1) * ChannelCount_ + channel] + wx3
1440  * pD[y_int - 1][(x_int + 2) * ChannelCount_ + channel]) * wy0 + (wx0
1441  * pD[y_int][(x_int - 1) * ChannelCount_ + channel] + wx1
1442  * pD[y_int][x_int * ChannelCount_ + channel] + wx2 * pD[y_int][(x_int
1443  + 1) * ChannelCount_ + channel] + wx3 * pD[y_int][(x_int + 2)
1444  * ChannelCount_ + channel]) * wy1 + (wx0 * pD[y_int + 1][(x_int - 1)
1445  * ChannelCount_ + channel] + wx1 * pD[y_int + 1][x_int
1446  * ChannelCount_ + channel] + wx2 * pD[y_int + 1][(x_int + 1)
1447  * ChannelCount_ + channel] + wx3 * pD[y_int + 1][(x_int + 2)
1448  * ChannelCount_ + channel]) * wy2 + (wx0 * pD[y_int + 2][(x_int - 1)
1449  * ChannelCount_ + channel] + wx1 * pD[y_int + 2][x_int
1450  * ChannelCount_ + channel] + wx2 * pD[y_int + 2][(x_int + 1)
1451  * ChannelCount_ + channel] + wx3 * pD[y_int + 2][(x_int + 2)
1452  * ChannelCount_ + channel]) * wy3);
1453  }
1454 
1455  template<class StorageType>
1456  int
1458  {
1459  StorageType *src1, *src2, *dst, *write;
1460 
1461  if (GetWidth() != img.GetWidth() || GetHeight() != img.GetHeight()
1462  || img.GetChannelCount() > 1)
1463  {
1464  BIASERR("Image::AppendChannel(): second image has different "
1465  <<"dimensions");
1466  return -1;
1467  }
1468  if (img.IsEmpty() || IsEmpty())
1469  {
1470  BIASERR("Image::Append(): one or both images are empty");
1471  return -1;
1472  }
1473 
1474  src1 = GetImageData();
1475  src2 = img.GetImageData();
1476 
1477  dst = new StorageType[GetWidth() * GetHeight() * (GetChannelCount() + 1)];
1478  write = dst;
1479 
1480  if (InterleavedDataOrder_)
1481  {
1482  for (unsigned long int p = 0; p < GetPixelCount(); p++)
1483  {
1484  for (unsigned long int c = 0; c < GetChannelCount(); c++)
1485  *write++ = *src1++;
1486  *write++ = *src2++;
1487  }
1488  }
1489  else
1490  {
1491  memcpy(write, src1, GetSizeByte());
1492  write += GetPixelCount() * GetChannelCount();
1493  memcpy(write, src2, img.GetSizeByte());
1494  }
1495 
1496  // if (GetChannelCount() == 4)
1497  // ColorModel_ = CM_RGBA;
1498  // if (GetChannelCount() == 2)
1499  // ColorModel_ = CM_GreyA;
1500 
1501  ReleaseImageDataPointer();
1502  ChannelCount_ += 1;
1503  if (InterleavedDataOrder_)
1504  WidthStep_ = Width_ * Depth_ * ChannelCount_;
1505  else
1506  WidthStep_ = Width_ * Depth_;
1507 
1508  RedirectImageDataPointer(dst);
1509 
1510  return 0;
1511  }
1512 
1513  template<class StorageType>
1514  int Image<StorageType>::DeleteNBorderPixel(int n, StorageType delVal)
1515  {
1516  unsigned cc = GetChannelCount();
1517  unsigned w = GetWidth();
1518  unsigned h = GetHeight();
1519  int count =0;
1520  StorageType **src = GetImageDataArray();
1521  for (int y = 0; y < (int)h; y++) {
1522  for (int x = 0; x < (int)w; x++) {
1523  for (unsigned c = 0; c < GetChannelCount(); c++){
1524  if(x<n || y<n || x> int(w)-n || y>int(h)-n){
1525  src[y][x*cc+c] = delVal;
1526  count++;
1527  }
1528  }
1529  }
1530  }
1531  return count;
1532  }
1533 
1534  template<class StorageType>
1535  int Image<StorageType>::RemoveChannel(unsigned int channel)
1536  {
1537  StorageType *src1,*dst, *write;
1538 
1539  if (IsEmpty()){
1540  BIASERR("Image::RemoveChannel(): image is empty");
1541  return -1;
1542  }
1543 
1544  src1 = GetImageData();
1545  dst = new StorageType[GetWidth() * GetHeight() * (GetChannelCount() -1)];
1546  write = dst;
1547 
1548  if (InterleavedDataOrder_) {
1549  for (unsigned long int p = 0; p < GetPixelCount(); p++) {
1550  for (unsigned long int c = 0; c < GetChannelCount(); c++){
1551  if(c != channel) *write++ = *src1++;
1552  else{src1++;}
1553  }
1554  }
1555  }
1556  else {
1557  for(unsigned i=0; i< GetChannelCount();i++){
1558  if(i != channel)
1559  memcpy(write, src1, GetPixelCount()); // copy first channel
1560  write += GetPixelCount(); //increase write position by one channel
1561  }
1562  }
1563 
1564  ReleaseImageDataPointer();
1565  ChannelCount_ -= 1;
1566  if (InterleavedDataOrder_)
1567  WidthStep_ = Width_ * Depth_ * ChannelCount_;
1568  else
1569  WidthStep_ = Width_ * Depth_;
1570 
1571  RedirectImageDataPointer(dst);
1572 
1573  return 0;
1574  }
1575 
1576 
1577  template<class StorageType>
1578  void
1580  {
1581  delete[] (char**) ImageDataArray_;
1582  ImageDataArray_ = NULL;
1583  delete[] (char*) ImageData_;
1584  ImageData_ = NULL;
1585  ChannelCount_ = 0;
1586  Width_ = Height_ = 0;
1587  // do not set depth to zero, it is fixed in the templated image case
1588  BitDepth_ = 8 * Depth_;
1589  WidthStep_ = 0;
1590  ColorModel_ = CM_invalid;
1591 
1592  GetROI()->Release();
1593  _MetaData.clear();
1594  }
1595 
1596  /// Jan Woetzel 01/2003
1597  template<class StorageType>
1598  Image<float>
1600  const unsigned short int channel)
1601  {
1602 
1603 #ifdef BIAS_DEBUG
1604  // test if this implementation is suitable...
1605  if (IsEmpty())
1606  BIASERR("Image<StorageType>::GetMinMaxPixelValueIgnoreZero() image is empty");
1607 
1608  if (channel> (GetChannelCount() - 1))
1609  BIASERR("Image<StorageType>::GetMinMaxPixelValueIgnoreZero() invalid channel");
1610 
1611  unsigned minx, miny, maxx, maxy;
1612  GetROI()->GetCorners(minx, miny, maxx, maxy);
1613  if (minx!=0 || miny!=0 || maxx!=GetWidth() || maxy!=GetHeight())
1614  BIASERR("Image<StorageType>::GetMinMaxPixelValueIgnoreZero() not implemented for ROI!");
1615 #endif
1616 
1617  // OK, work...
1618  Image<float>
1619  res(GetWidth
1620  (), GetHeight
1621  ()); // result image
1622  StorageType *p_src; // pointer to data in src image
1623  float *p_dest; // pointer to data in dest image
1624 
1625  p_src = GetImageData() + channel * GetPixelCount(); // pointer to start of data in src image
1626  p_dest = res.GetImageData(); // pointer to start of data in dest image
1627  for (unsigned int i = 0; i < GetPixelCount(); i++)
1628  {
1629  // set value
1630  if (p_src[i] == 0)
1631  {
1632  // divison by zero
1633  p_dest[i] = 0.0f; // 0, +inf or -inf. or...
1634  }
1635  else
1636  {
1637  p_dest[i] = float(factor / p_src[i]);
1638  };
1639  };
1640 
1641  return res;
1642 }
1643 
1644 
1645 template <class StorageType>
1648 {
1649  StorageType *p=GetImageData();
1650  unsigned int count = GetPixelCount() * GetChannelCount();
1651  for (register int i=count; i>0 ; i--){
1652  *p = MaxSTValue() - *p;
1653  p++;
1654  }
1655 }
1656 
1657 
1658 template<class StorageType>
1660 InitWithForeignData(unsigned int width, unsigned int height,
1661  unsigned int channels, void *data, const bool interleaved,
1662  const bool shouldRelease)
1663 {
1664  //BIASERR("this function does not work completly, the destructor core dumps after using InitWithForeignData(). First guess is that is messes up the ROI");
1665  // first implementation uses standard init, then releses allocated data
1666  // and adjusts data_ to data
1667  // this is quite inefficient and will be changed in the near future
1668  ImageBase::InitWithForeignData(width, height, channels, data, StorageType_,
1669  interleaved, shouldRelease);
1670  return 0;
1671 }
1672 
1673 } // namespace BIAS
1674 
1675 
1676 // implementation in extra file:
1677 #include "ImageOperators.cpp"
1678 //
1679 // solve explicit instantiation
1680 //
1681 
1682 #define INSTANCE_Image(type)\
1683 template class BIASImageBase_EXPORT Image<type>;
1684 
1685 // create instances
1686 namespace BIAS {
1687 INSTANCE_Image(unsigned char)
1688 INSTANCE_Image(float)
1689 #ifdef BUILD_IMAGE_INT
1690 INSTANCE_Image(int)
1691 #endif
1692 #ifdef BUILD_IMAGE_CHAR
1693 INSTANCE_Image(char)
1694 #endif
1695 #ifdef BUILD_IMAGE_SHORT
1696 INSTANCE_Image(short)
1697 #endif
1698 #if defined(BUILD_IMAGE_USHORT)
1699 INSTANCE_Image(unsigned short)
1700 #endif
1701 #ifdef BUILD_IMAGE_DOUBLE
1702 INSTANCE_Image(double)
1703 #endif
1704 #ifdef BUILD_IMAGE_UINT
1705 INSTANCE_Image(unsigned int)
1706 #endif
1707 }
void Release()
reimplemented from ImageBase
Definition: Image.cpp:1579
void Invert()
inverts every pixel value, i.e. MaxSTValue() - value
Definition: Image.cpp:1647
unsigned int BitDepth_
relevant bits per pixel per channel
Definition: ImageBase.hh:1062
int BinaryThreshold(StorageType Threshold, StorageType MinValue, StorageType MaxValue)
Test for every pixel wether it is &gt;= than the threshold.
Definition: Image.cpp:1254
int AboveThresholdToValue(StorageType Threshold, StorageType Value)
sets alls pixels with values above Threshold to Value
Definition: Image.cpp:1028
(16bit) unsigned integer image storage type
Definition: ImageBase.hh:114
StorageType GetMaxPixelValue(unsigned short int channel=0, unsigned int *coo=NULL) const
Get the maximal pixel value if coo!=NULL the coo[0]=x of max and coo[1]=y of max. ...
Definition: Image.cpp:995
double BilinearInterpolation(const double x, const double y, const unsigned short int channel=0) const
Generic bilinear interpolation.
Definition: Image.cpp:1341
enum EStorageType StorageType_
the storage type in a pixel channel
Definition: ImageBase.hh:1056
int DeleteNBorderPixel(int n, StorageType delVal=StorageType(0))
Deletes n pixels at border of image.
Definition: Image.cpp:1514
int Transpose(BIAS::Image< StorageType > &result)
Transposes an image on diagonal, rows become columns, columns become rows.
Definition: Image.cpp:1133
unsigned int Depth_
size of one channel of one pixel in bytes
Definition: ImageBase.hh:1060
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
int InvertValues(BIAS::Image< StorageType > &inverted, StorageType *newMax=NULL)
inverts values of image, new values are StorageType_MAX-oldvalue or newMax-oldvalue if newMax != NULL...
Definition: Image.cpp:1163
int BelowThresholdToValue(StorageType Threshold, StorageType Value)
sets alls pixels with values below Threshold to Value
Definition: Image.cpp:1013
ImageBase & operator=(const ImageBase &Source)
assignment operator, allocates memory structure via Init only if necessary
Definition: ImageBase.cpp:745
int AppendChannel(Image< StorageType > &img)
Definition: Image.cpp:1457
(8bit) signed char image storage type
Definition: ImageBase.hh:113
int ScaleShiftBetween(double Min, double Max)
scales and shifts image so afterwards every pixel has a value between Min and Max ...
Definition: Image.cpp:1118
void InitWithForeignData(unsigned int width, unsigned int height, unsigned int nChannels, void *data, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true, const bool shouldRelease=true)
Initialize image size and channels using a foreign data pointer.
Definition: ImageBase.cpp:155
unsigned int GetSizeByte() const
returns the nr.
Definition: ImageBase.hh:352
std::ostream & PrintData(std::ostream &os) const
writes data of IplImage_ to os (ascii)
Definition: Image.cpp:442
float image storage type
Definition: ImageBase.hh:118
double image storage type
Definition: ImageBase.hh:119
int ScaleShift(double Scale, double Shift)
scales and shifts image (all channels simultanously)
Definition: Image.cpp:1064
void Binarize(StorageType Threshold)
sets all pixels &gt;= Threshold to MaxPixelValue and all others to MinPixelValue only for one channel / ...
Definition: Image.cpp:1043
int InitWithForeignData(unsigned int width, unsigned int height, unsigned int channels, void *data, const bool interleaved=true, const bool shouldRelease=true)
This is used to construct a BIAS::Image hull around existing image data.
Definition: Image.cpp:1660
void GetMinMaxPixelValue(StorageType &min, StorageType &max, unsigned short int channel=0, unsigned int *mincoo=NULL, unsigned int *maxcoo=NULL) const
returns the minimal and maximal pixel value in channel only Finds minimum and maximum pixel value in ...
Definition: Image.cpp:802
unsigned int GetWidth() const
Definition: ImageBase.hh:312
void GetMeanPixelValue(StorageType mean[])
calculates mean of pixel
Definition: Image.cpp:623
(16bit) signed integer image storage type
Definition: ImageBase.hh:115
double BicubicInterpolation(const double &x, const double &y, const unsigned short int channel=0) const
Generic bicubic interpolation.
Definition: Image.cpp:1403
void ReInit(const unsigned int &width, const unsigned int &height, const unsigned int nChannels=1, const enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true, const EColorModel colormodel=CM_Grey)
(Re-)Initialize Image data if required.
Definition: ImageBase.cpp:131
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
std::ostream & PrintPointer(std::ostream &os) const
writes pointer of IplImage_ to os (ascii)
Definition: Image.cpp:431
unsigned int GetHeight() const
Definition: ImageBase.hh:319
void FillImageWithXValue()
fills image with value depending on x coordinate
Definition: Image.cpp:608
void FillImageWithConstValue(StorageType Value)
fill grey images
Definition: Image.cpp:456
The image template class for specific storage types.
Definition: Image.hh:78
bool GetMinMaxPixelValueIgnoreRange(StorageType &min, StorageType &max, const StorageType ignoreStart=0, const StorageType ignoreEnd=0, const unsigned short int channel=0) const
Get both, minimal and maximal pixel value –actual implementation only for planar images–.
Definition: Image.cpp:727
int ScaleShiftChannel(double Scale, double Shift, unsigned int channel)
similiar to ScaleShift, but only scales and shifts one image channel
Definition: Image.cpp:1079
void SetPixel(const StorageType &value, const unsigned int &x, const unsigned int &y, const unsigned short int channel=0)
Set the value of a given pixel (x,y) in channel to value.
Definition: Image.hh:171
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
Definition: Image.cpp:421
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
(32bit) signed integer image storage type
Definition: ImageBase.hh:117
void MaskValues(StorageType Threshold, Image< unsigned char > &binaryImage)
Calculates a mask image from given image depending on threshold.
Definition: Image.cpp:1302
void Init(unsigned int width, unsigned int height, unsigned int nChannels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
Initialize image size and channels.
Definition: ImageBase.cpp:229
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
StorageType GetMinPixelValue(unsigned short int channel=0, unsigned int *coo=NULL) const
Get the minimal pixel value if coo!=NULL the coo[0]=x of min and coo[1]=y of min. ...
Definition: Image.cpp:977
int RemoveChannel(unsigned int channel)
remove a channel from an image Remove means: RGB, remove channel 2 =&gt; RG CAUTION, channels start a 0 ...
Definition: Image.cpp:1535
void GetMeanPixelValueIgnoreRange(StorageType mean[], const StorageType ignoreStart=0, const StorageType ignoreEnd=(StorageType) 0) const
calculates mean of pixel ignoring values between ignoreStart and ignoreEnd
Definition: Image.cpp:671
This is the base class for images in BIAS.
Definition: ImageBase.hh:102
void Binarise(StorageType Threshold)
Wrapper for Binarize()
Definition: Image.cpp:1057
virtual ~Image()
Definition: Image.cpp:48
Image< float > Reciprocal(const float factor=1.0, const unsigned short int channel=0)
Calculates the reciprocal for each pixel: x&#39; = 1/x computes for exactly one channel (in case of multi...
Definition: Image.cpp:1599
void ClearChannel(const unsigned int channel, const StorageType value)
Sets all pixel values in the declared channel to the specified value.
Definition: Image.cpp:547
(32bit) unsigned integer image storage type
Definition: ImageBase.hh:116
int CalcScaleShift(double Min, double Max, double &Scale, double &Shift) const
calculate the values needed by ScaleShiftBetween
Definition: Image.cpp:1222
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153