Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ImageInline.hh
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 #include <Base/Common/W32Compat.hh>
25 #include <Base/Common/BIASpragmaStart.hh>
26 
27 template <class StorageType> inline StorageType Image<StorageType>::MaxSTValue()
28 {
29  BIASERR("no such StorageType");
30  return (StorageType)0;
31 }
32 
33 template <> inline unsigned char Image<unsigned char>::MaxSTValue()
34 { return (unsigned char)(UCHAR_MAX); }
35 
36 template <> inline float Image<float>::MaxSTValue()
37 { return FLT_MAX; }
38 
39 #ifdef BUILD_IMAGE_CHAR
40 template <> inline char Image<char>::MaxSTValue()
41 { return SCHAR_MAX; }
42 template <> inline char Image<char>::MinSTValue()
43 { return SCHAR_MIN; }
44 #endif
45 #ifdef BUILD_IMAGE_SHORT
46 template <> inline short Image<short>::MaxSTValue()
47 { return SHRT_MAX; }
48 template <> inline short Image<short>::MinSTValue()
49 { return SHRT_MIN; }
50 #endif
51 #ifdef BUILD_IMAGE_USHORT
52 template <> inline unsigned short Image<unsigned short>::MaxSTValue()
53 { return USHRT_MAX; }
54 template <> inline unsigned short Image<unsigned short>::MinSTValue()
55 { return 0; }
56 #endif
57 #ifdef BUILD_IMAGE_INT
58 template <> inline int Image<int>::MaxSTValue()
59 { return INT_MAX; }
60 template <> inline int Image<int>::MinSTValue()
61 { return INT_MIN; }
62 #endif
63 #ifdef BUILD_IMAGE_UINT
64 template <> inline unsigned int Image<unsigned int>::MaxSTValue()
65 { return UINT_MAX; }
66 template <> inline unsigned int Image<unsigned int>::MinSTValue()
67 { return 0; }
68 #endif
69 #ifdef BUILD_IMAGE_DOUBLE
70 template <> inline double Image<double>::MaxSTValue()
71 { return DBL_MAX; }
72 template <> inline double Image<double>::MinSTValue()
73 { return DBL_MIN; }
74 #endif
75 
76 template <class StorageType> inline StorageType Image<StorageType>::MinSTValue()
77 {
78  BIASERR("no such StorageType");
79  return (StorageType)0;
80 }
81 
82 template <> inline unsigned char Image<unsigned char>::MinSTValue()
83 { return 0; }
84 
85 template <> inline float Image<float>::MinSTValue()
86 { return FLT_MIN; }
87 
88 
89 template <class StorageType>
90 inline StorageType
91 Image<StorageType>::PixelValue(const unsigned int x, const unsigned int y,
92  const unsigned short int channel) const
93 {
94  CheckCoordinates((int)x, (int)y, "PixelValue");
95 
96  if (IsPlanar()) {
97  return GetImageData()[channel * GetPixelCount() + y * GetWidth() + x];
98  } else {
99  return GetImageData()[GetChannelCount() *
100  ( y * GetWidth() + x ) + channel ];
101  }
102 }
103 
104 template <class StorageType>
105 inline StorageType Image<StorageType>::
106 PixelValueInterleaved(const int x, const int y, const int channel) const
107 {
108  BIASASSERT(this->IsInterleaved());
109  CheckCoordinates(x, y, "PixelValueInterleaved");
110 
111  return GetImageDataArray()[y][x*GetChannelCount()+channel];
112 }
113 
114 
115 template <class StorageType>
116 inline StorageType & Image<StorageType>::
117 PixelValueRefInterleaved(const int x, const int y, const int channel)
118 {
119  BIASASSERT(this->IsInterleaved());
120  CheckCoordinates(x, y, "PixelValueRefInterleaved");
121 
122  return GetImageDataArray()[y][x*GetChannelCount()+channel];
123 }
124 
125 
126 template <class StorageType>
127 inline const StorageType& Image<StorageType>::GetPixelNearestNeighbor(
128  const double x, const double y, const unsigned short int channel) const
129 {
130  int x_res = (int) ((x - floor(x)) <= 0.5 ? floor(x) : floor(x) + 1);
131  int y_res = (int) ((y - floor(y)) <= 0.5 ? floor(y) : floor(y) + 1);
132 
133  CheckCoordinates(x_res, y_res, "GetNearestNeighbor");
134 
135  if (IsPlanar()) {
136 
137  // The image is planar
138  return
139  GetImageData()[GetPixelCount()*channel + x_res + GetWidth() * y_res];
140  } else {
141 
142  // The image is interleaved
143  return
144  GetImageData()[GetChannelCount()*(x_res+GetWidth()*y_res)+channel];
145  }
146 }
147 
148 
149 template <class StorageType>
150 inline const StorageType& Image<StorageType>::GetPixelNearestNeighbor(
151  const float x, const float y, const unsigned short int channel) const
152 {
153  //CheckCoordinates(x, y, "GetNearestNeighbor");
154 
155  return GetPixelNearestNeighbor((double) x, (double) y, channel);
156 }
157 
158 
159 // template <class StorageType>
160 // inline StorageType& Image<StorageType>::GetPixelNearestNeighbor(
161 // const float x, const float y, const enum TChannel channel) const
162 // {
163 // CheckCoordinates(x, y, "GetNearestNeighbor");
164 
165 // return GetPixelNearestNeighbor((double) x, (double) y, channel);
166 // }
167 
168 
169 template <class StorageType>
170 inline void
171 Image<StorageType>::SetPixel(const StorageType & value,
172  const unsigned int & x,
173  const unsigned int & y,
174  const unsigned short int channel)
175 {
176  CheckCoordinates((int)x, (int)y, "SetPixel");
177  CheckChannel(channel,"SetPixel");
178 
179  BIASASSERT( channel<GetChannelCount() );
180 
181  if (IsPlanar()) {
182  ((StorageType*)GetImageData())[channel * GetPixelCount() + y*GetWidth() +x] = value;
183  } else {
184  ((StorageType*)GetImageData())[GetChannelCount() * (y*GetWidth() +x) +channel ] = value;
185  };
186 }
187 
188 
189 template <class StorageType>
190 inline void
191 Image<StorageType>::SetPixel(const StorageType & value0,
192  const StorageType & value1,
193  const StorageType & value2,
194  const unsigned int & x,
195  const unsigned int & y )
196 {
197  CheckChannel(2, "SetPixel"); // channels 0,1,2 must be there
198 
199  SetPixel(value0, x, y, 0);
200  SetPixel(value1, x, y, 1);
201  SetPixel(value2, x, y, 2);
202 }
203 
204 template <class StorageType>
205 inline bool Image<StorageType>::
206 CheckBilinearInterpolation(const double x, const double y) const
207 {
208  return ((floor(x) >= 0) && (floor(y) >= 0) &&
209  (ceil(x) < GetWidth()) && (ceil(y) < GetHeight()));
210 }
211 
212 template <class StorageType>
213 inline bool Image<StorageType>::
214 CheckBicubicInterpolation(const double x, const double y) const
215 {
216  return ((floor(x) >= 1) && (floor(y) >= 1) &&
217  ((floor(x)+2) < GetWidth()) && ((floor(y)+2) < GetHeight()));
218 }
219 
220 template <class StorageType>
221 inline double Image<StorageType>::LinearInterpolation(
222  const unsigned int x, const double y) const
223 {
224 #ifdef BIAS_DEBUG
225  if ((x<0) || (x>(GetWidth()-1)))
226  BIASERR("LinearInterpolation() x out of bounds: "<<x);
227  if ((floor(y)<0) || (ceil(y)>(GetHeight()-1)))
228  BIASERR("LinearInterpolation() y out of bounds: "<<y);
229 #endif
230  double dy = y - floor(y);
231  StorageType **ImageDataArray = (StorageType**)GetImageDataArray();
232 
233  return ((1-dy)*(double)ImageDataArray[(unsigned int)floor(y)][x] +
234  dy*(double)ImageDataArray[(unsigned int)ceil(y)][x]);
235 }
236 
237 template <class StorageType>
238 inline double Image<StorageType>::LinearInterpolation(
239  const double x, const unsigned int y) const
240 {
241 #ifdef BIAS_DEBUG
242  if ((floor(x)<0) || ((ceil(x))>GetWidth()-1))
243  BIASERR("LinearInterpolation() x out of bounds: "<<x);
244  if ((y<0) || (y>(GetHeight()-1)))
245  BIASERR("LinearInterpolation() y out of bounds: "<<y);
246 #endif
247  double dx = x - floor(x);
248  StorageType **ImageDataArray = (StorageType**)GetImageDataArray();
249 
250  return ((1-dx)*(double)ImageDataArray[y][(unsigned int)floor(x)] +
251  dx*(double)ImageDataArray[y][(unsigned int)ceil(x)]);
252 }
253 
254 template <class StorageType>
255 inline double Image<StorageType>::
256 DistanceWeightedInterpolationGrey(const double x, const double y) const
257 {
258  StorageType **ida = (StorageType**)GetImageDataArray();
259  unsigned int x_floor=(unsigned int)floor(x);
260  unsigned int y_floor=(unsigned int)floor(y);
261  unsigned int x_ceil=(unsigned int)ceil(x);
262  unsigned int y_ceil=(unsigned int)ceil(y);
263  StorageType ul = ida[y_floor][x_floor];
264  StorageType ur = ida[y_floor][x_ceil];
265  StorageType ll = ida[y_ceil][x_floor];
266  StorageType lr = ida[y_ceil][x_ceil];
267  double dy = y - y_floor;
268  double dx = x - x_floor;
269  double ulw, urw, llw, lrw;
270  double sum=0.0;
271  llw=sqrt(pow(1.0-dx,2.0)+pow(dy,2.0));
272  lrw=sqrt(pow(dx,2.0)+pow(dy,2.0));
273  ulw=sqrt(pow(1.0-dx,2.0)+pow(1.0-dy,2.0));
274  urw=sqrt(pow(dx,2.0)+pow(1.0-dy,2.0));
275  sum+=llw;
276  sum+=lrw;
277  sum+=ulw;
278  sum+=urw;
279  llw/=sum;
280  lrw/=sum;
281  ulw/=sum;
282  urw/=sum;
283  return (ul*ulw + ll*llw + lr*lrw + ur*urw);
284 }
285 
286 template <class StorageType> inline double Image<StorageType>::
287 BilinearInterpolationGrey(const double x, const double y) const
288 {
289  StorageType **ida = (StorageType**)GetImageDataArray();
290  BIASASSERT(ida!=NULL);
291  unsigned int x_floor=(unsigned int)floor(x);
292  unsigned int y_floor=(unsigned int)floor(y);
293  unsigned int x_ceil=x_floor+1;
294  unsigned int y_ceil=y_floor+1;
295  StorageType *p = ida[y_floor];
296  StorageType ul = p[x_floor];
297  StorageType ur = p[x_ceil];
298  p = ida[y_ceil];
299  StorageType ll = p[x_floor];
300  StorageType lr = p[x_ceil];
301  double dy = y - y_floor;
302  double dx = x - x_floor;
303 
304  double dl = ll - ul;
305  double val = ul + dy*dl + dx*(ur - ul + dy*(lr - dl - ur ));
306 
307 /*
308 #ifdef BIAS_DEBUG
309  {
310  unsigned int x_floor=(unsigned int)floor(x);
311  unsigned int y_floor=(unsigned int)floor(y);
312  unsigned int x_ceil=(unsigned int)ceil(x);
313  unsigned int y_ceil=(unsigned int)ceil(y);
314  StorageType ul = ida[y_floor ][x_floor ];
315  StorageType ur = ida[y_floor ][x_ceil];
316  StorageType ll = ida[y_ceil][x_floor ];
317  StorageType lr = ida[y_ceil][x_ceil];
318  double dy = y - y_floor;
319  double dx = x - x_floor;
320 
321  double val2 = ul + dy*(ll - ul) + dx*(ur - ul) + dy*dx*(ul + lr - ll - ur );
322  BIASASSERT(Equal(val, val2, 1e-6));
323  }
324 #endif
325 */
326  return val;
327 }
328 
329 #define IMAGEPOINT_UP(x,y,width,height) x<=(width-1)&& y<=(height-1)
330 #define IMAGEPOINT_DOWN(x,y,width,height) x>=0&& y>=0
331 
332 
333 template <class StorageType> inline
334 double Image<StorageType>::
335 BilinearInterpolationGreyMinVal(const double x, const double y,
336  const StorageType & minVal) const
337 {
338  unsigned int x_ceil=(unsigned int)ceil(x);
339  unsigned int y_ceil=(unsigned int)ceil(y);
340  if(!(IMAGEPOINT_UP(x_ceil, y_ceil, Width_, Height_))) return minVal;
341  unsigned int x_floor=(unsigned int)floor(x);
342  unsigned int y_floor=(unsigned int)floor(y);
343  // if(!(IMAGEPOINT_DOWN(x_floor, y_floor, Width_, Height_))) return minVal;
344 
345  StorageType **ida = (StorageType**)GetImageDataArray();
346  // pixel values:
347  StorageType ul = ida[y_floor ][x_floor ];
348  if (ul<=minVal) return minVal;
349  StorageType ur = ida[y_floor ][x_ceil];
350  if (ur<=minVal) return minVal;
351  StorageType ll = ida[y_ceil][x_floor ];
352  if (ll<=minVal) return minVal;
353  StorageType lr = ida[y_ceil][x_ceil];
354  if (lr<=minVal) return minVal;
355 
356  // distance weights:
357  double dy = y - y_floor;
358  double dx = x - x_floor;
359 
360  // OK, compute sum for bilinear interpolation:
361  return ul
362  + dy*(ll - ul)
363  + dx*(ur - ul)
364  + dy*dx*(ul + lr - ll - ur );
365 }
366 
367 template <class StorageType> inline
368 double Image<StorageType>::
369 BilinearInterpolationGreyMaxVal(const double x, const double y,
370  const StorageType & maxVal) const
371 {
372  StorageType **ida = (StorageType**)GetImageDataArray();
373  unsigned int x_floor=(unsigned int)floor(x);
374  unsigned int y_floor=(unsigned int)floor(y);
375  unsigned int x_ceil=(unsigned int)ceil(x);
376  unsigned int y_ceil=(unsigned int)ceil(y);
377  // pixel values:
378  // return invalid if at least one of the four neighbors is invalid
379  StorageType ul = ida[y_floor ][x_floor ];
380  if (ul>=maxVal) return maxVal;
381  StorageType ur = ida[y_floor ][x_ceil];
382  if (ur>=maxVal) return maxVal;
383  StorageType ll = ida[y_ceil][x_floor ];
384  if (ll>=maxVal) return maxVal;
385  StorageType lr = ida[y_ceil][x_ceil];
386  if (lr>=maxVal) return maxVal;
387 
388  // distance weights:
389  double dy = y - y_floor;
390  double dx = x - x_floor;
391 
392  // OK, compute sum for bilinear interpolation:
393  return ul
394  + dy*(ll - ul)
395  + dx*(ur - ul)
396  + dy*dx*(ul + lr - ll - ur );
397 }
398 
399 
400 template <class StorageType>
401 inline StorageType Image<StorageType>::
402 FastBilinearInterpolationGrey(const double x, const double y) const
403 {
404  const StorageType **ida = GetImageDataArray();
405  unsigned int x_floor=(unsigned int)floor(x);
406  unsigned int y_floor=(unsigned int)floor(y);
407  unsigned int x_ceil=(unsigned int)ceil(x);
408  unsigned int y_ceil=(unsigned int)ceil(y);
409  StorageType ul = ida[y_floor][x_floor];
410  StorageType ur = ida[y_floor][x_ceil];
411  StorageType ll = ida[y_ceil][x_floor];
412  StorageType lr = ida[y_ceil][x_ceil];
413  double dy = y - y_floor;
414  double dx = x - x_floor;
415 
416  return (StorageType)(ul + dy*(ll - ul) + dx*(ur - ul) + dy*dx*(ul + lr - ll - ur ));
417 }
418 
419 /* Specific implementation is ca. 20 % faster than the generic function
420  using double values above (author: woelk, 01/2003)! */
421 template <> inline unsigned char
423  const double y) const
424 {
425  register const unsigned char **ida = GetImageDataArray();
426  register unsigned int x_floor = (unsigned int)floor(x);
427  register unsigned int y_floor = (unsigned int)floor(y);
428  register unsigned int x_ceil = x_floor+1;
429  register unsigned int y_ceil = y_floor+1;
430  register unsigned int ul = (unsigned int)ida[y_floor][x_floor];
431  register unsigned int ur = (unsigned int)ida[y_floor][x_ceil];
432  register unsigned int ll = (unsigned int)ida[y_ceil][x_floor];
433  register unsigned int lr = (unsigned int)ida[y_ceil][x_ceil];
434  register unsigned int dy = (unsigned int)rint((y - y_floor)*256);
435  register unsigned int dx = (unsigned int)rint((x - x_floor)*256);
436 
437  return (unsigned char)(((ul<<16) + (dy<<8)*(ll - ul) + (dx<<8)*(ur - ul) + dy*dx*(ul - ll - ur + lr))>>16);
438 }
439 
440 template <class StorageType> inline double Image<StorageType>::
441 BilinearInterpolationRGBPlanar(const double x, const double y,
442  unsigned int channel) const
443 {
444  StorageType **ida = ((StorageType**)GetImageDataArray())+channel*GetPixelCount();
445  unsigned int x_floor=(unsigned int)floor(x);
446  unsigned int y_floor=(unsigned int)floor(y);
447  unsigned int x_ceil=(unsigned int)ceil(x);
448  unsigned int y_ceil=(unsigned int)ceil(y);
449  StorageType ul = ida[y_floor][x_floor];
450  StorageType ur = ida[y_floor][x_ceil];
451  StorageType ll = ida[y_ceil][x_floor];
452  StorageType lr = ida[y_ceil][x_ceil];
453  double dy = y - y_floor;
454  double dx = x - x_floor;
455 
456  return ul + dy*(ll - ul) + dx*(ur - ul) + dy*dx*(ul - ll - ur + lr);
457 }
458 
459 template <class StorageType> inline double Image<StorageType>::
460 BilinearInterpolationRGBInterleaved(const double x, const double y,
461  unsigned int channel) const
462 {
463  unsigned int x_floor=(unsigned int)floor(x);
464  unsigned int y_floor=(unsigned int)floor(y);
465  unsigned int x_ceil=(unsigned int)ceil(x);
466  unsigned int y_ceil=(unsigned int)ceil(y);
467  StorageType ul =
468  ((StorageType**)GetImageDataArray())[y_floor][x_floor*
469  GetChannelCount()+channel];
470  StorageType ur =
471  ((StorageType**)GetImageDataArray())[y_floor][x_ceil*
472  GetChannelCount()+channel];
473  StorageType ll =
474  ((StorageType**)GetImageDataArray())[y_ceil][x_floor*
475  GetChannelCount()+channel];
476  StorageType lr =
477  ((StorageType**)GetImageDataArray())[y_ceil][x_ceil*
478  GetChannelCount()+channel];
479  double dy = y - y_floor;
480  double dx = x - x_floor;
481 
482  return ul + dy*(ll - ul) + dx*(ur - ul) + dy*dx*(ul - ll - ur + lr);
483 }
484 
485 template <>
486 inline void Image<unsigned char>::
487 BilinearInterpolationShiftRegion(const double& x, const double& y,
488  unsigned int hws_x, unsigned int hws_y,
489  unsigned char* buffer)
490 {
491 #ifdef BIAS_DEBUG
492  if (ChannelCount_!=1) {
493  BIASERR("invalid channel count != 1: channels="<<ChannelCount_);
494  BIASABORT;
495  }
496 #endif
497 
498  /*
499  // XXXXXXX only for debug purposes: copy region without shift XXXXXXXX
500  const unsigned int countx = int(x)+hws_x+1;
501  const unsigned int county = int(y)+hws_y+1;
502  for (unsigned int iy = int(y)-hws_y; iy< county; iy++) {
503  for (unsigned int ix = int(x)-hws_x; ix< countx; ix++) {
504  *buffer++ = GetImageDataArray()[iy][ix];
505  }
506  }
507  // XXXXXXXXX end debug code XXXXXXXX
508  */
509 
510  const unsigned char **ida = (const unsigned char**)GetImageDataArray();
511 
512  // get pixel position of upper left corner of region
513  const unsigned int x_floor = (unsigned int)floor(x) - hws_x;
514  const unsigned int y_floor = (unsigned int)floor(y) - hws_y;
515  const unsigned int x_ceil = (unsigned int)ceil(x) - hws_x;
516  const unsigned int y_ceil = (unsigned int)ceil(y) - hws_y;
517 
518  // get pointers to four pixels surrounding upperleft corner of new region
519  register unsigned char* ul = (unsigned char*) &ida[y_floor ][x_floor ];
520  register unsigned char* ur = (unsigned char*) &ida[y_floor ][x_ceil];
521  register unsigned char* ll = (unsigned char*) &ida[y_ceil][x_floor ];
522  register unsigned char* lr = (unsigned char*) &ida[y_ceil][x_ceil];
523 
524  // get pointer to output buffer
525  register unsigned char* result = buffer;
526 
527  // precompute frequently used weights
528  const double dy = y - floor(y);
529  const double dx = x - floor(x);
530  const double dxdy = dx*dy;
531 
532  // make loop numbers and offset const:
533  const unsigned int countx = 2*hws_x+1;
534  const unsigned int county = 2*hws_y+1;
535  const unsigned int lineoffset = GetWidth()-1-2*hws_x;
536 
537  // compute new grid pixel by pixel, shifting each pointer one to the right
538  for (unsigned int iy = 0; iy< county; iy++) {
539  for (unsigned int ix = 0; ix< countx; ix++, ul++, ur++, ll++, lr++) {
540  *result = (unsigned char)(*ul + dy*(*ll - *ul) + dx*(*ur - *ul) + dxdy*(*ul + *lr - *ll - *ur));
541  result++;
542  }
543  // end of a window row, go to start of next:
544  ul += lineoffset;
545  ur += lineoffset;
546  ll += lineoffset;
547  lr += lineoffset;
548  }
549 
550 }
551 
552 template <class StorageType>
553 inline void Image<StorageType>::
554 BilinearInterpolationShiftRegion(const double& x, const double& y,
555  unsigned int hws_x, unsigned int hws_y,
556  StorageType* buffer)
557 {
558  BIASERR("BilinearInterpolationShiftRegion is not implemented for other "
559  "storage types than unsigned char!");
560 }
561 
562 
563 #include <Base/Common/BIASpragmaEnd.hh>
564 
void BilinearInterpolationShiftRegion(const double &x, const double &y, unsigned int hws_x, unsigned int hws_y, unsigned char *buffer)
Interpolate shifted rectangular region centered at given subpixel position.
Definition: ImageInline.hh:487
The image template class for specific storage types.
Definition: Image.hh:78