/*
 * mainHelper.h
 *
 * real software engineering may be added at any time...
 * this is really just one flat file!
 */

/*
 * pixel getting function for rgb images
 */
inline void getrgb( IplImage* inputImage, int x, int y, int& r, int& g, int& b )
{
  uchar* pix = (uchar*)(inputImage->imageData + inputImage->widthStep*y);
  b = pix[x*3];
  g = pix[x*3+1];
  r = pix[x*3+2];
}

/*
 * pixel setting function for rgb images
 */
inline void setrgb( IplImage* outputImage, int x, int y, int r, int g, int b )
{
  uchar* pix = (uchar*)(outputImage->imageData + outputImage->widthStep*y);
  pix[x*3] = b;
  pix[x*3+1] = g;
  pix[x*3+2] = r;
}

inline void getbw( IplImage* inputImage, int x, int y, int& i )
{
  uchar* pix = (uchar*)(inputImage->imageData + inputImage->widthStep*y);
  i = pix[x];
}

/*
 * pixel setting function for rgb images
 */
inline void setbw( IplImage* outputImage, int x, int y, int i )
{
  uchar* pix = (uchar*)(outputImage->imageData + outputImage->widthStep*y);
  pix[x] = i;
}


// a helper function for RGBtoHSV
inline double mag(double x, double y, double z)
{
	return sqrt(x*x + y*y + z*z);
}

/*
 * RGBtoHSV algorithm from http://www.mandelbrot-dazibao.com/HSV/HSV.htm
 *   inputs: r, g, b, each from 0 to 255
 *   "outputs": h, s, and v from 0 to 1
 */
void RGBtoHSV(double r, double g, double b, double& h, double& s, double& v)
{
	double avg = (r + g + b)/3.0;
	double xaxis = (g - r)/sqrt(2.0);
	double yaxis = (2*b - r - g)/sqrt(6.0);
	h = atan2(yaxis, xaxis) * 180 / M_PI + 150; //now it's like a circle in degrees
	s = atan2(mag(r - avg, g - avg, b - avg), avg)/atan(sqrt(6.0));
	v = (r + g + b)/(3*255.0);
	if( (h) < 0 ) h += 360;
	h /= 360.0;
}

/*
 * data structure for simple threshold-based color definitions
 */
class ColorDefinition
{ public:
  
  int rmin, rmax, gmin, gmax, bmin, bmax;
  
  ColorDefinition()
  {
    reset();
  }
  
  void reset() // no pixels match
  {
    rmin = gmin = bmin = 256;
    rmax = gmax = bmax = -1;
  }
  
  void expandToFit( int r, int g, int b )
  {
    if ( r < rmin )  rmin = r;
    if ( r > rmax )  rmax = r;
    if ( g < gmin )  gmin = g;
    if ( g > gmax )  gmax = g;
    if ( b < bmin )  bmin = b;
    if ( b > bmax )  bmax = b;
  }
  
  bool pixelMatch( int r, int g, int b )
  {
    if ( r>=rmin && r<=rmax && g>=gmin && g<=gmax && b>=bmin && b<=bmax )
      return true;
    return false;
  }

  void loadFromFile( char* filename )
  {
    FILE* fp=fopen(filename, "r");
    fscanf(fp, "r: %d %d\n", &rmin, &rmax);
    fscanf(fp, "g: %d %d\n", &gmin, &gmax);
    fscanf(fp, "b: %d %d\n", &bmin, &bmax);
    //this->print();
    fclose(fp);
  }

  void saveToFile( char* filename )
  {
    FILE* fp= fopen(ROOT_FOLDER "colordef.txt", "w");
    fprintf(fp, "%s %d %d\n", "r: ", rmin, rmax);
    fprintf(fp, "%s %d %d\n", "g: ", gmin, gmax);
    fprintf(fp, "%s %d %d\n", "b: ", bmin, bmax);
    printf("%s saved.\n", filename);
    fclose(fp);
  }
  
  void print()
  {
    printf("rmin is %d\n", rmin);
    printf("rmax is %d\n", rmax);
    printf("gmin is %d\n", gmin);
    printf("gmax is %d\n", gmax);
    printf("bmin is %d\n", bmin);
    printf("bmax is %d\n\n", bmax);
  }
};

