+#ifdef HAVE_FFTW
+bool
+ImageFile::fft (ImageFile& result) const
+{
+ if (m_nx != result.nx() || m_ny != result.ny()) {
+ sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
+ return false;
+ }
+
+ if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
+ if (! result.convertRealToComplex ())
+ return false;
+ }
+
+ fftw_complex* in = new fftw_complex [m_nx * m_ny];
+
+ ImageFileArrayConst vReal = getArray();
+ ImageFileArrayConst vImag = getImaginaryArray();
+
+ unsigned int ix, iy;
+ unsigned int iArray = 0;
+ for (ix = 0; ix < m_nx; ix++)
+ for (iy = 0; iy < m_ny; iy++) {
+ in[iArray].re = vReal[ix][iy];
+ if (isComplex())
+ in[iArray].im = vImag[ix][iy];
+ else
+ in[iArray].im = 0;
+ iArray++;
+ }
+
+ fftwnd_plan plan = fftw2d_create_plan (m_nx, m_ny, FFTW_FORWARD, FFTW_IN_PLACE);
+
+ fftwnd_one (plan, in, NULL);
+
+ ImageFileArray vRealResult = result.getArray();
+ ImageFileArray vImagResult = result.getImaginaryArray();
+ iArray = 0;
+ unsigned int iScale = m_nx * m_ny;
+ for (ix = 0; ix < m_nx; ix++)
+ for (iy = 0; iy < m_ny; iy++) {
+ vRealResult[ix][iy] = in[iArray].re / iScale;
+ vImagResult[ix][iy] = in[iArray].im / iScale;
+ iArray++;
+ }
+
+ fftwnd_destroy_plan (plan);
+ delete in;
+
+
+ Fourier::shuffleFourierToNaturalOrder (result);
+
+ return true;
+}
+
+
+bool
+ImageFile::ifft (ImageFile& result) const
+{
+ if (m_nx != result.nx() || m_ny != result.ny()) {
+ sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::invertPixelValues]");
+ return false;
+ }
+
+ if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
+ if (! result.convertRealToComplex ())
+ return false;
+ }
+
+ ImageFileArrayConst vReal = getArray();
+ ImageFileArrayConst vImag = getImaginaryArray();
+ ImageFileArray vRealResult = result.getArray();
+ ImageFileArray vImagResult = result.getImaginaryArray();
+ unsigned int ix, iy;
+ for (ix = 0; ix < m_nx; ix++)
+ for (iy = 0; iy < m_ny; iy++) {
+ vRealResult[ix][iy] = vReal[ix][iy];
+ if (isComplex())
+ vImagResult[ix][iy] = vImag[ix][iy];
+ else
+ vImagResult[ix][iy] = 0;
+ }
+
+ Fourier::shuffleNaturalToFourierOrder (result);
+
+ fftw_complex* in = new fftw_complex [m_nx * m_ny];
+
+ unsigned int iArray = 0;
+ for (ix = 0; ix < m_nx; ix++)
+ for (iy = 0; iy < m_ny; iy++) {
+ in[iArray].re = vRealResult[ix][iy];
+ in[iArray].im = vImagResult[ix][iy];
+ iArray++;
+ }
+
+ fftwnd_plan plan = fftw2d_create_plan (m_nx, m_ny, FFTW_BACKWARD, FFTW_IN_PLACE);
+
+ fftwnd_one (plan, in, NULL);
+
+ iArray = 0;
+ for (ix = 0; ix < m_nx; ix++)
+ for (iy = 0; iy < m_ny; iy++) {
+ vRealResult[ix][iy] = in[iArray].re;
+ vImagResult[ix][iy] = in[iArray].im;
+ iArray++;
+ }
+
+ fftwnd_destroy_plan (plan);
+
+ delete in;
+
+ return true;
+}
+
+bool
+ImageFile::fftRows (ImageFile& result) const
+{
+ if (m_nx != result.nx() || m_ny != result.ny()) {
+ sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::fftRows]");
+ return false;
+ }
+
+ if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
+ if (! result.convertRealToComplex ())
+ return false;
+ }
+
+ fftw_complex* in = new fftw_complex [m_nx];
+
+ ImageFileArrayConst vReal = getArray();
+ ImageFileArrayConst vImag = getImaginaryArray();
+
+ fftw_plan plan = fftw_create_plan (m_nx, FFTW_FORWARD, FFTW_IN_PLACE);
+ std::complex<double>* pcRow = new std::complex<double> [m_nx];
+
+ unsigned int ix, iy;
+ unsigned int iArray = 0;
+ for (iy = 0; iy < m_ny; iy++) {
+ for (ix = 0; ix < m_nx; ix++) {
+ in[ix].re = vReal[ix][iy];
+ if (isComplex())
+ in[ix].im = vImag[ix][iy];
+ else
+ in[ix].im = 0;
+ }
+
+ fftw_one (plan, in, NULL);
+
+ for (ix = 0; ix < m_nx; ix++)
+ pcRow[ix] = std::complex<double>(in[ix].re, in[ix].im);
+
+ Fourier::shuffleFourierToNaturalOrder (pcRow, m_nx);
+ for (ix = 0; ix < m_nx; ix++) {
+ vReal[ix][iy] = pcRow[ix].real();
+ vImag[ix][iy] = pcRow[ix].imag();
+ }
+ }
+ delete [] pcRow;
+
+ fftw_destroy_plan (plan);
+ delete in;
+
+ return true;
+}
+
+bool
+ImageFile::ifftRows (ImageFile& result) const
+{
+ if (m_nx != result.nx() || m_ny != result.ny()) {
+ sys_error (ERR_WARNING, "Difference sizes of images [ImageFile::fftRows]");
+ return false;
+ }
+
+ if (result.dataType() == Array2dFile::DATA_TYPE_REAL) {
+ if (! result.convertRealToComplex ())
+ return false;
+ }
+
+ fftw_complex* in = new fftw_complex [m_nx];
+
+ ImageFileArrayConst vReal = getArray();
+ ImageFileArrayConst vImag = getImaginaryArray();
+
+ fftw_plan plan = fftw_create_plan (m_nx, FFTW_BACKWARD, FFTW_IN_PLACE);
+ std::complex<double>* pcRow = new std::complex<double> [m_nx];
+
+ unsigned int ix, iy;
+ unsigned int iArray = 0;
+ for (iy = 0; iy < m_ny; iy++) {
+ for (ix = 0; ix < m_nx; ix++) {
+ double dImag = 0;
+ if (isComplex())
+ dImag = vImag[ix][iy];
+ pcRow[ix] = std::complex<double> (vReal[ix][iy], dImag);
+ }
+
+ Fourier::shuffleNaturalToFourierOrder (pcRow, m_nx);
+
+ for (ix = 0; ix < m_nx; ix++) {
+ in[ix].re = pcRow[ix].real();
+ in[ix].im = pcRow[ix].imag();
+ }
+
+ fftw_one (plan, in, NULL);
+
+ for (ix = 0; ix < m_nx; ix++) {
+ vReal[ix][iy] = in[ix].re;
+ vImag[ix][iy] = in[ix].im;
+ }
+ }
+ delete [] pcRow;
+
+ fftw_destroy_plan (plan);
+ delete in;
+
+ return true;
+}
+
+bool
+ImageFile::fftCols (ImageFile& result) const
+{
+ return false;
+}
+
+bool
+ImageFile::ifftCols (ImageFile& result) const