home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / formats / gif / gen_code / median.c < prev    next >
Encoding:
Internet Message Format  |  1988-05-26  |  28.4 KB

  1. From: falk@sun.uucp (Ed Falk)
  2. Subject: Re: 24bitcolor --> 8bit colormap
  3. Date: 26 Mar 88 02:12:04 GMT
  4.  
  5. In article <221@abvax.UUCP>, gfs@abvax.UUCP (Greg F. Shay) writes:
  6. > Relating to the question of how to choose a 256 entry colormap to best
  7. > represent a 24bit full color image, the algorithm to use was published
  8. > by Paul Heckbert in the following:
  9. >     "Color image quantization for frame buffer display," SIGGRAPH 1982
  10. > Proceedings, pp.297-307.
  11.  
  12. OK, since everybody else wants to show how they do it, I'll submit
  13. my own work.
  14.  
  15. This is my implementation of the median cut algorithm.  It does all of
  16. the optimizations suggested by Heckbert in his paper.  It will dither
  17. a 1152x900x24  image in 1.5 minutes.  Floyd-Steinberg dithering is
  18. available as an option.   You can choose the size of your target color-table
  19. to be anything you want.
  20.  
  21. This should not be too hard to port to other image formats besides the
  22. sun rasterfile format.
  23.  
  24. I have made a couple of improvements over the original algorithm.  In this
  25. version, the subdivision is always performed based on the largest box
  26. rather than arbitrarily dividing them all down.
  27.  
  28. Issues:  these are some improvements I've been meaning to make, but haven't
  29. gotten around to it:
  30.  
  31. Currently, the largest box is chosen based purely on its
  32. volume r*g*b.  This should be biased according to perceptual rules.
  33.  
  34.     volume = r*.3 + g*.59 + b*.11
  35.  
  36. this may produce a better image.
  37.  
  38. Also, gamma-correction should be applied on the output, and inversely on the
  39. input.
  40.  
  41. Dithering remains a problem.  Dithering only works if you have two values
  42. to dither between.  For instance, if you're dithering a blue field, and you
  43. only have one shade of blue in the color table, and the nearest other color
  44. is white, then a slightly lighter area of blue will produce blue with
  45. undesirable white specs in the middle of it.  We need a method of either
  46. making sure the color table contains reasonable bracketing or of making
  47. sure that the accumulated error in F-S dithering does not go beyond a
  48. certain limit.
  49.  
  50. Many images look better *without* dithering, try it both ways.
  51.  
  52.     -ed falk, falk@sun
  53.  
  54.  
  55. ==================================
  56. /* quantize stuff:
  57.  *
  58.  * median [-csize n] [-fsd] [ifile [ofile]]
  59.  *
  60.  * -csize n    - set colortable size.  Default is 256.
  61.  * -fsd        - use Floyd-Steinberg dithering.
  62.  *
  63.  */
  64.  
  65.  
  66. #include <stdio.h>
  67. #include <sys/types.h>
  68. #include <pixrect/pixrect_hs.h>
  69.  
  70. #define    MAX_CMAP_SIZE    256
  71.  
  72. #define    COLOR_DEPTH    8
  73. #define    MAX_COLOR    256
  74.  
  75. #define    B_DEPTH        5        /* # bits/pixel to use */
  76. #define    B_LEN        (1<<B_DEPTH)
  77.  
  78. #define    C_DEPTH        2
  79. #define    C_LEN        (1<<C_DEPTH)    /* # cells/color to use */
  80.  
  81.  
  82.  
  83. typedef    struct colorbox {
  84.       struct colorbox    *next, *prev ;
  85.       int            rmin,rmax, gmin,gmax, bmin,bmax ;
  86.       int            total ;
  87.     } Colorbox ;
  88.  
  89. typedef struct {
  90.       int    num_ents ;
  91.       int    entries[MAX_CMAP_SIZE][2] ;
  92.     } C_cell ;
  93.  
  94. static    struct rasterfile    rh;
  95. static    colormap_t        colormap, ocmap ;
  96. static    unsigned char        rm[MAX_CMAP_SIZE],
  97.                 gm[MAX_CMAP_SIZE],
  98.                 bm[MAX_CMAP_SIZE] ;
  99. static    int            bytes_per_pixel ;
  100. static    int            num_colors ;
  101.  
  102. static    int            histogram[B_LEN][B_LEN][B_LEN] ;
  103.  
  104. static    Colorbox        *freeboxes ;
  105. static    Colorbox        *usedboxes ;
  106. static    Colorbox        *largest_box() ;
  107.  
  108. static    C_cell            **ColorCells ;
  109.  
  110.  
  111. static    char    *usage =
  112. "usage: median [-csize n] [-fsd] [ifile [ofile]]\n" ;
  113.  
  114.  
  115. main(argc, argv)
  116.     int argc;
  117.     char **argv;
  118. {
  119. static    struct rasterfile    outheader ;
  120.     int            i, j ;
  121.     int            dither = 0 ;
  122.     char            *ifile_name = NULL, *ofile_name = NULL ;
  123.     Colorbox        *box_list, *ptr ;
  124.  
  125.     num_colors = MAX_CMAP_SIZE ;
  126.  
  127.     while(--argc)
  128.     {
  129.       ++argv ;
  130.       if(strcmp(*argv,"-fsd") == 0)
  131.         dither = 1 ;
  132.  
  133.       else if(strcmp(*argv,"-csize") == 0)
  134.       {
  135.         if(argc < 2)
  136.         {
  137.           fprintf(stderr,"-csize requires 2 arguments, %s",usage) ;
  138.           exit(1) ;
  139.         }
  140.         else
  141.         {
  142.           argc -= 1 ;
  143.           num_colors = atoi(*++argv) ;
  144.           if(num_colors > MAX_CMAP_SIZE)
  145.           {
  146.         fprintf(stderr,"-csize specifies colormap greater than %d\n%s",
  147.             MAX_CMAP_SIZE,usage) ;
  148.         exit(1) ;
  149.           }
  150.         }
  151.       }
  152.  
  153.       else if(**argv == '-')
  154.       {
  155.         fprintf(stderr,"unknown argument '%s'\n%s",*argv,usage) ;
  156.         exit(1) ;
  157.       }
  158.  
  159.       else if(!ifile_name)
  160.       {
  161.         ifile_name = *argv ;
  162.       }
  163.  
  164.       else if(!ofile_name)
  165.       {
  166.         ofile_name = *argv ;
  167.       }
  168.  
  169.       else
  170.       {
  171.         fprintf(stderr, "Too many file names\n%s",usage) ;
  172.         exit(1) ;
  173.       }
  174.     }
  175.  
  176.     if(ifile_name)
  177.       if (freopen(ifile_name, "r", stdin) == NULL)
  178.       {
  179.         fprintf(stderr,"Cannot open input file %s\n%s", ifile_name,usage);
  180.         exit(1);
  181.       }
  182.  
  183.     if(ofile_name)
  184.       if (freopen(ofile_name, "w", stdout) == NULL)
  185.       {
  186.         fprintf(stderr,"Cannot open output file %s\n%s", ofile_name,usage);
  187.         exit(1);
  188.       }
  189.  
  190.  
  191.     if (pr_load_header(stdin, &rh) != 0  ||
  192.         pr_load_colormap(stdin, &rh, &colormap) != 0 )
  193.     {
  194.       fprintf(stderr,"Error reading rasterfile header.\n");
  195.       exit(1);
  196.     }
  197.  
  198.  
  199.  
  200.     switch( rh.ras_depth )
  201.     {
  202.       case 24: bytes_per_pixel = 3 ; break ;
  203.       case 32: bytes_per_pixel = 4 ; break ;
  204.       default:
  205.         fprintf(stderr,
  206.             "Image is %d bits deep, median only works with 24 or 32\n");
  207.         exit(1) ;
  208.     }
  209.  
  210.  
  211.     /*
  212.      * STEP 1:  create empty boxes
  213.      */
  214.  
  215.     usedboxes = NULL ;
  216.     box_list = freeboxes =
  217.         (Colorbox *) malloc( num_colors * sizeof(Colorbox) ) ;
  218.  
  219.     freeboxes[0].next = &freeboxes[1] ;
  220.     freeboxes[0].prev = NULL ;
  221.     for(i=1; i<num_colors-1; ++i)
  222.     {
  223.       freeboxes[i].next = &freeboxes[i+1] ;
  224.       freeboxes[i].prev = &freeboxes[i-1] ;
  225.     }
  226.     freeboxes[num_colors-1].next = NULL ;
  227.     freeboxes[num_colors-1].prev = &freeboxes[num_colors-2] ;
  228.  
  229.  
  230.  
  231.     /*
  232.      * STEP 2: get histogram, initialize first box
  233.      */
  234.  
  235.     ptr = freeboxes ;
  236.     freeboxes = ptr->next ;
  237.     if(freeboxes) freeboxes->prev = NULL ;
  238.  
  239.     ptr->next = usedboxes ;
  240.     usedboxes = ptr ;
  241.     if(ptr->next) ptr->next->prev = ptr ;
  242.     
  243.     get_histogram(ptr) ;
  244.  
  245.     if( fseek(stdin, 0L, 0) != 0)
  246.     {
  247.       fprintf(stderr, "median: input must be from file\n") ;
  248.       exit(1) ;
  249.     }
  250.  
  251.  
  252.  
  253.     /*
  254.      * STEP 3: continually subdivide boxes until no more free
  255.      * boxes remain
  256.      */
  257.  
  258.     while(freeboxes != NULL)
  259.     {
  260.       ptr = largest_box() ;
  261.       splitbox(ptr) ;
  262.     }
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.     /*
  270.      * STEP 4: assign colors to all boxes
  271.      */
  272.  
  273.     for(i=0, ptr=usedboxes; i<num_colors; ++i, ptr=ptr->next)
  274.       assign_color(ptr,&rm[i],&gm[i],&bm[i]) ;
  275.  
  276.     /* We're done with the boxes now */
  277.  
  278.     free(box_list) ;
  279.     box_list = freeboxes = usedboxes = NULL ;
  280.  
  281.  
  282.  
  283.  
  284.     /*
  285.      * STEP 5: scan histogram and map all values to closest color
  286.      */
  287.  
  288.     /* 5a: create cell list as described in Heckbert[2] */
  289.  
  290.     {
  291.       register C_cell    **ptr ;
  292.       register int        n = C_LEN*C_LEN*C_LEN ;
  293.  
  294.       ptr = ColorCells =
  295.         (C_cell **) malloc(C_LEN*C_LEN*C_LEN * sizeof(C_cell *));
  296.  
  297.       while( n-- > 0 )
  298.         *ptr++ = NULL ;
  299.     }
  300.  
  301.  
  302.  
  303.  
  304.     /* 5b: create mapping from truncated pixel space to color
  305.        table entries */
  306.  
  307.     map_colortable() ;
  308.  
  309.  
  310.  
  311.  
  312.  
  313.     /*
  314.      * STEP 6: scan image, match input values to table entries
  315.      */
  316.  
  317.     pr_load_header(stdin, &rh) ;
  318.     pr_load_colormap(stdin, &rh, &colormap) ;
  319.     pr_read_init(&rh) ;
  320.  
  321.     outheader.ras_magic = RAS_MAGIC ;
  322.     outheader.ras_width = rh.ras_width ;
  323.     outheader.ras_height = rh.ras_height ;
  324.     outheader.ras_depth = COLOR_DEPTH ;
  325.     outheader.ras_length =
  326.         ((outheader.ras_width+1) & ~1) * outheader.ras_height ;
  327.     outheader.ras_type = RT_STANDARD ;
  328.     outheader.ras_maptype = RMT_EQUAL_RGB ;
  329.     outheader.ras_maplength = num_colors*3 ;
  330.  
  331.     ocmap.type = RMT_EQUAL_RGB ;
  332.     ocmap.length = num_colors ;
  333.     ocmap.map[0] = rm ;
  334.     ocmap.map[1] = gm ;
  335.     ocmap.map[2] = bm ;
  336.  
  337.     pr_dump_header(stdout, &outheader, &ocmap) ;
  338.  
  339.     if(dither)
  340.       quant_fsdither() ;
  341.     else
  342.       quant() ;
  343.  
  344.     fclose(stdout) ;
  345. }
  346.  
  347.  
  348.  
  349.  
  350.  
  351. static
  352. get_histogram(box)
  353. register Colorbox    *box ;
  354. {
  355.     unsigned char    *inline ;
  356. register unsigned char    *inptr ;
  357.     int        i ;
  358. register int        j ;
  359.  
  360.  
  361.     pr_read_init(&rh) ;
  362.  
  363.     inline = (unsigned char *) alloca( rh.ras_width * bytes_per_pixel ) ;
  364.  
  365.     box->rmin = box->gmin = box->bmin = 999 ;
  366.     box->rmax = box->gmax = box->bmax = -1 ;
  367.     box->total = rh.ras_height*rh.ras_width ;
  368.  
  369.     {
  370.       register int *ptr = &histogram[0][0][0] ;
  371.       for(i=B_LEN*B_LEN*B_LEN; --i >= 0;)
  372.         *ptr++ = 0 ;
  373.     }
  374.  
  375.  
  376.     for(i=rh.ras_height; --i >= 0;)
  377.     {
  378.       pr_get_bytes(stdin, &rh, rh.ras_width * bytes_per_pixel, inline) ;
  379.       inptr = inline ;
  380.       for(j=rh.ras_width; --j >= 0;)
  381.       {
  382.         register int    red,green,blue ;
  383.  
  384.         if(rh.ras_depth == 32)
  385.           ++inptr ;
  386.         blue = *inptr++ ;
  387.         green = *inptr++ ;
  388.         red = *inptr++ ;
  389.  
  390.         if (rh.ras_maplength > 0)
  391.         {
  392.           red = *(colormap.map[0]+red) ;
  393.           green = *(colormap.map[1]+green) ;
  394.           blue = *(colormap.map[2]+blue) ;
  395.         }
  396.  
  397.         red >>= (COLOR_DEPTH-B_DEPTH) ;
  398.         green >>= (COLOR_DEPTH-B_DEPTH) ;
  399.         blue >>= (COLOR_DEPTH-B_DEPTH) ;
  400.  
  401.         if(red < box->rmin) box->rmin = red ;
  402.         if(red > box->rmax) box->rmax = red ;
  403.         if(green < box->gmin) box->gmin = green ;
  404.         if(green > box->gmax) box->gmax = green ;
  405.         if(blue < box->bmin) box->bmin = blue ;
  406.         if(blue > box->bmax) box->bmax = blue ;
  407.  
  408.         ++histogram[red][green][blue] ;
  409.       }
  410.     }
  411. }
  412.  
  413.  
  414.  
  415. static Colorbox *
  416. largest_box()
  417. {
  418. register Colorbox    *tmp = usedboxes, *ptr ;
  419. register int         size = -1 ;
  420.  
  421.     while(tmp != NULL)
  422.     {
  423.       if( (tmp->rmax > tmp->rmin  ||
  424.            tmp->gmax > tmp->gmin  ||
  425.            tmp->bmax > tmp->bmin)  &&  tmp->total > size )
  426.       {
  427.         ptr = tmp ;
  428.         size = tmp->total ;
  429.       }
  430.       tmp = tmp->next ;
  431.     }
  432.     return(ptr) ;
  433. }
  434.  
  435.  
  436.  
  437. static
  438. splitbox(ptr)
  439. register Colorbox    *ptr ;
  440. {
  441.     int        hist2[B_LEN] ;
  442.     int        first, last ;
  443. register Colorbox    *new ;
  444. register int        *iptr, *histp ;
  445. register int        i, j ;
  446.     enum        {RED,GREEN,BLUE} which ;
  447.  
  448.     /*
  449.      * see which axis is the largest, do a histogram along that
  450.      * axis.  Split at median point.  Contract both new boxes to
  451.      * fit points and return
  452.      */
  453.  
  454.     if( (i = ptr->rmax - ptr->rmin) >= (ptr->gmax - ptr->gmin)  &&
  455.         i >= (ptr->bmax - ptr->bmin) )
  456.       which = RED ;
  457.     else if( (ptr->gmax - ptr->gmin) >= (ptr->bmax - ptr->bmin) )
  458.       which = GREEN ;
  459.     else
  460.       which = BLUE ;
  461.  
  462.  
  463.  
  464.     /* get histogram along longest axis */
  465.     {
  466.       register int    ir,ig,ib ;
  467.       switch(which)
  468.       {
  469.         case RED:
  470.           histp = &hist2[ptr->rmin] ;
  471.           for(ir = ptr->rmin; ir <= ptr->rmax; ++ir)
  472.           {
  473.         *histp = 0 ;
  474.         for(ig = ptr->gmin; ig <= ptr->gmax; ++ig)
  475.         {
  476.           iptr = &histogram[ir][ig][ptr->bmin] ;
  477.           for(ib = ptr->bmin; ib <= ptr->bmax; ++ib)
  478.           {
  479.             *histp += *iptr ;
  480.             ++iptr ;
  481.           }
  482.         }
  483.         ++histp ;
  484.           }
  485.           first = ptr->rmin;  last = ptr->rmax ;
  486.           break ;
  487.  
  488.         case GREEN:
  489.           histp = &hist2[ptr->gmin] ;
  490.           for(ig = ptr->gmin; ig <= ptr->gmax; ++ig)
  491.           {
  492.         *histp = 0 ;
  493.         for(ir = ptr->rmin; ir <= ptr->rmax; ++ir)
  494.         {
  495.           iptr = &histogram[ir][ig][ptr->bmin] ;
  496.           for(ib = ptr->bmin; ib <= ptr->bmax; ++ib)
  497.           {
  498.             *histp += *iptr ;
  499.             ++iptr ;
  500.           }
  501.         }
  502.         ++histp ;
  503.           }
  504.           first = ptr->gmin;  last = ptr->gmax ;
  505.           break ;
  506.  
  507.         case BLUE:
  508.           histp = &hist2[ptr->bmin] ;
  509.           for(ib = ptr->bmin; ib <= ptr->bmax; ++ib)
  510.           {
  511.         *histp = 0 ;
  512.         for(ir = ptr->rmin; ir <= ptr->rmax; ++ir)
  513.         {
  514.           iptr = &histogram[ir][ptr->gmin][ib] ;
  515.           for(ig = ptr->gmin; ig <= ptr->gmax; ++ig)
  516.           {
  517.             *histp += *iptr ;
  518.             iptr += B_LEN ;
  519.           }
  520.         }
  521.         ++histp ;
  522.           }
  523.           first = ptr->bmin;  last = ptr->bmax ;
  524.           break ;
  525.       }
  526.     }
  527.  
  528.     /* find median point */
  529.     {
  530.       register int sum, sum2 ;
  531.       histp = &hist2[first] ;
  532.  
  533.       sum2 = ptr->total/2 ;
  534.       histp = &hist2[first] ;
  535.       sum = 0 ;
  536.       for( i=first; i<=last && (sum += *histp++) < sum2; ++i) ;
  537.       if( i == first ) ++i ;
  538.     }
  539.  
  540.     /* Create new box, re-allocate points */
  541.  
  542.     new = freeboxes ;
  543.     freeboxes = new->next ;
  544.     if(freeboxes) freeboxes->prev = NULL ;
  545.  
  546.     if(usedboxes) usedboxes->prev = new ;
  547.     new->next = usedboxes ;
  548.     usedboxes = new ;
  549.  
  550.     {
  551.       register int    sum1,sum2,j ;
  552.       int        total ;
  553.       total = ptr->total ;
  554.       histp = &hist2[first] ;
  555.       sum1 = 0 ;
  556.       for( j = first; j < i; ++j)
  557.         sum1 += *histp++ ;
  558.       sum2 = 0 ;
  559.       for( j = i; j <= last; ++j)
  560.         sum2 += *histp++ ;
  561. #ifdef    DEBUG
  562.       if( sum1+sum2 != total  ||  sum1 == 0  ||  sum2 == 0 )
  563.         fprintf(stderr, "??? splitbox: sum1=%d, sum2=%d, total=%d\n",
  564.         sum1,sum2,total) ;
  565. #endif    DEBUG
  566.       new->total = sum1 ;
  567.       ptr->total = sum2 ;
  568.     }
  569.  
  570.  
  571.     new->rmin = ptr->rmin ;
  572.     new->rmax = ptr->rmax ;
  573.     new->gmin = ptr->gmin ;
  574.     new->gmax = ptr->gmax ;
  575.     new->bmin = ptr->bmin ;
  576.     new->bmax = ptr->bmax ;
  577.     switch(which)
  578.     {
  579.       case RED:
  580.         new->rmax = i-1 ;
  581.         ptr->rmin = i ;
  582.         break ;
  583.  
  584.       case GREEN:
  585.         new->gmax = i-1 ;
  586.         ptr->gmin = i ;
  587.       break ;
  588.  
  589.       case BLUE:
  590.         new->bmax = i-1 ;
  591.         ptr->bmin = i ;
  592.       break ;
  593.     }
  594.     shrinkbox(new) ;
  595.     shrinkbox(ptr) ;
  596. }
  597.  
  598.  
  599.  
  600.  
  601. static
  602. shrinkbox(box)
  603. register Colorbox    *box ;
  604. {
  605. register int        *histp ;
  606. register int        ir,ig,ib ;
  607.  
  608.  
  609.     if(box->rmax > box->rmin)
  610.     {
  611.       for(ir = box->rmin; ir <= box->rmax; ++ir)
  612.         for(ig = box->gmin; ig <= box->gmax; ++ig)
  613.         {
  614.           histp = &histogram[ir][ig][box->bmin] ;
  615.           for(ib = box->bmin; ib <= box->bmax; ++ib)
  616.         if( *histp++ != 0 )
  617.         {
  618.           box->rmin = ir ;
  619.           goto have_rmin ;
  620.         }
  621.         }
  622. have_rmin:
  623.  
  624.       if(box->rmax > box->rmin)
  625.         for(ir = box->rmax; ir >= box->rmin; --ir)
  626.           for(ig = box->gmin; ig <= box->gmax; ++ig)
  627.           {
  628.         histp = &histogram[ir][ig][box->bmin] ;
  629.         for(ib = box->bmin; ib <= box->bmax; ++ib)
  630.           if( *histp++ != 0 )
  631.           {
  632.             box->rmax = ir ;
  633.             goto have_rmax ;
  634.           }
  635.           }
  636.     }
  637. have_rmax:
  638.  
  639.     if( box->gmax > box->gmin )
  640.     {
  641.       for(ig = box->gmin; ig <= box->gmax; ++ig)
  642.         for(ir = box->rmin; ir <= box->rmax; ++ir)
  643.         {
  644.           histp = &histogram[ir][ig][box->bmin] ;
  645.           for(ib = box->bmin; ib <= box->bmax; ++ib)
  646.         if( *histp++ != 0 )
  647.         {
  648.           box->gmin = ig ;
  649.           goto have_gmin ;
  650.         }
  651.         }
  652. have_gmin:
  653.  
  654.       if( box->gmax > box->gmin )
  655.         for(ig = box->gmax; ig >= box->gmin; --ig)
  656.           for(ir = box->rmin; ir <= box->rmax; ++ir)
  657.           {
  658.         histp = &histogram[ir][ig][box->bmin] ;
  659.         for(ib = box->bmin; ib <= box->bmax; ++ib)
  660.           if( *histp++ != 0 )
  661.           {
  662.             box->gmax = ig ;
  663.             goto have_gmax ;
  664.           }
  665.           }
  666.     }
  667. have_gmax:
  668.  
  669.     if( box->bmax > box->bmin )
  670.     {
  671.       for(ib = box->bmin; ib <= box->bmax; ++ib)
  672.         for(ir = box->rmin; ir <= box->rmax; ++ir)
  673.         {
  674.           histp = &histogram[ir][box->gmin][ib] ;
  675.           for(ig = box->gmin; ig <= box->gmax; ++ig)
  676.           {
  677.         if( *histp != 0 )
  678.         {
  679.           box->bmin = ib ;
  680.           goto have_bmin ;
  681.         }
  682.         histp += B_LEN ;
  683.           }
  684.         }
  685. have_bmin:
  686.  
  687.       if( box->bmax > box->bmin )
  688.         for(ib = box->bmax; ib >= box->bmin; --ib)
  689.           for(ir = box->rmin; ir <= box->rmax; ++ir)
  690.           {
  691.         histp = &histogram[ir][box->gmin][ib] ;
  692.         for(ig = box->gmin; ig <= box->gmax; ++ig)
  693.         {
  694.           if( *histp != 0 )
  695.           {
  696.             box->bmax = ib ;
  697.             goto have_bmax ;
  698.           }
  699.           histp += B_LEN ;
  700.         }
  701.           }
  702.     }
  703. have_bmax: return ;
  704. }
  705.  
  706.  
  707.  
  708.  
  709. static
  710. assign_color(ptr,rp,gp,bp)
  711. register Colorbox    *ptr ;
  712.     unsigned char    *rp,*gp,*bp ;
  713. {
  714. register int        *histp ;
  715. register int        ir,ig,ib ;
  716. register long        red = 0, green = 0, blue = 0 ;
  717.  
  718.     *rp = ((ptr->rmin + ptr->rmax) << (COLOR_DEPTH - B_DEPTH)) / 2 ;
  719.     *gp = ((ptr->gmin + ptr->gmax) << (COLOR_DEPTH - B_DEPTH)) / 2 ;
  720.     *bp = ((ptr->bmin + ptr->bmax) << (COLOR_DEPTH - B_DEPTH)) / 2 ;
  721.  
  722. #ifdef    COMMENT
  723. #ifdef    DEBUG
  724.     if( ptr->total <= 0 )
  725.     {
  726.       fprintf(stderr,"??? assign_color: total = %d\n",ptr->total) ;
  727.       return ;
  728.     }
  729. #endif    DEBUG
  730.  
  731.     for( ir = ptr->rmin; ir <= ptr->rmax; ++ir)
  732.       for( ig = ptr->gmin; ig <= ptr->gmax; ++ig)
  733.       {
  734.         histp = &histogram[ir][ig][ptr->bmin] ;
  735.         for( ib = ptr->bmin; ib <= ptr->bmax; ++ib)
  736.         {
  737.           if( *histp != 0 )
  738.           {
  739.         red += ir * *histp ;
  740.         green += ig * *histp ;
  741.         blue += ib * *histp ;
  742.           }
  743.           ++histp ;
  744.         }
  745.       }
  746.  
  747.     *rp = (red << (COLOR_DEPTH - B_DEPTH)) / ptr->total ;
  748.     *gp = (green << (COLOR_DEPTH - B_DEPTH)) / ptr->total ;
  749.     *bp = (blue << (COLOR_DEPTH - B_DEPTH)) / ptr->total ;
  750. #endif    COMMENT
  751. }
  752.  
  753.  
  754.  
  755. static    C_cell *
  756. create_colorcell(red,green,blue)
  757.     int        red,green,blue ;
  758. {
  759. register int        ir,ig,ib, i ;
  760.     int        mindist ;
  761. register C_cell        *ptr ;
  762.  
  763.     ir = red >> (COLOR_DEPTH-C_DEPTH) ;
  764.     ig = green >> (COLOR_DEPTH-C_DEPTH) ;
  765.     ib = blue >> (COLOR_DEPTH-C_DEPTH) ;
  766.  
  767.     red &= ~1 << (COLOR_DEPTH-C_DEPTH) ;
  768.     green &= ~1 << (COLOR_DEPTH-C_DEPTH) ;
  769.     blue &= ~1 << (COLOR_DEPTH-C_DEPTH) ;
  770.  
  771.     ptr = (C_cell *) malloc( sizeof(C_cell) ) ;
  772.     *( ColorCells + ir*C_LEN*C_LEN + ig*C_LEN + ib ) = ptr ;
  773.  
  774.     ptr->num_ents = 0 ;
  775.  
  776.  
  777.     /* step 1: find all colors inside this cell, while we're at
  778.           it, find distance of centermost point to furthest
  779.           corner */
  780.  
  781.     mindist = 99999999 ;
  782.     for(i=0; i<num_colors; ++i)
  783.       if( rm[i]>>(COLOR_DEPTH-C_DEPTH) == ir  &&
  784.           gm[i]>>(COLOR_DEPTH-C_DEPTH) == ig  &&
  785.           bm[i]>>(COLOR_DEPTH-C_DEPTH) == ib)
  786.       {
  787.         register int    tmp, dist ;
  788.  
  789.         ptr->entries[ptr->num_ents][0] = i ;
  790.         ptr->entries[ptr->num_ents][1] = 0 ;
  791.         ++ptr->num_ents ;
  792.  
  793.         tmp = rm[i] - red ;
  794.         if( tmp < (MAX_COLOR/C_LEN/2) )
  795.           tmp = MAX_COLOR/C_LEN-1 - tmp ;
  796.         dist = tmp*tmp ;
  797.  
  798.         tmp = gm[i] - green ;
  799.         if( tmp < (MAX_COLOR/C_LEN/2) )
  800.           tmp = MAX_COLOR/C_LEN-1 - tmp ;
  801.         dist += tmp*tmp ;
  802.  
  803.         tmp = bm[i] - blue ;
  804.         if( tmp < (MAX_COLOR/C_LEN/2) )
  805.           tmp = MAX_COLOR/C_LEN-1 - tmp ;
  806.         dist += tmp*tmp ;
  807.  
  808.         if( dist < mindist )
  809.           mindist = dist ;
  810.       }
  811.  
  812.  
  813.     /* step 3: find all points within that distance to box */
  814.  
  815.     for( i=0; i<num_colors; ++i )
  816.     {
  817.       register int    dist, tmp ;
  818.  
  819.       if( rm[i] >> (COLOR_DEPTH-C_DEPTH) != ir  ||
  820.           gm[i] >> (COLOR_DEPTH-C_DEPTH) != ig  ||
  821.           bm[i] >> (COLOR_DEPTH-C_DEPTH) != ib)
  822.       {
  823.         dist = 0 ;
  824.  
  825.         if( (tmp = red - rm[i]) > 0  ||
  826.         (tmp = rm[i] - (red + MAX_COLOR/C_LEN-1)) > 0 )
  827.           dist += tmp*tmp ;
  828.  
  829.         if( (tmp = green - gm[i]) > 0  ||
  830.         (tmp = gm[i] - (green + MAX_COLOR/C_LEN-1)) > 0 )
  831.           dist += tmp*tmp ;
  832.  
  833.         if( (tmp = blue - bm[i]) > 0  ||
  834.         (tmp = bm[i] - (blue + MAX_COLOR/C_LEN-1)) > 0 )
  835.           dist += tmp*tmp ;
  836.  
  837.         if( dist < mindist )
  838.         {
  839.           ptr->entries[ptr->num_ents][0] = i ;
  840.           ptr->entries[ptr->num_ents][1] = dist ;
  841.           ++ptr->num_ents ;
  842.         }
  843.       }
  844.     }
  845.  
  846.     /* sort color cells by distance, use cheap exchange sort */
  847.     {
  848.       register int    n, tmp, i ;
  849.       int        next_n ;
  850.  
  851.       n = ptr->num_ents - 1 ;
  852.       while( n > 0 )
  853.       {
  854.         next_n = 0 ;
  855.         for( i=0; i<n; ++i)
  856.         {
  857.           if( ptr->entries[i][1] > ptr->entries[i+1][1] )
  858.           {
  859.         tmp = ptr->entries[i][0] ;
  860.         ptr->entries[i][0] = ptr->entries[i+1][0] ;
  861.         ptr->entries[i+1][0] = tmp ;
  862.         tmp = ptr->entries[i][1] ;
  863.         ptr->entries[i][1] = ptr->entries[i+1][1] ;
  864.         ptr->entries[i+1][1] = tmp ;
  865.         next_n = i ;
  866.           }
  867.         }
  868.         n = next_n ;
  869.       }
  870.     }
  871.     return( ptr ) ;
  872. }
  873.  
  874.  
  875.  
  876.  
  877. static
  878. map_colortable()
  879. {
  880.     int        ir,ig,ib ;
  881. register int        *histp = &histogram[0][0][0] ;
  882. register C_cell        *cell ;
  883.  
  884.     for(ir = 0; ir < B_LEN; ++ir)
  885.       for(ig = 0; ig < B_LEN; ++ig)
  886.         for(ib = 0; ib < B_LEN; ++ib)
  887.         {
  888.           if( *histp == 0 )
  889.         *histp = -1 ;
  890.           else
  891.           {
  892.         int        i ;
  893.         register int    j, tmp, d2, dist ;
  894.  
  895.         cell = *( ColorCells + ( ((ir>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2)
  896.                   + ((ig>>(B_DEPTH-C_DEPTH)) << C_DEPTH )
  897.               + (ib>>(B_DEPTH-C_DEPTH)) ) ) ;
  898.         
  899.         if(cell == NULL )
  900.           cell = create_colorcell( ir<<(COLOR_DEPTH-B_DEPTH),
  901.                        ig<<(COLOR_DEPTH-B_DEPTH),
  902.                        ib<<(COLOR_DEPTH-B_DEPTH) ) ;
  903.  
  904.         dist = 9999999 ;
  905.         for(i = 0;
  906.             i < cell->num_ents  &&  dist > cell->entries[i][1] ;
  907.             ++i)
  908.         {
  909.           j = cell->entries[i][0] ;
  910.           d2 = rm[j] - (ir << (COLOR_DEPTH-B_DEPTH)) ;
  911.           d2 *= d2 ;
  912.           tmp = gm[j] - (ig << (COLOR_DEPTH-B_DEPTH)) ;
  913.           d2 += tmp*tmp ;
  914.           tmp = bm[j] - (ib << (COLOR_DEPTH-B_DEPTH)) ;
  915.           d2 += tmp*tmp ;
  916.           if( d2 < dist )
  917.           {
  918.             dist = d2 ;
  919.             *histp = j ;
  920.           }
  921.         }
  922. #ifdef    DEBUG
  923.         if( dist == 9999999 )
  924.           fprintf(stderr,"??? map_colortable: dist=9999999\n") ;
  925. #endif    DEBUG
  926.           }
  927.           ++histp ;
  928.         }
  929. }
  930.  
  931.  
  932.  
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940. /*
  941.  * straight quantization.  Each pixel is mapped to the colors
  942.  * closest to it.  Color values are rounded to the nearest color
  943.  * table entry.
  944.  */
  945.  
  946. static
  947. quant()
  948. {
  949.     unsigned char    *outline ;
  950.     unsigned char    *inline ;
  951. register unsigned char    *outptr ;
  952. register unsigned char    *inptr ;
  953. register int        i, j ;
  954.  
  955.  
  956.  
  957.  
  958.     inline = (unsigned char *) alloca( rh.ras_width * bytes_per_pixel ) ;
  959.  
  960.     outline = (unsigned char *) alloca( rh.ras_width ) ;
  961.  
  962.     for(i=0; i < rh.ras_height; ++i)
  963.     {
  964.       pr_get_bytes(stdin, &rh, rh.ras_width * bytes_per_pixel, inline) ;
  965.       inptr = inline ;
  966.       outptr = outline;
  967.       for(j=0; j < rh.ras_width; ++j)
  968.       {
  969.         register int    tmp,red,green,blue ;
  970.  
  971.         if(rh.ras_depth == 32)
  972.           ++inptr ;
  973.         blue = *inptr++ ;
  974.         green = *inptr++ ;
  975.         red = *inptr++ ;
  976.  
  977.         if (rh.ras_maplength > 0)
  978.         {
  979.           red = *(colormap.map[0]+red) ;
  980.           green = *(colormap.map[1]+green) ;
  981.           blue = *(colormap.map[2]+blue) ;
  982.         }
  983.  
  984.         red >>= (COLOR_DEPTH-B_DEPTH) ;
  985.         green >>= (COLOR_DEPTH-B_DEPTH) ;
  986.         blue >>= (COLOR_DEPTH-B_DEPTH) ;
  987.  
  988.         *outptr++ = histogram[red][green][blue] ;
  989.       }
  990.       fwrite(outline, 1, rh.ras_width, stdout) ;
  991.     }
  992. }
  993.  
  994.  
  995.  
  996.  
  997.  
  998. static
  999. quant_fsdither()
  1000. {
  1001.     unsigned char    *outline, *inline ;
  1002.     short        *thisline, *nextline, *tmpptr ;
  1003.     unsigned char    *inptr ;
  1004. register unsigned char    *outptr ;
  1005. register short        *thisptr, *nextptr ;
  1006. register int        i, j ;
  1007.     int        imax, jmax ;
  1008.     int        lastline, lastpixel ;
  1009.  
  1010.  
  1011.     imax = rh.ras_height - 1 ;
  1012.     jmax = rh.ras_width - 1 ;
  1013.  
  1014.     inline = (unsigned char *) alloca( rh.ras_width * bytes_per_pixel ) ;
  1015.     thisline = (short *) alloca( rh.ras_width * 3 * sizeof(short)) ;
  1016.     nextline = (short *) alloca( rh.ras_width * 3 * sizeof(short)) ;
  1017.  
  1018.     outline = (unsigned char *) alloca( rh.ras_width ) ;
  1019.  
  1020.     /*
  1021.      * get first line
  1022.      */
  1023.     pr_get_bytes(stdin, &rh, rh.ras_width * bytes_per_pixel, inline) ;
  1024.     {
  1025.       register int tmp ;
  1026.       inptr = inline ;
  1027.       nextptr = nextline ;
  1028.       for(j=0; j < rh.ras_width; ++j)
  1029.       {
  1030.         if(rh.ras_depth == 32)
  1031.           ++inptr ;
  1032.         if( rh.ras_maplength > 0)
  1033.         {
  1034.           *nextptr++ = *(colormap.map[0]+*inptr++) ;
  1035.           *nextptr++ = *(colormap.map[1]+*inptr++) ;
  1036.           *nextptr++ = *(colormap.map[2]+*inptr++) ;
  1037.         }
  1038.         else
  1039.         {
  1040.           *nextptr++ = *inptr++ ;
  1041.           *nextptr++ = *inptr++ ;
  1042.           *nextptr++ = *inptr++ ;
  1043.         }
  1044.       }
  1045.     }
  1046.  
  1047.     for(i=0; i < rh.ras_height; ++i)
  1048.     {
  1049.       tmpptr = thisline ;
  1050.       thisline = nextline ;
  1051.       nextline = tmpptr ;
  1052.       lastline = (i == imax) ;
  1053.       pr_get_bytes(stdin, &rh, rh.ras_width * bytes_per_pixel, inline) ;
  1054.       {
  1055.         register int tmp ;
  1056.         inptr = inline ;
  1057.         nextptr = nextline ;
  1058.         for(j=0; j < rh.ras_width; ++j)
  1059.         {
  1060.           if(rh.ras_depth == 32)
  1061.         ++inptr ;
  1062.           if( rh.ras_maplength > 0)
  1063.           {
  1064.         *nextptr++ = *(colormap.map[0]+*inptr++) ;
  1065.         *nextptr++ = *(colormap.map[1]+*inptr++) ;
  1066.         *nextptr++ = *(colormap.map[2]+*inptr++) ;
  1067.           }
  1068.           else
  1069.           {
  1070.         *nextptr++ = *inptr++ ;
  1071.         *nextptr++ = *inptr++ ;
  1072.         *nextptr++ = *inptr++ ;
  1073.           }
  1074.         }
  1075.       }
  1076.  
  1077.       thisptr = thisline ;
  1078.       nextptr = nextline ;
  1079.       outptr = outline;
  1080.  
  1081.       for(j=0; j < rh.ras_width ; ++j)
  1082.       {
  1083.         int            red,green,blue ;
  1084.         register int    oval, r2,g2,b2 ;
  1085.  
  1086.         lastpixel = (j == jmax) ;
  1087.  
  1088.         b2 = *thisptr++ ;
  1089.         g2 = *thisptr++ ;
  1090.         r2 = *thisptr++ ;
  1091.  
  1092.  
  1093.         if( r2 < 0 ) r2 = 0 ;
  1094.         else if( r2 >= MAX_COLOR ) r2 = MAX_COLOR-1 ;
  1095.         if( g2 < 0 ) g2 = 0 ;
  1096.         else if( g2 >= MAX_COLOR ) g2 = MAX_COLOR-1 ;
  1097.         if( b2 < 0 ) b2 = 0 ;
  1098.         else if( b2 >= MAX_COLOR ) b2 = MAX_COLOR-1 ;
  1099.  
  1100.         red = r2 ;
  1101.         green = g2 ;
  1102.         blue = b2 ;
  1103.  
  1104.         r2 >>= (COLOR_DEPTH-B_DEPTH) ;
  1105.         g2 >>= (COLOR_DEPTH-B_DEPTH) ;
  1106.         b2 >>= (COLOR_DEPTH-B_DEPTH) ;
  1107.  
  1108.         if( (oval = histogram[r2][g2][b2]) == -1)
  1109.         {
  1110.           int        ci ;
  1111.           register int    cj, tmp, d2, dist ;
  1112.           register C_cell    *cell ;
  1113.  
  1114.           cell = *( ColorCells + ( ((r2>>(B_DEPTH-C_DEPTH)) << C_DEPTH*2)
  1115.             + ((g2>>(B_DEPTH-C_DEPTH)) << C_DEPTH )
  1116.             + (b2>>(B_DEPTH-C_DEPTH)) ) ) ;
  1117.           
  1118.           if(cell == NULL )
  1119.         cell = create_colorcell( red, green, blue ) ;
  1120.  
  1121.  
  1122.           dist = 9999999 ;
  1123.           for(ci = 0;
  1124.           ci < cell->num_ents  &&  dist > cell->entries[ci][1] ;
  1125.           ++ci)
  1126.           {
  1127.         cj = cell->entries[ci][0] ;
  1128.         d2 = (rm[cj] >> (COLOR_DEPTH-B_DEPTH)) - r2 ;
  1129.         d2 *= d2 ;
  1130.         tmp = (gm[cj] >> (COLOR_DEPTH-B_DEPTH)) - g2 ;
  1131.         d2 += tmp*tmp ;
  1132.         tmp = (bm[cj] >> (COLOR_DEPTH-B_DEPTH)) - b2 ;
  1133.         d2 += tmp*tmp ;
  1134.         if( d2 < dist )
  1135.         {
  1136.           dist = d2 ;
  1137.           oval = cj ;
  1138.         }
  1139.           }
  1140.           histogram[r2][g2][b2] = oval ;
  1141. #ifdef    DEBUG
  1142.           if( dist == 9999999 )
  1143.         fprintf(stderr,"??? quant: dist=9999999\n") ;
  1144. #endif    DEBUG
  1145.         }
  1146.  
  1147.         *outptr++ = oval ;
  1148.  
  1149.         red -= rm[oval] ;
  1150.         green -= gm[oval] ;
  1151.         blue -= bm[oval] ;
  1152.  
  1153.  
  1154.         if( !lastpixel )
  1155.         {
  1156.           thisptr[0] += blue * 7 / 16 ;
  1157.           thisptr[1] += green * 7 / 16 ;
  1158.           thisptr[2] += red * 7 / 16 ;
  1159.         }
  1160.         if( !lastline )
  1161.         {
  1162.           if( j != 0 )
  1163.           {
  1164.         nextptr[-3] += blue * 3 / 16 ;
  1165.         nextptr[-2] += green * 3 / 16 ;
  1166.         nextptr[-1] += red * 3 / 16 ;
  1167.           }
  1168.           nextptr[0] += blue * 5 / 16 ;
  1169.           nextptr[1] += green * 5 / 16 ;
  1170.           nextptr[2] += red * 5 / 16 ;
  1171.           if( !lastpixel )
  1172.           {
  1173.         nextptr[3] += blue / 16 ;
  1174.         nextptr[4] += green / 16 ;
  1175.         nextptr[5] += red / 16 ;
  1176.           }
  1177.           nextptr += 3 ;
  1178.         }
  1179.       }
  1180.       fwrite(outline, 1, rh.ras_width, stdout) ;
  1181.     }
  1182. }
  1183.  
  1184.  
  1185.  
  1186.  
  1187. #ifdef    DEBUG
  1188. showboxes()
  1189. {
  1190.     Colorbox    *ptr ;
  1191.  
  1192.     printf("boxes:\n") ;
  1193.     ptr = usedboxes ;
  1194.     while(ptr != NULL)
  1195.     {
  1196.       printf("  %d<r<%d, %d<g<%d, %d<b<%d\n", ptr->rmin,ptr->rmax,
  1197.           ptr->gmin,ptr->gmax, ptr->bmin,ptr->bmax) ;
  1198.       ptr = ptr->next ;
  1199.     }
  1200. }
  1201.  
  1202.  
  1203.  
  1204. showcell(ptr)
  1205. register C_cell    *ptr ;
  1206. {
  1207.     int    i ;
  1208.     int    j ;
  1209.  
  1210.     fprintf(stderr, "n=%d\n", ptr->num_ents) ;
  1211.     for(i=0; i<ptr->num_ents; ++i)
  1212.     {
  1213.       j = ptr->entries[i][0] ;
  1214.       fprintf(stderr, "(%d,%d): (%d,%d,%d)\n",
  1215.           j, ptr->entries[i][1], rm[j],gm[j],bm[j]) ;
  1216.     }
  1217. }
  1218.  
  1219.  
  1220.  
  1221. int
  1222. testbox(box)
  1223. register Colorbox    *box ;
  1224. {
  1225. register int        ir,ig,ib, total ;
  1226.  
  1227.     total = 0 ;
  1228.     for(ir=box->rmin; ir<=box->rmax; ++ir)
  1229.       for(ig=box->gmin; ig<=box->gmax; ++ig)
  1230.         for(ib=box->bmin; ib<=box->bmax; ++ib)
  1231.           total += histogram[ir][ig][ib] ;
  1232.  
  1233.     return total ;
  1234. }
  1235. #endif    DEBUG
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242. /* pr_stream routines:  allow images to be read in stream
  1243.  * fasion rather than loading them into memory.
  1244.  *
  1245.  * These routines are used in conjunction with the pr_io routines.  It
  1246.  * is the application's responsibility to read the header and
  1247.  * colormaps
  1248.  *
  1249.  *
  1250.  * routines:
  1251.  *
  1252.  * pr_read_init(header)
  1253.  *    struct rasterfile *header ;
  1254.  *
  1255.  *    sets up to read an image
  1256.  *
  1257.  *
  1258.  * pr_get_bytes(file, header, len, buffer)
  1259.  *    FILE        *file ;
  1260.  *    struct rasterfile *header ;
  1261.  *    int        len ;
  1262.  *    char        *buffer ;
  1263.  *
  1264.  *    read data from input
  1265.  *
  1266.  *
  1267.  * int
  1268.  * pr_get_byte(file, header)
  1269.  *    FILE        *file ;
  1270.  *    struct rasterfile *header ;
  1271.  *
  1272.  *    read and return one byte from input
  1273.  *
  1274.  */
  1275.  
  1276. #include <stdio.h>
  1277. #include <sys/types.h>
  1278. #include <pixrect/pixrect.h>
  1279. #include <pixrect/memvar.h>
  1280. #include <pixrect/pr_io.h>
  1281. #include <rasterfile.h>
  1282.  
  1283. #define    ESCAPE    128
  1284.  
  1285.  
  1286.  
  1287. static    unsigned char    icvalue ;
  1288. static    int        icount ;
  1289.  
  1290.  
  1291.  
  1292. int
  1293. pr_read_init(header)
  1294.     struct rasterfile    *header ;
  1295. {
  1296.     icount = 0 ;
  1297. }
  1298.  
  1299.  
  1300.  
  1301. int
  1302. pr_get_bytes(file, header, len, buffer)
  1303. register FILE            *file ;
  1304. register struct rasterfile    *header ;
  1305. register int            len ;
  1306. register unsigned char        *buffer ;
  1307. {
  1308.     if(header->ras_type != RT_BYTE_ENCODED)
  1309.       return( fread(buffer, 1, len, file) ) ;
  1310.  
  1311.     else while(len-- > 0)
  1312.     {
  1313.       if(icount > 0)
  1314.       {
  1315.         --icount ;
  1316.         *buffer++ = icvalue ;
  1317.       }
  1318.       else
  1319.       {
  1320.         if( (icvalue = getc(file)) != ESCAPE )
  1321.           *buffer++ = icvalue ;
  1322.         else
  1323.         {
  1324.           if( (icount = getc(file)) == 0 )
  1325.         *buffer++ = ESCAPE ;
  1326.           else
  1327.           {
  1328.         *buffer++ = icvalue = getc(file) ;
  1329.           }
  1330.         }
  1331.       }
  1332.     }
  1333.     return 0 ;
  1334. }
  1335.  
  1336.  
  1337.  
  1338. unsigned char
  1339. pr_get_byte(file, header)
  1340.     FILE            *file ;
  1341.     struct rasterfile    *header ;
  1342. {
  1343.     unsigned char        rval ;
  1344.  
  1345.     pr_get_bytes(file, header, 1, &rval) ;
  1346.     return( rval ) ;
  1347. }
  1348. -- 
  1349.         -ed falk, sun microsystems
  1350.          sun!falk, falk@sun.com
  1351. terrorist, cryptography, DES, drugs, cipher, secret, decode, NSA, CIA, NRO.
  1352.