/*
 * Wavelets on Greyscale images (PGM)
 *
 * $Date$
 * $Revision$
 *
 */

#include <iostream>
#include <stdexcept>
#include <cassert>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <Wave.hh>

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

int
main (int argc, char *argv[])
{
  int stages = 1;
  FilterSet *flt = &Daub4;
  
  cout << "wavepgm version " << WAVE_VERSION << " (c) 2001-2004 by Herbert"
#ifdef PFI
       << " (pfi support enabled)"
#endif
       << endl;

  bool standard = false;

  if (argc > 2 && strcmp (argv[1], "-s") == 0)
    {
      standard = true;
      argc--;
      argv++;
    }

  if (argc < 3 || argc > 8)
    {
      cerr << "Usage: wavepgm [-s] <infile> <transformed> [<optional>]\n"
           << "      optional: "
           << "[stages [filter [<reconstructed> [<beautified>]]]]\n";
      return 1;
    }
  
  if (argc > 3)
    {
      if (sscanf (argv[3], "%d", &stages) != 1)
        {
          cerr << "Invalid stages: " << argv[3] << endl;
          return 1;
        }
    }
  if (argc > 4)
    {
      try
        {
          flt = &FilterSet::filterFromString (argv[4]);
        }
      catch (const exception &error)
        {
          cerr << "Error, : " << error.what () << endl;
          return 1;
        }
    }
  
  cout << "initialize:\n";
  
  Image *img = NEW (StillImage ());
  Image *beautified = NULL;
  
  cout << "read image " << argv[1] << "...\n";

  try
    {
      img->read (argv[1]);
    }
  catch (const exception &error)
    {
      cerr << "Reading image: " << error.what () <<endl;
      return 1;
    }

  WaveletTransform *transform;

  if (standard)
    {
      transform = NEW (StandardTransform (*img, *flt));
    }
  else
    {
      transform = NEW (PyramidTransform (*img, *flt));
    }
  
  cout << "analysis...\n";
  
  try
    {
      transform->analysis (stages);
    }
  catch (const exception &error)
    {
      cerr << "Analysis: " << error.what () <<endl;
      return 1;
    }

  cout << "write transformed image " << argv[2] << "...\n";
  try
    {
      img->write (argv[2]);
    }
  catch (const exception &error)
    {
      cerr << "Writing transformed image: " << error.what () << endl;
      return 1;
    }
  
  if (argc > 5)
    {

      if (argc > 6)
        {
          beautified = img->clone ();
        }
      
      cout << "synthesis...\n";
      
      try
        {
          transform->synthesis (stages, stages);
        }
      catch (const exception &error)
        {
          cerr << "Synthesis: " << error.what () <<endl;
          return 1;
        }

      cout << "write reconstructed image " << argv[5] << "...\n";

      try
        {
          img->write (argv[5]);
        }
      catch (const exception &error)
        {
          cerr << "Writing reconstructed image: " << error.what () << endl;
          return 1;
        }
    }

  if (argc > 6)
    {
      cout << "beautification...\n";
      int y, x, a, b;
      transform->where (LL, stages, y, x, a, b);
      beautified->beautify (y, x, a, b);
      
      cout << "write beautified image " << argv[6] << "...\n";

      try
        {
          beautified->write (argv[6]);
        }
      catch (const exception &error)
        {
          cerr << "Writing beautified image: " << error.what () << endl;
          return 1;
        }

      DELETE (beautified);
    }

  cout << "done.\n";
  
  DELETE (img);
  DELETE (transform);
  
  return 0;
}

