/*
 * Color video to greyscale video converter
 *
 * $Date$
 * $Revision$
 *
 */

#include <cassert>
#include <iostream>
#include <stdexcept>
#include <iomanip>
#include <WImage.hh>

#if !(defined __WATCOMC__ && __WATCOMC__ < 1230)
using namespace std;
#endif

int 
main (int argc, char *argv[])
{
  cout << "video2grey version " << WAVE_VERSION << " (c) 2001-2004 by Herbert"
       << endl;
  char *infile = NULL;
  char *outfile = NULL;
  int y = 0;
  int x = 0;
  int to = 0;
  int from = 0;
  int o = 0;

  if (argc < 3 || argc > 8)
    {
      cerr << "Usage: video2grey <infile> <outfile> "
           << "[<from> [<to> [<header> [<y> [<x>]]]]]" << endl;
      return 1;
    }

  infile = argv[1];
  outfile = argv[2];

  if (argc > 3)
    {
      if (sscanf (argv[3], "%d", &from) != 1)
        {
          cerr << "Invalid from: " << argv[3] << endl;
          return 1;
        }
    }
  
  if (argc > 4)
    {
      if (sscanf (argv[4], "%d", &to) != 1)
        {
          cerr << "Invalid to: " << argv[4] << endl;
          return 1;
        }
    }
  
  if (argc > 5)
    {
      if (sscanf (argv[5], "%d", &o) != 1)
        {
          cerr << "Invalid header: " << argv[5] << endl;
          return 1;
        }
    }

  if (argc > 6)
    {
      if (sscanf (argv[6], "%d", &y) != 1)
        {
          cerr << "Invalid y: " << argv[6] << endl;
          return 1;
        }
    }
  
  if (argc > 7)
    {
      if (sscanf (argv[7], "%d", &x) != 1)
        {
          cerr << "Invalid x: " << argv[7] << endl;
          return 1;
        }
    }
  
  
  FileName fn (infile);
  int z = 0;
  if (fn.guess () != fn_vid)
    {
      try 
        {
          ColorVideo::videoDimensions (infile, y, x, z, 3, o);
        }
      catch (const exception &error)
        {
          cerr << "Error getting dimensions: " << error.what () << endl;
          return 1;
        }
    }

  if (to == 0)
    {
      to = z;
    }
  int frames = to - from;
  cout << "Allocating memory...\n";
  ColorVideo *outVid = NULL; 
  ColorVideo *inVid = NULL; 
  try 
    {
      outVid = NEW (ColorVideo (1, cm_unknown, y, x, frames));
      inVid = NEW (ColorVideo ());
    }
  catch (const exception &error)
    {
      cerr << "Exception caught: " << error.what () << endl;
      return 2;
    }
  Image *inFrame = NULL;
  Image *outFrame = &outVid->currentFrameChannel (0);
#if 0
  ColorImage *cimage = NULL;
  char buf[256];
#endif

  cout << "Reading and converting...\n";
  for (int i = 0; i < frames; i++)
    {
      cout << "\r" << "                                                  " 
           << "\r" << "Frame " << std::setw (3) << i;
      cout.flush ();

      try
        {
          inVid->read (infile, from + i, from + i + 1, y, x, 3, cm_rgb, o);
          inVid->current (0);
#if 0
          cimage = &inVid->currentFrame ();
          sprintf (buf, "inframe%03d.ppm", i);
          cimage->write (buf);

          cimage->swapColors (0, 1);
          sprintf (buf, "inframe%03dbac.ppm", i);
          cimage->write (buf);
          
          cimage->swapColors (1, 2);
          sprintf (buf, "inframe%03dbca.ppm", i);
          cimage->write (buf);
          
          cimage->swapColors (0, 1);
          sprintf (buf, "inframe%03dcba.ppm", i);
          cimage->write (buf);
          
          cimage->swapColors (1, 2);
          sprintf (buf, "inframe%03dcab.ppm", i);
          cimage->write (buf);
          
          cimage->swapColors (0, 1);
          sprintf (buf, "inframe%03dacb.ppm", i);
          cimage->write (buf);
#endif
          cout << ": converting to yuv";
          cout.flush ();
          inVid->colormodel (cm_yuv);
          inFrame = &inVid->currentFrameChannel (0);
#if 0
          sprintf (buf, "inframe%03d.pgm", i);
          inFrame->write (buf);
#endif
          cout << ", copying...";
          cout.flush ();
          outVid->current (i);
          outFrame->copy (*inFrame);
        }
      catch (const exception &error)
        {
          cerr << "Exception caught: " << error.what () << endl;
          return 2;
        }
    }
  cout << endl << "Writing output...\n";
#if 0
  for (int i = 0; i < frames; i++)
    {
      try
        {
          outVid->current (i);
          sprintf (buf, "outframe%03d.pgm", i);
          outFrame->write (buf);
        }
      catch (const exception &error)
        {
          cerr << "Exception caught: " << error.what () << endl;
          return 2;
        }
    }
#endif
  try 
    {
      outVid->write (outfile, o, false);
    }
  catch (const exception &error)
    {
      cerr << "Exception caught: " << error.what () << endl;
      return 2;
    }

  cout << "Done.\n";

  DELETE (inVid);
  DELETE (outVid);
  
  return 0;
}

