
#ifndef __MFLOATIMAGE__
#define __MFLOATIMAGE__

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <assert.h>
#include <string.h> // memcpy, memset
#include <math.h> // sqrt
#include <vector>
using namespace std;

#include "MUtils.h"

#include "MCharImage.h"
#include "MSignedShortImage.h"
#include "MListePI.h"


class MListePI;
class MCharImage;
class MSignedShortImage;

class MFloatImage { // use mainly SSE instructions
  int x__, y__, xMin_, xMax_, yMin_, yMax_;
  float *Map;
  inline void SetSize(int x_, int y_);
 public:
  MFloatImage(int x_= 0, int y_= 0, int WithInit0= 0);
  ~MFloatImage();

  int x() const { return x__; }
  int y() const { return y__; }
  inline void Bound(int& xMin, int& xMax, int& yMin, int& yMax) const;
  const float& M_(int xx, int yy) const {return Map[xx+yy*x__];}
  float& M(int xx, int yy) {return Map[xx+yy*x__];}
  float M(int offset) {return Map[offset];} //pour debuggage

  
  friend ostream& operator<<(ostream& Out, const MFloatImage& Image);

  void ConvertFrom(const MCharImage& Image);
  void ConvertFrom(const MSignedShortImage& Image);
  
  const MFloatImage& operator=(const MFloatImage& Image);
  void Smooth121(int IsHorizontal0Vertical1, const MFloatImage& Data);
  void Gradient_101(int IsHorizontal0Vertical1, const MFloatImage& Data);
  void AbsMap();
  void Norm(const MFloatImage& xData, const MFloatImage& yData);
  void Laplacian1_41(const MFloatImage& Data, int WithAbsoluteValue);
  void Moravec5x5(const MCharImage& Data); // not divided by 25

  //Produit par une autre image en float
  void Product(const MFloatImage& Image);
  //Division par une autre image en float
  void Divide(const MFloatImage& Image);
  //Racine carree d'une image
  void SqrtImg(const MFloatImage& Image);

  //Filtre moyenneur 5x5
  void MFloatImage::Somme5x5(MFloatImage& Data);
  //idem mais dans une seule direction
  void MFloatImage::Somme5X(MFloatImage& Data);
  void MFloatImage::Somme5Y(MFloatImage& Data);

  
  //Calcul du critere de Harris
  void Harris(const MSignedShortImage& DataA,const MSignedShortImage& DataB, const MSignedShortImage & DataC);
  //Calcul de la plus petite valeur propre de la matrice de Harris
  void VPInf(const MSignedShortImage& DataA,const MSignedShortImage& DataB, const MSignedShortImage & DataC);
  int LocalMaximaList(float MinValue, int NbPointMax, int* x_yMxStride) const;

  void InverseStandartDeviation5x5(const MCharImage& Data, int BorderSize);
  void Zncc5x5(const MCharImage& Data0, const MCharImage& Data1,
	       const MFloatImage& InvStdDev0, const MFloatImage& InvStdDev1,
	       int x0, int y0, int x1, int y1, int dx, int dy);
  //Recherche les maxima locaux dans une zone de l'image et ajoute dans PointList
  //ceux dont la valeur depasse k*Max, avec Max= le maximum de la zone
  //L'ajout dans la liste se fait a partir de la valeur PosListe
  int AddLocalMaximaZone(float k,int nbPointMax,int* PointList,int PosListe,int& MeilleurMax,
			 int Zonexmin, int Zonexmax, int Zoneymin, int Zoneymax);
  //Recherche des maxima locaux, avec une valeur minimale par zone d'image fixee a k*le max de la zone
  //Les zones sont des cases rectangulaires NbCasesX et NbCasesY (doivent etre des diviseurs des dimensions de l'image)
  int LocalMaximaList(float k, int NbPointMax,int NbPointMaxZone,int* PointList,int NbCasesX,int NbCasesY);
  void LocalMaximaList(MListePI& ListePoints, float MinValue);
  //recherche la valeur maximum d'une zone d'image
  //si toutes les bornes sont à 0, ou appel sans arguments : recherche sur toute l'image
  float findMax(int Zonexmin=0, int Zonexmax=0, int Zoneymin=0, int Zoneymax=0);

	//méthodes de tri utilisée par LocalMaximaList
  void HeapSortMax(int numbers[], int array_size);
  void HeapSortMaxsiftDown(int numbers[],int root, int bottom);
};
void MCompare(const MFloatImage& Map0, const MFloatImage& Map1);

#endif

