#ifndef _IMAGE_CLASSES_H_
#define _IMAGE_CLASSES_H_

#define PI = 3.141592654;

#include <windows.h>
#include <malloc.h>

typedef struct {
	int gradient;
	int direction;
} edge_info;



class BinaryImage
{
	private:
		unsigned char *in_image;
		int numpixels;


	public:	
		BinaryImage() {}
		~BinaryImage() { free (in_image); }

		void SetImage(unsigned char *image, int width, int height);
		unsigned char * GetBinaryImage(int threshold);
		
};


class Negator
{
	private:
		unsigned char *in_image;
		int numpixels;


	public:	
		Negator() {}
		~Negator() { free (in_image); }

		void SetImage(unsigned char *image, int width, int height);
		unsigned char * GetNegatedImage();
		
};



class Smooth
{
	private:
		unsigned char *in_image, *out_image;
		int width, height, numpixels;


	public:	
		Smooth() {}
		~Smooth() { free(in_image);}

		void SetImage(unsigned char *image, int width, int height);
		unsigned char * GetSmoothedImage(int windowsize);
};



class GaussianFilter
{
	private:
		unsigned char *in_image;
		int width, height, numpixels;


	public:	
		GaussianFilter() {}
		~GaussianFilter() { free (in_image);}
		
		void SetImage(unsigned char *image, int width, int height);
		unsigned char * GetFilteredImage(double sigma, int T);
};




class EdgeDetector
{
	private:
		unsigned char *in_image;
		int width, height, numpixels;

		edge_info *GetGradientDirectionImage();


	public:
		EdgeDetector() {};
		~EdgeDetector() { free (in_image); };

		void SetImage(unsigned char *image, int width, int height);

		unsigned char * GetGradientImage();
		unsigned char *FindEdgesUsingGradient(int threshold);
		unsigned char *FindEdgesUsingGradientDirection(int threshold, int direction);
		
};



class FourierTransform
{
	private:
		unsigned char *in_image, *out_image;
		int width, height, numpixels;

	public:
		FourierTransform() {};
		~FourierTransform() { free (in_image); };

		void SetImage(unsigned char *image, int width, int height);

		unsigned char *ShowTransform();
		unsigned char *LowPass(int x, int y);
		unsigned char *HighPass(int x, int y);
		unsigned char *LocalHighPass(int startx, int starty, int endx, int endy, int x, int y);
		unsigned char *LocalLowPass(int startx, int starty, int endx, int endy, int x, int y);

};




class Equalizer
{
	private:
		unsigned char *in_image;
		int width, height, numpixels;

	public:
		Equalizer() {}
		~Equalizer() { free (in_image); }

		void SetImage(unsigned char *image, int width, int height);

		unsigned char * Equalize();
		unsigned char * EqualizeLocal(unsigned char *image, int startx, int starty, int endx, int endy, int inplace);
		unsigned char * Equalize4Areas();
		unsigned char * Equalize16Areas();
		
};



class HoughLine 
{
	private:
		unsigned char *in_image;
		unsigned char *edge_image;
		unsigned char **accumulator;
		int width, height, numpixels;
		int h_width, h_height;
		float *SIN, *COS;
		double pi;

		void DrawLine(float radius, float theta);
		void ComputeTransform();


	public:
		int edge_threshold, edge_direction;
		int use_direction;

		HoughLine();
		~HoughLine();

		void SetImage(unsigned char *image, int width, int height);

		unsigned char * GetHoughImage(int *w, int *h);
		void DetectLines();
		unsigned char *GetEdgeImage();
		unsigned char *GetSuperimposedImage();
};



class HoughCircle
{
	private:
		unsigned char *in_image, *edge_image;
		int ***accumulator;
		int width, height, numpixels;
		int max_r, max_a, max_b;
	
		void ComputeTransform();
		void DrawCircle(unsigned char *image, int xc, int yc, int r);


	public:
		int edge_threshold, edge_direction;
		int use_direction;

		HoughCircle();
		~HoughCircle();

		void SetImage(unsigned char *image, int width, int height);

		unsigned char * GetHoughImage(int slice, int *w, int *h);
		void DetectCircles();
		unsigned char * GetEdgeImage();
		unsigned char * GetSuperimposedImage();
};

#endif