#include <iostream.h>
#include <fstream.h>
#include <stdio.h>
#include <stdlib.h>

// for static matries
#define ACROSS 204
#define DOWN 382

const int ASCPGM = 2,  ASCPPM = 3,   // "MAGIC NUMBERS"
          BINPGM = 5,  BINPPM = 6;

void getAsciiPic(int [DOWN][ACROSS], char[]);  // get ascii, known dimensions
void putAsciiPic(int [DOWN][ACROSS], char[]);  // put ascii, known dim

void getBinaryPic(int [DOWN][ACROSS], char[]); // get binary, known dim
void putBinaryPic(int [DOWN][ACROSS], char[]); // put binary, known dim

int  getPic(int [DOWN][ACROSS], char[]);       // get either, known dim
void putPic(int [DOWN][ACROSS], char[], int);  // put specified, known dim

int ** getPic(char [], int &, int &, int &);   // get either, learn mN & dim
void putPic(int **, char [], int, int, int);   // put specified mN & dim

int main(void)
{
   int pic[DOWN][ACROSS], // row-column form, as opposed to x-y
       edg[DOWN][ACROSS],
       ** picd,
       mN, across, down;

   // static, ascii mode
      getAsciiPic(pic, "scascii.pgm");
      putAsciiPic(pic, "copiedascii.pgm");

   // static, binary mode
      getBinaryPic(pic, "scbinary.pgm");
      putBinaryPic(pic, "copiedbinary.pgm");

   // static, ascii or binary mode
      mN = getPic(pic, "scascii.pgm");
      putPic(pic, "copiedascii2.pgm", mN);
      mN = getPic(pic, "scbinary.pgm");
      putPic(pic, "copiedbinary2.pgm", mN);

   // dynamic, ascii or binary mode
      picd = getPic("scascii.pgm", mN, across, down);
      putPic(picd, "copiedascii3.pgm", mN, across, down);
      picd = getPic("scbinary.pgm", mN, across, down);
      putPic(picd, "copiedbinary3.pgm", mN, across, down);

   return 0;
}

void getAsciiPic(int pic[DOWN][ACROSS], char fn[])
{
   ifstream from;
   char bil[50];
   bool hasComment = false;

   from.open(fn);
   if (from.fail()) {cout << "darn from: " << fn << "\n\a"; exit(-1); }

   from.getline(bil, 50); // "P2"
   from.getline(bil, 50); // ACROSS DOWN
   if(bil[0] == '#') from.getline(bil, 50);
   from.getline(bil, 50); // "255"

   for (int y = 0; y < DOWN; y++)            // each row
      for (int x = 0; x < ACROSS; x++)         // across each row
          from >> pic[y][x]; // [row][column]

   from.close();
} // getAsciiPic

void putAsciiPic(int pic[DOWN][ACROSS], char fn[])
{
   ofstream to;

   to.open(fn);
   if (to.fail()) {cout << "failed to open " << fn << "\n\a"; exit(-1); }

   to << "P" << ASCPGM << endl
      << ACROSS << " " << DOWN << endl
      << 255 << endl;

   for (int y = 0; y < DOWN; y++)            // each row
      for (int x = 0; x < ACROSS; x++)         // across each row
          to << pic[y][x] << " "; // [row][column]

   to.close();
} // putAsciiPic

void getBinaryPic(int pic[DOWN][ACROSS], char fn[])
{
   FILE *p5;
   char bil[51];

   if(!(p5 = fopen(fn, "rb")))
   {cout << "failed to open file " << fn << "\n\a"; exit(-1); }

   fgets(bil, 50, p5);  // "P5"
   fgets(bil, 50, p5);  // ACROSS DOWN
   if(bil[0] == '#') fgets(bil, 50, p5);
   fgets(bil, 50, p5); // "255"

   for (int y = 0; y < DOWN; y++)            // each row
      for (int x = 0; x < ACROSS; x++)       // across each row
         pic[y][x] = (int) getc(p5);  // [row][column]

   fclose(p5);
} // getBinaryPic

void putBinaryPic(int pic[DOWN][ACROSS], char fn[])
{
   FILE *p5;

   p5 = fopen(fn, "wb");
   fprintf(p5, "P5\n%d %d\n255\n", ACROSS, DOWN);

   for (int y = 0; y < DOWN; y++)          // each row
      for (int x = 0; x < ACROSS; x++)     // across each row
         fprintf(p5, "%c", pic[y][x]);     // [row][column]

   fclose(p5);
} // putBinaryPic

