#ifdef _DLL_EXPORT_
#define _PX_ __declspec(dllexport)
#define _CT_ __declspec(dllexport)
#else
#define _PX_
#define _CT_
#endif

#define PGM_MAGIC "P5"
#define PPM_MAGIC "P6"
#define BMP_MAGIC "BM"
#define MPJ_MAGIC "MP"
#define NUM_MAGIC "\x00\x00"

// Image conversion
#define FOURTWOZERO 0
#define FOURTWOTWO 1

// Image types
#define PGM_TYPE 1
#define PPM_TYPE 2
#define BMP_TYPE 3
#define MPJ_TYPE 4
#define AVI_TYPE 5
#define MED_TYPE 6
#define DUT_TYPE 7
#define RAW_TYPE 8
#define ARGUSWIP_TYPE 9

// Image colors
#define GRAY 0
#define COLOR 1

// Image formats
#define BYTE_FORMAT 4
#define SHORT_FORMAT 7
#define INT_FORMAT 5
#define FLOAT_FORMAT 6

// Filter kernels
#define AVERAGE 0
#define GAUSSIAN 1
#define REPLICATE 0
#define INTERPOLATE 1

#ifndef _GAUSSIAN_KERNEL_
#define _GAUSSIAN_KERNEL_
static float gaussian_kernel[3][3]=
{
	{(float)0.,(float)1.,(float)0.},
	{(float)1.,(float)2.,(float)1.},
	{(float)0.,(float)1.,(float)0.}
};
#endif

// Ridge detector
#define ACCURACY 0.0001f
#define GRADTHR 0.0001f
#define CURVTHR 0.005f
#define DIFFTHR M_PI_3
#define SC 2.898959823f

/*************/
// Image class
#ifndef _CIMAGE_
#define _CIMAGE_
class _CT_ CImage:public CObject
{
	DECLARE_SERIAL(CImage)
public:
	// Members
	int m_row,m_col;	// Size of the image	
	int m_color;		// COLOR or GRAY
	int m_format;		// byte, short, int, or float
	int m_type;			// PGM, PPM, BMP, MPJ, or Numaris
	float **m_data;		// Raw data in the image
	float **m_mag;		// Edge magnitude
	float **m_dir;		// Edge direction
	float **m_costim;	// Cost array (can be used for additional data)
	// Constructors/Destructor
	CImage();
	CImage(int row,int col,int color =GRAY,int type =MPJ_TYPE,int format =FLOAT_FORMAT);
	CImage(CImage *image);
	CImage(int row,int col,int color,float **data,int type,int format);
	~CImage();
	// Operators
	void operator= (const CImage &image);
	// Set and get functions
	void SetPixel(int i,int j,float value);
	void SetPixel(int i,int j,COLORREF rgbvalue);
	// Input/Output
	int ReadImage(char *filename);
	int WriteImage(char *filename);
	// Geometry
	CImage *Extract(int frow,int fcol,int nrow,int ncol);
	CImage *Reduce(int scale,int mask =AVERAGE);
	CImage *Enlarge(int scale,int mask =REPLICATE);
	CImage *Translate(int tx,int ty);
	CImage *Rotate(int angle);
	CImage *Scale(float scalex,float scaley =(float)0);
	CImage *Scale(int row,int col);
	// Arithmetic
	CImage *Invert();
	CImage *Multseq(CImage *image);
	CImage *Addseq(CImage *image);
	CImage *Orseq(CImage *image);
	CImage *Andseq(CImage *image);
	CImage *Superpose(CImage *image);
	CImage *Maxseq(CImage *image);
	CImage *Minseq(CImage *image);
	// Filtering
	CImage *Median(int size);
	CImage *Threshold(float thr);
	CImage *DistanceFilter(int size);
	void SobelFilter();
	CImage *Chamfer();
	CImage *GNoise(float sigma);
	// Deriche Filters
	CImage *apply_IIR4_filter_x(float **para);
	CImage *apply_IIR4_filter_y(float **para);
	CImage *first_derivative_x(float sigma);
	CImage *first_derivative_y(float sigma);
	void edges_mag_dir(float sigma);
	CImage *smooth_image(float sigma);
	CImage *non_maximum_suppression();
	CImage *hysteresis_thresholding(float hthr,float lthr);
	void follow_edge(CImage *result,int x,int y,float lthr);
	// Color
	void Normalize(float lower,float upper);
	void WindowCenter(int *mapping);
	void ComputeRGB(CImage *R,CImage *G,CImage *B);
	CImage *MakeGray();
	CImage *MakeColor(int normalize =0);
	CImage *RGB_to_LUV();
	// Drawing Tools
	void DrawLine(int row1,int col1,int row2,int col2,float value);
	void DrawCircle(int rowpos,int colpos,float R,float value);
	void FillObject(int rowpos,int colpos,float value,float bnd);
	void FillConvexObject(float value);
	void DrawCross(int rowpos,int colpos,float value,int size);
	// Ridges
	void ridges(float sstart,float ssend,int nbs,int pflag,int nflag,CImage *mask =NULL);
};
#endif

/***********/
// Functions
extern _PX_ int are_equal(char *magic,char *predef);
extern _PX_ int acr_nema(char line[256]);
extern _PX_ float **read_image(char *filename,int *row,int *col,int *color);
extern _PX_ float **read_pgm_image(char *filename,int *row,int *col);
extern _PX_ float **read_ppm_image(char *filename,int *row,int *col);
extern _PX_ float **read_bmp_image(char *filename,int *row,int *col,int *color);
extern _PX_ float **read_mpj_image(char *filename,int *row,int *col,int *color,int *format);
extern _PX_ float **read_medical_image(char *filename,int *row,int *col);
extern _PX_ int write_image(float **image,char *filename,int row,int col,int type,int color);
extern _PX_ int write_pgm_image(float **image,char *filename,int row,int col,int color);
extern _PX_ int write_ppm_image(float **image,char *filename,int row,int col,int color);
extern _PX_ int write_bmp_image(float **image,char *filename,int row,int col,int color);
extern _PX_ int write_mpj_image(float **image,char *filename,int row,int col,int color,int format);
extern _PX_ int write_ppm_image(float **image,char *filename,int row,int col,int color);
extern _PX_ int write_bmp_image(float **image,char *filename,int row,int col,int color);
extern _PX_ int write_mpj_image(float **image,char *filename,int row,int col,int color,int format);
extern _PX_ int write_duta_image(float **image,char *filename,int row,int col);
extern _PX_ int write_raw_image(float **image,char *filename,int row,int col,int format);
extern _PX_ int write_arguswip_image(float **image,char *filename,int row,int col);
extern _PX_ CImage* Raw2Img(char *filename,int row,int col,int color,int format,int swap,int hdrsize);
extern _PX_ float getfloat(FILE* fp);
extern _PX_ int getint(FILE* fp);
extern _PX_ short getshort(FILE* fp);
extern _PX_ void putshort(short s,FILE* fp);
extern _PX_ float bilinear_int(float **Ax,float **Ay,int i,int j,float sigma,float phi);
extern _PX_ void RGB_to_LUV(float R,float G,float B,float *L,float *U,float *V);
extern _PX_ void LUV_to_RGB(float L,float U,float V,float *R,float *G,float *B);
extern _PX_ void ga(float sigma,float **para);
extern _PX_ void fdga(float sigma,float **para);
