/*
 * Denoise an image
 *
 * $Date$
 * $Revision$
 *
 */

#include <iostream>
#include <stdexcept>
#include <cstdio>
#include <cmath>
#include <cassert>
#include <WTools.hh>

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

int
main (int argc, char *argv[])
{
  cout << "pgmdenoise version " << WAVE_VERSION << " (c) 2001-2004 by Herbert"
#ifdef PFI
       << " (pfi support enabled)"
#endif
       << endl;

  char *infile;
  char *outfile;
  Image *image = NEW (StillImage ());
  coeff alpha = 1.0;
  int from = 0;
  int to = 0;
  unsigned areas = DENOISE_HL | DENOISE_LH | DENOISE_HH;
  int sfunction = SIGNIFICANT_COEFF; 
  int rfunction = REPLACE_SIMPLE; 
  FilterSet *filter = &Daub4;

  if (argc < 5 || argc > 10)
    {
      cerr << "Usage: pgmdenoise <infile> <outfile> <from> <to> [optional]" 
           << endl
           << "Optional are: [<alpha> [<filter> [<sfunction> [rfunction "
           << "[<areas>]]]]]" << endl;
      cerr << "Valid sfunctions are 0, 1, 2" << endl;
      cerr << "Valid rfunctions are 0, 1" << endl;
      cerr << "Valid areas are binary combinations of 1, 2, 4" << endl;
      
      return 1;
    }

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

  if (sscanf (argv[3], "%d", &from) != 1)
    {
      cerr << "Invalid from: " << argv[3] << endl;
      return 1;
    }

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

  if (argc > 5)
    {
      if (sscanf (argv[5], "%lf", &alpha) != 1 || alpha < 0)
        {
          cerr << "Invalid alpha: " << argv[5] << endl;
          return 1;
        }
    }

  if (argc > 6)
    {
      try
        {
          filter = &FilterSet::filterFromString (argv[6]);
        }
      catch (const exception &error)
        {
          cerr << "Error, : " << error.what () << endl;
          return 1;
        }
    }

  if (argc > 7)
    {
      if (sscanf (argv[7], "%d", &sfunction) != 1 
          || sfunction < 0 || sfunction > 2)
        {
          cerr << "Invalid sfunction: " << argv[7] << endl;
          return 1;
        }
    }

  if (argc > 8)
    {
      if (sscanf (argv[8], "%d", &rfunction) != 1 
          || rfunction < 0 || rfunction > 1)
        {
          cerr << "Invalid rfunction: " << argv[8] << endl;
          return 1;
        }
    }

  if (argc > 9)
    {
      if (sscanf (argv[9], "%u", &areas) != 1)
        {
          cerr << "Invalid areas: " << argv[9] << endl;
          return 1;
        }
    }

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

  //cout << "DEBUG: settings: " << endl
  //     << "infile: " << infile << endl
  //     << "outfile: " << outfile << endl
  //     << "from: " << from << endl
  //     << "to: " << to << endl
  //     << "alpha: " << alpha << endl
  //     << "filter: " << FilterSet::filterToString (*filter) << endl;

  try 
    {
      ImageDenoiser *denoiser;
      denoiser = NEW (ImageDenoiser (*image, 
                                     DENOISE_HL | DENOISE_LH | DENOISE_HH,
                                     from, to, alpha, *filter, sfunction, 
                                     rfunction));
      denoiser->denoise ();
      DELETE (denoiser);
    }
  catch (const exception &error)
    {
      cerr << "Denoising: " << error.what () << endl;
      return 1;
    }
  
  try
    {
      image->write (outfile);
    }
  catch (const exception &error)
    {
      cerr << "Writing image: " << error.what () << endl;
      return 1;
    }

  DELETE (image);
  
  return 0;
}

