home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / rexx / library2 / gbmrexx / gbm / gbmerr.c < prev    next >
C/C++ Source or Header  |  1993-11-10  |  36KB  |  1,176 lines

  1. /*
  2.  
  3. GBMERR.C  Error diffusion Module
  4.  
  5. */
  6.  
  7. /*...sincludes:0:*/
  8. #include <stdio.h>
  9. #include <stddef.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <memory.h>
  13. #include "standard.h"
  14. #include "gbm.h"
  15.  
  16. /*...vgbm\46\h:0:*/
  17. /*...e*/
  18. /*...svars:0:*/
  19. static BOOLEAN inited = FALSE;
  20.  
  21. /*
  22. Tables used for quick saturated addition and subtraction.
  23. */
  24.  
  25. static byte usat [256+256+256];
  26. #define    U_SAT_ADD(a,b)    usat [(a)+(b)+256]
  27.  
  28. static short ssat [256+256+256+256];
  29. #define    S_SAT_ADD(a,b)    ssat [(a)+(b)+512]
  30.  
  31. /*
  32. For 6Rx6Gx6B, 7Rx8Gx4B palettes etc.
  33. */
  34.  
  35. static byte index4 [0x100];
  36. static byte index6 [0x100];
  37. static byte index7 [0x100];
  38. static byte index8 [0x100];
  39. static byte index16 [0x100];
  40. static byte scale4 [] = { 0, 85, 170, 255 };
  41. static byte scale6 [] = { 0, 51, 102, 153, 204, 255 };
  42. static byte scale7 [] = { 0, 43, 85, 128, 170, 213, 255 };
  43. static byte scale8 [] = { 0, 36, 73, 109, 146, 182, 219, 255 };
  44. static byte scale16 [] = { 0, 17, 34, 51, 68, 85, 102, 119, 136,
  45.                153, 170, 187, 204, 221, 238, 255 };
  46.  
  47. static word randtab [0x100];
  48. static int randinx = 0;
  49. /*...e*/
  50. /*...sinit:0:*/
  51. /*
  52. This function initialises this module.
  53. It does this by preparing the quick saturated addition and subraction tables.
  54. */
  55.  
  56. /*...snearest_inx:0:*/
  57. #ifndef abs
  58. #define    abs(x)    (((x)>=0)?(x):-(x))
  59. #endif
  60.  
  61. static byte nearest_inx(byte value, byte ab [], unsigned short cb)
  62.     {
  63.     byte b, inx, inx_min;
  64.     short diff, diff_min;
  65.  
  66.     b = ab [0];
  67.     diff_min = abs((short) value - (short) b);
  68.     inx_min = 0;
  69.     for ( inx = 1; (unsigned short) inx < cb; inx++ )
  70.         {
  71.         b = ab [inx];
  72.         diff = abs((short) value - (short) b);
  73.         if ( diff < diff_min )
  74.             {
  75.             diff_min = diff;
  76.             inx_min = inx;
  77.             }
  78.         }
  79.     return ( inx_min );
  80.     }
  81. /*...e*/
  82.  
  83. static void init(void)
  84.     {
  85.     int i;
  86.  
  87.     if ( inited )
  88.         return;
  89.  
  90.     memset(usat, 0, 0x100);
  91.     for ( i = 0; i < 0x100; i++ )
  92.         usat [i +  0x100] = (byte) i;
  93.     memset(usat + 0x200, 0xff, 0x100);
  94.  
  95.     for ( i = -0x200; i < -0x100; i++ )
  96.         ssat [i + 0x200] = -0x100;
  97.     for ( i = -0x100; i < 0x100; i++ )
  98.         ssat [i + 0x200] = i;
  99.     for ( i = 0x100; i < 0x200; i++ )
  100.         ssat [i + 0x200] = 0xff;
  101.  
  102.     /* For 7 Red x 8 Green x 4 Blue palettes etc. */
  103.  
  104.     for ( i = 0; i < 0x100; i++ )
  105.         {
  106.         index4  [i] = nearest_inx((byte) i, scale4 , sizeof(scale4 ));
  107.         index6  [i] = nearest_inx((byte) i, scale6 , sizeof(scale6 ));
  108.         index7  [i] = nearest_inx((byte) i, scale7 , sizeof(scale7 ));
  109.         index8  [i] = nearest_inx((byte) i, scale8 , sizeof(scale8 ));
  110.         index16 [i] = nearest_inx((byte) i, scale16, sizeof(scale16));
  111.         }
  112.  
  113.     /* For faster random number calculation */
  114.  
  115.     for ( i = 0; i < 0x100; i++ )
  116.         randtab  [i] = (word) (rand() % (51*0x100));
  117.  
  118.     inited = TRUE;
  119.     }
  120. /*...e*/
  121. /*...serrdiff:0:*/
  122. static BOOLEAN errdiff(
  123.     GBM *gbm, byte *src, byte *dest,
  124.     int dest_bpp,
  125.     void (*errdiff_line)(byte *src, byte *dest, short *errs, int cx)
  126.     )
  127.     {
  128.     int    stride_src = ((gbm -> w * 3 + 3) & ~3);
  129.     int    stride_dest = ((gbm -> w * dest_bpp + 31) / 32) * 4;
  130.     byte    *buf;
  131.     short    *errs;
  132.     int    y;
  133.  
  134.     if ( (buf = malloc(stride_src + 3)) == NULL )
  135.         return ( FALSE );
  136.  
  137.     if ( (errs = malloc((gbm -> w + 1) * 3 * sizeof(short))) == NULL )
  138.         {
  139.         free(buf);
  140.         return ( FALSE );
  141.         }
  142.  
  143.     memset(errs, 0, (gbm -> w + 1) * 3 * sizeof(short));
  144.  
  145.     for ( y = 0; y < gbm -> h; y++ )
  146.         {
  147.         memcpy(buf, src + y * stride_src, stride_src);
  148.         (*errdiff_line)(buf, dest + y * stride_dest, errs, gbm -> w);
  149.         }
  150.  
  151.     free(buf);
  152.     free(errs);
  153.  
  154.     return ( TRUE );
  155.     }
  156. /*...e*/
  157.  
  158. /*...sgbm_errdiff_line_24     \45\ error diffuse to fewer bits per pixel one line:0:*/
  159. /*
  160. This function takes a line of RGB data, a destination buffer and a buffer of
  161. error terms and performs one lines worth (a given # of pixels) of error
  162. diffusion.
  163. */
  164.  
  165. void gbm_errdiff_line_24(byte *src, byte *dest, short *errs, int cx, byte rm, byte gm, byte bm)
  166.     {
  167.     int x, ptr = 0;
  168.  
  169.     init();
  170.  
  171.     /* Step 1: Add error terms to newly supplied line */
  172.  
  173.     for ( x = 0; x < cx * 3; x++ )
  174.         src [x] = U_SAT_ADD((int) src [x], (int) errs [x]);
  175.  
  176.     /* Step 2: Zero out error terms */
  177.  
  178.     memset(errs, 0, cx * 3 * sizeof(errs [0]));
  179.  
  180.     /* Step 3: Go along data, finding nearest colour and propagating error */
  181.  
  182.     randinx = rand();
  183.  
  184.     for ( x = 0; x < cx; x++ )
  185.         {
  186.         byte b     = *src++;
  187.         byte g     = *src++;
  188.         byte r     = *src++;
  189.         byte bi    = (b & bm);
  190.         byte gi    = (g & gm);
  191.         byte ri    = (r & rm);
  192.         int  be    = b - (int) bi;
  193.         int  ge    = g - (int) gi;
  194.         int  re    = r - (int) ri;
  195.         word rn    = randtab [(byte) (randinx++)];
  196.         int  right = (rn >> 8);
  197.         int  down  = ((rn & 0xff) % (63 - right));
  198.         int  be1   = ((be * right) >> 6);
  199.         int  ge1   = ((ge * right) >> 6);
  200.         int  re1   = ((re * right) >> 6);
  201.         int  be2   = ((be * down) >> 6);
  202.         int  ge2   = ((ge * down) >> 6);
  203.         int  re2   = ((re * down) >> 6);
  204.         int  be3   = be - be1 - be2;
  205.         int  ge3   = ge - ge1 - ge2;
  206.         int  re3   = re - re1 - re2;
  207.  
  208.         *dest++ = bi;
  209.         *dest++ = gi;
  210.         *dest++ = ri;
  211.  
  212.         src [0] = U_SAT_ADD((int) src [0], be1);
  213.         src [1] = U_SAT_ADD((int) src [1], ge1);
  214.         src [2] = U_SAT_ADD((int) src [2], re1);
  215.  
  216.         errs [ptr    ] = S_SAT_ADD((int) errs [ptr    ], be2);
  217.         errs [ptr + 1] = S_SAT_ADD((int) errs [ptr + 1], ge2);
  218.         errs [ptr + 2] = S_SAT_ADD((int) errs [ptr + 2], re2);
  219.  
  220.         ptr += 3;
  221.  
  222.         errs [ptr    ] = S_SAT_ADD((int) errs [ptr    ], be3);
  223.         errs [ptr + 1] = S_SAT_ADD((int) errs [ptr + 1], ge3);
  224.         errs [ptr + 2] = S_SAT_ADD((int) errs [ptr + 2], re3);
  225.         }
  226.     }
  227. /*...e*/
  228. /*...sgbm_errdiff_24          \45\ error diffuse to fewer bits per pixel:0:*/
  229. BOOLEAN    gbm_errdiff_24(GBM *gbm, byte *data24, byte *data24a, byte rm, byte gm, byte bm)
  230.     {
  231.     int    stride = ((gbm -> w * 3 + 3) & ~3);
  232.     byte    *buf;
  233.     short    *errs;
  234.     int    y;
  235.  
  236.     if ( (buf = malloc(stride + 3)) == NULL )
  237.         return ( FALSE );
  238.  
  239.     if ( (errs = malloc((gbm -> w + 1) * 3 * sizeof(short))) == NULL )
  240.         {
  241.         free(buf);
  242.         return ( FALSE );
  243.         }
  244.  
  245.     memset(errs, 0, (gbm -> w + 1) * 3 * sizeof(short));
  246.  
  247.     for ( y = 0; y < gbm -> h; y++ )
  248.         {
  249.         memcpy(buf, data24 + y * stride, stride);
  250.         gbm_errdiff_line_24(buf, data24a + y * stride, errs, gbm -> w, rm, gm, bm);
  251.         }
  252.  
  253.     free(buf);
  254.     free(errs);
  255.  
  256.     return ( TRUE );
  257.     }
  258. /*...e*/
  259.  
  260. /*...sgbm_errdiff_pal_6R6G6B  \45\ return 6Rx6Gx6B palette:0:*/
  261. /*
  262. This function makes the palette for the 6 red x 6 green x 6 blue palette.
  263. 216 palette entrys used. Remaining 40 left blank.
  264. */
  265.  
  266. void gbm_errdiff_pal_6R6G6B(GBMRGB *gbmrgb)
  267.     {
  268.     byte volatile r;    /* C-Set/2 optimiser fix */
  269.     byte volatile g;
  270.     byte volatile b;
  271.  
  272.     init();
  273.     memset(gbmrgb, 0x80, 0x100 * sizeof(GBMRGB));
  274.     for ( r = 0; r < 6; r++ )
  275.         for ( g = 0; g < 6; g++ )
  276.             for ( b = 0; b < 6; b++ )
  277.                 {
  278.                 gbmrgb -> r = scale6 [r];
  279.                 gbmrgb -> g = scale6 [g];
  280.                 gbmrgb -> b = scale6 [b];
  281.                 gbmrgb++;
  282.                 }
  283.     }
  284. /*...e*/
  285. /*...sgbm_errdiff_line_6R6G6B \45\ error diffuse to 6Rx6Gx6B one line:0:*/
  286. /*
  287. This function takes a line of RGB data, a destination buffer and a buffer of
  288. error terms and performs one lines worth (a given # of pixels) of error
  289. diffusion.
  290. */
  291.  
  292. void gbm_errdiff_line_6R6G6B(byte *src, byte *dest, short *errs, int cx)
  293.     {
  294.     int x, ptr = 0;
  295.  
  296.     init();
  297.  
  298.     /* Step 1: Add error terms to newly supplied line */
  299.  
  300.     for ( x = 0; x < cx * 3; x++ )
  301.         src [x] = U_SAT_ADD((int) src [x], (int) errs [x]);
  302.  
  303.     /* Step 2: Zero out error terms */
  304.  
  305.     memset(errs, 0, (cx + 1) * 3 * sizeof(errs [0]));
  306.  
  307.     /* Step 3: Go along data, finding nearest colour and propagating error */
  308.  
  309.     randinx = rand();
  310.  
  311.     for ( x = 0; x < cx; x++ )
  312.         {
  313.         byte b     = *src++;
  314.         byte g     = *src++;
  315.         byte r     = *src++;
  316.         byte bi    = index6 [b];
  317.         byte gi    = index6 [g];
  318.         byte ri    = index6 [r];
  319.         int  be    = b - ((int) scale6 [bi]);
  320.         int  ge    = g - ((int) scale6 [gi]);
  321.         int  re    = r - ((int) scale6 [ri]);
  322.         word rn    = randtab [(byte) (randinx++)];
  323.         int  right = (int) (rn >> 8);
  324.         int  down  = (int) ((rn & 0xff) % (63 - right));
  325.         int  be1   = ((be * right) >> 6);
  326.         int  ge1   = ((ge * right) >> 6);
  327.         int  re1   = ((re * right) >> 6);
  328.         int  be2   = ((be * down) >> 6);
  329.         int  ge2   = ((ge * down) >> 6);
  330.         int  re2   = ((re * down) >> 6);
  331.         int  be3   = be - be1 - be2;
  332.         int  ge3   = ge - ge1 - ge2;
  333.         int  re3   = re - re1 - re2;
  334.  
  335.         *dest++ = (byte) (6 * (6 * ri + gi) + bi);
  336.  
  337.         src [0] = U_SAT_ADD((int) src [0], be1);
  338.         src [1] = U_SAT_ADD((int) src [1], ge1);
  339.         src [2] = U_SAT_ADD((int) src [2], re1);
  340.  
  341.         errs [ptr    ] = S_SAT_ADD((int) errs [ptr    ], be2);
  342.         errs [ptr + 1] = S_SAT_ADD((int) errs [ptr + 1], ge2);
  343.         errs [ptr + 2] = S_SAT_ADD((int) errs [ptr + 2], re2);
  344.  
  345.         ptr += 3;
  346.  
  347.         errs [ptr    ] = S_SAT_ADD((int) errs [ptr    ], be3);
  348.         errs [ptr + 1] = S_SAT_ADD((int) errs [ptr + 1], ge3);
  349.         errs [ptr + 2] = S_SAT_ADD((int) errs [ptr + 2], re3);
  350.         }
  351.     }
  352. /*...e*/
  353. /*...sgbm_errdiff_6R6G6B      \45\ error diffuse to 6Rx6Gx6B:0:*/
  354. BOOLEAN    gbm_errdiff_6R6G6B(GBM *gbm, byte *data24, byte *data8)
  355.     {
  356.     return ( errdiff(gbm, data24, data8, 8, gbm_errdiff_line_6R6G6B) );
  357.     }
  358. /*...e*/
  359.  
  360. /*...sgbm_errdiff_pal_7R8G4B  \45\ return 7Rx8Gx4B palette:0:*/
  361. /*
  362. This function makes the palette for the 7 red x 8 green x 4 blue palette.
  363. 224 palette entrys used. Remaining 32 left blank.
  364. Colours calculated to match those used by 8514/A PM driver.
  365. */
  366.  
  367. void gbm_errdiff_pal_7R8G4B(GBMRGB *gbmrgb)
  368.     {
  369.     byte volatile r;    /* C-Set/2 optimiser fix */
  370.     byte volatile g;
  371.     byte volatile b;
  372.  
  373.     init();
  374.  
  375.     memset(gbmrgb, 0x80, 0x100 * sizeof(GBMRGB));
  376.     for ( r = 0; r < 7; r++ )
  377.         for ( g = 0; g < 8; g++ )
  378.             for ( b = 0; b < 4; b++ )
  379.                 {
  380.                 gbmrgb -> r = scale7 [r];
  381.                 gbmrgb -> g = scale8 [g];
  382.                 gbmrgb -> b = scale4 [b];
  383.                 gbmrgb++;
  384.                 }
  385.     }
  386. /*...e*/
  387. /*...sgbm_errdiff_line_7R8G4B \45\ error diffuse to 7Rx8Gx4B one line:0:*/
  388. /*
  389. This function takes a line of RGB data, a destination buffer and a buffer of
  390. error terms and performs one lines worth (a given # of pixels) of error
  391. diffusion.
  392. */
  393.  
  394. void gbm_errdiff_line_7R8G4B(byte *src, byte *dest, short *errs, int cx)
  395.     {
  396.     int x, ptr = 0;
  397.  
  398.     init();
  399.  
  400.     /* Step 1: Add error terms to newly supplied line */
  401.  
  402.     for ( x = 0; x < cx * 3; x++ )
  403.         src [x] = U_SAT_ADD((int) src [x], (int) errs [x]);
  404.  
  405.     /* Step 2: Zero out error terms */
  406.  
  407.     memset(errs, 0, (cx + 1) * 3 * sizeof(errs [0]));
  408.  
  409.     /* Step 3: Go along data, finding nearest colour and propagating error */
  410.  
  411.     randinx = rand();
  412.  
  413.     for ( x = 0; x < cx; x++ )
  414.         {
  415.         byte b     = *src++;
  416.         byte g     = *src++;
  417.         byte r     = *src++;
  418.         byte bi    = index4 [b];
  419.         byte gi    = index8 [g];
  420.         byte ri    = index7 [r];
  421.         int  be    = b - ((int) scale4 [bi]);
  422.         int  ge    = g - ((int) scale8 [gi]);
  423.         int  re    = r - ((int) scale7 [ri]);
  424.         word rn    = randtab [(byte) (randinx++)];
  425.         int  right = (rn >> 8);
  426.         int  down  = ((rn & 0xff) % (63 - right));
  427.         int  be1   = ((be * right) >> 6);
  428.         int  ge1   = ((ge * right) >> 6);
  429.         int  re1   = ((re * right) >> 6);
  430.         int  be2   = ((be * down) >> 6);
  431.         int  ge2   = ((ge * down) >> 6);
  432.         int  re2   = ((re * down) >> 6);
  433.         int  be3   = be - be1 - be2;
  434.         int  ge3   = ge - ge1 - ge2;
  435.         int  re3   = re - re1 - re2;
  436.  
  437.         *dest++ = (byte) (4 * (8 * ri + gi) + bi);
  438.  
  439.         src [0] = U_SAT_ADD((int) src [0], be1);
  440.         src [1] = U_SAT_ADD((int) src [1], ge1);
  441.         src [2] = U_SAT_ADD((int) src [2], re1);
  442.  
  443.         errs [ptr    ] = S_SAT_ADD((int) errs [ptr    ], be2);
  444.         errs [ptr + 1] = S_SAT_ADD((int) errs [ptr + 1], ge2);
  445.         errs [ptr + 2] = S_SAT_ADD((int) errs [ptr + 2], re2);
  446.  
  447.         ptr += 3;
  448.  
  449.         errs [ptr    ] = S_SAT_ADD((int) errs [ptr    ], be3);
  450.         errs [ptr + 1] = S_SAT_ADD((int) errs [ptr + 1], ge3);
  451.         errs [ptr + 2] = S_SAT_ADD((int) errs [ptr + 2], re3);
  452.         }
  453.     }
  454. /*...e*/
  455. /*...sgbm_errdiff_7R8G4B      \45\ error diffuse to 7Rx8Gx4B:0:*/
  456. BOOLEAN    gbm_errdiff_7R8G4B(GBM *gbm, byte *data24, byte *data8)
  457.     {
  458.     return ( errdiff(gbm, data24, data8, 8, gbm_errdiff_line_7R8G4B) );
  459.     }
  460. /*...e*/
  461.  
  462. /*...sgbm_errdiff_pal_VGA     \45\ return default VGA palette:0:*/
  463. /*
  464. This function makes the palette for the 16 colour VGA palette.
  465. */
  466.  
  467. static GBMRGB gbmrgb_vga [] =
  468.     {
  469.       0,  0,  0,
  470.     128,  0,  0,
  471.       0,128,  0,
  472.     128,128,  0,
  473.       0,  0,128,
  474.     128,  0,128,
  475.       0,128,128,
  476.     128,128,128,
  477.     204,204,204,
  478.     255,  0,  0,
  479.       0,255,  0,
  480.     255,255,  0,
  481.       0,  0,255,
  482.     255,  0,255,
  483.       0,255,255,
  484.     255,255,255,
  485.     };
  486.  
  487. void gbm_errdiff_pal_VGA(GBMRGB *gbmrgb)
  488.     {
  489.     init();
  490.     memcpy((char *) gbmrgb, (char *) gbmrgb_vga, sizeof(gbmrgb_vga));
  491.     }
  492. /*...e*/
  493. /*...sgbm_errdiff_line_VGA    \45\ error diffuse to default VGA palette one line:0:*/
  494. /*
  495. This function takes a line of RGB data, a destination buffer and a buffer of
  496. error terms and performs one lines worth (a given # of pixels) of error
  497. diffusion.
  498. */
  499.  
  500. /*...scalc_nearest:0:*/
  501. /*
  502. This function, when given am RGB colour, finds the VGA palette entry closest
  503. to it. We deliberately bias away from the two grey palette entries.
  504. */
  505.  
  506. static byte calc_nearest(byte r, byte g, byte b)
  507.     {
  508.     long min_dist = 3L * 256L * 256L * 10L;
  509.     byte bi, bi_min;
  510.  
  511.     for ( bi = 0; bi < 0x10; bi++ )
  512.         {
  513.         long b_dist = ((long) b - (long) gbmrgb_vga [bi].b);
  514.         long g_dist = ((long) g - (long) gbmrgb_vga [bi].g);
  515.         long r_dist = ((long) r - (long) gbmrgb_vga [bi].r);
  516.         long dist = r_dist * r_dist + g_dist * g_dist + b_dist * b_dist;
  517.  
  518.         if ( bi == 7 || bi == 8 )
  519.             /* Bias away from this colour */
  520.             dist <<= 3;
  521.  
  522.         if ( dist < min_dist )
  523.             {
  524.             min_dist = dist;
  525.             bi_min = bi;
  526.             }
  527.         }
  528.     return ( bi_min );
  529.     }
  530. /*...e*/
  531. /*...snearest_colour:0:*/
  532. /*
  533. This function finds the closest VGA palette colour to a given RGB value.
  534. It uses a lookup table to avoid performing distance calculations to the
  535. 16 palette entrys. The table is pre-calculated.
  536. */
  537.  
  538. /*...squick lookup table:0:*/
  539. /*...v_gbmerr\46\c \45\ used to make quick_tab:0:*/
  540.  
  541. static byte quick_tab [16][16][16] =
  542.     {
  543.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  544.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  545.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  546.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  547.     255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
  548.     2,2,2,2,255,6,6,6,6,6,6,6,6,255,12,12,
  549.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,12,
  550.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
  551.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
  552.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,14,
  553.     2,2,2,2,255,6,6,6,6,6,6,6,6,255,14,14,
  554.     2,2,2,2,255,6,6,6,6,6,6,6,255,14,14,14,
  555.     10,10,10,10,255,6,6,6,6,6,6,255,14,14,14,14,
  556.     10,10,10,10,10,255,6,6,6,6,255,14,14,14,14,14,
  557.     10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
  558.     10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
  559.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  560.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  561.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  562.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  563.     255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
  564.     2,2,2,2,255,6,6,6,6,6,6,6,6,255,12,12,
  565.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,12,
  566.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
  567.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
  568.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,14,
  569.     2,2,2,2,255,6,6,6,6,6,6,6,6,255,14,14,
  570.     2,2,2,2,255,6,6,6,6,6,6,6,255,14,14,14,
  571.     10,10,10,10,255,6,6,6,6,6,6,255,14,14,14,14,
  572.     10,10,10,10,10,255,6,6,6,6,255,14,14,14,14,14,
  573.     10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
  574.     10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
  575.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  576.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  577.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  578.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  579.     255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
  580.     2,2,2,2,255,6,6,6,6,6,6,6,6,255,12,12,
  581.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,12,
  582.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
  583.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
  584.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,14,
  585.     2,2,2,2,255,6,6,6,6,6,6,6,6,255,14,14,
  586.     2,2,2,2,255,6,6,6,6,6,6,6,255,14,14,14,
  587.     10,10,10,10,255,6,6,6,6,6,6,255,14,14,14,14,
  588.     10,10,10,10,10,255,6,6,6,6,255,14,14,14,14,14,
  589.     10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
  590.     10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
  591.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  592.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  593.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  594.     0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
  595.     255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
  596.     2,2,2,2,255,6,6,6,6,6,6,6,6,255,12,12,
  597.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,12,
  598.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
  599.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
  600.     2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,14,
  601.     2,2,2,2,255,6,6,6,6,6,6,6,6,255,14,14,
  602.     2,2,2,2,255,6,6,6,6,6,6,6,255,14,14,14,
  603.     10,10,10,10,255,6,6,6,6,6,6,255,14,14,14,14,
  604.     10,10,10,10,10,255,6,6,6,6,255,14,14,14,14,14,
  605.     10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
  606.     10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
  607.     255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
  608.     255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
  609.     255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
  610.     255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
  611.     255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
  612.     255,255,255,255,255,6,6,6,6,6,6,6,6,255,12,12,
  613.     255,255,255,255,255,6,6,6,6,6,6,6,6,6,255,12,
  614.     255,255,255,255,255,6,6,6,6,6,6,6,6,6,6,255,
  615.     255,255,255,255,255,6,6,6,6,6,6,6,6,6,6,255,
  616.     255,255,255,255,255,6,6,6,6,6,6,6,6,6,255,14,
  617.     255,255,255,255,255,6,6,6,6,6,6,6,6,255,14,14,
  618.     255,255,255,255,255,6,6,6,6,6,6,6,255,14,14,14,
  619.     255,255,255,255,255,6,6,6,6,6,6,255,14,14,14,14,
  620.     10,10,10,10,10,255,6,6,6,6,255,14,14,14,14,14,
  621.     10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
  622.     10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
  623.     1,1,1,1,255,5,5,5,5,5,5,5,5,255,12,12,
  624.     1,1,1,1,255,5,5,5,5,5,5,5,5,255,12,12,
  625.     1,1,1,1,255,5,5,5,5,5,5,5,5,255,12,12,
  626.     1,1,1,1,255,5,5,5,5,5,5,5,5,255,12,12,
  627.     255,255,255,255,255,5,5,5,5,5,5,5,5,255,12,12,
  628.     3,3,3,3,3,255,255,255,255,255,255,255,255,255,12,12,
  629.     3,3,3,3,3,255,6,6,6,6,6,6,6,6,255,12,
  630.     3,3,3,3,3,255,6,255,255,6,6,6,6,6,6,255,
  631.     3,3,3,3,3,255,6,255,255,6,6,6,6,6,6,255,
  632.     3,3,3,3,3,255,6,6,6,6,6,6,6,6,255,14,
  633.     3,3,3,3,3,255,6,6,6,6,6,6,6,255,14,14,
  634.     3,3,3,3,3,255,6,6,6,6,6,6,255,14,14,14,
  635.     3,3,3,3,3,255,6,6,6,6,6,255,14,14,14,14,
  636.     255,255,255,255,255,255,6,6,6,6,255,14,14,14,14,14,
  637.     10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
  638.     10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
  639.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,12,
  640.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,12,
  641.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,12,
  642.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,12,
  643.     255,255,255,255,255,5,5,5,5,5,5,5,5,5,255,12,
  644.     3,3,3,3,3,255,5,5,5,5,5,5,5,5,255,12,
  645.     3,3,3,3,3,3,255,255,255,255,255,255,255,255,255,12,
  646.     3,3,3,3,3,3,255,255,255,255,255,6,6,6,6,255,
  647.     3,3,3,3,3,3,255,255,255,255,255,6,6,6,6,255,
  648.     3,3,3,3,3,3,255,255,255,255,255,6,6,6,255,14,
  649.     3,3,3,3,3,3,255,255,255,255,6,6,6,255,14,14,
  650.     3,3,3,3,3,3,255,6,6,6,6,6,255,14,14,14,
  651.     3,3,3,3,3,3,255,6,6,6,6,255,14,14,14,14,
  652.     3,3,3,3,3,3,255,6,6,6,255,14,14,14,14,14,
  653.     255,255,255,255,255,255,255,6,6,255,14,14,14,14,14,14,
  654.     10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
  655.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
  656.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
  657.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
  658.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
  659.     255,255,255,255,255,5,5,5,5,5,5,5,5,5,5,255,
  660.     3,3,3,3,3,255,5,255,255,5,5,5,5,5,5,255,
  661.     3,3,3,3,3,3,255,255,255,255,255,5,5,5,5,255,
  662.     3,3,3,3,3,255,255,7,7,7,255,255,255,255,255,255,
  663.     3,3,3,3,3,255,255,7,7,7,255,6,6,6,6,255,
  664.     3,3,3,3,3,3,255,7,7,255,255,6,6,6,255,14,
  665.     3,3,3,3,3,3,255,255,255,255,255,6,6,255,14,14,
  666.     3,3,3,3,3,3,3,255,6,6,6,6,255,14,14,14,
  667.     3,3,3,3,3,3,3,255,6,6,6,255,14,14,14,14,
  668.     3,3,3,3,3,3,3,255,6,6,255,14,14,14,14,14,
  669.     3,3,3,3,3,3,3,255,6,255,14,14,14,14,14,14,
  670.     255,255,255,255,255,255,255,255,255,14,14,14,14,14,14,14,
  671.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
  672.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
  673.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
  674.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
  675.     255,255,255,255,255,5,5,5,5,5,5,5,5,5,5,255,
  676.     3,3,3,3,3,255,5,255,255,5,5,5,5,5,5,255,
  677.     3,3,3,3,3,3,255,255,255,255,255,5,5,5,5,255,
  678.     3,3,3,3,3,255,255,7,7,7,255,5,5,5,5,255,
  679.     3,3,3,3,3,255,255,7,7,7,255,255,255,255,255,255,
  680.     3,3,3,3,3,3,255,7,7,7,255,255,255,255,255,15,
  681.     3,3,3,3,3,3,255,255,255,255,255,255,255,255,15,15,
  682.     3,3,3,3,3,3,3,3,255,255,255,255,255,15,15,15,
  683.     3,3,3,3,3,3,3,3,255,255,255,255,15,15,15,15,
  684.     3,3,3,3,3,3,3,3,255,255,255,15,15,15,15,15,
  685.     3,3,3,3,3,3,3,3,255,255,15,15,15,15,15,15,
  686.     255,255,255,255,255,255,255,255,255,15,15,15,15,15,15,15,
  687.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,13,
  688.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,13,
  689.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,13,
  690.     1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,13,
  691.     255,255,255,255,255,5,5,5,5,5,5,5,5,5,255,13,
  692.     3,3,3,3,3,255,5,5,5,5,5,5,5,5,255,13,
  693.     3,3,3,3,3,3,255,255,255,255,255,5,5,5,255,13,
  694.     3,3,3,3,3,3,255,7,7,255,255,5,5,5,255,13,
  695.     3,3,3,3,3,3,255,7,7,7,255,255,255,255,255,15,
  696.     3,3,3,3,3,3,255,255,7,7,255,255,255,15,15,15,
  697.     3,3,3,3,3,3,255,255,255,255,255,255,15,15,15,15,
  698.     3,3,3,3,3,3,3,3,255,255,255,15,15,15,15,15,
  699.     3,3,3,3,3,3,3,3,255,255,15,15,15,15,15,15,
  700.     3,3,3,3,3,3,3,3,255,15,15,15,15,15,15,15,
  701.     255,255,255,255,255,255,255,255,255,15,15,15,15,15,15,15,
  702.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  703.     1,1,1,1,255,5,5,5,5,5,5,5,5,255,13,13,
  704.     1,1,1,1,255,5,5,5,5,5,5,5,5,255,13,13,
  705.     1,1,1,1,255,5,5,5,5,5,5,5,5,255,13,13,
  706.     1,1,1,1,255,5,5,5,5,5,5,5,5,255,13,13,
  707.     255,255,255,255,255,5,5,5,5,5,5,5,5,255,13,13,
  708.     3,3,3,3,3,255,5,5,5,5,5,5,5,255,13,13,
  709.     3,3,3,3,3,3,255,255,255,255,5,5,5,255,13,13,
  710.     3,3,3,3,3,3,255,255,255,255,255,5,5,255,13,13,
  711.     3,3,3,3,3,3,255,255,255,255,255,255,255,255,15,15,
  712.     3,3,3,3,3,3,255,255,255,255,255,255,15,15,15,15,
  713.     3,3,3,3,3,3,3,255,255,255,255,255,255,255,15,15,
  714.     3,3,3,3,3,3,3,3,255,255,255,255,255,255,255,15,
  715.     3,3,3,3,3,3,3,3,255,15,255,255,255,255,255,15,
  716.     255,255,255,255,255,255,255,255,255,15,255,255,255,255,15,15,
  717.     11,11,11,11,11,11,11,11,15,15,15,255,255,15,15,15,
  718.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  719.     1,1,1,1,255,5,5,5,5,5,5,5,255,13,13,13,
  720.     1,1,1,1,255,5,5,5,5,5,5,5,255,13,13,13,
  721.     1,1,1,1,255,5,5,5,5,5,5,5,255,13,13,13,
  722.     1,1,1,1,255,5,5,5,5,5,5,5,255,13,13,13,
  723.     255,255,255,255,255,5,5,5,5,5,5,5,255,13,13,13,
  724.     3,3,3,3,3,255,5,5,5,5,5,5,255,13,13,13,
  725.     3,3,3,3,3,3,255,5,5,5,5,5,255,13,13,13,
  726.     3,3,3,3,3,3,3,255,5,5,5,5,255,13,13,13,
  727.     3,3,3,3,3,3,3,3,255,255,255,255,255,15,15,15,
  728.     3,3,3,3,3,3,3,3,255,255,255,15,15,15,15,15,
  729.     3,3,3,3,3,3,3,3,255,255,255,255,255,255,255,15,
  730.     3,3,3,3,3,3,3,3,255,15,255,255,8,255,255,15,
  731.     255,255,255,255,255,255,255,255,255,15,255,8,8,8,255,15,
  732.     11,11,11,11,11,11,11,11,15,15,255,255,8,255,255,15,
  733.     11,11,11,11,11,11,11,11,15,15,255,255,255,255,15,15,
  734.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  735.     9,9,9,9,255,5,5,5,5,5,5,255,13,13,13,13,
  736.     9,9,9,9,255,5,5,5,5,5,5,255,13,13,13,13,
  737.     9,9,9,9,255,5,5,5,5,5,5,255,13,13,13,13,
  738.     9,9,9,9,255,5,5,5,5,5,5,255,13,13,13,13,
  739.     255,255,255,255,255,5,5,5,5,5,5,255,13,13,13,13,
  740.     3,3,3,3,3,255,5,5,5,5,5,255,13,13,13,13,
  741.     3,3,3,3,3,3,255,5,5,5,5,255,13,13,13,13,
  742.     3,3,3,3,3,3,3,255,5,5,5,255,13,13,13,13,
  743.     3,3,3,3,3,3,3,3,255,255,255,255,15,15,15,15,
  744.     3,3,3,3,3,3,3,3,255,255,15,15,15,15,15,15,
  745.     3,3,3,3,3,3,3,3,255,15,255,255,255,255,255,15,
  746.     255,255,255,255,255,255,255,255,255,15,255,8,8,8,255,15,
  747.     11,11,11,11,11,11,11,11,15,15,255,8,8,8,255,15,
  748.     11,11,11,11,11,11,11,11,15,15,255,8,8,255,255,15,
  749.     11,11,11,11,11,11,11,11,15,15,255,255,255,255,15,15,
  750.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  751.     9,9,9,9,9,255,5,5,5,5,255,13,13,13,13,13,
  752.     9,9,9,9,9,255,5,5,5,5,255,13,13,13,13,13,
  753.     9,9,9,9,9,255,5,5,5,5,255,13,13,13,13,13,
  754.     9,9,9,9,9,255,5,5,5,5,255,13,13,13,13,13,
  755.     9,9,9,9,9,255,5,5,5,5,255,13,13,13,13,13,
  756.     255,255,255,255,255,255,5,5,5,5,255,13,13,13,13,13,
  757.     3,3,3,3,3,3,255,5,5,5,255,13,13,13,13,13,
  758.     3,3,3,3,3,3,3,255,5,5,255,13,13,13,13,13,
  759.     3,3,3,3,3,3,3,3,255,255,255,15,15,15,15,15,
  760.     3,3,3,3,3,3,3,3,255,15,15,15,15,15,15,15,
  761.     255,255,255,255,255,255,255,255,255,15,255,255,255,255,15,15,
  762.     11,11,11,11,11,11,11,11,15,15,255,255,8,255,255,15,
  763.     11,11,11,11,11,11,11,11,15,15,255,8,8,255,255,15,
  764.     11,11,11,11,11,11,11,11,15,15,255,255,255,255,255,15,
  765.     11,11,11,11,11,11,11,11,15,15,15,255,255,255,15,15,
  766.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  767.     9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
  768.     9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
  769.     9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
  770.     9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
  771.     9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
  772.     9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
  773.     255,255,255,255,255,255,255,5,5,255,13,13,13,13,13,13,
  774.     3,3,3,3,3,3,3,255,5,255,13,13,13,13,13,13,
  775.     3,3,3,3,3,3,3,3,255,255,15,15,15,15,15,15,
  776.     255,255,255,255,255,255,255,255,255,15,15,15,15,15,15,15,
  777.     11,11,11,11,11,11,11,11,15,15,15,255,255,15,15,15,
  778.     11,11,11,11,11,11,11,11,15,15,255,255,255,255,15,15,
  779.     11,11,11,11,11,11,11,11,15,15,255,255,255,255,15,15,
  780.     11,11,11,11,11,11,11,11,15,15,15,255,255,255,15,15,
  781.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  782.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  783.     9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
  784.     9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
  785.     9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
  786.     9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
  787.     9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
  788.     9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
  789.     9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
  790.     255,255,255,255,255,255,255,255,255,13,13,13,13,13,13,13,
  791.     255,255,255,255,255,255,255,255,255,15,15,15,15,15,15,15,
  792.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  793.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  794.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  795.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  796.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  797.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  798.     11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
  799.     };
  800. /*...e*/
  801.  
  802. static byte nearest_colour(byte r, byte g, byte b)
  803.     {
  804.     byte i;
  805.  
  806.     if ( (i = quick_tab [r >> 4][g >> 4][b >> 4]) != (byte) 0xff )
  807.         return ( i );
  808.  
  809.     return ( calc_nearest(r, g, b) );
  810.     }
  811. /*...e*/
  812.  
  813. void gbm_errdiff_line_VGA(byte *src, byte *dest, short *errs, int cx)
  814.     {
  815.     BOOLEAN left = TRUE;
  816.     int x, ptr = 0;
  817.  
  818.     init();
  819.  
  820.     /* Step 1: Add error terms to newly supplied line */
  821.  
  822.     for ( x = 0; x < cx * 3; x++ )
  823.         src [x] = U_SAT_ADD((int) src [x], (int) errs [x]);
  824.  
  825.     /* Step 2: Zero out error terms */
  826.  
  827.     memset(errs, 0, (cx + 1) * 3 * sizeof(errs [0]));
  828.  
  829.     /* Step 3: Go along data, finding nearest colour and propagating error */
  830.  
  831.     randinx = rand();
  832.  
  833.     for ( x = 0; x < cx; x++ )
  834.         {
  835.         byte b     = *src++;
  836.         byte g     = *src++;
  837.         byte r     = *src++;
  838.         byte bi    = nearest_colour(r, g, b); 
  839.         int  be    = (int) b - (int) gbmrgb_vga [bi].b;
  840.         int  ge    = (int) g - (int) gbmrgb_vga [bi].g;
  841.         int  re    = (int) r - (int) gbmrgb_vga [bi].r;
  842.         word rn    = randtab [(byte) (randinx++)];
  843.         int  right = (rn >> 8);
  844.         int  down  = ((rn & 0xff) % (63 - right));
  845.         int  be1   = ((be * right) >> 6);
  846.         int  ge1   = ((ge * right) >> 6);
  847.         int  re1   = ((re * right) >> 6);
  848.         int  be2   = ((be * down) >> 6);
  849.         int  ge2   = ((ge * down) >> 6);
  850.         int  re2   = ((re * down) >> 6);
  851.         int  be3   = be - be1 - be2;
  852.         int  ge3   = ge - ge1 - ge2;
  853.         int  re3   = re - re1 - re2;
  854.  
  855.         if ( left )
  856.             *dest = (byte) (bi << 4);
  857.         else
  858.             *dest++ |= bi;
  859.  
  860.         left = !left;
  861.  
  862.         src [0] = U_SAT_ADD((int) src [0], be1);
  863.         src [1] = U_SAT_ADD((int) src [1], ge1);
  864.         src [2] = U_SAT_ADD((int) src [2], re1);
  865.  
  866.         errs [ptr    ] = S_SAT_ADD((int) errs [ptr    ], be2);
  867.         errs [ptr + 1] = S_SAT_ADD((int) errs [ptr + 1], ge2);
  868.         errs [ptr + 2] = S_SAT_ADD((int) errs [ptr + 2], re2);
  869.  
  870.         ptr += 3;
  871.  
  872.         errs [ptr    ] = S_SAT_ADD((int) errs [ptr    ], be3);
  873.         errs [ptr + 1] = S_SAT_ADD((int) errs [ptr + 1], ge3);
  874.         errs [ptr + 2] = S_SAT_ADD((int) errs [ptr + 2], re3);
  875.         }
  876.     }
  877. /*...e*/
  878. /*...sgbm_errdiff_VGA         \45\ error diffuse to default VGA palette:0:*/
  879. BOOLEAN    gbm_errdiff_VGA(GBM *gbm, byte *data24, byte *data4)
  880.     {
  881.     return ( errdiff(gbm, data24, data4, 4, gbm_errdiff_line_VGA) );
  882.     }
  883. /*...e*/
  884.  
  885. /*...sgbm_errdiff_pal_8       \45\ return default 8 colour palette:0:*/
  886. /*
  887. This function makes the palette for the 16 colour 8 colour palette.
  888. */
  889.  
  890. static GBMRGB gbmrgb_8 [] =
  891.     {
  892.       0,  0,  0,
  893.       0,  0,255,
  894.       0,255,  0,
  895.       0,255,255,
  896.     255,  0,  0,
  897.     255,  0,255,
  898.     255,255,  0,
  899.     255,255,255,
  900.       0,  0,  0,
  901.       0,  0,  0,
  902.       0,  0,  0,
  903.       0,  0,  0,
  904.       0,  0,  0,
  905.       0,  0,  0,
  906.       0,  0,  0,
  907.       0,  0,  0,
  908.     };
  909.  
  910. void gbm_errdiff_pal_8(GBMRGB *gbmrgb)
  911.     {
  912.     init();
  913.     memcpy((char *) gbmrgb, (char *) gbmrgb_8, sizeof(gbmrgb_8));
  914.     }
  915. /*...e*/
  916. /*...sgbm_errdiff_line_8      \45\ error diffuse to default 8 colour palette one line:0:*/
  917. /*
  918. This function takes a line of RGB data, a destination buffer and a buffer of
  919. error terms and performs one lines worth (a given # of pixels) of error
  920. diffusion.
  921. */
  922.  
  923. void gbm_errdiff_line_8(byte *src, byte *dest, short *errs, int cx)
  924.     {
  925.     BOOLEAN left = TRUE;
  926.     int x, ptr = 0;
  927.  
  928.     init();
  929.  
  930.     /* Step 1: Add error terms to newly supplied line */
  931.  
  932.     for ( x = 0; x < cx * 3; x++ )
  933.         src [x] = U_SAT_ADD((int) src [x], (int) errs [x]);
  934.  
  935.     /* Step 2: Zero out error terms */
  936.  
  937.     memset(errs, 0, (cx + 1) * 3 * sizeof(errs [0]));
  938.  
  939.     /* Step 3: Go along data, finding nearest colour and propagating error */
  940.  
  941.     randinx = rand();
  942.  
  943.     for ( x = 0; x < cx; x++ )
  944.         {
  945.         byte b     = *src++;
  946.         byte g     = *src++;
  947.         byte r     = *src++;
  948.         byte bi    = ((r&0x80)>>5) | ((g&0x80)>>6) | ((b&0x80)>>7);
  949.         int  be    = (int) b - (int) gbmrgb_8 [bi].b;
  950.         int  ge    = (int) g - (int) gbmrgb_8 [bi].g;
  951.         int  re    = (int) r - (int) gbmrgb_8 [bi].r;
  952.         word rn    = randtab [(byte) (randinx++)];
  953.         int  right = (rn >> 8);
  954.         int  down  = ((rn & 0xff) % (63 - right));
  955.         int  be1   = ((be * right) >> 6);
  956.         int  ge1   = ((ge * right) >> 6);
  957.         int  re1   = ((re * right) >> 6);
  958.         int  be2   = ((be * down) >> 6);
  959.         int  ge2   = ((ge * down) >> 6);
  960.         int  re2   = ((re * down) >> 6);
  961.         int  be3   = be - be1 - be2;
  962.         int  ge3   = ge - ge1 - ge2;
  963.         int  re3   = re - re1 - re2;
  964.  
  965.         if ( left )
  966.             *dest = (byte) (bi << 4);
  967.         else
  968.             *dest++ |= bi;
  969.  
  970.         left = !left;
  971.  
  972.         src [0] = U_SAT_ADD((int) src [0], be1);
  973.         src [1] = U_SAT_ADD((int) src [1], ge1);
  974.         src [2] = U_SAT_ADD((int) src [2], re1);
  975.  
  976.         errs [ptr    ] = S_SAT_ADD((int) errs [ptr    ], be2);
  977.         errs [ptr + 1] = S_SAT_ADD((int) errs [ptr + 1], ge2);
  978.         errs [ptr + 2] = S_SAT_ADD((int) errs [ptr + 2], re2);
  979.  
  980.         ptr += 3;
  981.  
  982.         errs [ptr    ] = S_SAT_ADD((int) errs [ptr    ], be3);
  983.         errs [ptr + 1] = S_SAT_ADD((int) errs [ptr + 1], ge3);
  984.         errs [ptr + 2] = S_SAT_ADD((int) errs [ptr + 2], re3);
  985.         }
  986.     }
  987. /*...e*/
  988. /*...sgbm_errdiff_8           \45\ error diffuse to default 8 colour palette:0:*/
  989. BOOLEAN    gbm_errdiff_8(GBM *gbm, byte *data24, byte *data4)
  990.     {
  991.     return ( errdiff(gbm, data24, data4, 4, gbm_errdiff_line_8) );
  992.     }
  993. /*...e*/
  994.  
  995. /*...sgbm_errdiff_pal_4G      \45\ return 4 bit greyscale palette:0:*/
  996. /*
  997. This function makes the palette for the 16 colour VGA palette.
  998. */
  999.  
  1000. void gbm_errdiff_pal_4G(GBMRGB *gbmrgb)
  1001.     {
  1002.     int i;
  1003.  
  1004.     init();
  1005.     for ( i = 0; i < 0x10; i++ )
  1006.         {
  1007.         gbmrgb [i].r = scale16 [i];
  1008.         gbmrgb [i].g = scale16 [i];
  1009.         gbmrgb [i].b = scale16 [i];
  1010.         }
  1011.     }
  1012. /*...e*/
  1013. /*...sgbm_errdiff_line_4G     \45\ error diffuse to 4 bit greyscale palette one line:0:*/
  1014. /*
  1015. This function takes a line of RGB data, a destination buffer and a buffer of
  1016. error terms and performs one lines worth (a given # of pixels) of error
  1017. diffusion.
  1018. */
  1019.  
  1020. void gbm_errdiff_line_4G(byte *src, byte *dest, short *errs, int cx)
  1021.     {
  1022.     BOOLEAN left = TRUE;
  1023.     int x, ptr = 0;
  1024.     byte *pb;
  1025.  
  1026.     init();
  1027.  
  1028.     /* Step 1: Add error terms to newly supplied line */
  1029.  
  1030.     for ( x = 0, pb = src; x < cx; x++ )
  1031.         {
  1032.         byte b = *pb++;
  1033.         byte g = *pb++;
  1034.         byte r = *pb++;
  1035.  
  1036.         src [x] = (byte) (((word) r * 77 + (word) g * 151 + (word) b * 28) >> 8);
  1037.         src [x] = U_SAT_ADD((int) src [x], (int) errs [x]);
  1038.         }
  1039.  
  1040.     /* Step 2: Zero out error terms */
  1041.  
  1042.     memset(errs, 0, (cx + 1) * sizeof(errs [0]));
  1043.  
  1044.     /* Step 3: Go along data, finding nearest colour and propagating error */
  1045.  
  1046.     randinx = rand();
  1047.  
  1048.     for ( x = 0; x < cx; x++ )
  1049.         {
  1050.         byte grey  = *src++;
  1051.         byte inx   = index16 [grey];
  1052.         int  err   = (int) grey - (int) scale16 [inx];
  1053.         word rn    = randtab [(byte) (randinx++)];
  1054.         int  right = (rn >> 8);
  1055.         int  down  = ((rn & 0xff) % (63 - right));
  1056.         int  err1  = ((err * right) >> 6);
  1057.         int  err2  = ((err * down ) >> 6);
  1058.         int  err3  = err - err1 - err2;
  1059.  
  1060.         if ( left )
  1061.             *dest = (byte) (inx << 4);
  1062.         else
  1063.             *dest++ |= inx;
  1064.  
  1065.         left = !left;
  1066.  
  1067.         src [0] = U_SAT_ADD((int) src [0], err1);
  1068.  
  1069.         errs [ptr] = S_SAT_ADD((int) errs [ptr], err2);
  1070.  
  1071.         ptr++;
  1072.  
  1073.         errs [ptr] = S_SAT_ADD((int) errs [ptr], err3);
  1074.         }
  1075.     }
  1076. /*...e*/
  1077. /*...sgbm_errdiff_4G          \45\ error diffuse to 4 bit greyscale palette:0:*/
  1078. BOOLEAN    gbm_errdiff_4G(GBM *gbm, byte *data24, byte *data4)
  1079.     {
  1080.     return ( errdiff(gbm, data24, data4, 4, gbm_errdiff_line_4G) );
  1081.     }
  1082. /*...e*/
  1083.  
  1084. /*...sgbm_errdiff_pal_BW      \45\ return black and white palette:0:*/
  1085. /*
  1086. This function returns the b/w palette.
  1087. (We consider the image to be likely black on white,
  1088. hence the ordering of the palette entries).
  1089. */
  1090.  
  1091. static GBMRGB gbmrgb_bw [] =
  1092.     {
  1093.     255,255,255,
  1094.     0,0,0,
  1095.     };
  1096.  
  1097. void gbm_errdiff_pal_BW(GBMRGB *gbmrgb)
  1098.     {
  1099.     init();
  1100.     memcpy((char *) gbmrgb, (char *) gbmrgb_bw, sizeof(gbmrgb_bw));
  1101.     }
  1102. /*...e*/
  1103. /*...sgbm_errdiff_line_BW     \45\ error diffuse to black and white one line:0:*/
  1104. /*
  1105. This function takes a line of RGB data, a destination buffer and a buffer of
  1106. error terms and performs one lines worth (a given # of pixels) of error
  1107. diffusion.
  1108. */
  1109.  
  1110. void gbm_errdiff_line_BW(byte *src, byte *dest, short *errs, int cx)
  1111.     {
  1112.     int x, bit = 0, ptr = 0;
  1113.     byte *pb;
  1114.  
  1115.     init();
  1116.  
  1117.     /* Step 1: Add error terms to newly supplied line */
  1118.  
  1119.     for ( x = 0, pb = src; x < cx; x++ )
  1120.         {
  1121.         byte b = *pb++;
  1122.         byte g = *pb++;
  1123.         byte r = *pb++;
  1124.  
  1125.         src [x] = (byte) (((word) r * 77 + (word) g * 151 + (word) b * 28) >> 8);
  1126.         src [x] = U_SAT_ADD((int) src [x], (int) errs [x]);
  1127.         }
  1128.         
  1129.     /* Step 2: Zero out error terms */
  1130.  
  1131.     memset(errs, 0, (cx + 1) * sizeof(errs [0]));
  1132.  
  1133.     /* Step 3: Go along data, finding nearest colour and propagating error */
  1134.  
  1135.     memset(dest, 0, (cx + 7) >> 3);
  1136.  
  1137.     randinx = rand();
  1138.  
  1139.     for ( x = 0; x < cx; x++ )
  1140.         {
  1141.         byte grey  = *src++;
  1142.         byte inx   = (byte) (grey < 0x80);
  1143.         int  err   = (int) grey - (int) gbmrgb_bw [inx].b;
  1144.         word rn    = randtab [(byte) (randinx++)];
  1145.         int  right = (rn >> 8);
  1146.         int  down  = ((rn & 0xff) % (63 - right));
  1147.         int  err1  = ((err * right) >> 6);
  1148.         int  err2  = ((err * down ) >> 6);
  1149.         int  err3  = err - err1 - err2;
  1150.  
  1151.         if ( inx )
  1152.             *dest |= (0x80 >> bit);
  1153.  
  1154.         if ( ++bit == 8 )
  1155.             {
  1156.             bit = 0;
  1157.             dest++;
  1158.             }
  1159.  
  1160.         src [0] = U_SAT_ADD((int) src [0], err1);
  1161.  
  1162.         errs [ptr] = S_SAT_ADD((int) errs [ptr], err2);
  1163.  
  1164.         ptr++;
  1165.  
  1166.         errs [ptr] = S_SAT_ADD((int) errs [ptr], err3);
  1167.         }
  1168.     }
  1169. /*...e*/
  1170. /*...sgbm_errdiff_BW          \45\ error diffuse to black and white:0:*/
  1171. BOOLEAN    gbm_errdiff_BW(GBM *gbm, byte *data24, byte *data1)
  1172.     {
  1173.     return ( errdiff(gbm, data24, data1, 1, gbm_errdiff_line_BW) );
  1174.     }
  1175. /*...e*/
  1176.