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

#define MAX_STR 256 

typedef struct {
  int width, height;
  complex double *image;
} GRID;

GRID *new_GRID(width, height) {
  GRID *grid;

  grid = (GRID *)malloc(sizeof(GRID));
  grid -> width = width;
  grid -> height = height;
  grid -> image = (complex double *)malloc(
    width * height * sizeof(complex double));
  return grid;
}

GRID *read_PGM(char *PGMname) {
  FILE *PGMfile;
  char str[MAX_STR];
  int i, width, height, max_intensity, intensity;
  complex double *ptr;
  GRID *grid;

  PGMfile = fopen(PGMname, "r");

  // check header line P2
  fgets(str, MAX_STR, PGMfile);
  if(str[0] != 'P' || str[1] != '2') return NULL;

  // skip comments
  do fgets(str, MAX_STR, PGMfile); while (str[0] == '#');

  // read width and height
  sscanf(str, "%d%d", &width, &height);
 
  // read max_intensity (usually 255)
  fscanf(PGMfile, "%d", &max_intensity);

  // allocate new PGM
  grid = new_GRID(width, height); 

  // read pixels
  ptr = grid -> image;
  for(i = 0; i < width * height; i++) {
    fscanf(PGMfile, "%d", &intensity); 
//    *ptr = (double)intensity / (double)max_intensity + I * 0.0;
    *ptr = (double)intensity + I * 0.0;
    ptr++;
  }

  fclose(PGMfile);
  return grid;
}

double assign(double complex z, char choice) {
  switch(choice) {
    case 'r' : return creal(z);
    case 'i' : return cimag(z);
    //case 'a' : return cabs(z);
    default  : return creal(z);
  }
}

int write_PGM(char *PGMname, GRID *grid, char choice, int scale) {
  const int max_intensity = 255;
  FILE *PGMfile;
  double value, dmax, dmin;
  double complex *ptr;
  int i, intensity;

  // find min & max
  ptr = grid -> image;
  dmin = dmax = assign(*ptr, choice);
  for(i = 1; i < grid -> width * grid -> height; i++) {
    value = assign(*ptr, choice);
    if(value < dmin) dmin = value;
    if(value > dmax) dmax = value;
    ptr++;
  }
  
  PGMfile = fopen(PGMname, "w");
  
  fprintf(PGMfile, "P2\n");
  fprintf(PGMfile, "# CREATOR: write_PGM Version 1.00  05/14/02\n");
  fprintf(PGMfile, "# Ivan Hip, Wuppertal University\n");
  fprintf(PGMfile, "%d %d\n", grid -> width, grid -> height);
  fprintf(PGMfile, "%d\n", max_intensity);

  ptr = grid -> image;
  for(i = 1; i <= grid -> width * grid -> height; i++) {
    value = assign(*ptr, choice);
    if(scale) 
      intensity = (int)(max_intensity * (value - dmin) / (dmax - dmin));
    else if(intensity < 0) intensity = 0;
    else intensity = (int)(value + 0.5);
    fprintf(PGMfile, "%4d", intensity); 
    ptr++;
    if(!(i % 15)) fprintf(PGMfile, "\n");
  } 
  fprintf(PGMfile, "\n");

  fclose(PGMfile);
}

