//***************************************************************************
#ifndef IMAGE_H
#define IMAGE_H
//***************************************************************************
#include "matrix.h"
//***************************************************************************
class GrayImage
{
   private:
        char magicNumber[2];
        int  allocateFlag;
        int  numBits;
        int  mincount;
        int  maxcount;
        int  MaxHist[10];
        int  MinHist[10];
        void allocateMem( );
        void deAllocateMem( );

    public:
        GrayImage( );           // Constructor
        GrayImage( int h, int w );              // Constructor
        GrayImage( int h, int w, int numLev );          // Constructor
        ~GrayImage( );          // Destructor
        void Init( );
        void Init (int h, int w, int numLev );
        int  height;            // Height of image
        int  width;             // Width of image
        int  numLevels;
        int  numpixels;         // Total number of pixels (height x width)
        int  numMaxHist;
        int  numMinHist;
        int  numComponents;     // Number of connected components
        unsigned char **p;      // Gray level value
        double **Phi;           // Invariant moments
        int *hist;              // Histogram data
        void allocatePhi (int num);

        int isRGB(char *FileName);
        int ReadFromFile (char *FileName);
        int ReadFromFile2 (char *FileName);
        int WriteToFile (char *FileName, char *fmt);
        int WriteToFile (char *FileName);
        void ThresholdWhite (unsigned char T);
        void Threshold (unsigned char T);
        void Threshold (unsigned char T1, unsigned char T2);
        void ThresholdBinary (unsigned char T);
        void ThresholdBinary (unsigned char T1, unsigned char T2);
        void reverseThreshold (unsigned char T);
        void reverseThreshold (unsigned char T1, unsigned char T2);
        void Histogram ( );
        void smoothenHistogram ( );
        void printHistogram (char *FileName);
        void calcHistogramPeaks ( );
        void printHistogramPeaks (char *FileName);
        int getHistMinima ( );
        int getHistMinima ( int i );
        int getHistMaxima ( );
        int getHistMaxima ( int i );
        void setValue (unsigned char T);
        GrayImage &operator= (const GrayImage &);
        GrayImage &operator+ (GrayImage &I1);
        GrayImage &operator- (GrayImage &I1);
        int Perimeter (int F);
        double Elongation (int P);
        int LabelComponents ( );
        int FindNeighbors (int i, int j);
        int Area (int P);
        void ConvertToBinary ( );
        void ReverseBinary ( );
        int WriteLabelsToFile (char *FileName);
        double Moment (int x, int y, int P);
        double CentralizedMoment (int x, int y, int P);
        double NormalizedCentralMoment (int x, int y, int P);
        void InvariantMoments (int P);
        double getInvariantMoment (int P, int i);
        void MinBoundRectangle (int P);
        
        // Image Filters
        void DilationNxN_Binary (int N, int num);
        void ErosionNxN_Binary (int N, int num);
        void OpeningNxN_Binary (int N, int num);
        void ClosingNxN_Binary (int N, int num);
        void OpeningNxN_Binary (int N);
        void ClosingNxN_Binary (int N);
        void DilationNxN_Binary (int N);
        void ErosionNxN_Binary (int N);
        void ErosionNxN (int N);
        void DilationNxN (int N);
        void OpeningNxN (int N);
        void ClosingNxN (int N);
        void Skeletonization ( );
        void MeanFilterNxN (int N);
        void MedianFilterNxN (int N);
        void GaussianFilterNxN (int N);
        void kNearestNeighboringFilterNxN (int N, int k);
        void kNearestNeighboringFilterNxN (int N);

        // Image Filters
        void addSaltandPepperNoise (double percent);
        void addGaussianNoise (double mean, double variance);

        // To read RGB images
        int ReadRGBimageFromFile2(char *FileName,
                GrayImage *rI, GrayImage *gI, GrayImage *bI);
        int ReadRGBimageFromFile(char *FileName,
                GrayImage *rI, GrayImage *gI, GrayImage *bI);
        int ReadFromMatrix(Matrix &M);
        int WriteToMatrix (Matrix *M);

        void RemoveLonelyPixels(void);
        void Zero(void);
        int isBoundaryPixel(int x, int y);
};
//***************************************************************************
double RMSerror(GrayImage *I1, GrayImage *I2);
void WriteMatrixToImageFile(Matrix &M, char *filename);
int WriteToRGBFile(char *FileName, char *fmt,
        GrayImage &rI, GrayImage &gI, GrayImage &bI);
int WriteToRGBFile(char *FileName,
        GrayImage &rI, GrayImage &gI, GrayImage &bI);
//***************************************************************************
#endif // IMAGE_H
//***************************************************************************