/*
 * A simple generic image converter.
 * 
 * $Date$
 * $Revision$
 *
 */

#include <iostream>
#include <stdexcept>
#include <Wave.hh>
#ifdef PFI
#include <pfi.h>
#endif

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

#define NFILES 2
#define COLORS 3

int 
main (int argc, char *argv[])
{
  if (argc != 3)
    {
      cout << "imgconvert, version " << WAVE_VERSION 
           << ", (c) 2001-2004 by Herbert,"
#ifdef PFI
           << " (pfi support enabled)"
#endif
           << endl;
      cout << "Usage: imgconvert <infile> <outfile>\n";
      return 1;
    }
  
  bool needBeautify = false;
  char *infile = argv[1];
  char *outfile = argv[2];
  FileName inFn (infile);
  FileName outFn (outfile);
  int inColors = 1;
  int outColors = 1;
#ifdef PFI
  int rows = 0, cols = 0, cmodel = 0;
#endif

  switch (inFn.guess ())
    {
#ifdef PFI
    case fn_pfi: 
      if (pfi_properties_name (infile, &rows, &cols, &inColors, &cmodel) < 0)
        {
          cerr << "Error reading image " << infile << endl;
          return 1;
        }
      needBeautify = true;
      break;
#endif
    case fn_ppm: 
      inColors = 3;
      break;
    case fn_pgm: 
      inColors = 1;
      break;
    case fn_raw:
      cerr << "Error, can't process raw images!" << endl;
      return 1;
    case fn_jpg: 
      inColors = 3;
      break;
    default: 
      cerr << "Error, unknown file type!" << endl;
      return 1;
    }
  
  switch (outFn.guess ())
    {
#ifdef PFI
    case fn_pfi: 
      /* can do any color depth */
      outColors = inColors;
      needBeautify = false;
      break;
#endif
    case fn_ppm: 
      outColors = 3;
      break;
    case fn_pgm: 
      outColors = 1;
      break;
    case fn_raw:
      cerr << "Error, can't process raw images!" << endl;
      return 1;
    case fn_jpg: 
      outColors = 3;
      break;
    default: 
      cerr << "Error, unknown file type!" << endl;
      return 1;
    }

  if (inColors < outColors)
    {
      cerr << "Error, target numbe of colors is greater than in source." 
           << endl;
      return 1;
    }
  
  /* Color image to color image */
  if (outColors == 3)
    {
      ColorImage *inFile = NEW (ColorImage ());
      try
        {
          inFile->read (infile);
        }
      catch (const exception &error)
        {
          cerr << "Error while reading: " << error.what () <<endl;
          return 1;
        }
      if (needBeautify)
        {
          inFile->beautify ();
        }
      try
        {
          inFile->write (outfile);
        }
      catch (const exception &error)
        {
          cerr << "Error while writing: " << error.what () << endl;
          return 1;
        }
      DELETE (inFile);
    }
  /* Color image to greyscale image */
  else if (inColors == 3)
    {
      ColorImage *inFile = NEW (ColorImage ());
      try
        {
          inFile->read (infile);
        }
      catch (const exception &error)
        {
          cerr << "Error while reading: " << error.what () <<endl;
          return 1;
        }
      inFile->colormodel (cm_yuv);
      Image *outFile = (inFile->channel (0)).clone ();
      if (needBeautify)
        {
          outFile->beautify ();
        }
      try
        {
          outFile->write (outfile);
        }
      catch (const exception &error)
        {
          cerr << "Error while writing: " << error.what () << endl;
          return 1;
        }
      DELETE (inFile);
      DELETE (outFile);
    }
  /* Greyscale image to greyscale image */
  else 
    {
      Image *inFile = NEW (StillImage ());
      try
        {
          inFile->read (infile);
        }
      catch (const exception &error)
        {
          cerr << "Error while reading: " << error.what () <<endl;
          return 1;
        }
      if (needBeautify)
        {
          inFile->beautify ();
        }
      try
        {
          inFile->write (outfile);
        }
      catch (const exception &error)
        {
          cerr << "Error while writing: " << error.what () << endl;
          return 1;
        }
      DELETE (inFile);
    }
  return 0;
}

