core/vil/vil_bilin_interp.h
Go to the documentation of this file.
00001 // This is core/vil/vil_bilin_interp.h
00002 #ifndef vil_bilin_interp_h_
00003 #define vil_bilin_interp_h_
00004 //:
00005 // \file
00006 // \brief Bilinear interpolation functions for 2D images
00007 // \author Tim Cootes
00008 //
00009 // The vil bicub source files were derived from the corresponding
00010 // vil bilin files, thus the vil bilin/bicub source files are very
00011 // similar.  If you modify something in this file, there is a
00012 // corresponding bicub file that would likely also benefit from
00013 // the same change.
00014 
00015 #include <vcl_cassert.h>
00016 #include <vcl_cstddef.h>
00017 #include <vil/vil_image_view.h>
00018 #include <vil/vil_na.h>
00019 
00020 //: Compute bilinear interpolation at (x,y), no bound checks. Requires 0<x<ni-2, 0<y<nj-2
00021 //  Image is nx * ny array of Ts. x,y element is data[xstep*x+ystep*y]
00022 //  No bound checks are done.
00023 template<class T>
00024 inline double vil_bilin_interp_unsafe(double x, double y, const T* data,
00025                                       vcl_ptrdiff_t xstep, vcl_ptrdiff_t ystep)
00026 {
00027   int p1x=int(x);
00028   double normx = x-p1x;
00029   int p1y=int(y);
00030   double normy = y-p1y;
00031 
00032   const T* pix1 = data + p1y*ystep + p1x*xstep;
00033 
00034   double i1 = pix1[0    ]+(pix1[      ystep]-pix1[0    ])*normy;
00035   double i2 = pix1[xstep]+(pix1[xstep+ystep]-pix1[xstep])*normy;
00036 
00037   return i1+(i2-i1)*normx;
00038 }
00039 
00040 
00041 //: Compute bilinear interpolation at (x,y), no bound checks. Requires 0<x<ni-2, 0<y<nj-2
00042 //  Image is nx * ny array of Ts. x,y element is data[xstep*x+ystep*y]
00043 //  No bound checks are done.
00044 //  This is a version of vil_bilin_interp_unsafe with the same function
00045 //  signature as vil_bilin_interp_safe.
00046 template<class T>
00047 inline double vil_bilin_interp_unsafe(double x, double y, const T* data,
00048                                       int /*nx*/, int /*ny*/,
00049                                       vcl_ptrdiff_t xstep, vcl_ptrdiff_t ystep)
00050 {
00051   return vil_bilin_interp_unsafe(x, y, data, xstep, ystep);
00052 }
00053 
00054 //: Compute bilinear interpolation at (x,y), no bound checks
00055 //  Image is nx * ny array of Ts. x,y element is data[xstep*x+ystep*y]
00056 //  No bound checks are done.
00057 template<class T>
00058 inline double vil_bilin_interp_raw(double x, double y, const T* data,
00059                                    vcl_ptrdiff_t xstep, vcl_ptrdiff_t ystep)
00060 {
00061   int p1x=int(x);
00062   double normx = x-p1x;
00063   int p1y=int(y);
00064   double normy = y-p1y;
00065 
00066   const T* pix1 = data + p1y*ystep + p1x*xstep;
00067 
00068   // special boundary cases can be handled more quickly first;
00069   // also avoids accessing an invalid pix1[t] which is going to have weight 0.
00070   if (normx == 0 && normy == 0) return pix1[0];
00071   if (normx == 0) return pix1[0]+(pix1[ystep]-pix1[0])*normy;
00072   if (normy == 0) return pix1[0]+(pix1[xstep]-pix1[0])*normx;
00073 
00074   double i1 = pix1[0    ]+(pix1[      ystep]-pix1[0    ])*normy;
00075   double i2 = pix1[xstep]+(pix1[xstep+ystep]-pix1[xstep])*normy;
00076 
00077   return i1+(i2-i1)*normx;
00078 }
00079 
00080 //: Compute bilinear interpolation at (x,y), no bound checks.
00081 //  Image is nx * ny array of Ts. x,y element is data[xstep*x+ystep*y]
00082 //  No bound checks are done.
00083 //  This is a version of vil_bilin_interp_raw with the same function
00084 //  signature as vil_bilin_interp_safe.
00085 template<class T>
00086 inline double vil_bilin_interp_raw(double x, double y, const T* data,
00087                                    int /*nx*/, int /*ny*/,
00088                                    vcl_ptrdiff_t xstep, vcl_ptrdiff_t ystep)
00089 {
00090   return vil_bilin_interp_raw(x, y, data, xstep, ystep);
00091 }
00092 
00093 //: Compute bilinear interpolation at (x,y), with bound checks
00094 //  Image is nx * ny array of Ts. x,y element is data[xstep*x+ystep*y]
00095 //  If (x,y) is outside interpolatable image region, zero is returned.
00096 //  The safe interpolatable region is [0,nx-1]*[0,ny-1].
00097 template<class T>
00098 inline double vil_bilin_interp_safe(double x, double y, const T* data,
00099                                     int nx, int ny,
00100                                     vcl_ptrdiff_t xstep, vcl_ptrdiff_t ystep)
00101 {
00102   if (x<0) return 0.0;
00103   if (y<0) return 0.0;
00104   if (x>nx-1) return 0.0;
00105   if (y>ny-1) return 0.0;
00106   return vil_bilin_interp_raw(x,y,data,xstep,ystep);
00107 }
00108 
00109 
00110 //: Compute bilinear interpolation at (x,y), with bound checks
00111 //  Image is nx * ny array of Ts. x,y element is data[xstep*x+ystep*y]
00112 //  If (x,y) is outside interpolatable image region, NA is returned.
00113 //  The safe interpolatable region is [0,nx-1]*[0,ny-1].
00114 template<class T>
00115 inline double vil_bilin_interp_safe_edgena(double x, double y, const T* data,
00116                                            int nx, int ny,
00117                                            vcl_ptrdiff_t xstep, vcl_ptrdiff_t ystep)
00118 {
00119   if (x<0 || y<0 || x>nx-1 || y>ny-1) return vil_na(double());
00120   return vil_bilin_interp_raw(x,y,data,xstep,ystep);
00121 }
00122 
00123 //: Compute bilinear interpolation at (x,y), with bound checks
00124 //  If (x,y) is outside interpolatable image region, zero is returned.
00125 //  The safe interpolatable region is [0,view.ni()-1]*[0,view.nj()-1].
00126 // \relatesalso vil_image_view
00127 template<class T>
00128 inline double vil_bilin_interp_safe(const vil_image_view<T> &view,
00129                                     double x, double y, unsigned p=0)
00130 {
00131   return vil_bilin_interp_safe(x, y, &view(0,0,p),
00132                                view.ni(), view.nj(),
00133                                view.istep(), view.jstep());
00134 }
00135 
00136 
00137 //: Compute bilinear interpolation at (x,y), with bound checks
00138 //  If (x,y) is outside interpolatable image region, NA is returned.
00139 //  The safe interpolatable region is [0,view.ni()-1]*[0,view.nj()-1].
00140 // \relatesalso vil_image_view
00141 template<class T>
00142 inline double vil_bilin_interp_safe_edgena(const vil_image_view<T> &view,
00143                                            double x, double y, unsigned p=0)
00144 {
00145   return vil_bilin_interp_safe_edgena(x, y, &view(0,0,p),
00146                                       view.ni(), view.nj(),
00147                                       view.istep(), view.jstep());
00148 }
00149 
00150 //: Compute bilinear interpolation at (x,y), with minimal bound checks
00151 //  Image is nx * ny array of Ts. x,y element is data[ystep*y+xstep*x]
00152 //  If (x,y) is outside interpolatable image region and NDEBUG is not defined
00153 //  the code will fail an ASSERT.
00154 //  The safe interpolatable region is [0,nx-1]*[0,ny-1].
00155 template<class T>
00156 inline double vil_bilin_interp(double x, double y, const T* data,
00157                                int nx, int ny,
00158                                vcl_ptrdiff_t xstep, vcl_ptrdiff_t ystep)
00159 {
00160   assert (x>=0);
00161   assert (y>=0);
00162   assert (x<=nx-1);
00163   assert (y<=ny-1);
00164   return vil_bilin_interp_raw(x,y,data,xstep,ystep);
00165 }
00166 
00167 //: Compute bilinear interpolation at (x,y), with minimal bound checks
00168 //  If (x,y) is outside interpolatable image region and NDEBUG is not defined
00169 //  the code will fail an ASSERT.
00170 //  The safe interpolatable region is [0,view.ni()-1]*[0,view.nj()-1].
00171 // \relatesalso vil_image_view
00172 template<class T>
00173 inline double vil_bilin_interp(const vil_image_view<T> &view,
00174                                double x, double y, unsigned p=0)
00175 {
00176   return vil_bilin_interp(x, y, &view(0,0,p),
00177                           view.ni(), view.nj(),
00178                           view.istep(), view.jstep());
00179 }
00180 
00181 
00182 //: Compute bilinear interpolation at (x,y), with bound checks
00183 //  Image is nx * ny array of Ts. x,y element is data[nx*y+x]
00184 //  If (x,y) is outside safe interpolatable image region, nearest pixel value is returned.
00185 //  The safe interpolatable region is [0,nx-1]*[0,ny-1].
00186 template<class T>
00187 inline double vil_bilin_interp_safe_extend(double x, double y, const T* data,
00188                                            int nx, int ny,
00189                                            vcl_ptrdiff_t xstep, vcl_ptrdiff_t ystep)
00190 {
00191   if (x<0) x= 0.0;
00192   if (y<0) y= 0.0;
00193   if (x>nx-1) x=nx-1.0;
00194   if (y>ny-1) y=ny-1.0;
00195   return vil_bilin_interp_raw(x,y,data,xstep,ystep);
00196 }
00197 
00198 //: Compute bilinear interpolation at (x,y), with bound checks
00199 //  If (x,y) is outside safe interpolatable image region, nearest pixel value is returned.
00200 //  The safe interpolatable region is [0,view.ni()-1]*[0,view.nj()-1].
00201 // \relatesalso vil_image_view
00202 template<class T>
00203 inline double vil_bilin_interp_safe_extend(const vil_image_view<T> &view,
00204                                            double x, double y, unsigned p=0)
00205 {
00206   return vil_bilin_interp_safe_extend(x, y, &view(0,0,p),
00207                                       view.ni(), view.nj(),
00208                                       view.istep(), view.jstep());
00209 }
00210 
00211 #endif // vil_bilin_interp_h_