#ifndef FFTWEXT_H
#define FFTWEXT_H

extern "C"
{
  // see fftw.org
  #include <fftw3.h>
}

#include <opencv/cv.hpp>

#define c_re(c) ((c)[0])
#define c_im(c) ((c)[1])

namespace seemicro
{

/**
  * Converts double value into coded color:
  * gray = normal, ie 0<=pixel<=255;
  * red = out of range, ie. fabs(pixel>255);
  * green = v>255 and above_threshold(v)
  */
inline CvScalar toColorScalar(double v, int (*above_threshold)(double) = NULL);

/**
  * Converts IplImage to a 2-dimensional double array
  * for use with fftw
  *   * can embed smaller image in bigger array
  *   * can embed smaller array in larger image
  *   * call with 2 args if size(ff) is same as size(img)
  *   * Image pixel values should be 0<=pixel<=255
  */
void IplImage2fftw_real(IplImage *img, double* ff, int ffwidth = 0, int ffheight = 0);

/**
  * Converts a 2-dimensional double array back into an IplImage
  */
void doubles2IplImage(double scale, IplImage *img, double* ff,
  int ffwidth = 0, int ffheight = 0, int (*above_threshold)(double) = NULL);

/**
  * Converts a 2-dimensional double array back into two IplImages
  */
void fftw_complex2IplImages(fftw_complex *ff, IplImage *outR, IplImage *outI);

/**
  * Berechnet aus den Real- und Imaginär-Ergebnisbildern der
  * Fourier-Vorwärtstransformation ein Betragsbild
  */
void fftw_complex2IplImageMagnitude(fftw_complex *ff, IplImage *magnitude);

/**
  * Multiplies complex arrays a and b elementwise, stores result in a
  */
void fftw_complex_multiply(fftw_complex *a, fftw_complex *b, int w, int h);

/** Returns maximum value & location of 4-connected region:
  * deletes checked values from input image,
  * searches recursively;
  *
  * TODO: hand over less arguments during recursion!!!
  * ff: fftw image (not complex) with width*height dimensions
  */
double try_mark_region(double *ff, int width, int height,
    int (*above_threshold)(double),
    int x, int y, int* x_max, int* y_max, double scale);

struct maximum { double v; int x,y; };

/**
  * in image ff, with dimensions width*height
  */
int find_maxima(struct maximum *maxima, int width, int height, double *ff,
    int (*above_threshold)(double), int max_maxima=1);

/**
  * Findet das globale Maximum im Bild in ff
  */
void findMaxPoint(int width, int height, double *ff, double threshold_value,
  maximum *max);

} // namespace seemicro

#endif