int getPic(int pic[DOWN][ACROSS], char fn[])
{
   int mN=-1, x, y, t, sum;
   FILE *fptr;
   char c, str[100];

   fptr = fopen(fn, "rb");
   if(fptr == NULL)
   {
      cout << "\n\n\aERROR opening file \"" << fn << "\" for input. \n";
      return -1;
   }

   fscanf(fptr, "%c%d%d", str, &mN, str); // P{mN} \n

   // {#...  ||  across down \n}
   fgets(str, 100, fptr);
   if(str[0] == '#') fgets(str, 100, fptr); // was a comment

   fgets(str, 100, fptr); // 255 \n

   // actual file
   if(mN == BINPGM)
   {
      for(y=0; y<DOWN; y++) for(x=0; x <ACROSS; x++)
         fscanf(fptr, "%c", &pic[y][x]);
   }
   else if(mN == ASCPGM)
   {
      for(y=0; y<DOWN; y++) for(x=0; x <ACROSS; x++)
         fscanf(fptr, "%d", &pic[y][x]);
   }
   else if(mN == BINPPM)
   {
      for(y=0; y<DOWN; y++) for(x=0; x <ACROSS; x++)
      {
         sum = 0;
         fscanf(fptr, "%c", &t); sum+=t;
         fscanf(fptr, "%c", &t); sum+=t;
         fscanf(fptr, "%c", &t); sum+=t;
         pic[y][x] = sum/3;
      }
   }
   else if(mN == ASCPPM)
   {
      for(y=0; y<DOWN; y++) for(x=0; x <ACROSS; x++)
      {
         sum = 0;
         fscanf(fptr, "%d", &t); sum+=t;
         fscanf(fptr, "%d", &t); sum+=t;
         fscanf(fptr, "%d", &t); sum+=t;
         pic[y][x] = sum/3;
      }
   }

   fclose(fptr);
   return mN;
} // getPic

void putPic(int pic[DOWN][ACROSS], char fn[], int mN)
{
   FILE *p5;

   p5 = fopen(fn, "wb");
   if (p5==NULL) {cout << "failed to open " << fn << "\n\a"; exit(-1); }

   fprintf(p5, "P5\n%d %d\n255\n", ACROSS, DOWN);

   if (mN == 5)	     // binary pgm
   {
      for (int y = 0; y < DOWN; y++)          // each row
         for (int x = 0; x < ACROSS; x++)       // across each row
            fprintf(p5, "%c", pic[y][x]);
   }

   else if (mN == 2)   // ASCII pgm
   {
      for (int y = 0; y < DOWN; y++)          // each row
         for (int x = 0; x < ACROSS; x++)       // across each row
             fprintf(p5, "%d ", pic[y][x]);
   }
   fclose(p5);
} // putPic

int ** getPic(char fn[], int &mN, int &across, int &down)
{
   int ** pic;
   int x, y, t, sum;
   FILE *fptr;
   char c, str[100];
   mN = -1;

   fptr = fopen(fn, "rb");
   if(fptr == NULL)
   {
      cout << "\n\n\aERROR opening file \"" << fn << "\" for input. \n";
      return NULL;
   }

   cout << "hdr1 \n";
   fscanf(fptr, "%c%d%d", str, &mN, str); // P{mN} \n

   cout << "hdr2 \n";
   // {#...  ||  across down \n}
   fgets(str, 100, fptr);
   if(str[0] == '#') fgets(str, 100, fptr); // was a comment

   cout << "dim \n";
   // width
   x = 0; while(str[x] != ' ') x++; across = atoi(str);
   // height
   x++; y = 0;
   while(str[x] != ' ' && str[x] != '\n') { str[y] = str[x]; x++; y++; }
   str[y] = '\0'; down = atoi(str);

   cout << "255 \n";
   fgets(str, 100, fptr); // 255 \n

   cout << "alloc:  across " << across << "   down " << down << "\n";
   // allocate memory to pic
   pic = new int * [down];
   for(int y = 0; y < down; y++)
      pic[y] = new int [across];

   cout << "file \n";
   // actual file
   if(mN == BINPGM)
   {
      for(y=0; y<down; y++) for(x=0; x <across; x++)
         fscanf(fptr, "%c", &pic[y][x]);
   }
   else if(mN == ASCPGM)
   {
      for(y=0; y<down; y++) for(x=0; x <across; x++)
         fscanf(fptr, "%d", &pic[y][x]);
   }
   else if(mN == BINPPM)
   {
      for(y=0; y<down; y++) for(x=0; x <across; x++)
      {
         sum = 0;
         fscanf(fptr, "%c", &t); sum+=t;
         fscanf(fptr, "%c", &t); sum+=t;
         fscanf(fptr, "%c", &t); sum+=t;
         pic[y][x] = sum/3;
      }
   }
   else if(mN == ASCPPM)
   {
      for(y=0; y<down; y++) for(x=0; x <across; x++)
      {
         sum = 0;
         fscanf(fptr, "%d", &t); sum+=t;
         fscanf(fptr, "%d", &t); sum+=t;
         fscanf(fptr, "%d", &t); sum+=t;
         pic[y][x] = sum/3;
      }
   }

   fclose(fptr);

   return pic;
} // getPic dynamic

void putPic(int ** pic, char fn[], int mN, int across, int down)
{
   FILE *p5;

   p5 = fopen(fn, "wb");
   if (p5 == NULL) {cout << "failed to open " << fn << "\n\a"; exit(-1); }

   fprintf(p5, "P5\n%d %d\n255\n", across, down);

   if (mN == 5)	     // binary pgm
   {
      for (int y = 0; y < down; y++)          // each row
         for (int x = 0; x < across; x++)       // across each row
            fprintf(p5, "%c", pic[y][x]);

   }

   else if (mN == 2)   // ASCII pgm
   {
      for (int y = 0; y < down; y++)          // each row
         for (int x = 0; x < across; x++)       // across each row
             fprintf(p5, "%d ", pic[y][x]);
   }
   fclose(p5);
} // putPic dynamic


