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

  1. /*****************************************************************
  2.  * flblue.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.  * flblue.c: Blue noise dithering
  9.  *
  10.  * CONTENTS
  11.  *    bluenoise_fbm (input, output, noiselevel)
  12.  *
  13.  * EDITLOG
  14.  *    LastEditDate = Sat May 20 19:06:08 1989 - Michael Mauldin
  15.  *    LastFileName = /usr2/mlm/src/misc/fbm/flblue.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.  * bluenoise_fbm:  Do Floyd-Steinberg halftoning with serpentine
  35.  *           raster and 'noiselevel' random weights.
  36.  *           (noise level runs from 0 to 100 percent)
  37.  *
  38.  * REFERENCES
  39.  *    Digital Halftoning, by Robert Ulichney (1986 MIT Press)
  40.  *****************************************************************/
  41.  
  42. # define RAND(RN) (((seed = 1103515245 * seed + 12345) >> 12) % (RN))
  43. # define INITERR(X,Y) \
  44.     (((int) X) - (((int) Y)?WHITE:BLACK) + ((WHITE/2)-((int) X))/2)
  45.  
  46. #ifndef lint
  47. static char *fbmid =
  48.     "$FBM flblue.c <0.94> 20-May-89  (C) 1989 by Michael Mauldin$";
  49. #endif
  50.  
  51. bluenoise_fbm (input, output, noiselevel)
  52. FBM *input, *output;
  53. double noiselevel;
  54. { register unsigned char *bmp, *obm;
  55.   register unsigned seed = 0;
  56.   register int i, j, rowlen, gray, error, w, h, den, outrow;
  57.   int w1, w3, w5, w7, smrange, lgrange, smnoise, lgnoise;
  58.   int *eerr, *oerr;
  59.  
  60.   if (input->hdr.planes != 1)
  61.   { fprintf (stderr, "bluenoise_fbm: can't halftone color images\n");
  62.     return (0);
  63.   }
  64.  
  65.   fprintf (stderr, "Blue noise, %1.2lf%% weights\n", noiselevel);
  66.  
  67.   /* Allocate output */
  68.   free_fbm (output);
  69.   output->hdr = input->hdr;
  70.   output->hdr.bits = 1;
  71.   output->hdr.physbits = 8;
  72.   outrow = 16 * ((input->hdr.cols + 15) / 16); /* Pad to even byte boundary */
  73.   output->hdr.rowlen = outrow;
  74.   output->hdr.plnlen = outrow*output->hdr.rows;
  75.   alloc_fbm (output);
  76.  
  77.   w = input->hdr.cols;
  78.   h = input->hdr.rows;
  79.   rowlen = input->hdr.rowlen;
  80.   
  81.   /* Allocate space for error arrays */
  82.   eerr = (int *) malloc ((unsigned) w * sizeof (*eerr));
  83.   oerr = (int *) malloc ((unsigned) w * sizeof (*oerr));
  84.   for (i=0; i<w; i++) eerr[i] = oerr[i] = 0;
  85.  
  86.     /* The left border */
  87.   error = 0;
  88.   for (j=0; j<h; j++)
  89.   { register int thresh = (WHITE/2 + RAND (129) - 64);
  90.  
  91.     gray = input->bm[j*rowlen] + error;
  92.     den = gray > thresh ? WHITE : BLACK;
  93.     error = gray - den;
  94.     output->bm[j*outrow] = den;
  95.   }
  96.  
  97.   /* The right border */
  98.   error = 0;
  99.   for (j=0; j<h; j++)
  100.   { register int thresh = (WHITE/2 + RAND (129) - 64);
  101.  
  102.     gray = input->bm[j*rowlen + (w-1)] + error;
  103.     den = gray > thresh ? WHITE : BLACK;
  104.     error = gray - den;
  105.     output->bm[j*outrow + (w-1)] = den;
  106.   }
  107.  
  108.   /* The top border */
  109.   error = 0;
  110.   for (i=0; i<w; i++)
  111.   { register int inp = input->bm[i], thresh = (WHITE/2 + RAND (129) - 64);
  112.  
  113.     gray = inp + error;
  114.     den = gray > thresh ? WHITE : BLACK;
  115.     error = gray - den;
  116.     output->bm[i] = den;
  117.     eerr[i] = INITERR (inp, den);
  118.   }
  119.  
  120.   /*
  121.    * Now process the interior bits
  122.    *
  123.    *  Weights:            1+n1  5+n5  3-n1
  124.    *                7-n5    *
  125.    *
  126.    * n1 and n5 are random noise from -0.5 to 0.5 and -2.5 to 2.5
  127.    */
  128.    
  129.   smrange = 2000 * noiselevel/100.0; smrange += 1;
  130.   lgrange = 10000 * noiselevel/100.0; lgrange += 1;
  131.   
  132. # ifdef DEBUG
  133.   fprintf (stderr, "Blue noise level %6.2lf (small %d..%d, large %d..%d)\n",
  134.       noiselevel, -(smrange/2), smrange/2, -(lgrange/2), lgrange/2);
  135. # endif
  136.  
  137.   for (j=1; j<h; j++)
  138.   { bmp = &input->bm[j*rowlen];
  139.     obm = &output->bm[j*outrow];
  140.  
  141.     if (j&1)                /* Odd rows */
  142.     { oerr[0] = INITERR (bmp[0], obm[0]);
  143.  
  144.       for (i=1; i<w-1; i++)
  145.       { /* Set random weights */
  146.     w1 = 1000; w3 = 3000; w5 = 5000; w7 = 7000;
  147.   
  148.     smnoise = RAND (smrange) - smrange/2;
  149.     w1 += smnoise; w3 -= smnoise;
  150.   
  151.     lgnoise = RAND (lgrange) - lgrange/2;
  152.     w5 += lgnoise; w7 -= lgnoise;
  153.   
  154.     error =  (w1 * eerr[i-1] +
  155.           w5 * eerr[i] +
  156.           w3 * eerr[i+1] +
  157.           w7 * oerr[i-1]) / 16000;
  158.     gray = bmp[i] + error;
  159.   
  160. # ifdef DEBUG
  161.     if (j>10 && j<14 && i>40 && i<44)
  162.     { fprintf (stderr,
  163.            "\n<%3d,%3d> input %d, error %d\n",
  164.            i, j, bmp[i], error);
  165.       fprintf (stderr, "Noise {%d,%d} Weights {%d,%d,%d,%d}\n",
  166.            smnoise, lgnoise, w1, w3, w5, w7);
  167.       fprintf (stderr,
  168.            "Errs:\t%5d  %5d  %5d\n\t%5d      *\n",
  169.            eerr[i-1], eerr[i], eerr[i+1], oerr[i-1]);
  170.     }
  171. # endif
  172.  
  173.     if (gray > (WHITE/2))
  174.     { obm[i] = 1;    oerr[i] = gray - WHITE; }
  175.     else
  176.     { obm[i] = 0;    oerr[i] = gray; }
  177.       }
  178.       
  179.       /* Set errors for ends of this row */
  180.       oerr[0]   = INITERR (bmp[0], obm[0]);
  181.       oerr[w-1] = INITERR (bmp[w-1], obm[w-1]);
  182.     }
  183.     else
  184.     { eerr[w-1] = INITERR (bmp[w-1], obm[w-1]);
  185.  
  186.       for (i=w-2; i>0; i--)
  187.       { /* Set random weights */
  188.     w1 = 1000; w3 = 3000; w5 = 5000; w7 = 7000;
  189.   
  190.     smnoise = RAND (smrange) - smrange/2;
  191.     w1 += smnoise; w3 -= smnoise;
  192.   
  193.     lgnoise = RAND (lgrange) - lgrange/2;
  194.     w5 += lgnoise; w7 -= lgnoise;
  195.   
  196.     error =  (w1 * oerr[i+1] +
  197.           w5 * oerr[i] +
  198.           w3 * oerr[i-1] +
  199.           w7 * eerr[i+1]) / 16000;
  200.     gray = bmp[i] + error;
  201.   
  202.     if (gray > (WHITE/2))
  203.     { obm[i] = 1;    eerr[i] = gray - WHITE; }
  204.     else
  205.     { obm[i] = 0;    eerr[i] = gray; }
  206.       }
  207.  
  208.       /* Set errors for ends of this row */
  209.       eerr[0]   = INITERR (bmp[0], obm[0]);
  210.       eerr[w-1] = INITERR (bmp[w-1], obm[w-1]);
  211.     }
  212.   }
  213.   return (1);
  214. }
  215.