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