From:	N%"gjb@cstvax"  3-DEC-1987 11:34
To:	jhb@uk.ac.ed.ecsvax
Subj:	

Date:	Thu, 3 Dec 87 11:36:25 GMT
From:	Gavin Brelstaff <gjb@uk.ac.ed.cstvax>

/* halftone.c - */

/* contains 2 procedures */
/*                       */
/* make_dither()         */
/*                       */
/* dot_line( ... )       */

#define MAX_CLUMP_SIZE 8
#define MAX_RAND_SIZE 4
#define MAX_DITH_SIZE MAX_CLUMP_SIZE*MAX_RAND_SIZE
unsigned char *clump[MAX_CLUMP_SIZE];
unsigned char *random[MAX_RAND_SIZE];
unsigned char dither[MAX_DITH_SIZE][MAX_DITH_SIZE];
int clump_size=4; /* side length of clump matrix */
int rand_xsize=4; /* width length of random matrix */
int rand_ysize=4; /* height length of random matrix */
int dith_xsize=16; /* width length of dither matrix */
int dith_ysize=16; /* height length of dither matrix */
int clump_scale_up=16;
#define NEW_DITHER 1
int dither_choice =NEW_DITHER;

/* Random number matrices */
static unsigned char random4_8[4][4] ={  /* NEW */
  { 0, 6, 3, 2},
  { 4, 7, 6, 7},
  { 3, 2, 1, 4},
  { 7, 0, 5, 1}
};

static unsigned char random4_16[4][4] ={ /* OLD */
  { 0, 8, 2,10},
  {12, 4,14, 6},
  { 3,11, 1, 9},
  {15, 7,13, 5}
};


/* clumping matrices */

/* Super Circle clumping */
static unsigned char clump4_16[4][4] ={  /* OLD */
  {12, 4,11,15},
  { 8, 0, 3, 7},
  { 6, 2, 1, 9},
  {14,10, 5,13}
};

/* this new matrix clumps white and black symmetrically */
/* so its better */
static unsigned char clump8_32[8][8] ={ /*NEW */
  {18,24,22,16,  13, 7, 9,15},
  {20,30,28,26,  11, 1, 3, 5},
  {27,29,31,21,   4, 2, 0,10},
  {17,23,25,19,  14, 8, 6,12},

  {13, 7, 9,15,  18,24,22,16},
  {11, 1, 3, 5,  20,30,28,26},
  { 4, 2, 0,10,  27,29,31,21},
  {14, 8, 6,12,  17,23,25,19}
};





/* must call make_dither() to build the dither matrix */
/* change dither_choice to 0 to get old dither */

make_dither()
{
int rand_row,rand_col,clump_row,clump_col;
int dith_row,dith_col;

  switch(dither_choice)
  {
    case NEW_DITHER :
      clump_size=8;rand_xsize=4;rand_ysize=4;clump_scale_up=8;
      /* painful but necessary 2D array set up */
      for(clump_row=0; clump_row<clump_size; clump_row++)
        clump[clump_row]=clump8_32[clump_row];

      for(rand_row=0; rand_row<rand_ysize; rand_row++)
        random[rand_row]=random4_8[rand_row];
      break;

    default :
      clump_size=4;rand_xsize=4;rand_ysize=4;clump_scale_up=16;
      /* painful but necessary 2D array set up */
      for(clump_row=0; clump_row<clump_size; clump_row++)
        clump[clump_row]=clump4_16[clump_row];

      for(rand_row=0; rand_row<rand_ysize; rand_row++)
        random[rand_row]=random4_16[rand_row];
      break;
  }
  dith_xsize = rand_xsize*clump_size;
  dith_ysize = rand_ysize*clump_size;


  for( rand_row=0; rand_row<rand_ysize; rand_row++)
  {
    dith_row = clump_size*rand_row;
    for( rand_col=0; rand_col<rand_xsize; rand_col++)
    {
      dith_col = clump_size*rand_col;
      for( clump_row=0; clump_row<clump_size; clump_row++)
        for( clump_col=0; clump_col<clump_size; clump_col++)
          dither[ clump_row+dith_row ][ clump_col+dith_col ] =
                clump_scale_up*clump[ clump_row ][ clump_col ] +
                   random[ rand_row ] [ rand_col ];
    }
  }
}

/* NOTE must have called make_dither() before using dot_line */

/* dot_line reads a buffer of bytes, */
/* applies grey-level dither comparison to obtain halftones. */
/* Halftones are output as buffer of shorts (16bits) one bit per */
/* input byte.  */
/* The number of bit output is off course rounded up to nearest */
/* multiple of 16 * - padded white `whites'/

dot_line(row,xs,bp,sb)   /* NOTE different parameter from old dot1.c */
int row;            /* output image row number */
short xs;           /* length_of_input_buffer */
unsigned char *bp;  /* pointer to input byte buffer */
short *sb;          /* pointer to output 'packed' shorts buffer */
{

unsigned char *dp;
short pattern;
int i,k,dcount;
#define PATTERN_SIZE 16

  dp = dither[row%dith_ysize];
  for(i=0,dcount=0; i<xs; )
  {
    for(k=0, pattern=0; k<PATTERN_SIZE; k++)
    {
      pattern<<=1;  /* shift pattern by 1 */
      if(i<xs)      /* if some input  buffer left */
      {
	i++;
        if(*bp !=  0)
	  pattern |= ((*bp) >= (*dp++));  /* dither comparison */
        bp++;
	if(dcount++ == dith_xsize) /* run off end of dither matrix */
	{dcount=0; dp= dither[row%dith_ysize];}
      }
    }
    *sb++ = ~pattern;   /* one's complement - inverts pattern */
  }
}
