contrib/mul/vil3d/vil3d_resample_trilinear.txx
Go to the documentation of this file.
00001 // This is mul/vil3d/vil3d_resample_trilinear.txx
00002 #ifndef vil3d_resample_trilinear_txx_
00003 #define vil3d_resample_trilinear_txx_
00004 //:
00005 // \file
00006 // \brief Resample a 3D image by a different factor in each dimension
00007 // \author Kevin de Souza, Ian Scott
00008 
00009 #include "vil3d_resample_trilinear.h"
00010 
00011 #include <vil/vil_convert.h>
00012 #include <vil3d/vil3d_trilin_interp.h>
00013 #include <vil3d/vil3d_plane.h>
00014 #include <vcl_cassert.h>
00015 
00016 
00017 inline bool vil3d_grid_corner_in_image(double x0, double y0, double z0,
00018                                        const vil3d_image_view_base& image)
00019 {
00020   if (x0<0.0) return false;
00021   if (x0>image.ni()-1.0) return false;
00022   if (y0<0.0) return false;
00023   if (y0>image.nj()-1.0) return false;
00024   if (z0<0.0) return false;
00025   if (z0>image.nk()-1.0) return false;
00026   return true;
00027 }
00028 
00029 
00030 //  Sample grid of points in one image and place in another, using trilinear interpolation.
00031 //  dest_image(i,j,k,p) is sampled from the src_image at
00032 //  (x0+i.dx1+j.dx2+k.dx3, y0+i.dy1+j.dy2+k.dy3, z0+i.dz1+j.dz2+k.dz3),
00033 //  where i=[0..n1-1], j=[0..n2-1], k=[0..n3-1]
00034 //  dest_image resized to (n1,n2,n3,src_image.nplanes())
00035 //  Points outside image return value of nearest pixel.
00036 template <class S, class T>
00037 void vil3d_resample_trilinear_edge_extend(const vil3d_image_view<S>& src_image,
00038                                           vil3d_image_view<T>& dest_image,
00039                                           double x0, double y0, double z0,
00040                                           double dx1, double dy1, double dz1,
00041                                           double dx2, double dy2, double dz2,
00042                                           double dx3, double dy3, double dz3,
00043                                           int n1, int n2, int n3)
00044 {
00045   bool all_in_image =
00046     vil3d_grid_corner_in_image(x0,
00047                                y0,
00048                                z0,
00049                                src_image) &&
00050     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1,
00051                                y0 + (n1-1)*dy1,
00052                                z0 + (n1-1)*dz1,
00053                                src_image) &&
00054     vil3d_grid_corner_in_image(x0 + (n2-1)*dx2,
00055                                y0 + (n2-1)*dy2,
00056                                z0 + (n2-1)*dz2,
00057                                src_image) &&
00058     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1 + (n2-1)*dx2,
00059                                y0 + (n1-1)*dy1 + (n2-1)*dy2,
00060                                z0 + (n1-1)*dz1 + (n2-1)*dz2,
00061                                src_image) &&
00062     vil3d_grid_corner_in_image(x0 + (n3-1)*dx3,
00063                                y0 + (n3-1)*dy3,
00064                                z0 + (n3-1)*dz3,
00065                                src_image) &&
00066     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1 + (n3-1)*dx3,
00067                                y0 + (n1-1)*dy1 + (n3-1)*dy3,
00068                                z0 + (n1-1)*dz1 + (n3-1)*dz3,
00069                                src_image) &&
00070     vil3d_grid_corner_in_image(x0 + (n2-1)*dx2 + (n3-1)*dx3,
00071                                y0 + (n2-1)*dy2 + (n3-1)*dy3,
00072                                z0 + (n2-1)*dz2 + (n3-1)*dz3,
00073                                src_image) &&
00074     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1 + (n2-1)*dx2 + (n3-1)*dx3,
00075                                y0 + (n1-1)*dy1 + (n2-1)*dy2 + (n3-1)*dy3,
00076                                z0 + (n1-1)*dz1 + (n2-1)*dz2 + (n3-1)*dz3,
00077                                src_image);
00078 
00079   vil_convert_round_pixel<double, T> cast_and_possibly_round;
00080   // Rounds only if T is int, unsigned or kind of. Doesn't round if T
00081   // is float, double or kind of.
00082 
00083   const unsigned ni = src_image.ni();
00084   const unsigned nj = src_image.nj();
00085   const unsigned nk = src_image.nk();
00086   const unsigned np = src_image.nplanes();
00087   const vcl_ptrdiff_t istep = src_image.istep();
00088   const vcl_ptrdiff_t jstep = src_image.jstep();
00089   const vcl_ptrdiff_t kstep = src_image.kstep();
00090   const vcl_ptrdiff_t pstep = src_image.planestep();
00091   const S* plane0 = src_image.origin_ptr();
00092 
00093   dest_image.set_size(n1,n2,n3,np);
00094   const vcl_ptrdiff_t d_istep = dest_image.istep();
00095   const vcl_ptrdiff_t d_jstep = dest_image.jstep();
00096   const vcl_ptrdiff_t d_kstep = dest_image.kstep();
00097   const vcl_ptrdiff_t d_pstep = dest_image.planestep();
00098   T* d_plane0 = dest_image.origin_ptr();
00099 
00100   if (all_in_image)
00101   {
00102     if (np==1)
00103     {
00104       double xk=x0, yk=y0, zk=z0;
00105       T *slice = d_plane0;
00106       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00107       {
00108         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00109         T *row = slice;
00110         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00111         {
00112           double x=xj, y=yj, z=zj;  // Start of j-th row
00113           T *dpt = row;
00114           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00115             cast_and_possibly_round( vil3d_trilin_interp_raw( x, y, z,
00116                                                               plane0,
00117                                                               istep, jstep, kstep ),
00118                                     *dpt);
00119         }
00120       }
00121     }
00122     else
00123     {
00124       double xk=x0, yk=y0, zk=z0;
00125       T *slice = d_plane0;
00126       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00127       {
00128         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00129         T *row = slice;
00130         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00131         {
00132           double x=xj, y=yj, z=zj;  // Start of j-th row
00133           T *dpt = row;
00134           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00135           {
00136             for (unsigned int p=0; p<np; ++p)
00137               cast_and_possibly_round( vil3d_trilin_interp_raw( x, y, z,
00138                                                                 plane0+p*pstep,
00139                                                                 istep, jstep, kstep),
00140                                        dpt[p*d_pstep]);
00141           }
00142         }
00143       }
00144     }
00145   }
00146   else
00147   {
00148     // Use safe interpolation with edge-extension
00149     if (np==1)
00150     {
00151       double xk=x0, yk=y0, zk=z0;
00152       T *slice = d_plane0;
00153       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00154       {
00155         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00156         T *row = slice;
00157         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00158         {
00159           double x=xj, y=yj, z=zj;  // Start of j-th row
00160           T *dpt = row;
00161           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00162             cast_and_possibly_round( vil3d_trilin_interp_safe_extend( x, y, z,
00163                                                                       plane0,
00164                                                                       ni, nj, nk,
00165                                                                       istep, jstep, kstep),
00166                                      *dpt );
00167         }
00168       }
00169     }
00170     else
00171     {
00172       double xk=x0, yk=y0, zk=z0;
00173       T *slice = d_plane0;
00174       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00175       {
00176         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00177         T *row = slice;
00178         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00179         {
00180           double x=xj, y=yj, z=zj;  // Start of j-th row
00181           T *dpt = row;
00182           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00183           {
00184             for (unsigned int p=0; p<np; ++p)
00185               cast_and_possibly_round( vil3d_trilin_interp_safe_extend( x, y, z,
00186                                                                         plane0+p*pstep,
00187                                                                         ni, nj, nk,
00188                                                                         istep, jstep, kstep),
00189                                        dpt[p*d_pstep] );
00190           }
00191         }
00192       }
00193     }
00194   }
00195 }
00196 
00197 
00198 
00199 //  Sample grid of points in one image and place in another, using trilinear interpolation.
00200 //  dest_image(i,j,k,p) is sampled from the src_image at
00201 //  (x0+i.dx1+j.dx2+k.dx3, y0+i.dy1+j.dy2+k.dy3, z0+i.dz1+j.dz2+k.dz3),
00202 //  where i=[0..n1-1], j=[0..n2-1], k=[0..n3-1]
00203 //  dest_image resized to (n1,n2,n3,src_image.nplanes())
00204 //  Points outside image return zero or \a outval
00205 template <class S, class T>
00206 void vil3d_resample_trilinear(const vil3d_image_view<S>& src_image,
00207                               vil3d_image_view<T>& dest_image,
00208                               double x0, double y0, double z0,
00209                               double dx1, double dy1, double dz1,
00210                               double dx2, double dy2, double dz2,
00211                               double dx3, double dy3, double dz3,
00212                               int n1, int n2, int n3,
00213                               T outval/*=0*/, double edge_tol/*=0*/)
00214 {
00215   bool all_in_image =
00216     vil3d_grid_corner_in_image(x0,
00217                                y0,
00218                                z0,
00219                                src_image) &&
00220     vil3d_grid_corner_in_image(x0 + (n1-1+edge_tol)*dx1,
00221                                y0 + (n1-1+edge_tol)*dy1,
00222                                z0 + (n1-1+edge_tol)*dz1,
00223                                src_image) &&
00224     vil3d_grid_corner_in_image(x0 + (n2-1+edge_tol)*dx2,
00225                                y0 + (n2-1+edge_tol)*dy2,
00226                                z0 + (n2-1+edge_tol)*dz2,
00227                                src_image) &&
00228     vil3d_grid_corner_in_image(x0 + (n1-1+edge_tol)*dx1 + (n2-1+edge_tol)*dx2,
00229                                y0 + (n1-1+edge_tol)*dy1 + (n2-1+edge_tol)*dy2,
00230                                z0 + (n1-1+edge_tol)*dz1 + (n2-1+edge_tol)*dz2,
00231                                src_image) &&
00232     vil3d_grid_corner_in_image(x0 + (n3-1+edge_tol)*dx3,
00233                                y0 + (n3-1+edge_tol)*dy3,
00234                                z0 + (n3-1+edge_tol)*dz3,
00235                                src_image) &&
00236     vil3d_grid_corner_in_image(x0 + (n1-1+edge_tol)*dx1 + (n3-1+edge_tol)*dx3,
00237                                y0 + (n1-1+edge_tol)*dy1 + (n3-1+edge_tol)*dy3,
00238                                z0 + (n1-1+edge_tol)*dz1 + (n3-1+edge_tol)*dz3,
00239                                src_image) &&
00240     vil3d_grid_corner_in_image(x0 + (n2-1+edge_tol)*dx2 + (n3-1+edge_tol)*dx3,
00241                                y0 + (n2-1+edge_tol)*dy2 + (n3-1+edge_tol)*dy3,
00242                                z0 + (n2-1+edge_tol)*dz2 + (n3-1+edge_tol)*dz3,
00243                                src_image) &&
00244     vil3d_grid_corner_in_image(x0 + (n1-1+edge_tol)*dx1 + (n2-1+edge_tol)*dx2 + (n3-1+edge_tol)*dx3,
00245                                y0 + (n1-1+edge_tol)*dy1 + (n2-1+edge_tol)*dy2 + (n3-1+edge_tol)*dy3,
00246                                z0 + (n1-1+edge_tol)*dz1 + (n2-1+edge_tol)*dz2 + (n3-1+edge_tol)*dz3,
00247                                src_image);
00248 
00249   vil_convert_round_pixel<double, T> cast_and_possibly_round;
00250 
00251   const unsigned ni = src_image.ni();
00252   const unsigned nj = src_image.nj();
00253   const unsigned nk = src_image.nk();
00254   const unsigned np = src_image.nplanes();
00255   const vcl_ptrdiff_t istep = src_image.istep();
00256   const vcl_ptrdiff_t jstep = src_image.jstep();
00257   const vcl_ptrdiff_t kstep = src_image.kstep();
00258   const vcl_ptrdiff_t pstep = src_image.planestep();
00259   const S* plane0 = src_image.origin_ptr();
00260 
00261   dest_image.set_size(n1,n2,n3,np);
00262   const vcl_ptrdiff_t d_istep = dest_image.istep();
00263   const vcl_ptrdiff_t d_jstep = dest_image.jstep();
00264   const vcl_ptrdiff_t d_kstep = dest_image.kstep();
00265   const vcl_ptrdiff_t d_pstep = dest_image.planestep();
00266   T* d_plane0 = dest_image.origin_ptr();
00267 
00268   if (all_in_image)
00269   {
00270     if (np==1)
00271     {
00272       double xk=x0, yk=y0, zk=z0;
00273       T *slice = d_plane0;
00274       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00275       {
00276         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00277         T *row = slice;
00278         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00279         {
00280           double x=xj, y=yj, z=zj;  // Start of j-th row
00281           T *dpt = row;
00282           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00283             cast_and_possibly_round( vil3d_trilin_interp_raw( x, y, z,
00284                                                               plane0,
00285                                                               istep, jstep, kstep),
00286                                      *dpt);
00287         }
00288       }
00289     }
00290     else
00291     {
00292       double xk=x0, yk=y0, zk=z0;
00293       T *slice = d_plane0;
00294       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00295       {
00296         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00297         T *row = slice;
00298         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00299         {
00300           double x=xj, y=yj, z=zj;  // Start of j-th row
00301           T *dpt = row;
00302           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00303           {
00304             for (unsigned int p=0; p<np; ++p)
00305               cast_and_possibly_round( vil3d_trilin_interp_raw( x, y, z,
00306                                                                 plane0+p*pstep,
00307                                                                 istep, jstep, kstep),
00308                                        dpt[p*d_pstep]);
00309           }
00310         }
00311       }
00312     }
00313   }
00314   else
00315   {
00316     // Use safe interpolation
00317     if (np==1)
00318     {
00319       double xk=x0, yk=y0, zk=z0;
00320       T *slice = d_plane0;
00321       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00322       {
00323         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00324         T *row = slice;
00325         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00326         {
00327           double x=xj, y=yj, z=zj;  // Start of j-th row
00328           T *dpt = row;
00329           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00330             cast_and_possibly_round( vil3d_trilin_interp_safe( x, y, z,
00331                                                                plane0,
00332                                                                ni, nj, nk,
00333                                                                istep, jstep, kstep, outval),
00334                                      *dpt);
00335         }
00336       }
00337     }
00338     else
00339     {
00340       double xk=x0, yk=y0, zk=z0;
00341       T *slice = d_plane0;
00342       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00343       {
00344         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00345         T *row = slice;
00346         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00347         {
00348           double x=xj, y=yj, z=zj;  // Start of j-th row
00349           T *dpt = row;
00350           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00351           {
00352             for (unsigned int p=0; p<np; ++p)
00353               cast_and_possibly_round( vil3d_trilin_interp_safe( x, y, z,
00354                                                                  plane0+p*pstep,
00355                                                                  ni, nj, nk,
00356                                                                  istep, jstep, kstep, outval),
00357                                        dpt[p*d_pstep]);
00358           }
00359         }
00360       }
00361     }
00362   }
00363 }
00364 
00365 
00366 //  Resample image to a specified dimensions (n1 * n2 * n3)
00367 template <class S, class T>
00368 void vil3d_resample_trilinear(const vil3d_image_view<S>& src_image,
00369                               vil3d_image_view<T>& dest_image,
00370                               int n1, int n2, int n3)
00371 {
00372   double f= 0.9999999; // so sampler doesn't go off edge of image
00373   double x0=0;
00374   double y0=0;
00375   double z0=0;
00376 
00377   double dx1=f*(src_image.ni()-1)*1.0/(n1-1);
00378   double dy1=0;
00379   double dz1=0;
00380 
00381   double dx2=0;
00382   double dy2=f*(src_image.nj()-1)*1.0/(n2-1);
00383   double dz2=0;
00384 
00385   double dx3=0;
00386   double dy3=0;
00387   double dz3=f*(src_image.nk()-1)*1.0/(n3-1);
00388 
00389   vil3d_resample_trilinear(src_image, dest_image, x0, y0, z0, dx1, dy1, dz1,
00390                            dx2, dy2, dz2, dx3, dy3, dz3, n1, n2, n3);
00391 }
00392 
00393 
00394 // Resample a 3D image by a different factor in each dimension.
00395 // Note: The upper image boundaries are extended.
00396 template <class T>
00397 void vil3d_resample_trilinear(const vil3d_image_view<T>& src_image,
00398                               vil3d_image_view<T>& dst_image,
00399                               const double dx,
00400                               const double dy,
00401                               const double dz)
00402 {
00403   assert (dx > 0.0 && dy > 0.0 && dz > 0.0);
00404 
00405   // Assume planes are the same for both images
00406   const unsigned np = src_image.nplanes();
00407 
00408   const unsigned sni = src_image.ni();
00409   const unsigned snj = src_image.nj();
00410   const unsigned snk = src_image.nk();
00411   const vcl_ptrdiff_t s_istep = src_image.istep();
00412   const vcl_ptrdiff_t s_jstep = src_image.jstep();
00413   const vcl_ptrdiff_t s_kstep = src_image.kstep();
00414   const vcl_ptrdiff_t s_pstep = src_image.planestep();
00415   const T* s_plane = src_image.origin_ptr();
00416 
00417   const unsigned dni = static_cast<unsigned>(sni*dx);
00418   const unsigned dnj = static_cast<unsigned>(snj*dy);
00419   const unsigned dnk = static_cast<unsigned>(snk*dz);
00420   dst_image.set_size(dni, dnj, dnk, np);
00421   const vcl_ptrdiff_t d_istep = dst_image.istep();
00422   const vcl_ptrdiff_t d_jstep = dst_image.jstep();
00423   const vcl_ptrdiff_t d_kstep = dst_image.kstep();
00424   const vcl_ptrdiff_t d_pstep = dst_image.planestep();
00425   T* d_plane = dst_image.origin_ptr();
00426 
00427   // Use this to convert from double to T with appropriate rounding
00428   vil_convert_round_pixel<double, T> cast_and_possibly_round;
00429 
00430   // Loop over all voxels in the destination image
00431   // and sample from the corresponding point in the source image
00432   // (except near upper boundaries).
00433   for (unsigned p=0; p<np; ++p, s_plane+=s_pstep, d_plane+=d_pstep)
00434   {
00435     T* d_slice = d_plane;
00436     for (unsigned k=0; k<static_cast<unsigned>(dnk-dz); ++k, d_slice+=d_kstep)
00437     {
00438       T* d_row = d_slice;
00439       for (unsigned j=0; j<static_cast<unsigned>(dnj-dy); ++j, d_row+=d_jstep)
00440       {
00441         T* d_pix = d_row;
00442         for (unsigned i=0; i<static_cast<unsigned>(dni-dx); ++i, d_pix+=d_istep)
00443         {
00444           cast_and_possibly_round( vil3d_trilin_interp_raw( i/dx, j/dy, k/dz,
00445                                                             s_plane,
00446                                                             s_istep, s_jstep, s_kstep),
00447                                    *d_pix);
00448         }
00449         // Process the pixels near the upper i boundary - safe_extend interpolation
00450         for (unsigned i=static_cast<unsigned>(dni-dx); i<dni; ++i, d_pix+=d_istep)
00451         {
00452           cast_and_possibly_round( vil3d_trilin_interp_safe_extend(i/dx, j/dy, k/dz,
00453                                                                    s_plane,
00454                                                                    sni, snj, snk,
00455                                                                    s_istep, s_jstep, s_kstep),
00456                                    *d_pix);
00457         }
00458       }
00459 
00460       // Process the pixels near the upper j boundary - safe_extend interpolation
00461       for (unsigned j=static_cast<unsigned>(dnj-dy); j<dnj; ++j, d_row+=d_jstep)
00462       {
00463         T* d_pix = d_row;
00464         for (unsigned i=0; i<dni; ++i, d_pix+=d_istep)
00465         {
00466           cast_and_possibly_round( vil3d_trilin_interp_safe_extend( i/dx, j/dy, k/dz,
00467                                                                     s_plane,
00468                                                                     sni, snj, snk,
00469                                                                     s_istep, s_jstep, s_kstep),
00470                                    *d_pix);
00471         }
00472       }
00473     }
00474 
00475     // Process the pixels near the upper k boundary - safe_extend interpolation
00476     for (unsigned k=static_cast<unsigned>(dnk-dz); k<dnk; ++k, d_slice+=d_kstep)
00477     {
00478       T* d_row = d_slice;
00479       for (unsigned j=0; j<dnj; ++j, d_row+=d_jstep)
00480       {
00481         T* d_pix = d_row;
00482         for (unsigned i=0; i<dni; ++i, d_pix+=d_istep)
00483         {
00484           cast_and_possibly_round( vil3d_trilin_interp_safe_extend( i/dx, j/dy, k/dz,
00485                                                                     s_plane,
00486                                                                     sni, snj, snk,
00487                                                                     s_istep, s_jstep, s_kstep),
00488                                    *d_pix);
00489         }
00490       }
00491     }
00492   }
00493 }
00494 
00495 
00496 template <class T>
00497 void vil3d_resample_trilinear_scale_2(
00498   const vil3d_image_view<T>& src_im,
00499   vil3d_image_view<T>& dest_im)
00500 {
00501   // Assume planes are the same for both images
00502   const unsigned np = src_im.nplanes();
00503 
00504   const unsigned ni = src_im.ni();
00505   const unsigned nj = src_im.nj();
00506   const unsigned nk = src_im.nk();
00507   dest_im.set_size(ni*2-1, nj*2-1, nk*2-1, np);
00508 
00509   for (unsigned p = 0; p<np; ++p)
00510   {
00511     const vil3d_image_view<T> src = vil3d_plane(src_im, p);
00512     vil3d_image_view<T> dest = vil3d_plane(dest_im, p);
00513 
00514     for (unsigned k=0; k<nk-1; ++k)
00515     {
00516       for (unsigned j=0; j<nj-1; ++j)
00517       {
00518         // Do all except last slice.
00519         for (unsigned i=0; i<ni-1; ++i)
00520         {
00521           // s0-s7 are the values at 8 neighbouring positions (on a cube) in src.
00522           // d0-d7 are the values at 8 neighbouring positions (on a cube of 1/8 the above cube's size) in dest.
00523           // They are aligned so that s0 = d0.
00524           // d6t2 is the value of d6 time 2, etc.
00525           T s0 = src(i,j,k);
00526           T s1 = src(i+1, j  , k  );
00527           T s2 = src(i,   j+1, k  );
00528           T s3 = src(i+1, j+1, k  );
00529           T s4 = src(i  , j  , k+1);
00530           T s5 = src(i+1, j  , k+1);
00531           T s6 = src(i  , j+1, k+1);
00532           T s7 = src(i+1, j+1, k+1);
00533                                     dest(2*i  , 2*j  , 2*k  ) = s0;
00534           T d1t2 = s0+s1;           dest(2*i+1, 2*j  , 2*k  ) = d1t2/2;
00535           T d2t2 = s0+s2;           dest(2*i  , 2*j+1, 2*k  ) = d2t2/2;
00536           T d4t2 = s0+s4;           dest(2*i  , 2*j  , 2*k+1) = d4t2/2;
00537           T d3t4 = d2t2 + s1+s3;    dest(2*i+1, 2*j+1, 2*k  ) = d3t4/4;
00538           T d5t4 = d4t2 + s1+s5;    dest(2*i+1, 2*j  , 2*k+1) = d5t4/4;
00539           T d6t4 = d4t2 + s2+s6;    dest(2*i  , 2*j+1, 2*k+1) = d6t4/4;
00540                                     dest(2*i+1, 2*j+1, 2*k+1) = (d6t4 + s1+s3+s5+s7)/8;
00541         }
00542         T s0 = src(ni-1, j  , k  );
00543         T s2 = src(ni-1, j+1, k  );
00544         T s4 = src(ni-1, j  , k+1);
00545         T s6 = src(ni-1, j+1, k+1);
00546         dest(ni*2-2, j*2  , k*2  ) = s0;
00547         dest(ni*2-2, j*2+1, k*2  ) = (s0 + s2)/2;
00548         dest(ni*2-2, j*2  , k*2+1) = (s0 + s4)/2;
00549         dest(ni*2-2, j*2+1, k*2+1) = (s0 + s2 + s4 + s6)/4;
00550       }
00551       // Do last plane
00552       for (unsigned i=0; i<ni-1; ++i)
00553       {
00554         T s0 = src(i  , nj-1, k  );
00555         T s1 = src(i+1, nj-1, k  );
00556         T s4 = src(i  , nj-1, k+1);
00557         T s5 = src(i+1, nj-1, k+1);
00558         dest(i*2  , nj*2-2, k*2  ) = s0;
00559         dest(i*2+1, nj*2-2, k*2  ) = (s0 + s1)/2;
00560         dest(i*2  , nj*2-2, k*2+1) = (s0 + s4)/2;
00561         dest(i*2+1, nj*2-2, k*2+1) = (s0 + s1 + s4 + s5)/4;
00562       }
00563       T s0 = src(ni-1, nj-1, k);
00564       dest(ni*2-2, nj*2-2, k*2  ) = s0;
00565       dest(ni*2-2, nj*2-2, k*2+1) = (s0 + src(ni-1, nj-1, k+1))/2;
00566     }
00567     // Do last plane
00568     for (unsigned j=0; j<nj-1; ++j)
00569     {
00570       for (unsigned i=0; i<ni-1; ++i)
00571       {
00572         T s0 = src(i  , j  , nk-1);
00573         T s1 = src(i+1, j  , nk-1);
00574         T s2 = src(i  , j+1, nk-1);
00575         T s3 = src(i+1, j+1, nk-1);
00576         dest(i*2  , j*2  , nk*2-2) = s0;
00577         dest(i*2+1, j*2  , nk*2-2) = (s0 + s1)/2;
00578         dest(i*2  , j*2+1, nk*2-2) = (s0 + s2)/2;
00579         dest(i*2+1, j*2+1, nk*2-2) = (s0 + s1 + s2 + s3)/4;
00580       }
00581       T s0 = src(ni-1, j, nk-1);
00582       dest(ni*2-2, j*2  , nk*2-2) = s0;
00583       dest(ni*2-2, j*2+1, nk*2-2) = (s0 + src(ni-1, j+1, nk-1))/2;
00584     }
00585     for (unsigned i=0; i<ni-1; ++i)
00586     {
00587       T s0 = src(i, nj-1, nk-1);
00588       dest(i*2  , nj*2-2, nk*2-2) = s0;
00589       dest(i*2+1, nj*2-2, nk*2-2) = (s0 + src(i+1, nj-1, nk-1))/2;
00590     }
00591     dest(ni*2-2, nj*2-2, nk*2-2) = src(ni-1, nj-1, nk-1);
00592   }
00593 }
00594 
00595 
00596 #define VIL3D_RESAMPLE_TRILINEAR_INSTANTIATE( T, S ) \
00597 template void vil3d_resample_trilinear(const vil3d_image_view< S >& src_image, \
00598                                        vil3d_image_view< T >& dest_image, \
00599                                        double x0, double y0, double z0, \
00600                                        double dx1, double dy1, double dz1, \
00601                                        double dx2, double dy2, double dz2, \
00602                                        double dx3, double dy3, double dz3, \
00603                                        int n1, int n2, int n3, \
00604                                        T outval, double edge_tol); \
00605 template void vil3d_resample_trilinear_edge_extend(const vil3d_image_view< S >& src_image, \
00606                                                    vil3d_image_view< T >& dest_image, \
00607                                                    double x0, double y0, double z0, \
00608                                                    double dx1, double dy1, double dz1, \
00609                                                    double dx2, double dy2, double dz2, \
00610                                                    double dx3, double dy3, double dz3, \
00611                                                    int n1, int n2, int n3); \
00612 template void vil3d_resample_trilinear(const vil3d_image_view< S >& src_image, \
00613                                        vil3d_image_view< T >& dest_image, \
00614                                        int n1, int n2, int n3); \
00615 template void vil3d_resample_trilinear(const vil3d_image_view< T >& src_image, \
00616                                        vil3d_image_view< T >& dst_image, \
00617                                        const double dx, \
00618                                        const double dy, \
00619                                        const double dz); \
00620 template void vil3d_resample_trilinear_scale_2(const vil3d_image_view< T >& src_image, \
00621                                                vil3d_image_view< T >& dst_image)
00622 
00623 #endif // vil3d_resample_trilinear_txx_