
// PGM: declarations and routines
// Version 2.09, 29.Jan.98
// (c) 1997/98 by Stefan Diener

#ifndef STIMP_PGM_INC
#define STIMP_PGM_INC

#include <STIMP/misc.c>

#ifndef NO_PSEUDO_PGM_MODE
#ifndef NO_PSEUDO_PPM_MODE
#define NO_PSEUDO_PPM_MODE
#endif
#include <STIMP/pbm.c>
#include <STIMP/ppm.c>
#endif

struct PGM_Info
{
  unsigned int height;
  unsigned int width;
  unsigned int maxval;
  unsigned char *Data;
};

int ReadPGMFile(char *name, struct PGM_Info *info)
// read a PGM-file
{
  FILE *datei;
  char tempo[5];
  int i;
  unsigned char *src;

  if (strcmp("-",name)==0) datei=stdin;   // use stdin
  else
  {
    // really open a file
    datei=fopen(name,"rb");
    if (datei==0)
    {
      PrintMessage("File %s not found !", name);
      return 1;
    }
  }

  // set buffer size
  setvbuf(datei,0,_IOFBF,500);

  // check type
  fgets(tempo, 4, datei);
  correct(tempo);
  if (strcmp(tempo,"P5")!=0)
  {
    if (strcmp("-",name)==0)
    {
      PrintMessage("Unknown file type: %s !",name);
      return 1;
    }
    else
    {
#ifndef NO_PSEUDO_PGM_MODE
      int error=0;
      struct PBM_Info infoB;
      struct PPM_Info infoP;

      fclose(datei);
      switch (GetType(name))
      {
        case TYPE_PBM: error=ReadPBMFile(name, &infoB);
                                  if (!error)
                                  {
                                    info->width=infoB.width;
                                    info->height=infoB.height;
                                    info->maxval=255;
                                    info->Data=infoB.Data;
                                  }
                                  return error;
                                  break;

        case TYPE_PPM: error=ReadPPMFile(name, &infoP);
                                  if (!error)
                                  {
                                    info->width=infoP.width;
                                    info->height=infoP.height;
                                    info->maxval=infoP.maxval;
                                    info->Data=infoP.redData;
                                    free((void *) infoP.greenData);
                                    free((void *) infoP.blueData);
                                  }
                                  return error;
                                  break;

        default: return 1;
                     break;
      }
#else
      fclose(datei);
      PrintMessage("Unknown file type: %s !",name);
      return 1;
#endif
    }
  }

  // read dimensions and maxval
  // skip comments !!!
  ReadComment(datei);
  fscanf(datei,"%i %i\n",&info->width,&info->height);
  ReadComment(datei);
  fscanf(datei,"%i\n",&info->maxval);

  // print it on the screen
  PrintMessage("Reading %s (PGM, %ix%i)", name, info->width, info->height);

  // allocate memory for picture data
  info->Data=NULL;
  info->Data=(unsigned char *) malloc(info->height*info->width*sizeof(unsigned char));
  if (info->Data==NULL)
  {
    PrintMessage("No memory for the picture data left !");
    if (strcmp("-",name)!=0) fclose(datei);
    return 1;
  }

  // need an empty picture
  src=info->Data;
  for (i=0; i<info->width*info->height; i++) *src++=0;

  // read picture data
  i=fread((void *) info->Data, sizeof(unsigned char), info->width*info->height, datei);
  if (i!=(info->width*info->height)) PrintMessage("Error while reading the file !");

  // close file
  if (strcmp("-",name)!=0) fclose(datei);

  // ok
  return 0;
}

int WritePGMFile(char *name, struct PGM_Info *info)
// write a PGM-file
{
  FILE *datei;
  int i;

  if (strcmp("-",name)==0) datei=stdout;   // use stdout
  else
  {
    // really open a file
    datei=fopen(name,"wb");
    if (datei==0)
    {
      PrintMessage("Could not open destination file %s !", name);
      return 1;
    }
  }

  PrintMessage("Writing %s (PGM, %ix%i)", name, info->width, info->height);

  // set buffer size
  setvbuf(datei,0,_IOFBF,500);

  // write file header
  fprintf(datei,"P5\n");
  fprintf(datei,"# written by: "OP_NAME" "VERSION" ("DATE"), author: "AUTHOR"\n");
  fprintf(datei,"%i %i\n",info->width,info->height);
  fprintf(datei,"%i\n",info->maxval);

  // write picture data
  i=fwrite((void *) info->Data, sizeof(unsigned char), info->width*info->height, datei);
  if (i!=(info->width*info->height)) PrintMessage("Error while writing the file !");

  // flush buffer and close file
  fflush(datei);
  if (strcmp("-",name)!=0) fclose(datei);

  // ok
  return 0;
}

int CreatePGMArray(int y, int x, struct PGM_Info *info)
// allocate memory for a PGM-picture
{
  int i;
  unsigned char *dst;

  // save dimensions and maxval
  info->width=x;
  info->height=y;
  info->maxval=255;

  // allocate memory
  info->Data=NULL;
  info->Data=(unsigned char *) malloc(x*y*sizeof(unsigned char));
  if (info->Data==NULL)
  {
    PrintMessage("No memory for picture data left !");
    return 1;
  }

  // need an empty picture
  dst=info->Data;
  for (i=0; i<info->width*info->height; i++) *dst++=0;

  // ok
  return 0;
}

void FreePGMArray(struct PGM_Info *info)
// free memory of a PGM-picture
{
  free((void *) info->Data);
}

#endif
