1994.08.26 18:01 "tiffdither inserts noise", by Uwe Bonnes

1994.08.26 19:46 "Re: tiffdither inserts noise", by Bill Cattey

After tiffdither, a grayscale image with some black lines on a white background has noise random distributed all over the image. I can adjust the threshold, the lower I set the threshold, the less noise I get, but it is always there in some (unacceptable) degree. Am I doing somthing wrong? As the original data I want to process is a B/W-postscript-File I would request a function "pbm2tiff" to avoid the necessarity of going the way ps --> ppm --> ppm2tiff --> tiff2bw --> tiffdither.

I do not know how this is done with the tiff library, but last month I worked inside some code which had the same problem. I suspect the same class of problem is happening here.

Simple algorithms to dither a monochrome image into a gray scal image do so by looking at neighboring pixels and adding a little bit or subtracting a little bit from the pixel value depending on the values of the neighbors.

Below is an example of such a dithering algorithm.

I added the code:

    if (!(error < -(MinErr) || error >MinErr)) error = 0;

But picking MinErr was tricky.

In the value scheme in this application:

#define MaxIntensity  65536     /* maximum possible Intensity */

#define MaxGrey       32768     /* limits on the grey levels used */
#define Threshold     16384     /* in the dithering process */
#define MinGrey           0
#define MinErr         2048     /* eliminate error smaller than this */
                                /* Smaller than 2048 and you will get */
                                /* tiny turds in your white zones. */

The value for MinErr must be small enough so that bonafide blurring due to neighboring values still occurs. But it must be big enough so that when you get PAST the neighbors, the error value gets set to zero.

If, in the tiff library dithering code there is no such value possible, then the only thing you can do is widen the range in your dithering values -- i.e. make MaxIntensity bigger.

I hope this helps.


 * dither a line from left to right
static void LeftToRight(curr, next, width)
     int *curr;
     int *next;
     int  width;
  int idx;
  int error;
  int output;

  for (idx=0; idx<width; idx++)
    output       = (curr[idx] > Threshold) ? MaxGrey : MinGrey;
    error        = curr[idx] - output;

    /* Dither will ring with tiny errors if we don't
     damp them to zero. */
    if (!(error < -(MinErr) || error >MinErr)) error = 0;

    curr[idx]    = output;
    next[idx-1] += error * 3 / 16;
    next[idx]   += error * 5 / 16;
    next[idx+1] += error * 1 / 16;
    curr[idx+1] += error * 7 / 16;