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