/*
 * Wavelets on Color images (PPM)
 *
 * $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 << "waveppm version " << WAVE_VERSION << " (c) 2001-2003 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: [-s] waveppm <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";
  
  ColorImage *ppm = NEW (ColorImage ());

  cout << "read image " << argv[1] << "...\n";

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

  WaveletTransform **transforms = NEW (WaveletTransform* [ppm->colors ()]);
  ColorImage *beautified = NULL;

  for (int i = 0; i < ppm->colors (); i++)
    {
      if (standard)
        {
          transforms[i] = NEW (StandardTransform (ppm->channel (i), *flt));
        }
      else
        {
          transforms[i] = NEW (PyramidTransform (ppm->channel (i), *flt));
        }
    }
  
  cout << "analysis...\n";
  
  for (int i = 0; i < ppm->colors (); i++)
    {
      try
        {
          transforms[i]->analysis (stages);
        }
      catch (const exception &error)
        {
          cerr << "Analysis: " << error.what () <<endl;
          return 1;
        }
    }

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

  if (argc > 5)
    {

      if (argc > 6)
        {
          beautified = ppm->clone ();
        }

      cout << "synthesis...\n";

      for (int i = 0; i < ppm->colors (); i++)
        {
          try
            {
              transforms[i]->synthesis (stages);
            }
          catch (const exception &error)
            {
              cerr << "Synthesis: " << error.what () <<endl;
              return 1;
            }
        }

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

      try
        {
          ppm->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;
      transforms[0]->where (LL, stages, y, x, a, b);

      for (int i = 0; i < ppm->colors (); i++)
        {
          (beautified->channel (i)).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";
  
  for (int i = 0; i < ppm->colors (); i++)
    {
      DELETE (transforms[i]);
    }
  DELETEAR (transforms);
  DELETE (ppm);
  
  return 0;
}

