/*****************************************************************
 * flcavg.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.
 *
 * flcavg.c: Constrained average halftoning
 *
 * CONTENTS
 *	constravg_fbm (input, output, gamma)
 *
 * EDITLOG
 *	LastEditDate = Mon Jun 25 00:04:57 1990 - Michael Mauldin
 *	LastFileName = /usr2/mlm/src/misc/fbm/flcavg.c
 *
 * HISTORY
 * 25-Jun-90  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
 *	Package for Release 1.0
 *
 * 20-May-89  Michael Mauldin (mlm) at Carnegie Mellon University
 *	Bug fix from Dave Cohrs <dave@cs.wisc.edu>
 *
 * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
 *	Beta release (version 0.9) 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"

/****************************************************************
 * constravg_fbm: Constrained Average halftoning
 * Reference: Jarvis & Roberts, IEEE Trans. on Commun., v24n8, p 891-898
 ****************************************************************/

# define NBR 9

#ifndef lint
static char *fbmid =
"$FBM flcavg.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

constravg_fbm (input, output, gamma)
FBM *input, *output;
double gamma;
{ register unsigned char *bmp, *obm;
  register int i, j, rowlen, w, h, sum, thresh, outrow;
  int gamma100 = gamma * 100;

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

  fprintf (stderr, "Constrained average halftoning, gamma %1.2lf\n", gamma);

  /* Allocate output */
  output->hdr = input->hdr;
  output->hdr.bits = 1;
  output->hdr.physbits = 8;
  outrow = 16 * ((input->hdr.cols + 15) / 16); /* Pad to even byte boundary */
  output->hdr.rowlen = outrow;
  output->hdr.plnlen = outrow*output->hdr.rows;
  alloc_fbm (output);

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

  /* Use threshold of 1/2 in the output border */
  for (j=0; j<h; j++)
  { output->bm[j*outrow]         = input->bm[j*rowlen]         > (WHITE/2);
    output->bm[j*outrow + (w-1)] = input->bm[j*rowlen + (w-1)] > (WHITE/2);
  }

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

  /*
   * Now process the interior bits (use sum instead of average and divide
   * by 9 when we are all done -- this allows fixed point arithmetic)
   */

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

    for (i=1; i<w-1; i++)
    { sum = bmp[(i-w) - 1] + bmp[(i-w)] + bmp[(i-w) + 1] +
	    bmp[i-1]       + bmp[i]     + bmp[i+1] +
	    bmp[i+w-1]     + bmp[i+w]   + bmp[i+w+1];
      
      thresh = gamma100/100 + (sum*WHITE - 2*gamma100*sum/100) / (NBR*WHITE);
      obm[i] = (bmp[i] > thresh) ? 1 : 0;
    }
  }

  return (1);
}
