/*
 * PHOTOQUANTIGRAPHIC imaging toolkit (http://wearcam.org/orbits)
 * See also, http://wearcam.org/lightspaces/index.html
 * etc...
 *
 * Related references: Proc. IEEE Nov. 1998, etc.. http://wearcam.org
 *
 * photoquantigraphic image compositing toolkit
 *
 * pnmuchar2double.c - converts byte image to double precision image
 * to compile: gcc -Wall pnmuchar2double.c -o pnmuchar2double -lm
 * to run: pnmumath v080.ppm -o pork.ppm
 *
 * steve; from ndf's diff.c, with help of sbeck on parsing input images
 *
 * bugs: writes one too many pixels, e.g. color image is 24 bytes too long
 *
 */

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

struct image_params {

  char * filename;
  int width;
  int height;
  /* max_val is the maximum colour component value - often 255 */
  int max_val;
  /* type is either '5' to indicate a P5 file or '6' to indicate a P6 file */
  int type;
};

/* double pow(double x, double y); */

void
usage(void)
{
  fprintf(stderr, "Use: pnmumath image1 [-o imageout]\n");
  exit(EXIT_SUCCESS);
}

void
parse_commandline(int argc, char ** argv, struct image_params * a_params,
		  char ** output_filename)
{
  int i;

  if (argc<3) usage();

  for (i=1;i<argc;i++)
    {
      if (!strcasecmp(argv[i], "-o"))
	{
	  if (argc<=(i+1)) usage();
	  *output_filename=(char *)strdup(argv[++i]);
	}
      else if (a_params->filename==NULL)
	a_params->filename=(char *)strdup(argv[i]);
      else usage();
    }

  if (a_params->filename==NULL) usage();
}

void
get_image_params(FILE * ifs, struct image_params * params)
{
  int c;
  int dims[3];
  int dims_scanned;
  if( ifs == NULL ) { /* check for file pointers to non existant files */
    fprintf(stderr,"get_frame_params: non-existant file\n");
    exit(EXIT_FAILURE);
  }

  if (fgetc(ifs)!='P') /* image must start with P5, P6, P7, or P8 */
    {
      fprintf(stderr, "get_frame_params: file not ppm file (doesn't start with"
	              " ``P'').\n");
      exit(EXIT_FAILURE);
    }
  c=fgetc(ifs);
  if (c!='5' && c!='6' && c!='7' && c!='8')
    {
      fprintf(stderr, "get_frame_params: input image must begin with "
                      "P5 for grey byte, P6 for colour byte, "
                      "P7 for grey double, or P8 for colour double\n");
      exit(EXIT_FAILURE);
    }
  params->type=c;
  /* enter a loop
   * skip comments which start with #
   * and look for the dimensions
   */
  dims_scanned = 0;
  do {
    char line[80];
    fgets( line, sizeof(line), ifs );
    printf("parsed one line of pnm header: %s", line );
    if( *line != '#' ) {
      char *p = strtok(line," \n" );
      while( p && (*p != '#') ) {
        sscanf(p,"%d", &dims[dims_scanned] );
        dims_scanned++;
        p = strtok( NULL, " \n" );
      }
    }
    printf("dims_scanned=%d\n", dims_scanned);
  } while( dims_scanned < 3 );

  params->width = dims[0];
  params->height = dims[1];
  params->max_val = dims[2];

  if( params->max_val != 255 ){
    fprintf(stderr,"get_frame_params: max value must be 255\n");
    exit( EXIT_FAILURE );
  }

}

int
main(int argc, char ** argv)
{
  struct image_params a_params={NULL,0,0,0,0};
  char * dest_filename=NULL;
  FILE * a, * b, * dest;
  double p_inv;  /* 1.0/p */
  double scale_factor; /* to make the result on same interval is input */
  unsigned char a_pixel[3];
  unsigned char same_pixel[3]= {0,0,0};
/*  unsigned char out_pixel[3]; */
  double out_pixel[3]; /* 3 doubles (24 bytes) enough for grey or colour */
  int bytes_per_pixel, i;
  int m,n;

  parse_commandline(argc, argv, &a_params, &dest_filename);

  if ((a=fopen(a_params.filename, "r"))==NULL)
    {
      fprintf(stderr, "Unable to open %s.\n", a_params.filename);
      exit(EXIT_FAILURE);
    }

  if (dest_filename==NULL) dest=stdout;
  else if ((dest=fopen(dest_filename, "w"))==NULL)
    {
      fprintf(stderr, "Unable to open %s.\n", dest_filename);
      exit(EXIT_FAILURE);
    }

  get_image_params(a, &a_params);

  if (a_params.type=='5') {
    bytes_per_pixel=1;
    fprintf(stderr,"a_params.type=5, so pgm file must have 1 byte per pixel\n");
   }
  else if (a_params.type=='6') {
    bytes_per_pixel=3;
    fprintf(stderr,"a_params.type=6, so ppm file must have 3bytes per pixel\n");
   }
  else if (a_params.type=='7') {
    bytes_per_pixel=8;
    fprintf(stderr,"a_params.type=7; float grey image 8 bytes per pixel\n");
   }
  else if (a_params.type=='8') {
    bytes_per_pixel=24;
    fprintf(stderr,"a_params.type=8; float colour image 24bytes per pixel\n");
   }
  else {fprintf(stderr,"unrecognized pnm image type\n"); exit(0);}

  if (a_params.type=='5') {
    fprintf(stderr,"writing a P7 output image because input was a P5 image\n");
    /*fprintf(dest, "P%c\n%d %d\n%d\n", a_params.type, a_params.width,*/
    fprintf(dest, "P7\n%d %d\n%d\n", a_params.width,
            a_params.height, a_params.max_val);
  }
  if (a_params.type=='6') {
    fprintf(stderr,"writing a P8 output image because input was a P6 image\n");
    /*fprintf(dest, "P%c\n%d %d\n%d\n", a_params.type, a_params.width,*/
    fprintf(dest, "P8\n%d %d\n%d\n", a_params.width,
            a_params.height, a_params.max_val);
  }

  m=0; n=0;
  while (!feof(a))
    {
      fread(a_pixel, sizeof(unsigned char), bytes_per_pixel, a);
	  for (i=0;i<bytes_per_pixel;i++)
	    out_pixel[i]=(double)
              ( 
                     a_pixel[i]
              );
          /* if (2*(m/2)!=m) uncomment to write out only odd field */
	  fwrite(out_pixel, sizeof(double), bytes_per_pixel, dest);
          n++;
          if (n==a_params.width) {
            n=0;
            m++;
          }
    }

  fclose(a); fclose(dest);
  exit(EXIT_SUCCESS);
}

