//www.societyofrobots.com

typedef struct pgm {
  int w;
  int h;
  int max;
  int* pData;
} pgm;

#include <stdio.h>
#include <stdlib.h>

void LoadPGM( char* filename, pgm* pPgm )
{
  FILE* ifp;
  int word;
  int nRead = 0;
  char readChars[256];

  //open the file, check if successful
  ifp = fopen( filename, "r" );
  if (!ifp) {
    printf("Error: Unable to open file %s.\n\n", filename);
    exit(1);
  }

  //read headers from file
  printf ("Reading PGM file: %s...\n", filename);
  fscanf (ifp, "%s", readChars);

  if (strcmp(readChars, "P2") == 0) {
    //valid file type
    //get a word from the file
    fscanf (ifp, "%s", readChars);
    while (readChars[0] == '#') {
      //if a comment, get the rest of the line and a new word
      fgets (readChars, 255, ifp);
      fscanf (ifp, "%s", readChars);
    }
    
    //ok, comments are gone
    //get width, height, color depth
    sscanf (readChars, "%d", &pPgm->w);
    fscanf (ifp, "%d", &pPgm->h);
    fscanf (ifp, "%d", &pPgm->max);

    // allocate some memory, note that on the HandyBoard you want to 
    // use constant memory and NOT use calloc/malloc
    pPgm->pData = (int*)malloc(sizeof(int) * pPgm->w * pPgm->h);
    
    // now read in the image data itself    
    for (nRead = 0; nRead < pPgm->w * pPgm->h; nRead++) {
      fscanf(ifp, "%d" ,&word);
      pPgm->pData[nRead] = word;
      // printf("nRead = %d %d\n",nRead,pPgm->pData[nRead]);
    }

    printf ("Loaded PGM. Size: %dx%d, Greyscale: %d \n", 
	    pPgm->w, pPgm->h, pPgm->max + 1);
  }
  else {
    printf ("Error: Read file type %s. Format unsupported.\n\n", 
readChars);
    exit(1);
  }
  fclose(ifp);
}

/* Simply saves the PGM file to a file whose name is in filename */

void WritePGM( char* filename, pgm* pPgm ) {
  FILE* ofp;
  int w, h, max;
  int nWrite = 0;
  int i,j;

  strcat(filename, ".out.pgm");
  ofp = fopen(filename, "w");
  if (!ofp) {
    printf("Error: Unable to open file %s.\n\n", filename);
    exit(1);
  }

  printf ("Writing ouput PGM: %s\n\n", filename);

  //write the header
  fprintf( ofp, "P2\n" );
  fprintf( ofp, "%d %d\n", pPgm->w, pPgm->h );
  fprintf( ofp, "%d\n", pPgm->max );

  //write the image data
  for (i = 0; i < pPgm->h;i++) {
    for (j = 0; j < pPgm->w; j++)
      fprintf(ofp,"%d ",*(pPgm->pData + i * pPgm->w + j));
    fprintf(ofp,"\n");
  }
  fclose(ofp);	
}

/* We gave you a freebie */
void Thresh( pgm* pPgm, int n ) {
   int* pBuff;
   int size;

   size = pPgm->w * pPgm->h;
   pBuff = pPgm->pData;

   while( size-- ) {
     if( *pBuff > n ) {
       *pBuff = 0;
     }
     else {
       *pBuff = 255;
     }
     pBuff++;
   }
}

void Histo( pgm* pPgm )
{
   int* pBuff;
   int size;
   int i;
   int count;

   printf("\n\nPixel:    #\n");

   for (i = 0; i < 255 ; i++)
   {
     count = 0;
     pBuff = pPgm->pData;
     size = pPgm->w * pPgm->h;
     while( size-- )
       {
	 if ((*pBuff) == i)
	   count++;
	 pBuff++;
       }
     printf("\n%d:       %d \n",i,count);

     //graphic display per 10 pixels for mona
     //grpahic display per 5 pixels for letters
     while (count > 0)
       {
	 count = count - 5;
	 printf("I");
       }
   }
}

Contrast( pgm* pPgm )
{
   int ratio;
   int max = 0;
   int min = 255;
   int size;
   int i;
   int j;
   int* pBuff;
   
   size = pPgm->w * pPgm->h;
   pBuff = pPgm->pData;

   //finding min and max
   while( size-- )
   {
      if (*pBuff < min)
	 min = (*pBuff);
      if (*pBuff > max)
	 max = (*pBuff);
   }

  size = pPgm->w * pPgm->h;
  while ( size-- )
	*pBuff = 255 * ((*pBuff)-min)/(max-min);
}

int main(int argc, char * argv[]) {

  pgm* image;
  char filename[256];
  int val;
  int errchk;

  //check if a filename was given, if not, ask for one
  if (argc > 1) {
    strcpy(filename, argv[1]);
  }
  else {
    printf ("Enter filename: ");
    scanf ("%s", filename);
  }

  //allocate memory for the pgm struct
  image = (pgm *) malloc (sizeof(pgm));
  
  //read the file
  LoadPGM(filename, image);

  // --- now do something with the data ---

  //thresholding for instance...
  //get thresholding value
  if (argc > 2) {
    errchk = sscanf (argv[2], "%d", &val);
  }
  else {
    printf ("Enter threshold value: ");
    errchk = scanf ("%d", &val);
  }

  // make sure it's not really screwed up
  if (!errchk || val >= 255 || val < 0) {
    printf("Error: Bad thresholding value\n\n");
    exit(1);
  }

  //run thresholding
  //uncomment either histo, contrast, or thresh
  Histo(image);
  //Contrast(image);
  //Thresh(image, val);

  //finally write the new file
  WritePGM(filename, image);
  
  //all done
  printf("Done. Have a nice day...\n\n");
}

