home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume19 / fbm / part03 / flflyd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-08  |  4.3 KB  |  161 lines

  1. /*****************************************************************
  2.  * flflyd.c: FBM Library 0.94 (Beta test) 20-May-89  Michael Mauldin
  3.  *
  4.  * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  5.  * use this file in whole or in part provided that you do not sell it
  6.  * for profit and that this copyright notice is retained unchanged.
  7.  *
  8.  * flflyd.c: 
  9.  *
  10.  * CONTENTS
  11.  *    floyd_fbm (input, output)
  12.  *
  13.  * EDITLOG
  14.  *    LastEditDate = Sat May 20 19:13:12 1989 - Michael Mauldin
  15.  *    LastFileName = /usr2/mlm/src/misc/fbm/flflyd.c
  16.  *
  17.  * HISTORY
  18.  * 20-May-89  Michael Mauldin (mlm) at Carnegie Mellon University
  19.  *    Bug fix from Dave Cohrs <dave@cs.wisc.edu>
  20.  *
  21.  * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  22.  *    Beta release (version 0.9) mlm@cs.cmu.edu
  23.  *
  24.  * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  25.  *    Created.
  26.  *****************************************************************/
  27.  
  28. # include <stdio.h>
  29. # include <math.h>
  30. # include <ctype.h>
  31. # include "fbm.h"
  32.  
  33. /*****************************************************************
  34.  * floyd_fbm: Classical Floyd-Steinberg Halftoning
  35.  *
  36.  * REFERENCES
  37.  *    Digital Halftoning, by Robert Ulichney (1986 MIT Press)
  38.  *****************************************************************/
  39.  
  40. # define RAND(RN) (((seed = 1103515245 * seed + 12345) >> 12) % (RN))
  41. # define INITERR(X,Y) \
  42.     (((int) X) - (((int) Y)?WHITE:BLACK) + ((WHITE/2)-((int) X))/2)
  43.  
  44. #ifndef lint
  45. static char *fbmid =
  46.     "$FBM flflyd.c <0.94> 20-May-89  (C) 1989 by Michael Mauldin$";
  47. #endif
  48.  
  49. floyd_fbm (input, output)
  50. FBM *input, *output;
  51. { register unsigned char *bmp, *obm;
  52.   register int i, j, rowlen, gray, error, w, h, den, outrow;
  53.   int *lerr, *cerr, *terr;
  54.   register int seed = 0;
  55.  
  56.   if (input->hdr.planes != 1)
  57.   { fprintf (stderr, "floyd_fbm: can't halftone color images\n");
  58.     return (0);
  59.   }
  60.  
  61.   fprintf (stderr, "Floyd-Steinberg halftoning\n");
  62.  
  63.   /* Allocate output */
  64.   free_fbm (output);
  65.   output->hdr = input->hdr;
  66.   output->hdr.bits = 1;
  67.   output->hdr.physbits = 8;
  68.   outrow = 16 * ((input->hdr.cols + 15) / 16); /* Pad to even byte boundary */
  69.   output->hdr.rowlen = outrow;
  70.   output->hdr.plnlen = outrow*output->hdr.rows;
  71.   alloc_fbm (output);
  72.  
  73.   w = input->hdr.cols;
  74.   h = input->hdr.rows;
  75.   rowlen = input->hdr.rowlen;
  76.   
  77.   /* Allocate space for error arrays */
  78.   lerr = (int *) malloc (w * sizeof (*lerr));
  79.   cerr = (int *) malloc (w * sizeof (*cerr));
  80.   for (i=0; i<w; i++) lerr[i] = cerr[i] = 0;
  81.  
  82.   /* The left border */
  83.   error = 0;
  84.   for (j=0; j<h; j++)
  85.   { register int thresh = (WHITE/2 + RAND (129) - 64);
  86.  
  87.     gray = input->bm[j*rowlen] + error;
  88.     den = gray > thresh ? WHITE : BLACK;
  89.     error = gray - den;
  90.     output->bm[j*outrow] = den;
  91.   }
  92.  
  93.   /* The right border */
  94.   error = 0;
  95.   for (j=0; j<h; j++)
  96.   { register int thresh = (WHITE/2 + RAND (129) - 64);
  97.  
  98.     gray = input->bm[j*rowlen + (w-1)] + error;
  99.     den = gray > thresh ? WHITE : BLACK;
  100.     error = gray - den;
  101.     output->bm[j*outrow + (w-1)] = den;
  102.   }
  103.  
  104.   /* The top border */
  105.   error = 0;
  106.   for (i=0; i<w; i++)
  107.   { register int thresh = (WHITE/2 + RAND (129) - 64);
  108.  
  109.     gray = input->bm[i] + error;
  110.     den = gray > thresh ? WHITE : BLACK;
  111.     error = gray - den;
  112.     output->bm[i] = den;
  113.     lerr[i] = INITERR (input->bm[i], den);
  114.   }
  115.  
  116.   /*
  117.    * Now process the interior bits
  118.    *
  119.    *  Weights:            1 5 3
  120.    *                7 *
  121.    */
  122.  
  123.   for (j=1; j<h; j++)
  124.   { /* scan left to right */
  125.     bmp = &input->bm[j*rowlen];
  126.     obm = &output->bm[j*outrow];
  127.  
  128.     cerr[0] = INITERR (bmp[0], obm[0]);
  129.  
  130.     for (i=1; i<w-1; i++)
  131.     {
  132.       error =  (lerr[i-1] + 5 * lerr[i] + 3 * lerr[i+1] + 7 * cerr[i-1]) / 16;
  133.  
  134. # ifdef DEBUG
  135.       if (i > 5 && i < 9 && j > 5 && j < 9)
  136.       { fprintf (stderr, "<%2d,%2d>  Input %3d, Error %5d, Output %d\n",
  137.          i, j, bmp[i], error, bmp[i] + error > (WHITE/2));
  138.     fprintf (stderr, "Errors:   %5d  %5d  %5d\n          %5d      *\n\n", 
  139.          lerr[i-1], lerr[i], lerr[i+1], cerr[i-1]);
  140.       }
  141. # endif
  142.  
  143.       gray = bmp[i] + error;
  144.  
  145.       if (gray > (WHITE/2))
  146.       { obm[i] = WHITE;    cerr[i] = gray - WHITE; }
  147.       else
  148.       { obm[i] = BLACK;    cerr[i] = gray - BLACK; }
  149.     }
  150.     
  151.     /* Set errors for ends of the row */
  152.     cerr[0]   = INITERR (bmp[0], obm[0]);
  153.     cerr[w-1] = INITERR (bmp[w-1], obm[w-1]);
  154.     
  155.     /* Swap error buffers */
  156.     terr = lerr; lerr = cerr; cerr = terr;
  157.   }
  158.   
  159.   return (1);
  160. }
  161.