home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / rexx / library2 / gbmrexx / gbm / gbmht.c < prev    next >
C/C++ Source or Header  |  1993-08-27  |  35KB  |  1,492 lines

  1. /*
  2.  
  3. GBMHT.C  Halftoner
  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. For 6Rx6Gx6B, 7Rx8Gx4B palettes etc.
  23. */
  24.  
  25. static byte index4 [0x400];
  26. static byte index6 [0x400];
  27. static byte index7 [0x400];
  28. static byte index8 [0x400];
  29. static byte scale4 [] = { 0, 85, 170, 255 };
  30. static byte scale6 [] = { 0, 51, 102, 153, 204, 255 };
  31. static byte scale7 [] = { 0, 43, 85, 128, 170, 213, 255 };
  32. static byte scale8 [] = { 0, 36, 73, 109, 146, 182, 219, 255 };
  33.  
  34. static byte map_to_012 [0x900];
  35.     /* Returns 0 if index <  0x80                  */
  36.     /*         1 if index >= 0x80 and index < 0xff */
  37.     /*         2 if index  = 0xff                  */
  38. static byte map_to_inx [3][3][3];
  39.  
  40. static GBMRGB gbmrgb_vga [] =
  41.     {
  42.       0,  0,  0,
  43.     128,  0,  0,
  44.       0,128,  0,
  45.     128,128,  0,
  46.       0,  0,128,
  47.     128,  0,128,
  48.       0,128,128,
  49.     128,128,128,
  50.     204,204,204,
  51.     255,  0,  0,
  52.       0,255,  0,
  53.     255,255,  0,
  54.       0,  0,255,
  55.     255,  0,255,
  56.       0,255,255,
  57.     255,255,255,
  58.     };
  59.  
  60. static GBMRGB gbmrgb_8 [] =
  61.     {
  62.       0,  0,  0,
  63.       0,  0,255,
  64.       0,255,  0,
  65.       0,255,255,
  66.     255,  0,  0,
  67.     255,  0,255,
  68.     255,255,  0,
  69.     255,255,255,
  70.       0,  0,  0,
  71.       0,  0,  0,
  72.       0,  0,  0,
  73.       0,  0,  0,
  74.       0,  0,  0,
  75.       0,  0,  0,
  76.       0,  0,  0,
  77.       0,  0,  0,
  78.     };
  79. /*...e*/
  80. /*...sdivt:0:*/
  81. /*
  82. This fold encompases a way to get rapid division via lookup tables.
  83. */
  84.  
  85. static word divt9 [9 * 0x100];
  86. static word divt7 [9 * 0x100];
  87. static word divt6 [9 * 0x100];
  88. static word divt5 [9 * 0x100];
  89. static word divt3 [9 * 0x100];
  90.  
  91. /*...smake_divt:0:*/
  92. static void make_divt(word *divt, int size, int by)
  93.     {
  94.     int i;
  95.  
  96.     for ( i = 0; i < size; i++ )
  97.         divt [i] = (word) (i / by);
  98.     }
  99. /*...e*/
  100.  
  101. #define    div9(w)    divt9[w]
  102. #define    div8(w)    ((w)>>3)
  103. #define    div7(w)    divt7[w]
  104. #define    div6(w)    divt6[w]
  105. #define    div5(w)    divt5[w]
  106. #define    div4(w)    ((w)>>2)
  107. #define    div3(w)    divt3[w]
  108. #define    div2(w)    ((w)>>1)
  109. /*...e*/
  110. /*...sinit:0:*/
  111. /*
  112. This function initialises this module.
  113. */
  114.  
  115. /*...stakeout_inx:0:*/
  116. /*
  117. For the supplied value, find the index of the highest value in the scale
  118. less than or equal to the value.
  119. */
  120.  
  121. static byte takeout_inx(int value, byte ab [], unsigned short cb)
  122.     {
  123.     byte inx = 0;
  124.     unsigned short i;
  125.  
  126.     for ( i = 0; i < cb; i++ )
  127.         if ( (unsigned short) ab [i] <= (unsigned short) value )
  128.             inx = i;
  129.  
  130.     return ( inx );
  131.     }
  132. /*...e*/
  133. /*...stakeout_inx_vga:0:*/
  134. /*
  135. The idea is to take as much of the r, g and b as possible by chosing a
  136. colour from the VGA palette that leaves as little left over as possible.
  137. Since there are 2 mid-greys, we discourage the use of one.
  138. The only justification for this is that the results seem to come out better!
  139. Also, I have tried allowing takefrom to return the closest index, allowing
  140. more to be taken than r,g and b. This gives less grey results, but the
  141. output is a lot dirtier and speckled.
  142. */
  143.  
  144. static byte takeout_inx_vga(word r, word g, word b)
  145.     {
  146.     byte inx;
  147.     byte inx_min = 0;
  148.     int e_min = (int) ( r + g + b );
  149.  
  150.     for ( inx = 1; inx < 16; inx++ )
  151.         if ( inx != 8 )
  152.             {
  153.             int re = (int) ( r - (word) gbmrgb_vga [inx].r );
  154.             int ge = (int) ( g - (word) gbmrgb_vga [inx].g );
  155.             int be = (int) ( b - (word) gbmrgb_vga [inx].b );
  156.  
  157.             if ( re >= 0 && ge >= 0 && be >= 0 )
  158.                 {
  159.                 int e = re + ge + be;
  160.  
  161.                 if ( e < e_min )
  162.                     {
  163.                     e_min = e;
  164.                     inx_min = inx;
  165.                     }
  166.                 }
  167.             }
  168.     return ( inx_min );
  169.     }
  170. /*...e*/
  171.  
  172. static void init(void)
  173.     {
  174.     static word val [] = { 0, 0x80, 0xff };
  175.     int i;
  176.     int volatile r;        /* C-Set/2 optimiser fix */
  177.     int volatile g;
  178.     int volatile b;
  179.  
  180.     if ( inited )
  181.         return;
  182.  
  183.     /* For 7 Red x 8 Green x 4 Blue palettes etc. */
  184.  
  185.     for ( i = 0; i < 0x400; i++ )
  186.         {
  187.         index4 [i] = takeout_inx(i, scale4 , sizeof(scale4));
  188.         index6 [i] = takeout_inx(i, scale6 , sizeof(scale6));
  189.         index7 [i] = takeout_inx(i, scale7 , sizeof(scale7));
  190.         index8 [i] = takeout_inx(i, scale8 , sizeof(scale8));
  191.         }
  192.  
  193.     memset(map_to_012, 0, 0x80);
  194.     memset(map_to_012 + 0x80, 1, 0x7f);
  195.     memset(map_to_012 + 0xff, 2, 0x801);
  196.  
  197.     for ( r = 0; r < 3; r++ )
  198.         for ( g = 0; g < 3; g++ )
  199.             for ( b = 0; b < 3; b++ )
  200.                 map_to_inx [r][g][b] = takeout_inx_vga(val [r], val [g], val [b]);
  201.  
  202.     make_divt(divt9, sizeof(divt9)/sizeof(word), 9);
  203.     make_divt(divt7, sizeof(divt7)/sizeof(word), 7);
  204.     make_divt(divt6, sizeof(divt6)/sizeof(word), 6);
  205.     make_divt(divt5, sizeof(divt5)/sizeof(word), 5);
  206.     make_divt(divt3, sizeof(divt3)/sizeof(word), 3);
  207.  
  208.     inited = TRUE;
  209.     }
  210. /*...e*/
  211. /*...stakefrom:0:*/
  212. #define    takefrom(r,g,b) ( map_to_inx [map_to_012 [r]][map_to_012 [g]][map_to_012 [b]] )
  213. /*...e*/
  214. /*...ssplit_into:0:*/
  215. /* n is only ever 2, 3, 4, 6 or 9 */
  216.  
  217. static void split_into(
  218.     word r, word g, word b,
  219.     int n, byte *inxs
  220.     )
  221.     {
  222.     byte inx;
  223.  
  224.     if ( n >= 9 )
  225.         {
  226.         inx = takefrom(div9(r), div9(g), div9(b));
  227.         b -= gbmrgb_vga [inx].b;
  228.         g -= gbmrgb_vga [inx].g;
  229.         r -= gbmrgb_vga [inx].r;
  230.         *inxs++ = inx;
  231.  
  232.         inx = takefrom(div8(r), div8(g), div8(b));
  233.         b -= gbmrgb_vga [inx].b;
  234.         g -= gbmrgb_vga [inx].g;
  235.         r -= gbmrgb_vga [inx].r;
  236.         *inxs++ = inx;
  237.  
  238.         inx = takefrom(div7(r), div7(g), div7(b));
  239.         b -= gbmrgb_vga [inx].b;
  240.         g -= gbmrgb_vga [inx].g;
  241.         r -= gbmrgb_vga [inx].r;
  242.         *inxs++ = inx;
  243.         }
  244.  
  245.     if ( n >= 6 )
  246.         {
  247.         inx = takefrom(div6(r), div6(g), div6(b));
  248.         b -= gbmrgb_vga [inx].b;
  249.         g -= gbmrgb_vga [inx].g;
  250.         r -= gbmrgb_vga [inx].r;
  251.         *inxs++ = inx;
  252.  
  253.         inx = takefrom(div5(r), div5(g), div5(b));
  254.         b -= gbmrgb_vga [inx].b;
  255.         g -= gbmrgb_vga [inx].g;
  256.         r -= gbmrgb_vga [inx].r;
  257.         *inxs++ = inx;
  258.         }
  259.  
  260.     if ( n >= 4 )
  261.         {
  262.         inx = takefrom(div4(r), div4(g), div4(b));
  263.         b -= gbmrgb_vga [inx].b;
  264.         g -= gbmrgb_vga [inx].g;
  265.         r -= gbmrgb_vga [inx].r;
  266.         *inxs++ = inx;
  267.         }
  268.  
  269.     if ( n >= 3 )
  270.         {
  271.         inx = takefrom(div3(r), div3(g), div3(b));
  272.         b -= gbmrgb_vga [inx].b;
  273.         g -= gbmrgb_vga [inx].g;
  274.         r -= gbmrgb_vga [inx].r;
  275.         *inxs++ = inx;
  276.         }
  277.  
  278.     inx = takefrom(div2(r), div2(g), div2(b));
  279.     b -= gbmrgb_vga [inx].b;
  280.     g -= gbmrgb_vga [inx].g;
  281.     r -= gbmrgb_vga [inx].r;
  282.     *inxs++ = inx;
  283.  
  284.     *inxs = takefrom(r, g, b);
  285.     }
  286. /*...e*/
  287. /*...stakefrom8:0:*/
  288. /*
  289. Find the largest colour from the 8 colour palette.
  290. */
  291.  
  292. #define    takefrom8(r,g,b) ( (((r)>=255)<<2) | (((g)>=255)<<1) | ((b)>=255) )
  293. /*...e*/
  294. /*...ssplit_into8:0:*/
  295. /* n is only ever 2, 3, 4, 6 or 9 */
  296.  
  297. static void split_into8(
  298.     word r, word g, word b,
  299.     int n, byte *inxs
  300.     )
  301.     {
  302.     byte inx;
  303.  
  304.     if ( n >= 9 )
  305.         {
  306.         inx = takefrom8(div9(r), div9(g), div9(b));
  307.         b -= gbmrgb_8 [inx].b;
  308.         g -= gbmrgb_8 [inx].g;
  309.         r -= gbmrgb_8 [inx].r;
  310.         *inxs++ = inx;
  311.  
  312.         inx = takefrom8(div8(r), div8(g), div8(b));
  313.         b -= gbmrgb_8 [inx].b;
  314.         g -= gbmrgb_8 [inx].g;
  315.         r -= gbmrgb_8 [inx].r;
  316.         *inxs++ = inx;
  317.  
  318.         inx = takefrom8(div7(r), div7(g), div7(b));
  319.         b -= gbmrgb_8 [inx].b;
  320.         g -= gbmrgb_8 [inx].g;
  321.         r -= gbmrgb_8 [inx].r;
  322.         *inxs++ = inx;
  323.         }
  324.  
  325.     if ( n >= 6 )
  326.         {
  327.         inx = takefrom8(div6(r), div6(g), div6(b));
  328.         b -= gbmrgb_8 [inx].b;
  329.         g -= gbmrgb_8 [inx].g;
  330.         r -= gbmrgb_8 [inx].r;
  331.         *inxs++ = inx;
  332.  
  333.         inx = takefrom8(div5(r), div5(g), div5(b));
  334.         b -= gbmrgb_8 [inx].b;
  335.         g -= gbmrgb_8 [inx].g;
  336.         r -= gbmrgb_8 [inx].r;
  337.         *inxs++ = inx;
  338.         }
  339.  
  340.     if ( n >= 4 )
  341.         {
  342.         inx = takefrom8(div4(r), div4(g), div4(b));
  343.         b -= gbmrgb_8 [inx].b;
  344.         g -= gbmrgb_8 [inx].g;
  345.         r -= gbmrgb_8 [inx].r;
  346.         *inxs++ = inx;
  347.         }
  348.  
  349.     if ( n >= 3 )
  350.         {
  351.         inx = takefrom8(div3(r), div3(g), div3(b));
  352.         b -= gbmrgb_8 [inx].b;
  353.         g -= gbmrgb_8 [inx].g;
  354.         r -= gbmrgb_8 [inx].r;
  355.         *inxs++ = inx;
  356.         }
  357.  
  358.     inx = takefrom8(div2(r), div2(g), div2(b));
  359.     b -= gbmrgb_8 [inx].b;
  360.     g -= gbmrgb_8 [inx].g;
  361.     r -= gbmrgb_8 [inx].r;
  362.     *inxs++ = inx;
  363.  
  364.     *inxs = takefrom8(r, g, b);
  365.     }
  366. /*...e*/
  367.  
  368. /*...sgbm_ht_24_2x2     \45\ halftone by 2x2 to r\58\g\58\b bits:0:*/
  369. void gbm_ht_24_2x2(GBM *gbm, byte *src24, byte *dest24, byte rm, byte gm, byte bm)
  370.     {
  371.     int stride = ((gbm -> w * 3 + 3) & ~3);
  372.     int x, y;
  373.  
  374.     init();
  375.  
  376.     src24 -= stride;
  377.     dest24 -= stride;
  378.  
  379.     for ( y = 0; y < gbm -> h - 1; y += 2 )
  380.         {
  381.         byte *src24a  = (src24 += stride);
  382.         byte *src24b  = (src24 += stride);
  383.         byte *dest24a = (dest24 += stride);
  384.         byte *dest24b = (dest24 += stride);
  385.  
  386.         for ( x = 0; x < gbm -> w - 1; x += 2 )
  387. /*...s2x2 case:24:*/
  388. {
  389. word r,g,b;
  390. byte ri,gi,bi;
  391. byte *tmp;
  392.  
  393. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  394. b += *src24a++;    g += *src24a++;    r += *src24a++;
  395. b += *src24b++;    g += *src24b++;    r += *src24b++;
  396. b += *src24b++;    g += *src24b++;    r += *src24b++;
  397.  
  398. bi = (div4(b) & bm); gi = (div4(g) & gm); ri = (div4(r) & rm);
  399. *dest24a++ = bi; *dest24a++ = gi; *dest24a++ = ri;
  400. b -= bi; g -= gi; r -= ri;
  401.  
  402. if ( b > 255 * 3 ) b = 255 * 3;
  403. if ( g > 255 * 3 ) g = 255 * 3;
  404. if ( r > 255 * 3 ) r = 255 * 3;
  405.  
  406. bi = (div3(b) & bm); gi = (div3(g) & gm); ri = (div3(r) & rm);
  407. *dest24a++ = bi; *dest24a++ = gi; *dest24a++ = ri;
  408. b -= bi; g -= gi; r -= ri;
  409.  
  410. if ( b > 255 * 2 ) b = 255 * 2;
  411. if ( g > 255 * 2 ) g = 255 * 2;
  412. if ( r > 255 * 2 ) r = 255 * 2;
  413.  
  414. bi = (div2(b) & bm); gi = (div2(g) & gm); ri = (div2(r) & rm);
  415. *dest24b++ = bi; *dest24b++ = gi; *dest24b++ = ri;
  416. b -= bi; g -= gi; r -= ri;
  417.  
  418. if ( b > 255 ) b = 255;
  419. if ( g > 255 ) g = 255;
  420. if ( r > 255 ) r = 255;
  421.  
  422. bi = (b & bm); gi = (g & gm); ri = (r & rm);
  423. *dest24b++ = bi; *dest24b++ = gi; *dest24b++ = ri;
  424.  
  425. tmp = dest24a; dest24a = dest24b; dest24b = tmp;
  426. }
  427. /*...e*/
  428.         if ( x < gbm -> w )
  429. /*...s1x2 case:24:*/
  430. {
  431. word r,g,b;
  432. byte ri, gi, bi;
  433.  
  434. b  = *src24a++;    g  = *src24a++;    r  = *src24a;
  435. b += *src24b++;    g += *src24b++;    r += *src24b;
  436.  
  437. bi = (div2(b) & bm); gi = (div2(g) & gm); ri = (div2(r) & rm);
  438. *dest24a++ = bi; *dest24a++ = gi; *dest24a++ = ri;
  439. b -= bi; g -= gi; r -= ri;
  440.  
  441. if ( b > 255 ) b = 255;
  442. if ( g > 255 ) g = 255;
  443. if ( r > 255 ) r = 255;
  444.  
  445. bi = (b & bm); gi = (g & gm); ri = (r & rm);
  446. *dest24b++ = bi; *dest24b++ = gi; *dest24b   = ri;
  447. }
  448. /*...e*/
  449.         }
  450.     if ( y < gbm -> h )
  451.         {
  452.         byte *src24a  = src24 + stride;
  453.         byte *dest24a = dest24 + stride;
  454.  
  455.         for ( x = 0; x < gbm -> w - 1; x += 2 )
  456. /*...s2x1 case:24:*/
  457. {
  458. word r,g,b;
  459. byte ri, gi, bi;
  460.  
  461. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  462. b += *src24a++;    g += *src24a++;    r += *src24a++;
  463.  
  464. bi = (div2(b) & bm); gi = (div2(g) & gm); ri = (div2(r) & rm);
  465. *dest24a++ = bi; *dest24a++ = gi; *dest24a++ = ri;
  466. b -= bi; g -= gi; r -= ri;
  467.  
  468. if ( b > 255 ) b = 255;
  469. if ( g > 255 ) g = 255;
  470. if ( r > 255 ) r = 255;
  471.  
  472. bi = (b & bm); gi = (g & gm); ri = (r & rm);
  473. *dest24a++ = bi; *dest24a++ = gi; *dest24a++ = ri;
  474. }
  475. /*...e*/
  476.         if ( x < gbm -> w )
  477. /*...s1x1 case:24:*/
  478. {
  479. byte ri, gi, bi;
  480.  
  481. bi = ((*src24a++) & bm); gi = ((*src24a++) & gm); ri = ((*src24a) & rm);
  482. *dest24a++ = bi; *dest24a++ = gi; *dest24a = ri;
  483. }
  484. /*...e*/
  485.         }
  486.     }
  487. /*...e*/
  488.  
  489. /*...sgbm_ht_pal_6R6G6B \45\ return 6Rx6Gx6B palette:0:*/
  490. /*
  491. This function makes the palette for the 6 red x 6 green x 6 blue palette.
  492. 216 palette entrys used. Remaining 40 left blank.
  493. */
  494.  
  495. void gbm_ht_pal_6R6G6B(GBMRGB *gbmrgb)
  496.     {
  497.     byte volatile r;    /* C-Set/2 optimiser fix */
  498.     byte volatile g;
  499.     byte volatile b;
  500.  
  501.     init();
  502.     memset(gbmrgb, 0x80, 0x100 * sizeof(GBMRGB));
  503.     for ( r = 0; r < 6; r++ )
  504.         for ( g = 0; g < 6; g++ )
  505.             for ( b = 0; b < 6; b++ )
  506.                 {
  507.                 gbmrgb -> r = scale6 [r];
  508.                 gbmrgb -> g = scale6 [g];
  509.                 gbmrgb -> b = scale6 [b];
  510.                 gbmrgb++;
  511.                 }
  512.     }
  513. /*...e*/
  514. /*...sgbm_ht_6R6G6B_2x2 \45\ halftone by 2x2 to 6Rx6Gx6B palette:0:*/
  515. #define    PIX666(ri,gi,bi)    (byte) (6 * (6 * ri + gi) + bi)
  516.  
  517. void gbm_ht_6R6G6B_2x2(GBM *gbm, byte *src24, byte *dest8)
  518.     {
  519.     int stride24 = ((gbm -> w * 3 + 3) & ~3);
  520.     int stride8  = ((gbm -> w     + 3) & ~3);
  521.     int x, y;
  522.  
  523.     init();
  524.  
  525.     src24 -= stride24;
  526.     dest8 -= stride8;
  527.  
  528.     for ( y = 0; y < gbm -> h - 1; y += 2 )
  529.         {
  530.         byte *src24a = (src24 += stride24);
  531.         byte *src24b = (src24 += stride24);
  532.         byte *dest8a = (dest8 += stride8);
  533.         byte *dest8b = (dest8 += stride8);
  534.  
  535.         for ( x = 0; x < gbm -> w - 1; x += 2 )
  536. /*...s2x2 case:24:*/
  537. {
  538. word r,g,b;
  539. byte ri,gi,bi;
  540. byte *tmp;
  541.  
  542. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  543. b += *src24a++;    g += *src24a++;    r += *src24a++;
  544. b += *src24b++;    g += *src24b++;    r += *src24b++;
  545. b += *src24b++;    g += *src24b++;    r += *src24b++;
  546.  
  547. bi = index6 [div4(b)]; gi = index6 [div4(g)]; ri = index6 [div4(r)];
  548. *dest8a++ = PIX666(ri,gi,bi);
  549. b -= scale6 [bi]; g -= scale6 [gi]; r -= scale6 [ri];
  550.  
  551. bi = index6 [div3(b)]; gi = index6 [div3(g)]; ri = index6 [div3(r)];
  552. *dest8a++ = PIX666(ri,gi,bi);
  553. b -= scale6 [bi]; g -= scale6 [gi]; r -= scale6 [ri];
  554.  
  555. bi = index6 [div2(b)]; gi = index6 [div2(g)]; ri = index6 [div2(r)];
  556. *dest8b++ = PIX666(ri,gi,bi);
  557. b -= scale6 [bi]; g -= scale6 [gi]; r -= scale6 [ri];
  558.  
  559. bi = index6 [b      ]; gi = index6 [g      ]; ri = index6 [r      ];
  560. *dest8b++ = PIX666(ri,gi,bi);
  561.  
  562. tmp = dest8a; dest8a = dest8b; dest8b = tmp;
  563. }
  564. /*...e*/
  565.         if ( x < gbm -> w )
  566. /*...s1x2 case:24:*/
  567. {
  568. word r,g,b;
  569. byte ri, gi, bi;
  570.  
  571. b  = *src24a++;    g  = *src24a++;    r  = *src24a;
  572. b += *src24b++;    g += *src24b++;    r += *src24b;
  573.  
  574. bi = index6 [div2(b)]; gi = index6 [div2(g)]; ri = index6 [div2(r)];
  575. *dest8a = PIX666(ri,gi,bi);
  576. b -= scale6 [bi]; g -= scale6 [gi]; r -= scale6 [ri];
  577.  
  578. bi = index6 [b      ]; gi = index6 [g      ]; ri = index6 [r      ];
  579. *dest8b = PIX666(ri,gi,bi);
  580. }
  581. /*...e*/
  582.         }
  583.     if ( y < gbm -> h )
  584.         {
  585.         byte *src24a = src24 + stride24;
  586.         byte *dest8a = dest8 + stride8;
  587.  
  588.         for ( x = 0; x < gbm -> w - 1; x += 2 )
  589. /*...s2x1 case:24:*/
  590. {
  591. word r,g,b;
  592. byte ri, gi, bi;
  593.  
  594. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  595. b += *src24a++;    g += *src24a++;    r += *src24a++;
  596.  
  597. bi = index6 [div2(b)]; gi = index6 [div2(g)]; ri = index6 [div2(r)];
  598. *dest8a++ = PIX666(ri,gi,bi);
  599. b -= scale6 [bi]; g -= scale6 [gi]; r -= scale6 [ri];
  600.  
  601. bi = index6 [b      ]; gi = index6 [g      ]; ri = index6 [r      ];
  602. *dest8a++ = PIX666(ri,gi,bi);
  603. }
  604. /*...e*/
  605.         if ( x < gbm -> w )
  606. /*...s1x1 case:24:*/
  607. {
  608. byte ri, gi, bi;
  609.  
  610. bi = index6 [*src24a++]; gi = index6 [*src24a++]; ri = index6 [*src24a];
  611. *dest8a = PIX666(ri,gi,bi);
  612. }
  613. /*...e*/
  614.         }
  615.     }
  616. /*...e*/
  617.  
  618. /*...sgbm_ht_pal_7R8G4B \45\ return 7Rx8Gx4B palette:0:*/
  619. /*
  620. This function makes the palette for the 7 red x 8 green x 4 blue palette.
  621. 224 palette entrys used. Remaining 32 left blank.
  622. Colours calculated to match those used by 8514/A PM driver.
  623. */
  624.  
  625. void gbm_ht_pal_7R8G4B(GBMRGB *gbmrgb)
  626.     {
  627.     byte volatile r;    /* C-Set/2 optimiser fix */
  628.     byte volatile g;
  629.     byte volatile b;
  630.  
  631.     init();
  632.  
  633.     memset(gbmrgb, 0x80, 0x100 * sizeof(GBMRGB));
  634.     for ( r = 0; r < 7; r++ )
  635.         for ( g = 0; g < 8; g++ )
  636.             for ( b = 0; b < 4; b++ )
  637.                 {
  638.                 gbmrgb -> r = scale7 [r];
  639.                 gbmrgb -> g = scale8 [g];
  640.                 gbmrgb -> b = scale4 [b];
  641.                 gbmrgb++;
  642.                 }
  643.     }
  644. /*...e*/
  645. /*...sgbm_ht_7R8G4B_2x2 \45\ halftone by 2x2 to 7Rx8Gx4B palette:0:*/
  646. #define    PIX784(ri,gi,bi)    (byte) (((((ri)<<3)+(gi))<<2)+(bi))
  647.  
  648. void gbm_ht_7R8G4B_2x2(GBM *gbm, byte *src24, byte *dest8)
  649.     {
  650.     int stride24 = ((gbm -> w * 3 + 3) & ~3);
  651.     int stride8  = ((gbm -> w     + 3) & ~3);
  652.     int x, y;
  653.  
  654.     init();
  655.  
  656.     src24 -= stride24;
  657.     dest8 -= stride8;
  658.  
  659.     for ( y = 0; y < gbm -> h - 1; y += 2 )
  660.         {
  661.         byte *src24a = (src24 += stride24);
  662.         byte *src24b = (src24 += stride24);
  663.         byte *dest8a = (dest8 += stride8);
  664.         byte *dest8b = (dest8 += stride8);
  665.  
  666.         for ( x = 0; x < gbm -> w - 1; x += 2 )
  667. /*...s2x2 case:24:*/
  668. {
  669. word r,g,b;
  670. byte ri,gi,bi;
  671. byte *tmp;
  672.  
  673. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  674. b += *src24a++;    g += *src24a++;    r += *src24a++;
  675. b += *src24b++;    g += *src24b++;    r += *src24b++;
  676. b += *src24b++;    g += *src24b++;    r += *src24b++;
  677.  
  678. bi = index4 [div4(b)]; gi = index8 [div4(g)]; ri = index7 [div4(r)];
  679. *dest8a++ = PIX784(ri,gi,bi);
  680. b -= scale4 [bi]; g -= scale8 [gi]; r -= scale7 [ri];
  681.  
  682. bi = index4 [div3(b)]; gi = index8 [div3(g)]; ri = index7 [div3(r)];
  683. *dest8a++ = PIX784(ri,gi,bi);
  684. b -= scale4 [bi]; g -= scale8 [gi]; r -= scale7 [ri];
  685.  
  686. bi = index4 [div2(b)]; gi = index8 [div2(g)]; ri = index7 [div2(r)];
  687. *dest8b++ = PIX784(ri,gi,bi);
  688. b -= scale4 [bi]; g -= scale8 [gi]; r -= scale7 [ri];
  689.  
  690. bi = index4 [b      ]; gi = index8 [g      ]; ri = index7 [r      ];
  691. *dest8b++ = PIX784(ri,gi,bi);
  692.  
  693. tmp = dest8a; dest8a = dest8b; dest8b = tmp;
  694. }
  695. /*...e*/
  696.         if ( x < gbm -> w )
  697. /*...s1x2 case:24:*/
  698. {
  699. word r,g,b;
  700. byte ri, gi, bi;
  701.  
  702. b  = *src24a++;    g  = *src24a++;    r  = *src24a;
  703. b += *src24b++;    g += *src24b++;    r += *src24b;
  704.  
  705. bi = index4 [div2(b)]; gi = index8 [div2(g)]; ri = index7 [div2(r)];
  706. *dest8a = PIX784(ri,gi,bi);
  707. b -= scale4 [bi]; g -= scale8 [gi]; r -= scale7 [ri];
  708.  
  709. bi = index4 [b      ]; gi = index8 [g      ]; ri = index7 [r      ];
  710. *dest8b = PIX784(ri,gi,bi);
  711. }
  712. /*...e*/
  713.         }
  714.     if ( y < gbm -> h )
  715.         {
  716.         byte *src24a = src24 + stride24;
  717.         byte *dest8a = dest8 + stride8;
  718.  
  719.         for ( x = 0; x < gbm -> w - 1; x += 2 )
  720. /*...s2x1 case:24:*/
  721. {
  722. word r,g,b;
  723. byte ri, gi, bi;
  724.  
  725. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  726. b += *src24a++;    g += *src24a++;    r += *src24a++;
  727.  
  728. bi = index4 [div2(b)]; gi = index8 [div2(g)]; ri = index7 [div2(r)];
  729. *dest8a++ = PIX784(ri,gi,bi);
  730. b -= scale4 [bi]; g -= scale8 [gi]; r -= scale7 [ri];
  731.  
  732. bi = index4 [b      ]; gi = index8 [g      ]; ri = index7 [r      ];
  733. *dest8a++ = PIX784(ri,gi,bi);
  734. }
  735. /*...e*/
  736.         if ( x < gbm -> w )
  737. /*...s1x1 case:24:*/
  738. {
  739. byte ri, gi, bi;
  740.  
  741. bi = index4 [*src24a++]; gi = index8 [*src24a++]; ri = index7 [*src24a];
  742. *dest8a = PIX784(ri,gi,bi);
  743. }
  744. /*...e*/
  745.         }
  746.     }
  747. /*...e*/
  748.  
  749. /*...sgbm_ht_pal_VGA    \45\ return default VGA palette:0:*/
  750. /*
  751. This function makes the palette for the 16 colour VGA palette.
  752. */
  753.  
  754. void gbm_ht_pal_VGA(GBMRGB *gbmrgb)
  755.     {
  756.     init();
  757.     memcpy((char *) gbmrgb, (char *) gbmrgb_vga, sizeof(gbmrgb_vga));
  758.     }
  759. /*...e*/
  760. /*...sgbm_ht_VGA_2x2    \45\ halftone by 2x2 to default VGA palette:0:*/
  761. void gbm_ht_VGA_2x2(GBM *gbm, byte *src24, byte *dest4)
  762.     {
  763.     int stride24 = ((gbm -> w * 3 + 3) & ~3);
  764.     int stride4  = ((gbm -> w * 4 + 31) / 32) * 4;
  765.     int x, y;
  766.  
  767.     init();
  768.  
  769.     src24 -= stride24;
  770.     dest4 -= stride4;
  771.  
  772.     for ( y = 0; y < gbm -> h - 1; y += 2 )
  773.         {
  774.         byte *src24a = (src24 += stride24);
  775.         byte *src24b = (src24 += stride24);
  776.         byte *dest4a = (dest4 += stride4);
  777.         byte *dest4b = (dest4 += stride4);
  778.  
  779.         for ( x = 0; x < gbm -> w - 1; x += 2 )
  780. /*...s2x2 case:24:*/
  781. {
  782. word r,g,b;
  783. byte inx;
  784. byte *tmp;
  785.  
  786. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  787. b += *src24a++;    g += *src24a++;    r += *src24a++;
  788. b += *src24b++;    g += *src24b++;    r += *src24b++;
  789. b += *src24b++;    g += *src24b++;    r += *src24b++;
  790.  
  791. inx = takefrom(div4(r), div4(g), div4(b)); *dest4a    = (inx << 4);
  792. b -= gbmrgb_vga [inx].b; g -= gbmrgb_vga [inx].g; r -= gbmrgb_vga [inx].r;
  793.  
  794. inx = takefrom(div3(r), div3(g), div3(b)); *dest4a++ |= inx;
  795. b -= gbmrgb_vga [inx].b; g -= gbmrgb_vga [inx].g; r -= gbmrgb_vga [inx].r;
  796.  
  797. inx = takefrom(div2(r), div2(g), div2(b)); *dest4b    = (inx << 4);
  798. b -= gbmrgb_vga [inx].b; g -= gbmrgb_vga [inx].g; r -= gbmrgb_vga [inx].r;
  799.  
  800. inx = takefrom(r      , g      , b      ); *dest4b++ |= inx;
  801.  
  802. tmp = dest4a; dest4a = dest4b; dest4b = tmp;
  803. }
  804. /*...e*/
  805.         if ( x < gbm -> w )
  806. /*...s1x2 case:24:*/
  807. {
  808. word r,g,b;
  809. byte inx;
  810.  
  811. b  = *src24a++;    g  = *src24a++;    r  = *src24a;
  812. b += *src24b++;    g += *src24b++;    r += *src24b;
  813.  
  814. inx = takefrom(div2(r), div2(g), div2(b)); *dest4a = (inx << 4);
  815. b -= gbmrgb_vga [inx].b; g -= gbmrgb_vga [inx].g; r -= gbmrgb_vga [inx].r;
  816.  
  817. inx = takefrom(r      , g      , b      ); *dest4b = (inx << 4);
  818. }
  819. /*...e*/
  820.         }
  821.     if ( y < gbm -> h )
  822.         {
  823.         byte *src24a = src24 + stride24;
  824.         byte *dest4a = dest4 + stride4;
  825.  
  826.         for ( x = 0; x < gbm -> w - 1; x += 2 )
  827. /*...s2x1 case:24:*/
  828. {
  829. word r,g,b;
  830. byte inx;
  831.  
  832. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  833. b += *src24a++;    g += *src24a++;    r += *src24a++;
  834.  
  835. inx = takefrom(div2(r), div2(g), div2(b)); *dest4a = (inx << 4);
  836. b -= gbmrgb_vga [inx].b; g -= gbmrgb_vga [inx].g; r -= gbmrgb_vga [inx].r;
  837.  
  838. inx = takefrom(r      , g      , b      ); *dest4a++ |= inx;
  839. }
  840. /*...e*/
  841.         if ( x < gbm -> w )
  842. /*...s1x1 case:24:*/
  843. {
  844. word r, g, b;
  845. byte inx;
  846.  
  847. b = *src24a++; g = *src24a++; r = *src24a;
  848. inx = takefrom(r, g, b); *dest4a = (inx << 4);
  849. }
  850. /*...e*/
  851.         }
  852.     }
  853. /*...e*/
  854. /*...sgbm_ht_VGA_3x3    \45\ halftone by 3x3 to default VGA palette:0:*/
  855. void gbm_ht_VGA_3x3(GBM *gbm, byte *src24, byte *dest4)
  856.     {
  857.     int stride24 = ((gbm -> w * 3 + 3) & ~3);
  858.     int stride4  = ((gbm -> w * 4 + 31) / 32) * 4;
  859.     int x, y;
  860.  
  861.     init();
  862.  
  863.     src24 -= stride24;
  864.     dest4 -= stride4;
  865.  
  866.     for ( y = 0; y < gbm -> h - 2; y += 3 )
  867.         {
  868.         byte *src24a = (src24 += stride24);
  869.         byte *src24b = (src24 += stride24);
  870.         byte *src24c = (src24 += stride24);
  871.         byte *dest4a = (dest4 += stride4);
  872.         byte *dest4b = (dest4 += stride4);
  873.         byte *dest4c = (dest4 += stride4);
  874.         BOOLEAN left = TRUE;
  875.  
  876.         for ( x = 0; x < gbm -> w - 2; x += 3, left = !left )
  877. /*...s3x3 case:24:*/
  878. {
  879. word r,g,b;
  880. byte inxs [9];
  881. byte *tmp;
  882.  
  883. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  884. b += *src24a++;    g += *src24a++;    r += *src24a++;
  885. b += *src24a++;    g += *src24a++;    r += *src24a++;
  886. b += *src24b++;    g += *src24b++;    r += *src24b++;
  887. b += *src24b++;    g += *src24b++;    r += *src24b++;
  888. b += *src24b++;    g += *src24b++;    r += *src24b++;
  889. b += *src24c++;    g += *src24c++;    r += *src24c++;
  890. b += *src24c++;    g += *src24c++;    r += *src24c++;
  891. b += *src24c++;    g += *src24c++;    r += *src24c++;
  892.  
  893. split_into(r, g, b, 9, inxs);
  894.  
  895. if ( left )
  896.     {
  897.     *dest4a++ = ((inxs [0] << 4) | inxs [1]); *dest4a = (inxs [2] << 4);
  898.     *dest4b++ = ((inxs [3] << 4) | inxs [4]); *dest4b = (inxs [5] << 4);
  899.     *dest4c++ = ((inxs [6] << 4) | inxs [7]); *dest4c = (inxs [8] << 4);
  900.     }
  901. else
  902.     {
  903.     *dest4a++ |= inxs [0]; *dest4a++ = ((inxs [1] << 4) | inxs [2]);
  904.     *dest4b++ |= inxs [3]; *dest4b++ = ((inxs [4] << 4) | inxs [5]);
  905.     *dest4c++ |= inxs [6]; *dest4c++ = ((inxs [7] << 4) | inxs [8]);
  906.     }
  907.  
  908. tmp = dest4a; dest4a = dest4b; dest4b = dest4c; dest4c = tmp;
  909. }
  910. /*...e*/
  911.         if ( x < gbm -> w - 1 )
  912. /*...s2x3 case:24:*/
  913. {
  914. word r,g,b;
  915. byte inxs [6];
  916.  
  917. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  918. b += *src24a++;    g += *src24a++;    r += *src24a++;
  919. b += *src24b++;    g += *src24b++;    r += *src24b++;
  920. b += *src24b++;    g += *src24b++;    r += *src24b++;
  921. b += *src24c++;    g += *src24c++;    r += *src24c++;
  922. b += *src24c++;    g += *src24c++;    r += *src24c++;
  923.  
  924. split_into(r, g, b, 6, inxs);
  925.  
  926. if ( left )
  927.     {
  928.     *dest4a = ((inxs [0] << 4) | inxs [1]);
  929.     *dest4b = ((inxs [2] << 4) | inxs [3]);
  930.     *dest4c = ((inxs [4] << 4) | inxs [5]);
  931.     }
  932. else
  933.     {
  934.     *dest4a++ |= inxs [0]; *dest4a = (inxs [1] << 4);
  935.     *dest4b++ |= inxs [2]; *dest4b = (inxs [3] << 4);
  936.     *dest4c++ |= inxs [4]; *dest4c = (inxs [5] << 4);
  937.     }
  938. }
  939. /*...e*/
  940.         else if ( x < gbm -> w )
  941. /*...s1x3 case:24:*/
  942. {
  943. word r,g,b;
  944. byte inxs [3];
  945.  
  946. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  947. b += *src24b++;    g += *src24b++;    r += *src24b++;
  948. b += *src24c++;    g += *src24c++;    r += *src24c++;
  949.  
  950. split_into(r, g, b, 3, inxs);
  951.  
  952. if ( left )
  953.     {
  954.     *dest4a = (inxs [0] << 4);
  955.     *dest4b = (inxs [1] << 4);
  956.     *dest4c = (inxs [2] << 4);
  957.     }
  958. else
  959.     {
  960.     *dest4a |= inxs [0];
  961.     *dest4b |= inxs [1];
  962.     *dest4c |= inxs [2];
  963.     }
  964. }
  965. /*...e*/
  966.         }
  967.     if ( y < gbm -> h - 1 )
  968.         {
  969.         byte *src24a = (src24 += stride24);
  970.         byte *src24b = (src24 += stride24);
  971.         byte *dest4a = (dest4 += stride4);
  972.         byte *dest4b = (dest4 += stride4);
  973.         BOOLEAN left = TRUE;
  974.  
  975.         for ( x = 0; x < gbm -> w - 2; x += 3, left = !left )
  976. /*...s3x2 case:24:*/
  977. {
  978. word r,g,b;
  979. byte inxs [6];
  980. byte *tmp;
  981.  
  982. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  983. b += *src24a++;    g += *src24a++;    r += *src24a++;
  984. b += *src24a++;    g += *src24a++;    r += *src24a++;
  985. b += *src24b++;    g += *src24b++;    r += *src24b++;
  986. b += *src24b++;    g += *src24b++;    r += *src24b++;
  987. b += *src24b++;    g += *src24b++;    r += *src24b++;
  988.  
  989. split_into(r, g, b, 6, inxs);
  990.  
  991. if ( left )
  992.     {
  993.     *dest4a++ = (inxs [0] << 4) | inxs [1]; *dest4a = (inxs [2] << 4);
  994.     *dest4b++ = (inxs [3] << 4) | inxs [4]; *dest4b = (inxs [5] << 4);
  995.     }
  996. else
  997.     {
  998.     *dest4a++ |= inxs [0]; *dest4a++ = ((inxs [1] << 4) | inxs [2]);
  999.     *dest4b++ |= inxs [3]; *dest4b++ = ((inxs [4] << 4) | inxs [5]);
  1000.     }
  1001.  
  1002. tmp = dest4a; dest4a = dest4b; dest4b = tmp;
  1003. }
  1004. /*...e*/
  1005.         if ( x < gbm -> w - 1 )
  1006. /*...s2x2 case:24:*/
  1007. {
  1008. word r,g,b;
  1009. byte inxs [4];
  1010.  
  1011. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1012. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1013. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1014. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1015.  
  1016. split_into(r, g, b, 4, inxs);
  1017.  
  1018. if ( left )
  1019.     {
  1020.     *dest4a = ((inxs [0] << 4) | inxs [1]);
  1021.     *dest4b = ((inxs [2] << 4) | inxs [3]);
  1022.     }
  1023. else
  1024.     {
  1025.     *dest4a++ |= inxs [0]; *dest4a = (inxs [1] << 4);
  1026.     *dest4b++ |= inxs [2]; *dest4b = (inxs [3] << 4);
  1027.     }
  1028. }
  1029. /*...e*/
  1030.         else if ( x < gbm -> w )
  1031. /*...s1x2 case:24:*/
  1032. {
  1033. word r,g,b;
  1034. byte inxs [2];
  1035.  
  1036. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1037. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1038.  
  1039. split_into(r, g, b, 2, inxs);
  1040.  
  1041. if ( left )
  1042.     {
  1043.     *dest4a = (inxs [0] << 4);
  1044.     *dest4b = (inxs [1] << 4);
  1045.     }
  1046. else
  1047.     {
  1048.     *dest4a |= inxs [0];
  1049.     *dest4b |= inxs [1];
  1050.     }
  1051. }
  1052. /*...e*/
  1053.         }
  1054.     else if ( y < gbm -> h )
  1055.         {
  1056.         byte *src24a = (src24 += stride24);
  1057.         byte *dest4a = (dest4 += stride4);
  1058.         BOOLEAN left = TRUE;
  1059.  
  1060.         for ( x = 0; x < gbm -> w - 2; x += 3, left = !left )
  1061. /*...s3x1 case:24:*/
  1062. {
  1063. word r,g,b;
  1064. byte inxs [3];
  1065.  
  1066. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1067. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1068. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1069.  
  1070. split_into(r, g, b, 3, inxs);
  1071.  
  1072. if ( left )
  1073.     {
  1074.     *dest4a++ = ((inxs [0] << 4) | inxs [1]); *dest4a = (inxs [2] << 4);
  1075.     }
  1076. else
  1077.     {
  1078.     *dest4a++ |= inxs [0]; *dest4a++ = ((inxs [1] << 4) | inxs [2]);
  1079.     }
  1080. }
  1081. /*...e*/
  1082.         if ( x < gbm -> w - 1 )
  1083. /*...s2x1 case:24:*/
  1084. {
  1085. word r,g,b;
  1086. byte inxs [2];
  1087.  
  1088. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1089. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1090.  
  1091. split_into(r, g, b, 4, inxs);
  1092.  
  1093. if ( left )
  1094.     *dest4a = ((inxs [0] << 4) | inxs [1]);
  1095. else
  1096.     {
  1097.     *dest4a++ |= inxs [0]; *dest4a = (inxs [1] << 4);
  1098.     }
  1099. }
  1100. /*...e*/
  1101.         else if ( x < gbm -> w )
  1102. /*...s1x1 case:24:*/
  1103. {
  1104. word r,g,b;
  1105. byte inx;
  1106.  
  1107. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1108.  
  1109. inx = takefrom(r, g, b);
  1110.  
  1111. if ( left )
  1112.     *dest4a = (inx << 4);
  1113. else
  1114.     *dest4a |= inx;
  1115. }
  1116. /*...e*/
  1117.         }
  1118.     }
  1119. /*...e*/
  1120.  
  1121. /*...sgbm_ht_pal_8      \45\ return default 8 colour palette:0:*/
  1122. /*
  1123. This function makes the palette for the 8 colour palette.
  1124. */
  1125.  
  1126. void gbm_ht_pal_8(GBMRGB *gbmrgb)
  1127.     {
  1128.     init();
  1129.     memcpy((char *) gbmrgb, (char *) gbmrgb_8, sizeof(gbmrgb_8));
  1130.     }
  1131. /*...e*/
  1132. /*...sgbm_ht_8_2x2      \45\ halftone by 2x2 to default 8 colour palette:0:*/
  1133. void gbm_ht_8_2x2(GBM *gbm, byte *src24, byte *dest4)
  1134.     {
  1135.     int stride24 = ((gbm -> w * 3 + 3) & ~3);
  1136.     int stride4  = ((gbm -> w * 4 + 31) / 32) * 4;
  1137.     int x, y;
  1138.  
  1139.     init();
  1140.  
  1141.     src24 -= stride24;
  1142.     dest4 -= stride4;
  1143.  
  1144.     for ( y = 0; y < gbm -> h - 1; y += 2 )
  1145.         {
  1146.         byte *src24a = (src24 += stride24);
  1147.         byte *src24b = (src24 += stride24);
  1148.         byte *dest4a = (dest4 += stride4);
  1149.         byte *dest4b = (dest4 += stride4);
  1150.  
  1151.         for ( x = 0; x < gbm -> w - 1; x += 2 )
  1152. /*...s2x2 case:24:*/
  1153. {
  1154. word r,g,b;
  1155. byte inx;
  1156. byte *tmp;
  1157.  
  1158. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1159. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1160. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1161. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1162.  
  1163. inx = takefrom8(r >> 2, g >> 2, b >> 2); *dest4a    = (inx << 4);
  1164. b -= gbmrgb_8 [inx].b; g -= gbmrgb_8 [inx].g; r -= gbmrgb_8 [inx].r;
  1165.  
  1166. inx = takefrom8(r  / 3, g  / 3, b  / 3); *dest4a++ |= inx;
  1167. b -= gbmrgb_8 [inx].b; g -= gbmrgb_8 [inx].g; r -= gbmrgb_8 [inx].r;
  1168.  
  1169. inx = takefrom8(r >> 1, g >> 1, b >> 1); *dest4b    = (inx << 4);
  1170. b -= gbmrgb_8 [inx].b; g -= gbmrgb_8 [inx].g; r -= gbmrgb_8 [inx].r;
  1171.  
  1172. inx = takefrom8(r     , g     , b     ); *dest4b++ |= inx;
  1173.  
  1174. tmp = dest4a; dest4a = dest4b; dest4b = tmp;
  1175. }
  1176. /*...e*/
  1177.         if ( x < gbm -> w )
  1178. /*...s1x2 case:24:*/
  1179. {
  1180. word r,g,b;
  1181. byte inx;
  1182.  
  1183. b  = *src24a++;    g  = *src24a++;    r  = *src24a;
  1184. b += *src24b++;    g += *src24b++;    r += *src24b;
  1185.  
  1186. inx = takefrom8(r >> 1, g >> 1, b >> 1); *dest4a = (inx << 4);
  1187. b -= gbmrgb_8 [inx].b; g -= gbmrgb_8 [inx].g; r -= gbmrgb_8 [inx].r;
  1188.  
  1189. inx = takefrom8(r     , g     , b     ); *dest4b = (inx << 4);
  1190. }
  1191. /*...e*/
  1192.         }
  1193.     if ( y < gbm -> h )
  1194.         {
  1195.         byte *src24a = src24 + stride24;
  1196.         byte *dest4a = dest4 + stride4;
  1197.  
  1198.         for ( x = 0; x < gbm -> w - 1; x += 2 )
  1199. /*...s2x1 case:24:*/
  1200. {
  1201. word r,g,b;
  1202. byte inx;
  1203.  
  1204. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1205. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1206.  
  1207. inx = takefrom8(r >> 1, g >> 1, b >> 1); *dest4a    = (inx << 4);
  1208. b -= gbmrgb_8 [inx].b; g -= gbmrgb_8 [inx].g; r -= gbmrgb_8 [inx].r;
  1209.  
  1210. inx = takefrom8(r     , g     , b     ); *dest4a++ |= inx;
  1211. }
  1212. /*...e*/
  1213.         if ( x < gbm -> w )
  1214. /*...s1x1 case:24:*/
  1215. {
  1216. word r, g, b;
  1217. byte inx;
  1218.  
  1219. b = *src24a++; g = *src24a++; r = *src24a;
  1220. inx = takefrom8(r, g, b); *dest4a = (inx << 4);
  1221. }
  1222. /*...e*/
  1223.         }
  1224.     }
  1225. /*...e*/
  1226. /*...sgbm_ht_8_3x3      \45\ halftone by 3x3 to default 8 colour palette:0:*/
  1227. void gbm_ht_8_3x3(GBM *gbm, byte *src24, byte *dest4)
  1228.     {
  1229.     int stride24 = ((gbm -> w * 3 + 3) & ~3);
  1230.     int stride4  = ((gbm -> w * 4 + 31) / 32) * 4;
  1231.     int x, y;
  1232.  
  1233.     init();
  1234.  
  1235.     src24 -= stride24;
  1236.     dest4 -= stride4;
  1237.  
  1238.     for ( y = 0; y < gbm -> h - 2; y += 3 )
  1239.         {
  1240.         byte *src24a = (src24 += stride24);
  1241.         byte *src24b = (src24 += stride24);
  1242.         byte *src24c = (src24 += stride24);
  1243.         byte *dest4a = (dest4 += stride4);
  1244.         byte *dest4b = (dest4 += stride4);
  1245.         byte *dest4c = (dest4 += stride4);
  1246.         BOOLEAN left = TRUE;
  1247.  
  1248.         for ( x = 0; x < gbm -> w - 2; x += 3, left = !left )
  1249. /*...s3x3 case:24:*/
  1250. {
  1251. word r,g,b;
  1252. byte inxs [9];
  1253. byte *tmp;
  1254.  
  1255. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1256. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1257. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1258. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1259. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1260. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1261. b += *src24c++;    g += *src24c++;    r += *src24c++;
  1262. b += *src24c++;    g += *src24c++;    r += *src24c++;
  1263. b += *src24c++;    g += *src24c++;    r += *src24c++;
  1264.  
  1265. split_into8(r, g, b, 9, inxs);
  1266.  
  1267. if ( left )
  1268.     {
  1269.     *dest4a++ = ((inxs [0] << 4) | inxs [1]); *dest4a = (inxs [2] << 4);
  1270.     *dest4b++ = ((inxs [3] << 4) | inxs [4]); *dest4b = (inxs [5] << 4);
  1271.     *dest4c++ = ((inxs [6] << 4) | inxs [7]); *dest4c = (inxs [8] << 4);
  1272.     }
  1273. else
  1274.     {
  1275.     *dest4a++ |= inxs [0]; *dest4a++ = ((inxs [1] << 4) | inxs [2]);
  1276.     *dest4b++ |= inxs [3]; *dest4b++ = ((inxs [4] << 4) | inxs [5]);
  1277.     *dest4c++ |= inxs [6]; *dest4c++ = ((inxs [7] << 4) | inxs [8]);
  1278.     }
  1279.  
  1280. tmp = dest4a; dest4a = dest4b; dest4b = dest4c; dest4c = tmp;
  1281. }
  1282. /*...e*/
  1283.         if ( x < gbm -> w - 1 )
  1284. /*...s2x3 case:24:*/
  1285. {
  1286. word r,g,b;
  1287. byte inxs [6];
  1288.  
  1289. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1290. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1291. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1292. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1293. b += *src24c++;    g += *src24c++;    r += *src24c++;
  1294. b += *src24c++;    g += *src24c++;    r += *src24c++;
  1295.  
  1296. split_into8(r, g, b, 6, inxs);
  1297.  
  1298. if ( left )
  1299.     {
  1300.     *dest4a = ((inxs [0] << 4) | inxs [1]);
  1301.     *dest4b = ((inxs [2] << 4) | inxs [3]);
  1302.     *dest4c = ((inxs [4] << 4) | inxs [5]);
  1303.     }
  1304. else
  1305.     {
  1306.     *dest4a++ |= inxs [0]; *dest4a = (inxs [1] << 4);
  1307.     *dest4b++ |= inxs [2]; *dest4b = (inxs [3] << 4);
  1308.     *dest4c++ |= inxs [4]; *dest4c = (inxs [5] << 4);
  1309.     }
  1310. }
  1311. /*...e*/
  1312.         else if ( x < gbm -> w )
  1313. /*...s1x3 case:24:*/
  1314. {
  1315. word r,g,b;
  1316. byte inxs [3];
  1317.  
  1318. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1319. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1320. b += *src24c++;    g += *src24c++;    r += *src24c++;
  1321.  
  1322. split_into8(r, g, b, 3, inxs);
  1323.  
  1324. if ( left )
  1325.     {
  1326.     *dest4a = (inxs [0] << 4);
  1327.     *dest4b = (inxs [1] << 4);
  1328.     *dest4c = (inxs [2] << 4);
  1329.     }
  1330. else
  1331.     {
  1332.     *dest4a |= inxs [0];
  1333.     *dest4b |= inxs [1];
  1334.     *dest4c |= inxs [2];
  1335.     }
  1336. }
  1337. /*...e*/
  1338.         }
  1339.     if ( y < gbm -> h - 1 )
  1340.         {
  1341.         byte *src24a = (src24 += stride24);
  1342.         byte *src24b = (src24 += stride24);
  1343.         byte *dest4a = (dest4 += stride4);
  1344.         byte *dest4b = (dest4 += stride4);
  1345.         BOOLEAN left = TRUE;
  1346.  
  1347.         for ( x = 0; x < gbm -> w - 2; x += 3, left = !left )
  1348. /*...s3x2 case:24:*/
  1349. {
  1350. word r,g,b;
  1351. byte inxs [6];
  1352. byte *tmp;
  1353.  
  1354. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1355. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1356. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1357. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1358. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1359. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1360.  
  1361. split_into8(r, g, b, 6, inxs);
  1362.  
  1363. if ( left )
  1364.     {
  1365.     *dest4a++ = (inxs [0] << 4) | inxs [1]; *dest4a = (inxs [2] << 4);
  1366.     *dest4b++ = (inxs [3] << 4) | inxs [4]; *dest4b = (inxs [5] << 4);
  1367.     }
  1368. else
  1369.     {
  1370.     *dest4a++ |= inxs [0]; *dest4a++ = ((inxs [1] << 4) | inxs [2]);
  1371.     *dest4b++ |= inxs [3]; *dest4b++ = ((inxs [4] << 4) | inxs [5]);
  1372.     }
  1373.  
  1374. tmp = dest4a; dest4a = dest4b; dest4b = tmp;
  1375. }
  1376. /*...e*/
  1377.         if ( x < gbm -> w - 1 )
  1378. /*...s2x2 case:24:*/
  1379. {
  1380. word r,g,b;
  1381. byte inxs [4];
  1382.  
  1383. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1384. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1385. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1386. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1387.  
  1388. split_into8(r, g, b, 4, inxs);
  1389.  
  1390. if ( left )
  1391.     {
  1392.     *dest4a = ((inxs [0] << 4) | inxs [1]);
  1393.     *dest4b = ((inxs [2] << 4) | inxs [3]);
  1394.     }
  1395. else
  1396.     {
  1397.     *dest4a++ |= inxs [0]; *dest4a = (inxs [1] << 4);
  1398.     *dest4b++ |= inxs [2]; *dest4b = (inxs [3] << 4);
  1399.     }
  1400. }
  1401. /*...e*/
  1402.         else if ( x < gbm -> w )
  1403. /*...s1x2 case:24:*/
  1404. {
  1405. word r,g,b;
  1406. byte inxs [2];
  1407.  
  1408. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1409. b += *src24b++;    g += *src24b++;    r += *src24b++;
  1410.  
  1411. split_into8(r, g, b, 2, inxs);
  1412.  
  1413. if ( left )
  1414.     {
  1415.     *dest4a = (inxs [0] << 4);
  1416.     *dest4b = (inxs [1] << 4);
  1417.     }
  1418. else
  1419.     {
  1420.     *dest4a |= inxs [0];
  1421.     *dest4b |= inxs [1];
  1422.     }
  1423. }
  1424. /*...e*/
  1425.         }
  1426.     else if ( y < gbm -> h )
  1427.         {
  1428.         byte *src24a = (src24 += stride24);
  1429.         byte *dest4a = (dest4 += stride4);
  1430.         BOOLEAN left = TRUE;
  1431.  
  1432.         for ( x = 0; x < gbm -> w - 2; x += 3, left = !left )
  1433. /*...s3x1 case:24:*/
  1434. {
  1435. word r,g,b;
  1436. byte inxs [3];
  1437.  
  1438. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1439. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1440. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1441.  
  1442. split_into8(r, g, b, 3, inxs);
  1443.  
  1444. if ( left )
  1445.     {
  1446.     *dest4a++ = ((inxs [0] << 4) | inxs [1]); *dest4a = (inxs [2] << 4);
  1447.     }
  1448. else
  1449.     {
  1450.     *dest4a++ |= inxs [0]; *dest4a++ = ((inxs [1] << 4) | inxs [2]);
  1451.     }
  1452. }
  1453. /*...e*/
  1454.         if ( x < gbm -> w - 1 )
  1455. /*...s2x1 case:24:*/
  1456. {
  1457. word r,g,b;
  1458. byte inxs [2];
  1459.  
  1460. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1461. b += *src24a++;    g += *src24a++;    r += *src24a++;
  1462.  
  1463. split_into8(r, g, b, 4, inxs);
  1464.  
  1465. if ( left )
  1466.     *dest4a = ((inxs [0] << 4) | inxs [1]);
  1467. else
  1468.     {
  1469.     *dest4a++ |= inxs [0]; *dest4a = (inxs [1] << 4);
  1470.     }
  1471. }
  1472. /*...e*/
  1473.         else if ( x < gbm -> w )
  1474. /*...s1x1 case:24:*/
  1475. {
  1476. word r,g,b;
  1477. byte inx;
  1478.  
  1479. b  = *src24a++;    g  = *src24a++;    r  = *src24a++;
  1480.  
  1481. inx = takefrom8(r, g, b);
  1482.  
  1483. if ( left )
  1484.     *dest4a = (inx << 4);
  1485. else
  1486.     *dest4a |= inx;
  1487. }
  1488. /*...e*/
  1489.         }
  1490.     }
  1491. /*...e*/
  1492.