#ifndef POLARMODULE_H
#define POLARMODULE_H

#include "imagesource.h"
#include "../micro.h"
extern "C"
{
  #include <opencv/highgui.h>
}

namespace seemicro
{

inline uchar getInterpolated8u_1(IplImage *img, float xf, float yf)
{
  float dx = xf-int(xf);
  float dy = yf-int(yf);
  assert(dx>=0);
  assert(dx<1);

  uchar p01 = getPixel8u_1(img, int(xf)  , int(yf)  );
  uchar p00 = getPixel8u_1(img, int(xf)+1, int(yf)  );
  uchar p11 = getPixel8u_1(img, int(xf)  , int(yf)+1);
  uchar p10 = getPixel8u_1(img, int(xf)+1, int(yf)+1);

  uchar i = uchar( (1-dy)*(1-dx)*p00 + (1-dy)*dx*p10 + dy*(1-dx)*p01 + dx*dy*p11 );

  return i;
}

/**
  * Wandelt RGB-Bild in src
  * in eine Polardarstellung in img um.
  * in img ist x ~= theta und y ~= rho
  */
struct PolarModule : public ImageSource
{
  ImageSource& src;
  Micro& m;

  PolarModule(ImageSource& As, Micro& Am, int resTheta, int resRho) : src(As), m(Am)
  {
    img = cvCreateImage(cvSize(resTheta, resRho), IPL_DEPTH_8U, src.img->nChannels);
  }

  ~PolarModule()
  {
    cvReleaseImage(&img);
  }

  void processFrame(myrect *ROI=NULL)
  {
    // we need our own ROI coz can't live with keyframes

    // ROI bezieht sich auf das Eingabebild
    myrect ROI2 = myrect(
	int(m.mitte.p.x-m.radius), int(m.mitte.p.y-m.radius),
	int(2*m.radius), int(2*m.radius) );

    // auch vom Ausgabebild kann der Ausschnitt begrenzt werden
    float thetaStart = 0;
    float thetaEnd = 2*M_PI;
    float thetaStep = (thetaEnd-thetaStart) / img->width;

    float rhoStart = 0.01;
    float rhoEnd = 1;
    float rhoStep = (rhoEnd-rhoStart) / img->height;

    if(img->nChannels != 1 && img->nChannels != 3)
    {
      cerr << "Image format unsupported (nChannels must be 1 or 3).\n";
      return;
    }

    for(int r=0; r<img->width; r++)
      for(int t=0; t<img->height ; t++)
      {
	float theta = thetaStart + float(t)*thetaStep;
        float rho = rhoStart + float(r)*rhoStep;
	float xf = ROI2.r.x + ROI2.r.width/2. + rho*cos(theta)*ROI2.r.width/2.;// elliptic...
	float yf = ROI2.r.y + ROI2.r.height/2. + rho*sin(theta)*ROI2.r.height/2.;

	// TODO "if" für jedes pixel = langsam
	if(img->nChannels==1)
	  //putPixel8u_1(img, t, r, getInterpolated8u_1(src.img, xf, yf));
	  putPixel8u_1(img, t, r, getPixel8u_1(src.img, int(xf), int(yf)));
	else
	  putPixel8u_3(img, t, r, getPixel8u_3(src.img, int(xf), int(yf)));
      }

//cvSmooth(img, img, CV_GAUSSIAN, 3, 3);
#ifdef DEBUG
    if(DEBUGLEVEL>=3) cerr << "<-PolarModule::processFrame()\n";
#endif
  }

  void processKeyFrame(void)
  {
#ifdef DEBUG
    if(DEBUGLEVEL>=3) cerr << "->PolarModule::processKeyFrame()\n";
#endif
    processFrame();
  }

}; // PolarModule

} // seemicro

#endif // POLARMODULE_H
