home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / x11 / lib2 / to_8.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-02  |  7.1 KB  |  264 lines

  1. /*    TO_8 . C
  2. #
  3. %    little slow but can handle both ILL & ILC in one
  4. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  5.  
  6. This software is copyright (C) by the Lawrence Berkeley Laboratory.
  7. Permission is granted to reproduce this software for non-commercial
  8. purposes provided that this notice is left intact.
  9.  
  10. It is acknowledged that the U.S. Government has rights to this software
  11. under Contract DE-AC03-765F00098 between the U.S.  Department of Energy
  12. and the University of California.
  13.  
  14. This software is provided as a professional and academic contribution
  15. for joint exchange. Thus, it is experimental, and is provided ``as is'',
  16. with no warranties of any kind whatsoever, no support, no promise of
  17. updates, or printed documentation. By using this software, you
  18. acknowledge that the Lawrence Berkeley Laboratory and Regents of the
  19. University of California shall have no liability with respect to the
  20. infringement of other copyrights by any part of this software.
  21.  
  22. For further information about this notice, contact William Johnston,
  23. Bld. 50B, Rm. 2239, Lawrence Berkeley Laboratory, Berkeley, CA, 94720.
  24. (wejohnston@lbl.gov)
  25.  
  26. For further information about this software, contact:
  27.     Jin Guojun
  28.     Bld. 50B, Rm. 2275, Lawrence Berkeley Laboratory, Berkeley, CA, 94720.
  29.     g_jin@lbl.gov
  30.  
  31. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  32. %
  33. % AUTHOR:    Jin Guojun - LBL
  34. */
  35.  
  36. #include "header.def"
  37. #include "imagedef.h"
  38.  
  39. #define    RED    0
  40. #define    GREEN    1
  41. #define    BLUE    2
  42. #define    ADJ_BTM_RIGHT    0
  43. #define    ADJ_BTM_LEFT    1
  44. #define    ADJ_BOTTOM    2
  45. #define    ADJ_NEXT    3
  46. #define truncate(a, b, c)    ((a<b) ? a=b : (a>c) ? a=c : a)
  47.  
  48. static    byte    fsb_table[4][MaxColors];
  49. static    int    TrueCheck(), dither_to8();
  50.  
  51. To_8(img, rg_cmap, quant, nc)
  52. U_IMAGE    *img;
  53. cmap_t    *rg_cmap[];
  54. {
  55. VType    *tbuf = nzalloc(img->width, img->height, "to_8");
  56.  
  57. if (verify_buffer_size(rg_cmap, img->cmaplen=MaxColors, 3*sizeof(rg_cmap[0]),
  58.         "to_8-cmap"))
  59.     rg_cmap[1] = rg_cmap[0] + MaxColors,
  60.     rg_cmap[2] = rg_cmap[1] + MaxColors;
  61.  
  62. if (TrueCheck(rg_cmap, img->src, tbuf, img->width, img->height, nc,
  63.         img->color_form == CFM_ILL))
  64. #ifdef    QUANTIZING_TO_8
  65.     if (quant)
  66.     quant = quant_to_8(img, img->cmaplen=nc, rg_cmap, tbuf);
  67.     else
  68. #endif
  69.     /* for raw input, set img->color_form = img->in_color    */
  70.     quant = dither_to8(img->src, tbuf, img->width, img->height,
  71.             img->color_form == CFM_ILL, rg_cmap);
  72.  
  73. img->color_form = CFM_SCF;
  74. img->in_form = IFMT_SCF;
  75. img->channels = img->mono_img = 1;
  76. free(img->src);
  77. img->src = tbuf;
  78. return    quant;
  79. }
  80.  
  81. void
  82. init_FS_tables(rg_cmap)    /* initialize Floyd-Steinberg tables */
  83. cmap_t    *rg_cmap[];
  84. {
  85. register int    i=MaxColors;
  86.     while (i--) {
  87.         fsb_table[ADJ_BTM_RIGHT][i] = i >> 4;
  88.         fsb_table[ADJ_BTM_LEFT][i] = 3*i >> 4;
  89.         fsb_table[ADJ_BOTTOM][i] = 5*i >> 4;
  90.         fsb_table[ADJ_NEXT][i] = 7*i >> 4;
  91.         if (!rg_cmap)    continue;
  92.         /* build colormap (RRRGGGBB)    */
  93.         rg_cmap[RED][i] =  ((i&0xE0) * 255) / 0xE0;
  94.         rg_cmap[GREEN][i]= ((i&0x1C) * 255) / 0x1C;
  95.         rg_cmap[BLUE][i] = ((i&0x03) * 255) / 0x03;
  96.     }
  97. }
  98.  
  99. static
  100. dither_to8(rgbp, obuf, w, h, is_rle, rg_cmap)
  101. byte    *rgbp, *obuf;
  102. int    w, h, is_rle;
  103. cmap_t    *rg_cmap[];
  104. {
  105. byte    *pp = obuf;
  106. int    pinc, rnext, gnext, bnext, rleft, gleft, bleft, rright, gright, bright;
  107. int    *line1, *line2;
  108. int    i, j, rerr, gerr, berr, rgb_width = w * 3;
  109. int    imax = h-1, jmax = w-1;
  110. register int    *cur_p, *dither_p, dr, dg, db;
  111.  
  112.     init_FS_tables(rg_cmap);
  113.  
  114.     /* floyd-steinberg dithering.
  115.     %
  116.     % no-effect    x    + 7/16*err
  117.     % +3/16*err  +5/16*err    + 1/16*err
  118.     %
  119.     %    err = x mod (2 ** bits)
  120.     */
  121.  
  122.     line1 = (int *) nzalloc(rgb_width, sizeof(*line1));
  123.     line2 = (int *) nzalloc(rgb_width, sizeof(*line2));
  124.  
  125.     rnext = 0;
  126.     if (is_rle)    {
  127.         pinc = 1;    gnext = rnext + w;    bnext = gnext + w;
  128.         rleft = -1;    gleft = gnext + rleft;    bleft = bnext + rleft;
  129.         rright = 1;    gright = gnext+rright;    bright = bnext+rright;
  130.     } else    {
  131.         pinc = 3;    gnext = 1;    bnext = 2;
  132.         rleft = -3;    gleft = -2;    bleft = -1;
  133.         rright = 3;    gright = 4;    bright = 5;
  134.     }
  135.  
  136.     /*    convert first line to int    */
  137.     for (j=rgb_width, cur_p=line1; j--;)
  138.         *cur_p++ = *rgbp++;
  139.  
  140.     for (i=0; i<h; i++) {
  141.  
  142.         if (i<imax)   /* convert next line */
  143.         for (j=rgb_width, cur_p=line2; j--;)
  144.             *cur_p++ = *rgbp++;
  145.  
  146.         for (j=0, cur_p=line1, dither_p=line2; j<w; j++) {
  147.         dr = cur_p[rnext];
  148.         dg = cur_p[gnext];
  149.         db = cur_p[bnext];
  150.         cur_p += pinc;
  151.         truncate(dr,0,255);  truncate(dg,0,255);  truncate(db,0,255);
  152.         rerr = dr & 0x1F;  gerr = dg & 0x1F;  berr = db & 0x3F;
  153.  
  154.         *pp++ = dr & 0xE0 | (dg>>3) & 0x1C | (db>>6);
  155.  
  156.         if (j<jmax) {
  157.             cur_p[rnext] += fsb_table[ADJ_NEXT][rerr];
  158.             cur_p[gnext] += fsb_table[ADJ_NEXT][gerr];
  159.             cur_p[bnext] += fsb_table[ADJ_NEXT][berr];
  160.         }
  161.  
  162.         if (i<imax) {
  163.             dither_p[rnext] += fsb_table[ADJ_BOTTOM][rerr];
  164.             dither_p[gnext] += fsb_table[ADJ_BOTTOM][gerr];
  165.             dither_p[bnext] += fsb_table[ADJ_BOTTOM][berr];
  166.  
  167.             if (j) {
  168.             dither_p[rleft] += fsb_table[ADJ_BTM_LEFT][rerr];
  169.             dither_p[gleft] += fsb_table[ADJ_BTM_LEFT][gerr];
  170.             dither_p[bleft] += fsb_table[ADJ_BTM_LEFT][berr];
  171.             }
  172.  
  173.             if (j<jmax) {
  174.             dither_p[rright] += fsb_table[ADJ_BTM_RIGHT][rerr];
  175.             dither_p[gright] += fsb_table[ADJ_BTM_RIGHT][gerr];
  176.             dither_p[bright] += fsb_table[ADJ_BTM_RIGHT][berr];
  177.             }
  178.             dither_p += pinc;
  179.         }
  180.         }
  181.     /*    line1 ^= line2;  line2 ^= line1;  line1 ^= line2;    */
  182.     cur_p = line1;    line1 = line2;    line2 = cur_p;
  183.     }
  184. free(line1);    free(line2);
  185. return    0;
  186. }
  187.  
  188. static
  189. TrueCheck(rg_cmap, rgbp, obuf, iw, ih, maxcol, is_rle)
  190. cmap_t    *rg_cmap[];
  191. byte    *rgbp, *obuf;
  192. {
  193. longword    colors[MaxColors],col;
  194. int    i, j, nc, low, high, mid, pinc=1;
  195. byte    *pr, *pg, *pb=rgbp, *pix;
  196.  
  197.     if (maxcol>MaxColors)    maxcol = MaxColors;
  198.  
  199.     if (!is_rle)
  200.         pr = pb,    pg = pr + 1,    pb = pg + 1,    pinc = 3;
  201.     for (nc=mid=0, i=ih; i--;) {
  202.         if (is_rle)
  203.         pr = pb,    pg = pr + iw,    pb = pg + iw;
  204.         for (j=iw; j--;)    {
  205.         col = *pr << 16;    pr += pinc;
  206.         col += *pg << 8;    pg += pinc;
  207.         col += *pb;    pb += pinc;
  208.  
  209.         /* binary search the 'colors' array to see if it's in there */
  210.         low = 0;    high = nc-1;
  211.         while (low <= high) {
  212.             mid = low + high >> 1;
  213.             if (col < colors[mid]) high = mid - 1;
  214.             else if (col > colors[mid]) low  = mid + 1;
  215.             else    break;
  216.         }
  217.  
  218.         if (high < low) { /* if not in list, add it in */
  219.             if (nc >= maxcol)    return    1;
  220.             /*    do overlapped copy    */
  221. #    ifdef    NO_BCOPY
  222.             for (high=nc; high>low; high--)
  223.                 colors[high] = colors[high-1];
  224. #    else
  225.             bcopy(colors+low, colors+low+1, (nc-low) * sizeof(*colors));
  226. #    endif
  227.             colors[low] = col;
  228.             nc++;
  229.         }
  230.         }
  231.     }
  232.  
  233.     /* run through the data a 2nd time to convert to 8    */
  234.     pb = rgbp;
  235.     if (!is_rle)
  236.         pr = pb,    pg = pr + 1,    pb = pg + 1;
  237.     for (i=ih, pix=obuf; i--;) {
  238.         if (is_rle)
  239.         pr = pb,    pg = pr + iw,    pb = pg + iw;
  240.         for (j=iw; j--;)    {
  241.         col = *pr << 16;    col += *pg << 8;    col += *pb;
  242.         pr += pinc;    pg += pinc;    pb += pinc;
  243.  
  244.         low = 0;    high = nc-1;
  245.         while (low <= high) {
  246.             mid = low + high >> 1;
  247.             if (col < colors[mid]) high = mid - 1;
  248.             else if (col > colors[mid]) low  = mid + 1;
  249.             else    break;
  250.         }
  251.         if (high < low)
  252.             prgmerr(DEBUGANY, "TrueColor Check: double entry");
  253.         *pix++ = mid;    /* set output */
  254.         }
  255.     }
  256.  
  257.     for (i=nc; i--;) {    /* set colormap */
  258.         rg_cmap[RED][i] =  (colors[i]>>16) & 0xFF;
  259.         rg_cmap[GREEN][i] = (colors[i]>>8) & 0xFF;
  260.         rg_cmap[BLUE][i] =  colors[i] & 0xFF;
  261.     }
  262. return    0;
  263. }
  264.