00001 /*! @file Image/FFTWWrapper.C -- 00002 Bare bones wrapper for freely dowloadable 00003 fftw fast Fourier transfom C libraries, which also come 00004 with lots of helpful documentation from fftw.com 00005 Basic idea is, assuming you've got a certain image size 00006 that you're going to be computing FTs for again and again, you 00007 pass in a pointer to the image memory location at initialization, 00008 and FFTW comes up with "a plan". 00009 Then you can call the compute fuction repeatedly as needed, 00010 passing in a memory location for it to put the FT. 00011 FFTW returns just a halfwidth+1 size image, 00012 because the rest is redundatnt, but I make the fullsize image here. 00013 00014 00015 Christopher Ackerman 00016 7/30/2003 00017 */ 00018 00019 00020 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/FFTWWrapper.C $ 00021 // $Id: FFTWWrapper.C 10794 2009-02-08 06:21:09Z itti $ 00022 00023 #include "Image/FFTWWrapper.H" 00024 #include "Util/log.H" 00025 00026 FFTWWrapper::FFTWWrapper(int width, int height){ 00027 #ifndef HAVE_FFTW3_H 00028 LFATAL("you must have fftw3 installed to use this function"); 00029 #else 00030 imagewidth = width; 00031 imageheight = height; 00032 00033 // Allocate here to make sure that we only every allocate 00034 // with the constructor since we free with the destructor 00035 out = (double(*)[2])fftw_malloc(sizeof(fftw_complex) * 00036 imageheight * (imagewidth/2+1)); 00037 if(out == NULL) 00038 LINFO("Memory allocation error"); 00039 00040 #endif 00041 } 00042 00043 // ###################################################################### 00044 void FFTWWrapper::init(double *image){ 00045 #ifndef HAVE_FFTW3_H 00046 LFATAL("you must have fftw3 installed to use this function"); 00047 #else 00048 in = image; 00049 p = fftw_plan_dft_r2c_2d(imageheight, imagewidth, in, out, FFTW_MEASURE); 00050 #endif 00051 } 00052 00053 // ###################################################################### 00054 void FFTWWrapper::compute(double** magspec){ 00055 #ifndef HAVE_FFTW3_H 00056 LFATAL("you must have fftw3 installed to use this function"); 00057 #else 00058 fftw_execute(p); 00059 00060 const int halfwidth = imagewidth/2 + 1; 00061 // make other half --skip zero freq? 00062 for(int i = 0; i < imageheight; i++) 00063 for(int j = 0; j < halfwidth; j++) 00064 magspec[i][j] = mag(out[i*halfwidth+j/*+1*/]); 00065 #endif 00066 } 00067 00068 // ###################################################################### 00069 void FFTWWrapper::compute(double* magspec){ 00070 #ifndef HAVE_FFTW3_H 00071 LFATAL("you must have fftw3 installed to use this function"); 00072 #else 00073 fftw_execute(p); 00074 00075 const int halfwidth = imagewidth/2 + 1; 00076 // make other half --skip zero freq? 00077 for(int i = 0; i < imageheight; i++) 00078 for(int j = 0; j < halfwidth; j++) 00079 magspec[i * halfwidth + j] = mag(out[i*halfwidth+j/*+1*/]); 00080 #endif 00081 } 00082 00083 // ###################################################################### 00084 FFTWWrapper::~FFTWWrapper(){ 00085 #ifndef HAVE_FFTW3_H 00086 // don't use LFATAL in a destructor 00087 LERROR("you must have fftw3 installed to use this function"); 00088 #else 00089 fftw_destroy_plan(p); 00090 // Since the image data comes from outside, we do not own the data 00091 // so do not free it. We have only malloc'd out, so we free that 00092 //fftw_free(in); 00093 fftw_free(out); 00094 #endif 00095 }