core/vil/vil_rotate.txx
Go to the documentation of this file.
00001 // This is core/vil/vil_rotate.txx
00002 #ifndef vil_rotate_txx_
00003 #define vil_rotate_txx_
00004 //:
00005 // \file
00006 // \brief rotate an image, using the resampling functions
00007 // \author dac
00008 //
00009 // A front end to the resampling functions that allows
00010 // an image to be rotated by any angle theta
00011 
00012 #include "vil_rotate.h"
00013 #include <vil/vil_resample_bilin.h>
00014 #include <vcl_cassert.h>
00015 #include <vcl_cmath.h> // for vcl_fmod()
00016 
00017 //: Calculate theta in range 0 to x
00018 static double calc_theta_mod(double theta, double x)
00019 {
00020   if (x<0) x=-x;
00021   double theta_x = vcl_fmod(theta,x);
00022   if (theta_x<0)
00023     theta_x += x;
00024   return theta_x;
00025 }
00026 
00027 //: Rotate image by angle theta ( here theta is in degrees)
00028 template <class sType, class dType>
00029 void vil_rotate_image(const vil_image_view<sType>& src_image,
00030                       vil_image_view<dType>& dest_image,
00031                       double theta_deg)
00032 {
00033   // nb if theta = 0, 90, 180 or 270 should employ a simpler + faster method
00034   // of rotating the image!  But at least, in those cases, d[xy][12] are 0 or 1.
00035 
00036   double theta_90= calc_theta_mod( theta_deg, 90.0 );
00037   double theta_360= calc_theta_mod( theta_deg, 360.0 );
00038 #ifdef DEBUG
00039   vcl_cout<<"theta_90 = "<<theta_90<<vcl_endl
00040           <<"theta_360= "<<theta_360<<vcl_endl;
00041 #endif
00042 
00043   // calculate dimensions of rotated image
00044   // a---b
00045   // |   |
00046   // c---d
00047   int src_ni = src_image.ni();
00048   int src_nj = src_image.nj();
00049   double c= vcl_cos(theta_90*3.14159265358979323846/180);
00050   double s= vcl_sin(theta_90*3.14159265358979323846/180);
00051 
00052   // calc corners of grid to sample (in original image frame)
00053   double ai= -src_nj*s*c;
00054   double aj=  src_nj*s*s;
00055   double bi=  src_ni*c*c;
00056   double bj= -src_ni*s*c;
00057   double ci=  src_ni*s*s;
00058   double cj=  src_nj-bj;
00059   double di=  src_ni-ai;
00060   double dj=  src_nj*c*c;
00061 
00062   // size of destination image
00063   int l1= int( src_nj*s+ src_ni*c );
00064   int l2= int( src_nj*c+ src_ni*s );
00065 
00066   // set up directions for sampling src image
00067   // nb varies every 90 degrees ( ie different corner at top of image!)
00068   double dx1, dy1, dx2, dy2, x0, y0;
00069   int n1,n2;
00070 
00071   assert(theta_360>= 0.0 && theta_360 < 360.0);
00072 
00073   if ( theta_360< 90.0 )
00074   {
00075     dx1= (bi-ai)/l1;
00076     dy1= (bj-aj)/l1;
00077     dx2= (ci-ai)/l2;
00078     dy2= (cj-aj)/l2;
00079     x0 = ai;
00080     y0 = aj;
00081     n1 = l1;
00082     n2 = l2;
00083   }
00084   else if (theta_360< 180.0 )
00085   {
00086     dx1= (ai-ci)/l2;
00087     dy1= (aj-cj)/l2;
00088     dx2= (di-ci)/l1;
00089     dy2= (dj-cj)/l1;
00090     x0 = ci;
00091     y0 = cj;
00092     n1 = l2;
00093     n2 = l1;
00094   }
00095   else if (theta_360< 270.0 )
00096   {
00097     dx1= (ci-di)/l1;
00098     dy1= (cj-dj)/l1;
00099     dx2= (bi-di)/l2;
00100     dy2= (bj-dj)/l2;
00101     x0 = di;
00102     y0 = dj;
00103     n1 = l1;
00104     n2 = l2;
00105   }
00106   else // if (theta_360< 360.0 )
00107   {
00108     dx1= (di-bi)/l2;
00109     dy1= (dj-bj)/l2;
00110     dx2= (ai-bi)/l1;
00111     dy2= (aj-bj)/l1;
00112     x0 = bi;
00113     y0 = bj;
00114     n1 = l2;
00115     n2 = l1;
00116   }
00117 
00118   vil_resample_bilin(src_image, dest_image, x0, y0, dx1, dy1, dx2, dy2, n1, n2 );
00119 }
00120 
00121 #define VIL_ROTATE_INSTANTIATE( sType, dType ) \
00122 template void vil_rotate_image(const vil_image_view<sType >& src_image, \
00123                                vil_image_view<dType >& dest_image, \
00124                                double theta)
00125 
00126 #endif // vil_rotate_txx_