/* converts pgm (greyscale) or ppm (color) file to Matlab matrix(matrices) */
/*  to compile: cmex loadppm.c CFLAGS=-Aa   */

#include "mex.h"
#include<stdio.h>

#define True 1
#define False 0

/* - - prototypes - - */
#ifdef __STDC__     /* ansi c */
void load_ppm_file(char * whateverisinside);
#else   /* not ansi c    (Function prototypes are an ANSI feature.) */
load_ppm_file(); /* don't think there's such thing as void in old non ansi c */
#endif

Matrix *red_matrix, *green_matrix, *blue_matrix, *grey_matrix;
double *red_ptr, *green_ptr, *blue_ptr, *grey_ptr;
int IsColor = False;

/* - - - GATEWAY ROUTINE - - - */
#ifdef __STDC__
void mexFunction(int nlhs, Matrix  *plhs[],
		 int nrhs, Matrix  *prhs[])
#else
mexFunction(nlhs, plhs, nrhs, prhs)
     int nlhs, nrhs;
     Matrix *plhs[], *prhs[];
#endif
{ 
  char * name;
  int N;

  /* check numbers of arguments */

  if(nrhs != 1)
    {
      mexErrMsgTxt("loadppm: must have exactly 1 rhs arg. (the filename).\n");
    }
  
  if (mxIsString(prhs[0])) {
      N = mxGetN(prhs[0]) + 1;
      name = mxCalloc(N, sizeof(char));
      mxGetString(prhs[0], name, N);
      if(nlhs == 3)
	IsColor = True;
      else
	IsColor = False;
      load_ppm_file(name);
      if(nlhs == 3)
	{
	  mexPrintf("       : 3 lhs args specified so assuming color (24b)\n");
	  plhs[0] = red_matrix;
	  plhs[1] = green_matrix;
	  plhs[2] = blue_matrix;
	  

      }
      else if(nlhs == 1)
	{
	  mexPrintf("       : 1 lhs arg. specified so assuming grey (8bit)\n");
	  IsColor = False;
	  plhs[0] = grey_matrix;
	}
    }
  else
    mexErrMsgTxt("loadppm: rhs arg. must be a string (filename).\n");

  /* mexPrintf("loadppm: done\n"); */

}


/* - - - LOAD IN A PPM FILE INTO AN MATRIX RETURNED IN MATLAB - - - */
#ifdef __STDC__
void load_ppm_file(char * file_name)
#else
load_ppm_file(file_name)
  char * file_name;
#endif
{
  int magic_number;
  char * comments;
  int width, height, depth;
  int c;                        /* for reading comments */
  unsigned int garbage;

  unsigned char pixelr, pixelb, pixelg, grey_pixel;
  FILE * file_ptr;
  unsigned int file_index;
  unsigned int row_index, col_index;
  unsigned int grey_index;
  char * fileNULLerrmessage;

  mexPrintf("loadppm: loading file ``%s''... ", file_name);
  fflush(stdout);

  file_ptr = fopen(file_name, "r");
  if (file_ptr==NULL) {
    mexPrintf("loadppm: about to define file err message string\n");
    sprintf(fileNULLerrmessage,"loadppm: with file %s, fopen returned NULL\n",file_name);
    mexPrintf("loadppm: about to print ErrMsg\n");
    mexErrMsgTxt(fileNULLerrmessage);
  }

  /* - - GET INFO FROM PPM HEADER - - */
  fscanf(file_ptr,"P%d", &magic_number);

  /* ignore comments in ppm file (lines beginning with ``#'') */
  c = getc(file_ptr);
  while (1)
    {
      if (c == '#')
        {
          while (1)
            {
              c = getc(file_ptr);
              if (c == '\n' || c == EOF)
                break;    
            }
        }
      if (c==EOF)
        return;
      if (c>='0' && c<='9')
        {
          /* rewind file pointer 1 char position */
          fseek(file_ptr, -1, SEEK_CUR); 
          break;  
        }
      /* see if we are getting garbage (non-whitespace) */
      if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=',')
        garbage=1;
      
      c = getc(file_ptr);
    }
  

  fscanf(file_ptr,"%d %d %d", &width, &height, &depth);
  mexPrintf("P%d, 0..%d, M=%d, N=%d\n",
            magic_number, depth, height, width);
  if (depth != 255)
    {
      mexErrMsgTxt("loadppm: image not 255+1 deep; still to implement.\n");
    }

  if(IsColor)
    {
      red_matrix = mxCreateFull(height, width, REAL);
      red_ptr = mxGetPr(red_matrix);
      green_matrix = mxCreateFull(height, width, REAL);
      green_ptr = mxGetPr(green_matrix);
      blue_matrix = mxCreateFull(height, width,  REAL);
      blue_ptr = mxGetPr(blue_matrix);
    }
  else
    {
      grey_matrix = mxCreateFull(height, width, REAL);
      grey_ptr = mxGetPr(grey_matrix);
    }

  if(IsColor)
    {
      for(row_index = 0; row_index < height; row_index++)	    
	{
	  for(col_index = 0; col_index < width; col_index++)
	    {
	      fread(&pixelr, 1, 1, file_ptr);
	      fread(&pixelg, 1, 1, file_ptr);
	      fread(&pixelb, 1, 1, file_ptr);
	      
	      red_ptr[(col_index*height) + row_index] = pixelr;
	      green_ptr[(col_index*height) + row_index] = pixelg;
	      blue_ptr[(col_index*height) + row_index] = pixelb; 

	      if(row_index == 0)
		mexPrintf("R:%d, G:%d, B:%d", pixelr, pixelg, pixelb);
	      

	    }
	}
    }
  else
    {
      for(row_index = 0; row_index < height; row_index++)	    
	{
	  for(col_index = 0; col_index < width; col_index++)
	    { 
	      fread(&grey_pixel, sizeof(unsigned char), 1, file_ptr);
	      grey_ptr[(col_index*height) + row_index] = grey_pixel;
	    }
	}
/*
      for(grey_index = 0; grey_index < (height*width); grey_index++)
      {
	fread(&grey_pixel, sizeof(unsigned char), 1, file_ptr);
	grey_ptr[(col_index*height) + row_index] = grey_pixel;

      }
*/
    }    

      
  fclose(file_ptr);
  /* printf("loadppm: done void load_ppm_file(char * file_name)\n"); */
  


}

