// This program takes the name of a PPM file and rips it apart
// into lots of PPM files representing individual images.
// The new ones are named "image00000.ppm", "image00001.ppm",
// and so on. Be sure to do this in a temporary directory!

#include <iostream>
#include <ctype.h> // for isspace
#include <fstream>
#include <stdio.h> // for sprintf


void process(std::ifstream& i)
{
  size_t imnum = 0;
  while (EOF != i.peek())
    {
      unsigned char c1, c2, c3;
      c1 = c2 = c3 = 0; // To ensure no overlap between loops.
      i.get(c1);
      i.get(c2);
      size_t width, height, maxval;
      i >> width >> height >> maxval;
      i.get(c3);

      size_t multiplier = (maxval < 256)? 3 : 6;
      size_t bytecount = multiplier * width * height;

      std::cout << "Type: " << c1 << c2 << " Width: " << width << " Height: ";
      std::cout << height << " Maxval: " << maxval << " Bytes: " << bytecount;
      std::cout << std::endl;

      // The extra whitespace after maxval seems to have already
      // been removed from the input stream. Bizarre.
      if ('P' != c1 || '6' != c2 || !isspace(c3))
	throw "Input file is not PPM.";
      char* buf = new char[bytecount];
      i.read(buf, bytecount);

      char fname[64];
      sprintf(fname, "image%05d.ppm", imnum);
      ofstream o(fname, std::ios::bin);
      o << "P6 " << width << " " << height << " " << maxval << "\n";
      o.write(buf, bytecount);

      delete[] buf;
      ++imnum;
    }
  std::cout << "Successfully wrote " << imnum << " images." << std::endl;
}


int main(size_t argc, char* argv[])
{
  std::cout << "This is " << argv[0] << " 1.0 (16 Feb 2002) by Alexander Perlis." << std::endl;
  if (argc < 1)
    {
      std::cout << "Usage:\n  " << argv[0] << " INPUTIMAGE.ppm\n";
      std::cout << "Program writes 'image00000.ppm', 'image00001.ppm',\n";
      std::cout << "and so on, one per image in input file.\n";
      return 0;
    }
  std::ifstream i(argv[1], std::ios::bin);
  if (!i)
    {
      std::cout << "Error opening input file.\n";
      return 1;
    }

  try
    {
      process(i);
    }
  catch (const char* e)
    {
      std::cout << "Exception: " << e << std::endl;
      return 1;
    }
  catch (...)
    {
      std::cout << "Exception: unknown." << std::endl;
      return 1;
    }
  return 0;
}

