/*
 * Print the max and min greyscale values in an image and their neighbourhood
 *
 * $Date$
 * $Revision$
 *
 */

#include <iostream>
#include <iomanip>
#include <stdexcept>
#include <cstdio>
#include <WTools.hh>

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

static void print_value (const char *message, Image *image, CoeffInformation &ci);
static int print_stats (char *fname);

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

  char *fname;

  if (argc > 1)
    {
      fname = argv[1];
      cout << "File " << fname << endl;
    }
  else
    {
      fname = NULL;
      cout << "File (stdin)" << endl;
    }

  print_stats (fname);
  for (int i = 2; i < argc; i++)
    {
      fname = argv[i];
      cout << "File " << fname << endl;
      print_stats (fname);
    }
  
  return 0;
}

static int
print_stats (char *fname)
{
  Image *image = NEW (StillImage ());
  ImageInformation *ii;
  
  try
    {
      if (fname == NULL)
        {
          image->read (fname, fn_pgm);
        }
      else
        {
          image->read (fname);
        }
    }
  catch (const exception &error)
    {
      cerr << "Reading image: " << error.what () << endl;
      return -1;
    }

  ii = NEW (ImageInformation (*image));
  ii->ssort ();

  int last = ii->size () - 1;
  CoeffInformation min = ii->at (0);
  CoeffInformation max = ii->at (last);

  print_value ((char*)"min: ", image, min);

  for (int i = 1; min.svcmp (ii->at (i)) == 0; i++)
    {
      print_value ("---- ", image, ii->at (i));
    }

  print_value ("max: ", image, max);

  for (int i = last - 1; max.svcmp (ii->at (i)) == 0; i--)
    {
      print_value ("++++ ", image, ii->at (i));
    }

  DELETE (ii);
  DELETE (image);
  
  return 0;
}

  
static void 
print_value (const char *message, Image *image, CoeffInformation &ci)
{
  cout.setf (ios::fixed, ios::floatfield);
  cout << message << std::setprecision (3) << std::setw (8) << ci.val ()
       << " at (" << ci.xpos () << ", " << ci.ypos () << ")" << endl;

  int xmin = ci.xpos () > 0? ci.xpos () - 1: 0;
  int ymin = ci.ypos () > 0? ci.ypos () - 1: 0;

  int xmax = ci.xpos () < image->cols () - 1? ci.xpos () + 2: image->cols ();
  int ymax = ci.ypos () < image->rows () - 1? ci.ypos () + 2: image->rows ();
  
  for (int row = ymin; row < ymax; row++)
    {
      cout << "\t";
      for (int col = xmin; col < xmax; col++)
        {
          cout << std::setprecision (3) << std::setw (8) 
               << image->at (row, col) << "  ";
        }
      cout << endl;
    }
  cout << endl;
}

