home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fonts 1 / freshfonts1.bin / programs / amiga / pastex / src / specialhost / dither.c < prev    next >
C/C++ Source or Header  |  1991-02-28  |  8KB  |  239 lines

  1. /* ############### C A U T I O N ################         */
  2. /*                                  */
  3. /* These routines are written for speed, not for readableness.     */
  4. /* Read at your own risk, but look also at the object code.     */
  5. /*                                */
  6. /****************************************************************/
  7.  
  8.  
  9.  
  10. extern UBYTE    IFFColors[64];        /* gray-values of the 64 IFF-colors */
  11. extern UBYTE    HAMColors[16][16][16];  /* gray-values of all 4096 colors   */
  12. extern WORD    ColorTab[64];            /* the original colormap        */
  13.  
  14.  
  15. /* this routine unpacks one row of the BitMap */
  16.  
  17. static void UnPack(struct BitMap *BMin, USHORT Row, USHORT w, UBYTE *UnPacked,
  18.            BOOL IsHam)
  19. /* BMin        -- the BitMap to be unpacked                  */
  20. /* Row         -- the line to be unpacked                    */
  21. /* w        -- the width of the BitMap (in Pixel)       */
  22. /* UnPacked     -- the result,  should be UBYTE UnPacked[w] */
  23. /* IsHam    -- TRUE if picture is HAM            */
  24.  
  25. {
  26.  UBYTE  *InRow[6], BitMask, Colour, Colour4;
  27.  UBYTE  r, g, b;
  28.  USHORT col;
  29.  
  30.  const ULONG offset = (ULONG)BMin->BytesPerRow * (ULONG)Row;
  31.  
  32.  /* 1st HAM color is always color 0 */
  33.  r = ColorTab[0] >> 8 & 0x0F;
  34.  g = ColorTab[0] >> 4 & 0x0F;
  35.  b = ColorTab[0] >> 0 & 0x0F;
  36.  
  37.  /* init pointers to beginning of row */
  38.  switch(BMin->Depth)
  39.  {
  40.   case 6  : InRow[5] = BMin->Planes[5] + offset;
  41.   case 5  : InRow[4] = BMin->Planes[4] + offset;
  42.   case 4  : InRow[3] = BMin->Planes[3] + offset;
  43.   case 3  : InRow[2] = BMin->Planes[2] + offset;
  44.   case 2  : InRow[1] = BMin->Planes[1] + offset;
  45.   default : InRow[0] = BMin->Planes[0] + offset;
  46.  }
  47.  
  48.  /* 1st bit has mask %10000000 = 0x80 */
  49.  BitMask = 0x80;
  50.  for(col=0; col<w; col++)
  51.  {
  52.   Colour = 0;
  53.   switch(BMin->Depth)
  54.   {
  55.    case 6  : if (*InRow[5] & BitMask) Colour |= 0x20; /* set bit 5 */
  56.    case 5  : if (*InRow[4] & BitMask) Colour |= 0x10; /* set bit 4 */
  57.    case 4  : if (*InRow[3] & BitMask) Colour |= 0x08; /* set bit 3 */
  58.    case 3  : if (*InRow[2] & BitMask) Colour |= 0x04; /* set bit 2 */
  59.    case 2  : if (*InRow[1] & BitMask) Colour |= 0x02; /* set bit 1 */
  60.    default : if (*InRow[0] & BitMask) Colour |= 0x01; /* set bit 0 */
  61.   }
  62.   
  63.   /* calculate gray value */
  64.   if (IsHam)
  65.   {
  66.    Colour4 = Colour & 0x0F;
  67.    switch (Colour >> 4)
  68.    {
  69.     case 0 :  r = ColorTab[Colour4] >> 8 & 0x0F;
  70.            g = ColorTab[Colour4] >> 4 & 0x0F;
  71.               b = ColorTab[Colour4] >> 0 & 0x0F;
  72.           break;
  73.     case 1 :  b = Colour4;
  74.               break;
  75.     case 2 :  r = Colour4;
  76.               break;
  77.     case 3 :  g = Colour4;
  78.               break;
  79.    }
  80.    UnPacked[col] = HAMColors[r][g][b];
  81.   }
  82.   else UnPacked[col] = IFFColors[Colour];
  83.   
  84.   /* advance to next pixel */
  85.   BitMask >>= 1;
  86.   if (!BitMask)
  87.   {
  88.    switch(BMin->Depth)
  89.    {
  90.     case 6  : InRow[5]++;
  91.     case 5  : InRow[4]++;
  92.     case 4  : InRow[3]++;
  93.     case 3  : InRow[2]++;
  94.     case 2  : InRow[1]++;
  95.     default : InRow[0]++;
  96.    }
  97.    BitMask = 0x80;
  98.   }
  99.  }
  100. }
  101.  
  102.  
  103. /* this is the great dithering matrix             */
  104. /* see c't 3/88 article 'Pixel-Domino' for more details */
  105. static const UBYTE Dither0[16][16] =
  106. {  0, 128,  32, 160,   8, 136,  40, 168,   2, 130,  34, 162,  10, 138,  42, 170,
  107.  192,  64, 224,  96, 200,  72, 232, 104, 194,  66, 226,  98, 202,  74, 234, 106,
  108.   48, 176,  16, 144,  56, 184,  24, 152,  50, 178,  18, 146,  58, 186,  26, 154,
  109.  240, 112, 208,  80, 248, 120, 216,  88, 242, 114, 210,  82, 250, 122, 218,  90,
  110.   12, 140,  44, 172,   4, 132,  36, 164,  14, 142,  46, 174,   6, 134,  38, 166,
  111.  204,  76, 236, 108, 196,  68, 228, 100, 206,  78, 238, 110, 198,  70, 230, 102,
  112.   60, 188,  28, 156,  52, 180,  20, 148,  62, 190,  30, 158,  54, 182,  22, 150,
  113.  252, 124, 220,  92, 244, 116, 212,  84, 254, 126, 222,  94, 246, 118, 214,  86,
  114.    3, 131,  35, 163,  11, 139,  43, 171,   1, 129,  33, 161,   9, 137,  41, 169,
  115.  195,  67, 227,  99, 203,  75, 235, 107, 193,  65, 225,  97, 201,  73, 233, 105,
  116.   51, 179,  19, 147,  59, 187,  27, 155,  49, 177,  17, 145,  57, 185,  25, 153,
  117.  243, 115, 211,  83, 251, 123, 219,  91, 241, 113, 209,  81, 249, 121, 217,  89,
  118.   15, 143,  47, 175,   7, 135,  39, 167,  13, 141,  45, 173,   5, 133,  37, 165,
  119.  207,  79, 239, 111, 199,  71, 231, 103, 205,  77, 237, 109, 197,  69, 229, 101,
  120.   63, 191,  31, 159,  55, 183,  23, 151,  61, 189,  29, 157,  53, 181,  21, 149,
  121.  255, 127, 223,  95, 247, 119, 215,  87, 253, 125, 221,  93, 245, 117, 213,  85,
  122. };
  123.  
  124. /* Dither is Dither0 scaled by a factor to save some multiplications */
  125. static ULONG Dither[16][16];
  126.  
  127. /* an array of bitmasks */
  128. static const UBYTE  Bit[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
  129.  
  130.  
  131. /* the main dither routine                      */
  132. /* it is based on extract_one from the FBM graphics package, */
  133. /* but is heavy optimized for speed, like elimanation of     */
  134. /* loop invariants, loop unrolling etc.                 */
  135. /*                                 */
  136. /* PS: if you don't understand it, don't shame             */
  137. /*     i'm sure, in a few weeks, i'll have difficulties         */
  138. /*     to understand it myself.   ;->                 */
  139.  
  140. void dither(struct BitMap *BMin, USHORT w, struct BitMap * BMout, USHORT ow,
  141.         BOOL IsHam)
  142. /* BMin        -- the original BitMap           */
  143. /* w        -- the width of BMin in pixel      */
  144. /* BMout    -- the new BitMap (to be printed) */
  145. /* ow        -- the width of BMout in pixel      */
  146. /* IsHam    -- TRUE if picture is HAM         */
  147. {
  148.   USHORT xf, yf, xi, yi, row, col, read;
  149.   USHORT OutByte, OutBit;
  150.   UBYTE  *Temp, *OutRow;
  151.   UBYTE  BitMask;
  152.  
  153.   UBYTE     *InRow1 = NULL;
  154.   UBYTE  *InRow2 = NULL;
  155.  
  156.   const USHORT outlen = BMout->BytesPerRow;
  157.   const USHORT h      = BMin->Rows;
  158.   const USHORT oh     = BMout->Rows;
  159.  
  160.   const ULONG  wh     = (ULONG)ow * (ULONG)oh;
  161.   const USHORT xm     = w % ow;
  162.   const USHORT xd     = w / ow;
  163.   const USHORT ym     = h % oh;
  164.   const USHORT yd     = h / oh;
  165.   const ULONG  d1     = xm * oh;
  166.  
  167.   if ((InRow1 = AllocMem(w, MEMF_PUBLIC)) && (InRow2 = AllocMem(w, MEMF_PUBLIC)))
  168.   {
  169.    for(row=0; row<16; row++) for(col=0; col<16; col++)
  170.     Dither[row][col] = Dither0[row][col] * wh;
  171.    
  172.    UnPack(BMin, 0, w, InRow1, IsHam);
  173.    UnPack(BMin, 1, w, InRow2, IsHam);
  174.    read = 0;
  175.    
  176.    yf = 0; yi = 0; OutRow = BMout->Planes[0];
  177.    for(row=0; row<oh; row++)
  178.    {
  179.     ULONG  b0, b1, c0, c3, d0, d2;
  180.  
  181.     if (yi == read) ;
  182.     else if (yi == read+1)
  183.     {
  184.      Temp = InRow1; InRow1 = InRow2; InRow2 = Temp;
  185.      UnPack(BMin, read+2, w, InRow2, IsHam);
  186.      read++;
  187.     }
  188.     else
  189.     {
  190.      UnPack(BMin, yi  , w, InRow1, IsHam);
  191.      UnPack(BMin, yi+1, w, InRow2, IsHam);
  192.      read = yi;
  193.     }
  194.     b0 = ow*yf; b1 = wh - b0;
  195.     if (!(row % 100)) pline("   work on line %d (from %d lines)", row, oh);
  196.     xf = 0; xi = 0; c0 = 0; c3 = 0;
  197.     d0 = xm*yf; d2 = ow*yf;
  198.     for(col=0; col<ow; col++)
  199.     {
  200.      OutByte = col >> 3;    OutBit = col & 0x07;
  201.      BitMask = Bit[OutBit];
  202.      if(xi > w-2 || yi > h-2)
  203.      {
  204.       if((xi == w-1 && yi <= h-1) || (yi == h-1 && xi <= w-1))
  205.       {
  206.        if (InRow1[xi] < Dither0[row&15][col&15]) OutRow[OutByte] |= BitMask;
  207.       }
  208.      }
  209.      else
  210.      {
  211.       ULONG  dc;
  212.       const ULONG  c2 = c0 - c3;
  213.  
  214.       dc = InRow1[xi] * (b1-c2);
  215.       dc += InRow2[xi] * (b0 - c0);
  216.       dc += InRow1[xi+1] * c2;
  217.       dc += InRow2[xi+1] * c0;
  218.       if (dc < Dither[row&15][col&15]) OutRow[OutByte] |= BitMask;
  219.      }
  220.      xf += xm; xi += xd; c0 += d0; c3 += d1;
  221.      if (xf >= ow)
  222.      {
  223.       xf -= ow; c0 -= d2; c3 -= wh;
  224.       xi ++;
  225.      }
  226.     }
  227.     OutRow += outlen;
  228.     yf += ym; yi += yd;
  229.     if (yf >= oh)
  230.     {
  231.      yf -= oh; yi++;
  232.     }
  233.    }
  234.   }
  235.   else pline("Sorry! no memory for buffers");
  236.   if (InRow1) FreeMem(InRow1, w); 
  237.   if (InRow2) FreeMem(InRow2, w);
  238. }
  239.