
/************************************************************************/
#define OP_NAME      "pgmlulu"
#define VERSION      "1.01"
#define DATE         "30.01.98"
#define AUTHOR       "Stefan Diener"
/************************************************************************/

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#include <STIMP/pgm.c>

#define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b))

struct PGM_Info source, desti;
static int m, n;
static int parallel=TRUE;

int L8(int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8, int x9)
{
  int m1, m2, m3, m4;

  m1=min(min(x1,x2), min(x5,x4));
  m2=min(min(x3,x2), min(x5,x6));
  m3=min(min(x4,x5), min(x7,x8));
  m4=min(min(x5,x6), min(x8,x9));

  return(max(max(m1,m2), max(m3,m4)));
}

int U8(int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8, int x9)
{
  int m1, m2, m3, m4;

  m1=max(max(x1,x2), max(x4,x5));
  m2=max(max(x3,x2), max(x5,x6));
  m3=max(max(x4,x5), max(x7,x8));
  m4=max(max(x5,x6), max(x8,x9));

  return (min(min(m1,m2), min(m3,m4)));
}

void Do_It(void)
{
  int i, k, x1, x2, x3, x4, x5, x6, x7, x8, x9, tempo;
  unsigned char *src, *dst;

  src=source.Data;
  if (parallel)
  {
    dst=desti.Data;
    desti.maxval=source.maxval;
  }

  /* oberen Rand ueberlesen */
  src=src+n;

  for(k=2; k<m-1; k++)
  {
    /* linken Rand ueberlesen */
    src++;

    /* Mitte via LULU bestimmen */
    for (i=1; i<n-1; i++)
    {
      x1=*(src-1-n);
      x2=*(src-n);
      x3=*(src+1-n);
      x4=*(src-1);
      x5=*src;
      x6=*(src+1);
      x7=*(src-1+n);
      x8=*(src+n);
      x9=*(src+1+n);

      tempo=L8(x1,x2,x3,x4,x5,x6,x7,x8,x9);

      if (parallel)
      {
        *dst++ = U8(x1,x2,x3,x4,tempo,x6,x7,x8,x9);
        src++;
      }
      else *src++ = U8(x1,x2,x3,x4,tempo,x6,x7,x8,x9);
    }

    /* rechten Rand ueberlesen */
    src++;
  }
}

int main(int argc,char **argv)
/* main program */
{
  int i;

  /* say hello */
  PrintOpening(argc,argv);

  /* read the parameters */
  for (i=1; i<argc; i++)
  {
    if ((argv[i][0]=='-') && argv[i][1])
    {
      switch (argv[i][1])
      {
        case 'p': parallel=TRUE;
                      break;

        case 's': parallel=FALSE;
                      break;

        case 'v': beVerbose=FALSE;
                      break;

        default: PrintMessage("Unknown parameter: %s", argv[i]);
                     Hilfe();
                     exit(-1);
                     break;
      }
    }

    if (argv[i][0]=='+')
    {
      switch (argv[i][1])
      {
        case 'v': beVerbose=TRUE;
                      break;

        default: PrintMessage("Unknown parameter: %s", argv[i]);
                     Hilfe();
                     exit(-1);
                     break;
      }
    }
  }

  /* check minimal number of arguments */
  if (argc<3)
  {
    PrintMessage("Not enough arguments !");
    Hilfe();
    exit(-1);
  }

  /* check number of file names */
  if (FilenameCount(argc, argv)!=2)
  {
    PrintMessage("Wrong number of file names !");
    Hilfe();
    exit(-1);
  }

  if (ReadPGMFile(GetFilename(1,argc,argv), &source)==0)
  {
    m=source.height;
    n=source.width;

    if (parallel)
    {
      if (CreatePGMArray(m-2, n-2, &desti)==0)
      {
        PrintMessage("Working ...");
        Do_It();

        WritePGMFile(GetFilename(2,argc,argv), &desti);
        FreePGMArray(&desti);
      }
    }
    else
    {
      PrintMessage("Working ...");
      Do_It();

      WritePGMFile(GetFilename(2,argc,argv), &source);
    }

    FreePGMArray(&source);
  }

  PrintClosing();
  exit(0);
}

