/*****************************************************************
 * flshrp.c: FBM Release 1.0 25-Feb-90 Michael Mauldin
 *
 * Copyright (C) 1989,1990 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.
 *
 * flshrp.c: 
 *
 * CONTENTS
 *	sharpen_fbm (input, output, beta)
 *
 * EDITLOG
 *	LastEditDate = Mon Jun 25 00:18:02 1990 - Michael Mauldin
 *	LastFileName = /usr2/mlm/src/misc/fbm/flshrp.c
 *
 * HISTORY
 * 25-Jun-90  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
 *	Package for Release 1.0
 *
 * 05-Sep-89  Michael Mauldin (mlm) at Carnegie Mellon University
 *	Beta release (version 0.96) mlm@cs.cmu.edu
 *
 * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
 *	Created.
 *****************************************************************/

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

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

#ifndef lint
static char *fbmid =
"$FBM flshrp.c <1.0> 25-Jun-90  (C) 1989,1990 by Michael Mauldin, source \
code available free from MLM@CS.CMU.EDU and from UUNET archives$";
#endif

sharpen_fbm (input, output, beta)
FBM *input, *output;
double beta;
{
  if (input->hdr.planes == 1 && input->hdr.clrlen == 0)
  { return (sharpen_bw (input, output, beta)); }
  else
  { return (sharpen_clr (input, output, beta)); }
}

/****************************************************************
 * sharpen_bw: use a digital Laplacian filter to sharpen a BW image
 ****************************************************************/

sharpen_bw (input, output, beta)
FBM *input, *output;
double beta;
{ register unsigned char *bmp, *obm;
  register int i, j, rowlen, w, h, sum;
  int new, delta, beta100 = beta * 100;

  if (input->hdr.planes != 1)
  { fprintf (stderr, "sharpen_bw: can't sharpen color images\n");
    return (0);
  }

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

  w = input->hdr.cols;
  h = input->hdr.rows;
  rowlen = input->hdr.rowlen;

  /* Copy edges directly */
  for (j=0; j<h; j++)
  { output->bm[j*rowlen] = input->bm[j*rowlen];
    output->bm[j*rowlen + w-1] = input->bm[j*rowlen + w-1];
  }

  for (i=0; i<w; i++)
  { output->bm[i] = input->bm[i];
    output->bm[(h-1)*rowlen + i] = input->bm[(h-1)*rowlen + i];
  }

  for (j=1; j < h-1; j++)
  { bmp = &(input->bm[j*rowlen]);
    obm = &(output->bm[j*rowlen]);
    
    for (i=1; i < w-1; i++)
    { sum = bmp[i-rowlen-1] +     bmp[i-rowlen] + bmp[i-rowlen+1] +
	    bmp[i-1]        - 8 * bmp[i]        + bmp[i+1]        +
	    bmp[i+rowlen-1] +     bmp[i+rowlen] + bmp[i+rowlen+1];

      if (sum < 0)
      { delta = - (beta100 * bmp[i] * -sum / (8*WHITE*100)); }
      else
      { delta = beta100 * bmp[i] * sum / (8*WHITE*100); }

      new = bmp[i] - delta;

      if (new < BLACK) new = BLACK;
      else if (new > WHITE) new = WHITE;
      
      obm[i] = new;
    }
  }
  
  return (1);
}

/****************************************************************
 * sharpen_clr: use a digital Laplacian filter to sharpen a CLR image
 ****************************************************************/

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

  if (input->hdr.clrlen > 0)
  { fprintf (stderr,
	 "cannot sharpen mapped color images, use 'gray2clr -u' first\n");
    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;
  
  /* Calculate the intensity plane */
  gray = (unsigned char *) malloc (plnlen);

  for (j=0; j<h; j++)  
  { bmp = &(input->bm[j*rowlen]);
    avg = &(gray[j*rowlen]);    

    for (i=0; i<w; i++)
    { sum = 0;
      for (k=0; k<p; k++)
      { sum += bmp[i+k*plnlen]; }
      avg[i] = sum/p;
    }
  }
  
  /* Copy edges directly */
  for (k=0; k<p; k++)
  {  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];
    }
  }

  for (j=1; j < h-1; j++)
  { avg = &(gray[j*rowlen]);
    
    for (i=1; i < w-1; i++)
    { sum = avg[i-rowlen-1] +     avg[i-rowlen] + avg[i-rowlen+1] +
	    avg[i-1]        - 8 * avg[i]        + avg[i+1]        +
	    avg[i+rowlen-1] +     avg[i+rowlen] + avg[i+rowlen+1];

      for (k=0; k<p; k++)
      { bmp =  &(input->bm[k*plnlen + j*rowlen + i]);
        obm = &(output->bm[k*plnlen + j*rowlen + i]);
        
	if (sum < 0)
	{ delta = - (beta100 * *bmp * -sum / (8*WHITE*100)); }
	else
	{ delta = beta100 * *bmp * sum / (8*WHITE*100); }
  
	new = *bmp - delta;
  
	if (new < BLACK) new = BLACK;
	else if (new > WHITE) new = WHITE;
	
	*obm = new;
      }
    }
  }
  
  return (1);
}
