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 vil3dresample_trilin_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     vil3dresample_trilin_corner_in_image(x0,
00047                                          y0,
00048                                          z0,
00049                                          src_image) &&
00050     vil3dresample_trilin_corner_in_image(x0 + (n1-1)*dx1,
00051                                          y0 + (n1-1)*dy1,
00052                                          z0 + (n1-1)*dz1,
00053                                          src_image) &&
00054     vil3dresample_trilin_corner_in_image(x0 + (n2-1)*dx2,
00055                                          y0 + (n2-1)*dy2,
00056                                          z0 + (n2-1)*dz2,
00057                                          src_image) &&
00058     vil3dresample_trilin_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     vil3dresample_trilin_corner_in_image(x0 + (n3-1)*dx3,
00063                                          y0 + (n3-1)*dy3,
00064                                          z0 + (n3-1)*dz3,
00065                                          src_image) &&
00066     vil3dresample_trilin_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     vil3dresample_trilin_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     vil3dresample_trilin_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 //  Sample grid of points in one image and place in another, using trilinear interpolation.
00199 //  dest_image(i,j,k,p) is sampled from the src_image at
00200 //  (x0+i.dx1+j.dx2+k.dx3, y0+i.dy1+j.dy2+k.dy3, z0+i.dz1+j.dz2+k.dz3),
00201 //  where i=[0..n1-1], j=[0..n2-1], k=[0..n3-1]
00202 //  dest_image resized to (n1,n2,n3,src_image.nplanes())
00203 //  Points outside image return zero or \a outval
00204 template <class S, class T>
00205 void vil3d_resample_trilinear(const vil3d_image_view<S>& src_image,
00206                               vil3d_image_view<T>& dest_image,
00207                               double x0, double y0, double z0,
00208                               double dx1, double dy1, double dz1,
00209                               double dx2, double dy2, double dz2,
00210                               double dx3, double dy3, double dz3,
00211                               int n1, int n2, int n3,
00212                               T outval/*=0*/, double edge_tol/*=0*/)
00213 {
00214   bool all_in_image =
00215     vil3dresample_trilin_corner_in_image(x0,
00216                                          y0,
00217                                          z0,
00218                                          src_image) &&
00219     vil3dresample_trilin_corner_in_image(x0 + (n1-1+edge_tol)*dx1,
00220                                          y0 + (n1-1+edge_tol)*dy1,
00221                                          z0 + (n1-1+edge_tol)*dz1,
00222                                          src_image) &&
00223     vil3dresample_trilin_corner_in_image(x0 + (n2-1+edge_tol)*dx2,
00224                                          y0 + (n2-1+edge_tol)*dy2,
00225                                          z0 + (n2-1+edge_tol)*dz2,
00226                                          src_image) &&
00227     vil3dresample_trilin_corner_in_image(x0 + (n1-1+edge_tol)*dx1 + (n2-1+edge_tol)*dx2,
00228                                          y0 + (n1-1+edge_tol)*dy1 + (n2-1+edge_tol)*dy2,
00229                                          z0 + (n1-1+edge_tol)*dz1 + (n2-1+edge_tol)*dz2,
00230                                          src_image) &&
00231     vil3dresample_trilin_corner_in_image(x0 + (n3-1+edge_tol)*dx3,
00232                                          y0 + (n3-1+edge_tol)*dy3,
00233                                          z0 + (n3-1+edge_tol)*dz3,
00234                                          src_image) &&
00235     vil3dresample_trilin_corner_in_image(x0 + (n1-1+edge_tol)*dx1 + (n3-1+edge_tol)*dx3,
00236                                          y0 + (n1-1+edge_tol)*dy1 + (n3-1+edge_tol)*dy3,
00237                                          z0 + (n1-1+edge_tol)*dz1 + (n3-1+edge_tol)*dz3,
00238                                          src_image) &&
00239     vil3dresample_trilin_corner_in_image(x0 + (n2-1+edge_tol)*dx2 + (n3-1+edge_tol)*dx3,
00240                                          y0 + (n2-1+edge_tol)*dy2 + (n3-1+edge_tol)*dy3,
00241                                          z0 + (n2-1+edge_tol)*dz2 + (n3-1+edge_tol)*dz3,
00242                                          src_image) &&
00243     vil3dresample_trilin_corner_in_image(x0 + (n1-1+edge_tol)*dx1 + (n2-1+edge_tol)*dx2 + (n3-1+edge_tol)*dx3,
00244                                          y0 + (n1-1+edge_tol)*dy1 + (n2-1+edge_tol)*dy2 + (n3-1+edge_tol)*dy3,
00245                                          z0 + (n1-1+edge_tol)*dz1 + (n2-1+edge_tol)*dz2 + (n3-1+edge_tol)*dz3,
00246                                          src_image);
00247 
00248   vil_convert_round_pixel<double, T> cast_and_possibly_round;
00249 
00250   const unsigned ni = src_image.ni();
00251   const unsigned nj = src_image.nj();
00252   const unsigned nk = src_image.nk();
00253   const unsigned np = src_image.nplanes();
00254   const vcl_ptrdiff_t istep = src_image.istep();
00255   const vcl_ptrdiff_t jstep = src_image.jstep();
00256   const vcl_ptrdiff_t kstep = src_image.kstep();
00257   const vcl_ptrdiff_t pstep = src_image.planestep();
00258   const S* plane0 = src_image.origin_ptr();
00259 
00260   dest_image.set_size(n1,n2,n3,np);
00261   const vcl_ptrdiff_t d_istep = dest_image.istep();
00262   const vcl_ptrdiff_t d_jstep = dest_image.jstep();
00263   const vcl_ptrdiff_t d_kstep = dest_image.kstep();
00264   const vcl_ptrdiff_t d_pstep = dest_image.planestep();
00265   T* d_plane0 = dest_image.origin_ptr();
00266 
00267   if (all_in_image)
00268   {
00269     if (np==1)
00270     {
00271       double xk=x0, yk=y0, zk=z0;
00272       T *slice = d_plane0;
00273       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00274       {
00275         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00276         T *row = slice;
00277         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00278         {
00279           double x=xj, y=yj, z=zj;  // Start of j-th row
00280           T *dpt = row;
00281           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00282             cast_and_possibly_round( vil3d_trilin_interp_raw( x, y, z,
00283                                                               plane0,
00284                                                               istep, jstep, kstep),
00285                                      *dpt);
00286         }
00287       }
00288     }
00289     else
00290     {
00291       double xk=x0, yk=y0, zk=z0;
00292       T *slice = d_plane0;
00293       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00294       {
00295         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00296         T *row = slice;
00297         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00298         {
00299           double x=xj, y=yj, z=zj;  // Start of j-th row
00300           T *dpt = row;
00301           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00302           {
00303             for (unsigned int p=0; p<np; ++p)
00304               cast_and_possibly_round( vil3d_trilin_interp_raw( x, y, z,
00305                                                                 plane0+p*pstep,
00306                                                                 istep, jstep, kstep),
00307                                        dpt[p*d_pstep]);
00308           }
00309         }
00310       }
00311     }
00312   }
00313   else
00314   {
00315     // Use safe interpolation
00316     if (np==1)
00317     {
00318       double xk=x0, yk=y0, zk=z0;
00319       T *slice = d_plane0;
00320       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00321       {
00322         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00323         T *row = slice;
00324         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00325         {
00326           double x=xj, y=yj, z=zj;  // Start of j-th row
00327           T *dpt = row;
00328           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00329             cast_and_possibly_round( vil3d_trilin_interp_safe( x, y, z,
00330                                                                plane0,
00331                                                                ni, nj, nk,
00332                                                                istep, jstep, kstep, outval),
00333                                      *dpt);
00334         }
00335       }
00336     }
00337     else
00338     {
00339       double xk=x0, yk=y0, zk=z0;
00340       T *slice = d_plane0;
00341       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00342       {
00343         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00344         T *row = slice;
00345         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00346         {
00347           double x=xj, y=yj, z=zj;  // Start of j-th row
00348           T *dpt = row;
00349           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00350           {
00351             for (unsigned int p=0; p<np; ++p)
00352               cast_and_possibly_round( vil3d_trilin_interp_safe( x, y, z,
00353                                                                  plane0+p*pstep,
00354                                                                  ni, nj, nk,
00355                                                                  istep, jstep, kstep, outval),
00356                                        dpt[p*d_pstep]);
00357           }
00358         }
00359       }
00360     }
00361   }
00362 }
00363 
00364 
00365 //  Resample image to a specified dimensions (n1 * n2 * n3)
00366 template <class S, class T>
00367 void vil3d_resample_trilinear(const vil3d_image_view<S>& src_image,
00368                               vil3d_image_view<T>& dest_image,
00369                               int n1, int n2, int n3)
00370 {
00371   double f= 0.9999999; // so sampler doesn't go off edge of image
00372   double x0=0;
00373   double y0=0;
00374   double z0=0;
00375 
00376   double dx1=f*(src_image.ni()-1)*1.0/(n1-1);
00377   double dy1=0;
00378   double dz1=0;
00379 
00380   double dx2=0;
00381   double dy2=f*(src_image.nj()-1)*1.0/(n2-1);
00382   double dz2=0;
00383 
00384   double dx3=0;
00385   double dy3=0;
00386   double dz3=f*(src_image.nk()-1)*1.0/(n3-1);
00387 
00388   vil3d_resample_trilinear(src_image, dest_image, x0, y0, z0, dx1, dy1, dz1,
00389                            dx2, dy2, dz2, dx3, dy3, dz3, n1, n2, n3);
00390 }
00391 
00392 
00393 // Resample a 3D image by a different factor in each dimension.
00394 // Note: The upper image boundaries are extended.
00395 template <class T>
00396 void vil3d_resample_trilinear(const vil3d_image_view<T>& src_image,
00397                               vil3d_image_view<T>& dst_image,
00398                               const double dx,
00399                               const double dy,
00400                               const double dz)
00401 {
00402   assert (dx > 0.0 && dy > 0.0 && dz > 0.0);
00403 
00404   // Assume planes are the same for both images
00405   const unsigned np = src_image.nplanes();
00406 
00407   const unsigned sni = src_image.ni();
00408   const unsigned snj = src_image.nj();
00409   const unsigned snk = src_image.nk();
00410   const vcl_ptrdiff_t s_istep = src_image.istep();
00411   const vcl_ptrdiff_t s_jstep = src_image.jstep();
00412   const vcl_ptrdiff_t s_kstep = src_image.kstep();
00413   const vcl_ptrdiff_t s_pstep = src_image.planestep();
00414   const T* s_plane = src_image.origin_ptr();
00415 
00416   const unsigned dni = static_cast<unsigned>(sni*dx);
00417   const unsigned dnj = static_cast<unsigned>(snj*dy);
00418   const unsigned dnk = static_cast<unsigned>(snk*dz);
00419   dst_image.set_size(dni, dnj, dnk, np);
00420   const vcl_ptrdiff_t d_istep = dst_image.istep();
00421   const vcl_ptrdiff_t d_jstep = dst_image.jstep();
00422   const vcl_ptrdiff_t d_kstep = dst_image.kstep();
00423   const vcl_ptrdiff_t d_pstep = dst_image.planestep();
00424   T* d_plane = dst_image.origin_ptr();
00425 
00426   // Use this to convert from double to T with appropriate rounding
00427   vil_convert_round_pixel<double, T> cast_and_possibly_round;
00428 
00429   // Loop over all voxels in the destination image
00430   // and sample from the corresponding point in the source image
00431   // (except near upper boundaries).
00432   for (unsigned p=0; p<np; ++p, s_plane+=s_pstep, d_plane+=d_pstep)
00433   {
00434     T* d_slice = d_plane;
00435     for (unsigned k=0; k<static_cast<unsigned>(dnk-dz); ++k, d_slice+=d_kstep)
00436     {
00437       T* d_row = d_slice;
00438       for (unsigned j=0; j<static_cast<unsigned>(dnj-dy); ++j, d_row+=d_jstep)
00439       {
00440         T* d_pix = d_row;
00441         for (unsigned i=0; i<static_cast<unsigned>(dni-dx); ++i, d_pix+=d_istep)
00442         {
00443           cast_and_possibly_round( vil3d_trilin_interp_raw( i/dx, j/dy, k/dz,
00444                                                             s_plane,
00445                                                             s_istep, s_jstep, s_kstep),
00446                                    *d_pix);
00447         }
00448         // Process the pixels near the upper i boundary - safe_extend interpolation
00449         for (unsigned i=static_cast<unsigned>(dni-dx); i<dni; ++i, d_pix+=d_istep)
00450         {
00451           cast_and_possibly_round( vil3d_trilin_interp_safe_extend(i/dx, j/dy, k/dz,
00452                                                                    s_plane,
00453                                                                    sni, snj, snk,
00454                                                                    s_istep, s_jstep, s_kstep),
00455                                    *d_pix);
00456         }
00457       }
00458 
00459       // Process the pixels near the upper j boundary - safe_extend interpolation
00460       for (unsigned j=static_cast<unsigned>(dnj-dy); j<dnj; ++j, d_row+=d_jstep)
00461       {
00462         T* d_pix = d_row;
00463         for (unsigned i=0; i<dni; ++i, d_pix+=d_istep)
00464         {
00465           cast_and_possibly_round( vil3d_trilin_interp_safe_extend( i/dx, j/dy, k/dz,
00466                                                                     s_plane,
00467                                                                     sni, snj, snk,
00468                                                                     s_istep, s_jstep, s_kstep),
00469                                    *d_pix);
00470         }
00471       }
00472     }
00473 
00474     // Process the pixels near the upper k boundary - safe_extend interpolation
00475     for (unsigned k=static_cast<unsigned>(dnk-dz); k<dnk; ++k, d_slice+=d_kstep)
00476     {
00477       T* d_row = d_slice;
00478       for (unsigned j=0; j<dnj; ++j, d_row+=d_jstep)
00479       {
00480         T* d_pix = d_row;
00481         for (unsigned i=0; i<dni; ++i, d_pix+=d_istep)
00482         {
00483           cast_and_possibly_round( vil3d_trilin_interp_safe_extend( i/dx, j/dy, k/dz,
00484                                                                     s_plane,
00485                                                                     sni, snj, snk,
00486                                                                     s_istep, s_jstep, s_kstep),
00487                                    *d_pix);
00488         }
00489       }
00490     }
00491   }
00492 }
00493 
00494 
00495 template <class T>
00496 void vil3d_resample_trilinear_scale_2(
00497   const vil3d_image_view<T>& src_im,
00498   vil3d_image_view<T>& dest_im)
00499 {
00500   // Assume planes are the same for both images
00501   const unsigned np = src_im.nplanes();
00502 
00503   const unsigned ni = src_im.ni();
00504   const unsigned nj = src_im.nj();
00505   const unsigned nk = src_im.nk();
00506   dest_im.set_size(ni*2-1, nj*2-1, nk*2-1, np);
00507 
00508   for (unsigned p = 0; p<np; ++p)
00509   {
00510     const vil3d_image_view<T> src = vil3d_plane(src_im, p);
00511     vil3d_image_view<T> dest = vil3d_plane(dest_im, p);
00512 
00513     for (unsigned k=0; k<nk-1; ++k)
00514     {
00515       for (unsigned j=0; j<nj-1; ++j)
00516       {
00517         // Do all except last slice.
00518         for (unsigned i=0; i<ni-1; ++i)
00519         {
00520           // s0-s7 are the values at 8 neighbouring positions (on a cube) in src.
00521           // d0-d7 are the values at 8 neighbouring positions (on a cube of 1/8 the above cube's size) in dest.
00522           // They are aligned so that s0 = d0.
00523           // d6t2 is the value of d6 time 2, etc.
00524           T s0 = src(i,j,k);
00525           T s1 = src(i+1, j  , k  );
00526           T s2 = src(i,   j+1, k  );
00527           T s3 = src(i+1, j+1, k  );
00528           T s4 = src(i  , j  , k+1);
00529           T s5 = src(i+1, j  , k+1);
00530           T s6 = src(i  , j+1, k+1);
00531           T s7 = src(i+1, j+1, k+1);
00532                                     dest(2*i  , 2*j  , 2*k  ) = s0;
00533           T d1t2 = s0+s1;           dest(2*i+1, 2*j  , 2*k  ) = d1t2/2;
00534           T d2t2 = s0+s2;           dest(2*i  , 2*j+1, 2*k  ) = d2t2/2;
00535           T d4t2 = s0+s4;           dest(2*i  , 2*j  , 2*k+1) = d4t2/2;
00536           T d3t4 = d2t2 + s1+s3;    dest(2*i+1, 2*j+1, 2*k  ) = d3t4/4;
00537           T d5t4 = d4t2 + s1+s5;    dest(2*i+1, 2*j  , 2*k+1) = d5t4/4;
00538           T d6t4 = d4t2 + s2+s6;    dest(2*i  , 2*j+1, 2*k+1) = d6t4/4;
00539                                     dest(2*i+1, 2*j+1, 2*k+1) = (d6t4 + s1+s3+s5+s7)/8;
00540         }
00541         T s0 = src(ni-1, j  , k  );
00542         T s2 = src(ni-1, j+1, k  );
00543         T s4 = src(ni-1, j  , k+1);
00544         T s6 = src(ni-1, j+1, k+1);
00545         dest(ni*2-2, j*2  , k*2  ) = s0;
00546         dest(ni*2-2, j*2+1, k*2  ) = (s0 + s2)/2;
00547         dest(ni*2-2, j*2  , k*2+1) = (s0 + s4)/2;
00548         dest(ni*2-2, j*2+1, k*2+1) = (s0 + s2 + s4 + s6)/4;
00549       }
00550       // Do last plane
00551       for (unsigned i=0; i<ni-1; ++i)
00552       {
00553         T s0 = src(i  , nj-1, k  );
00554         T s1 = src(i+1, nj-1, k  );
00555         T s4 = src(i  , nj-1, k+1);
00556         T s5 = src(i+1, nj-1, k+1);
00557         dest(i*2  , nj*2-2, k*2  ) = s0;
00558         dest(i*2+1, nj*2-2, k*2  ) = (s0 + s1)/2;
00559         dest(i*2  , nj*2-2, k*2+1) = (s0 + s4)/2;
00560         dest(i*2+1, nj*2-2, k*2+1) = (s0 + s1 + s4 + s5)/4;
00561       }
00562       T s0 = src(ni-1, nj-1, k);
00563       dest(ni*2-2, nj*2-2, k*2  ) = s0;
00564       dest(ni*2-2, nj*2-2, k*2+1) = (s0 + src(ni-1, nj-1, k+1))/2;
00565     }
00566     // Do last plane
00567     for (unsigned j=0; j<nj-1; ++j)
00568     {
00569       for (unsigned i=0; i<ni-1; ++i)
00570       {
00571         T s0 = src(i  , j  , nk-1);
00572         T s1 = src(i+1, j  , nk-1);
00573         T s2 = src(i  , j+1, nk-1);
00574         T s3 = src(i+1, j+1, nk-1);
00575         dest(i*2  , j*2  , nk*2-2) = s0;
00576         dest(i*2+1, j*2  , nk*2-2) = (s0 + s1)/2;
00577         dest(i*2  , j*2+1, nk*2-2) = (s0 + s2)/2;
00578         dest(i*2+1, j*2+1, nk*2-2) = (s0 + s1 + s2 + s3)/4;
00579       }
00580       T s0 = src(ni-1, j, nk-1);
00581       dest(ni*2-2, j*2  , nk*2-2) = s0;
00582       dest(ni*2-2, j*2+1, nk*2-2) = (s0 + src(ni-1, j+1, nk-1))/2;
00583     }
00584     for (unsigned i=0; i<ni-1; ++i)
00585     {
00586       T s0 = src(i, nj-1, nk-1);
00587       dest(i*2  , nj*2-2, nk*2-2) = s0;
00588       dest(i*2+1, nj*2-2, nk*2-2) = (s0 + src(i+1, nj-1, nk-1))/2;
00589     }
00590     dest(ni*2-2, nj*2-2, nk*2-2) = src(ni-1, nj-1, nk-1);
00591   }
00592 }
00593 
00594 
00595 #define VIL3D_RESAMPLE_TRILINEAR_INSTANTIATE( T, S ) \
00596 template void vil3d_resample_trilinear(const vil3d_image_view< S >& src_image, \
00597                                        vil3d_image_view< T >& dest_image, \
00598                                        double x0, double y0, double z0, \
00599                                        double dx1, double dy1, double dz1, \
00600                                        double dx2, double dy2, double dz2, \
00601                                        double dx3, double dy3, double dz3, \
00602                                        int n1, int n2, int n3, \
00603                                        T outval, double edge_tol); \
00604 template void vil3d_resample_trilinear_edge_extend(const vil3d_image_view< S >& src_image, \
00605                                                    vil3d_image_view< T >& dest_image, \
00606                                                    double x0, double y0, double z0, \
00607                                                    double dx1, double dy1, double dz1, \
00608                                                    double dx2, double dy2, double dz2, \
00609                                                    double dx3, double dy3, double dz3, \
00610                                                    int n1, int n2, int n3); \
00611 template void vil3d_resample_trilinear(const vil3d_image_view< S >& src_image, \
00612                                        vil3d_image_view< T >& dest_image, \
00613                                        int n1, int n2, int n3); \
00614 template void vil3d_resample_trilinear(const vil3d_image_view< T >& src_image, \
00615                                        vil3d_image_view< T >& dst_image, \
00616                                        const double dx, \
00617                                        const double dy, \
00618                                        const double dz); \
00619 template void vil3d_resample_trilinear_scale_2(const vil3d_image_view< T >& src_image, \
00620                                                vil3d_image_view< T >& dst_image)
00621 
00622 #endif // vil3d_resample_trilinear_txx_