#ifndef TYPE_IMAGE_H
#define TYPE_IMAGE_H

#include <string>
using std::string;

enum enum_type_couleur { ROUGE, VERT, BLEU };

// Classe qui représente le tableau contenant l'image

class type_image
{
	int Width, Height;
	float *PtrImage;

public:
	// Constructeur et destructeur
	inline type_image(int W = 0, int H = 0)
	{ Width = W; Height = H; PtrImage = new float[Width*Height*3]; }
	inline ~type_image() { delete []PtrImage; }

	
	// Opérateur servant à accéder aux cases du tableau de pixels
	inline float& operator() (int i, int j, enum_type_couleur c)
	{ return PtrImage[(i + j*Width)*3 + int(c)]; }
	// Fonction qui s'assure que la couleur est correcte
	inline void Valide(float& Couleur)
	{ if (Couleur < 0) Couleur = 0;
	  else if (Couleur > 1) Couleur = 1; }

	
	// Fonction qui sauvegarde l'image en .bmp
	bool SauveBMP(const string& NomFic) const;
	friend bool SauveBMP24(const string& NomFic, const type_image& Image);
	// Fonction qui charge l'image d'un .bmp
	bool ChargeBMP(const string& NomFic);


// Effets très simples

	// Effet d'inversion horizontale
	void Eff01FlipH(void);
	// Effet d'inversion verticale
	void Eff01FlipV(void);

	// Rotation vers la droite (clock-wise) d'un quart de tour
	void Eff01RotCW(void);
	// Rotation vers la gauche (counter-clock-wise) d'un quart de tour
	void Eff01RotCCW(void);

	// Effet d'élimination du rouge
	void Eff01KillRouge(void);
	// Effet d'élimination du vert
	void Eff01KillVert(void);
	// Effet d'élimination du bleu
	void Eff01KillBleu(void);
	// Effet de filtre rouge
	void Eff01FiltreRouge(void) { Eff01KillVert(); Eff01KillBleu(); }
	// Effet de filtre vert
	void Eff01FiltreVert(void) { Eff01KillRouge(); Eff01KillBleu(); }
	// Effet de filtre bleu
	void Eff01FiltreBleu(void) { Eff01KillRouge(); Eff01KillVert(); }
	// Effet d'intensité lumineuse
	void Eff01Intensite(float Facteur);

	// Inversion de l'image: négatif
	void Eff01Negatif(void);
	// Transformation de l'image en ton de gris
	void Eff01TonGris(void);
	// Contour #1	
	void Eff01Contour1(float Facteur = 0.4f);

// Fin des effets très simples

// Effets de bruit

	// Bruit aléatoire probabiliste
	void Eff02BruitRand(float Prob);
	// Bruit multiplicatif de Gauss
	void Eff02BruitGauss(float Range);
	// Bruit additif de Laplace
	void Eff02BruitLaplace(float Coef);

	// Moving average filter
	void Eff02FilterMovAv(int sizex, int sizey);
	// Median filter
	void Eff02FilterMedian(int sizex, int sizey);
	// Multistage median filter
	void Eff02FilterMedianMulti(int size);
	// Max filter
	void Eff02FilterMax(int sizex, int sizey);
	// Min filter
	void Eff02FilterMin(int sizex, int sizey);
	// Local adaptive filter
	void Eff02FilterLocalAdapt(int sizex, int sizey, float NoiseVar);




// Effets composés

	inline void Eff10DessinCoul(float Facteur = 0.4f)
	{ Eff01Contour1(Facteur); Eff01Negatif(); }
	inline void Eff10DessinNetB(float Facteur = 0.4f)
	{ Eff10DessinCoul(Facteur); Eff01TonGris(); }


	// Fonctions temporaire de tests
	type_image(char *);
	void validation()
	{
		for (int i = 0; i < Width; i++)
			for (int j = 0; j < Height; j++)
				for (int k = 0; k < 3; k++)
					if( ( (*this)(i,j, enum_type_couleur(k)) < 0)
					 || ( (*this)(i,j, enum_type_couleur(k)) > 1) )
						abort();
	}
	friend void Cercle(type_image& Image, float x, float y, float rr, float r, float g, float b);
	friend void Rectangle(type_image& Image, float x, float y, float xx, float yy, float r, float g, float b);
	friend void afficher(type_image&);
	friend void display();
	friend int main(void);
};

#endif
