/*****************************************************************
 * flmedn.c: FBM Release 1.1 04-Feb-93 Michael Mauldin
 *
 * Copyright (C) 1993 by Michael Mauldin.  Permission is granted
 * to use this file in whole or in part for any purpose, educational,
 * recreational or commercial, provided that this copyright notice
 * is retained unchanged.  This software is available to all free of
 * charge by anonymous FTP and in the UUNET archives.
 *
 * flmedn.c: 
 *
 * CONTENTS
 *	median_fbm (input, output)
 *
 * EDITLOG
 *	LastEditDate = Mon Jun 25 00:18:02 1990 - Michael Mauldin
 *	LastFileName = /usr2/mlm/src/misc/fbm/flmedn.c
 *
 * HISTORY
 * 04-Feb-93  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
 *	Created.
 *****************************************************************/

# include <stdio.h>
# include <math.h>
# include <ctype.h>
# include "fbm.h"

/****************************************************************
 * median_fbm: determine whether image is in color, and call the
 *	        appropriate medianing routine.
 ****************************************************************/

#ifndef lint
static char *fbmid =
"$FBM flmedn.c <1.0> 04-Feb-93  (C) 1993 by Michael Mauldin, source \
code available free from MLM@CS.CMU.EDU and from UUNET archives$";
#endif


/****************************************************************
 * median_fbm: median filter an unmapped image
 ****************************************************************/

median_fbm (input, output, beta)
FBM *input, *output;
double beta;
{ register unsigned char *bmp, *obm, *ibm;
  register int i, j, k, rowlen, plnlen, w, h, p, sum;
  int new, delta, beta100 = beta * 100;
  int mdn[9];
  unsigned char *gray;

  if (input->hdr.physbits != 8)
  { fprintf (stderr, "median_bw: can't median images with %d physbits\n",
	     input->hdr.physbits);
    return (0);
  }

  if (input->hdr.clrlen > 0)
  { fprintf (stderr, "median_bw: can't median images with %d physbits\n",
	     input->hdr.physbits);
    return (0);
  }


  /* Allocate output */
  output->hdr = input->hdr;
  alloc_fbm (output);

  w = input->hdr.cols;
  h = input->hdr.rows;
  p = input->hdr.planes;
  rowlen = input->hdr.rowlen;
  plnlen = input->hdr.plnlen;
  
  for (k=0; k<p; k++)
  {
    /* Copy edges directly */
    for (j=0; j<h; j++)
    { output->bm[k*plnlen + j*rowlen] =
	input->bm[k*plnlen + j*rowlen];
      output->bm[k*plnlen + j*rowlen + w-1] =
	input->bm[k*plnlen + j*rowlen + w-1];
    }
  
    for (i=0; i<w; i++)
    { output->bm[k*plnlen + i] =
	input->bm[k*plnlen + i];
      output->bm[k*plnlen + (h-1)*rowlen + i] =
	input->bm[k*plnlen + (h-1)*rowlen + i];
    }

    /* Now set each pixel to median of 9 */
    for (j=1; j < h-1; j++)
    { ibm = &(input->bm[k*plnlen + j*rowlen]);
      obm = &(output->bm[k*plnlen + j*rowlen]);
        
      for (i=1; i < w-1; i++)
      { mdn[0] = ibm[i-rowlen-1];
	mdn[1] = ibm[i-rowlen];
	mdn[2] = ibm[i-rowlen+1];
	mdn[3] = ibm[i-1];
	mdn[4] = ibm[i];
	mdn[5] = ibm[i+1];
	mdn[6] = ibm[i+rowlen-1];
	mdn[7] = ibm[i+rowlen];
	mdn[8] = ibm[i+rowlen+1];

	obm[i] = median (mdn, 9);
      }
    }
  }
  
  return (1);
}

/****************************************************************
 * median: Return the median of an array, perhaps reordering the
 * elements of the array.  Uses bubble sort 
 ****************************************************************/

median (arr, n)
register int *arr, n;
{ register int swapped = 1, t, i, mid = n>>1;

  while (swapped)
  { swapped = 0;

    for (i=1; i<n; i++)
    { if (arr[i-1] > arr[i])
      { t = arr[i];
        arr[i] = arr[i-1];
	arr[i-1] = t;
	swapped++;
      }
    }
  }
  
  if (n&1)
  { return (arr[mid]); }
  else
  { return ((arr[mid - 1] + arr[mid]) / 2); }
}

# ifdef TESTING
main (argc, argv)
char *argv[];
{ int arr[32], n=0;

  for (n=1; n<argc; n++)
  { arr[n-1] = atoi (argv[n]); }
  n--;

  fprintf (stderr, "median = %d\n", median (arr, n));
}
# endif
