home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libcnv / colorqnt.c next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  20.9 KB  |  598 lines

  1. #include "xp_core.h" //used to make library compile faster on win32 do not ifdef this or it wont work
  2.  
  3. /* taken from libppm3.c - ppm utility library part 3
  4. **
  5. ** Colormap routines.
  6. **
  7. ** Copyright (C) 1989, 1991 by Jef Poskanzer.
  8. **
  9. ** Permission to use, copy, modify, and distribute this software and its
  10. ** documentation for any purpose and without fee is hereby granted, provided
  11. ** that the above copyright notice appear in all copies and that both that
  12. ** copyright notice and this permission notice appear in supporting
  13. ** documentation.  This software is provided "as is" without express or
  14. ** implied warranty.
  15. */
  16. #include <stdio.h>
  17. #include <memory.h>
  18. #include <malloc.h>
  19. #include <process.h>
  20. #include <search.h>        
  21. #include <stdlib.h>        
  22. #include "xp_core.h"/*defines of int32, etc.*/
  23. #include "xp_mem.h"/*defines of XP_ALLOC, etc.*/
  24. #include "xp_str.h"/*defines of XP_MEMCPY, etc.*/
  25. #include "xpassert.h"
  26. #include "xp_qsort.h"
  27. #include "ntypes.h" /* for MWContext to include libcnv.h*/
  28.  
  29. #include "libcnv.h"
  30. #include "pbmplus.h"
  31. #include "ppm.h"
  32. #include "ppmcmap.h"
  33. #include "colorqnt.h"
  34.  
  35. #define LARGE_NORM 1
  36. #define REP_AVERAGE_COLORS 1
  37.  
  38. #define MAXCOLORS 256
  39.  
  40. #define FLOYD_DEFAULT 1/*use floyd algorithm*/
  41. #define FS_SCALE 1024
  42.  
  43. typedef struct box* box_vector;
  44. struct box
  45.     {
  46.     int16 ind;
  47.     int16 colors;
  48.     int32 sum;
  49.     };
  50.  
  51. static colorhist_vector mediancut ARGS(( colorhist_vector chv, int16 colors, int32 sum, pixval maxval, int16 newcolors ));
  52. static int redcompare ARGS(( const colorhist_vector ch1, const colorhist_vector ch2 ));
  53. static int greencompare ARGS(( const colorhist_vector ch1, const colorhist_vector ch2 ));
  54. static int bluecompare ARGS(( const colorhist_vector ch1, const colorhist_vector ch2 ));
  55. static int sumcompare ARGS(( const box_vector b1, const box_vector b2 ));
  56.  
  57. /*used for quick sort of color table*/
  58. typedef int (* qsortprototype)(const void *, const void *);
  59.  
  60. /*EFFECTS:modifies imagearray to reflect colors in colorhistogram
  61.  MODIFIES:imagearray, pchv,maxcolorvalue,colors
  62.   RETURNS:CONV_OK if success
  63.     INPUT:
  64.     imagearray= RGB tripples
  65.     imagewidth= width of image
  66.     imageheight=height of image
  67.     maxcolorvalue=passed in as maximum value for each R,G or B 
  68.     colors= valid pointer to int16
  69.     maxcolorvalue= valid pointer to int16
  70.    OUTPUT:
  71.     maxcolorvalue=leaves with what was assigned as the maximum value
  72.     colors= number of colors in the mapping
  73.     pchv= leaves pointing to the new color table. calling function reponsible for deleting!
  74. SPECIAL NOTE!
  75. the returned color table is in the range of 0 to maxcolorvalue.
  76. you must divide my maxcolorvalue and multiply times the input maxcolorvalue to get 
  77. colors in the range of 0-MAXCOLORS-1
  78. */
  79. CONVERT_IMAGERESULT
  80. quantize_colors(CONVERT_IMG_ARRAY imagearray,int16 imagewidth,int16 imageheight,int16 *maxcolorvalue,int16 *colors,colorhist_vector *pchv)
  81. {
  82.     pixval newmaxval=0;
  83.     int16 row=0;
  84.     colorhist_vector chv=NULL;
  85.     colorhist_vector colormap=NULL;
  86.     pixel *pP=NULL;
  87.     pixval maxval=(pixval)(MAXCOLORS-1);
  88.     colorhash_table cht=NULL;
  89.     int32* thisrerr=NULL;
  90.     int32* nextrerr=NULL;
  91.     int32* thisgerr=NULL;
  92.     int32* nextgerr=NULL;
  93.     int32* thisberr=NULL;
  94.     int32* nextberr=NULL;
  95.     int32* temperr=NULL;
  96.     int16 usehash,floyd=FLOYD_DEFAULT;
  97.     int16 fs_direction;
  98.     register int16 col, limitcol;
  99.     register int32 sr, sg, sb, err;
  100.     register int16 ind;
  101.     pixel** copy = 0;
  102.  
  103.     *pchv=NULL;
  104.     XP_ASSERT(colors);
  105.     XP_ASSERT(maxcolorvalue);
  106.     /*
  107.     ** Step 1: attempt to make a histogram of the colors, unclustered.
  108.     ** If at first we don't succeed, lower maxval to increase color
  109.     ** coherence and try again.  This will eventually terminate, with
  110.     ** maxval at worst 15, since 32^3 is approximately MAXCOLORS.
  111.     */
  112.     /* Make a copy of the image pixels */
  113.     copy = XP_ALLOC(sizeof(pixel*) * imageheight);
  114.     {
  115.         int i;
  116.         pixel* pixelRow;
  117.         pixel* sourceRow;
  118.         for(i = 0; i < imageheight; i++){
  119.             pixelRow = XP_ALLOC(imagewidth*sizeof(pixel));
  120.             copy[i] = pixelRow;
  121.             sourceRow = (pixel*) imagearray[i];
  122.             /* XP_MEMCPY(pixelRow, sourceRow, sizeof(pixel)*imagewidth); */
  123.             {
  124.                 int j;
  125.                 for(j = 0; j < imagewidth; j++){
  126.                     pixelRow[j] = sourceRow[j];
  127.                 }
  128.             }
  129.         }
  130.     }
  131.  
  132.     for ( ; ; )
  133.     {
  134.         chv = ppm_computecolorhist(
  135.             (pixel **)copy, imagewidth, imageheight, MAXCOLORS, colors );
  136.         if ( chv != (colorhist_vector) 0 )
  137.             break;
  138.         newmaxval = maxval / 2;
  139.         for ( row = 0; row < imageheight; ++row )
  140.             for ( col = 0, pP = (pixel *)copy[row]; col < imagewidth; ++col, ++pP ){
  141.                 PPM_DEPTH( *pP, *pP, maxval, newmaxval );
  142.             }
  143.         maxval=newmaxval;
  144.     }
  145.     /* Free copy of image */
  146.     {
  147.         int i;
  148.         for(i = 0; i < imageheight; i++){
  149.             XP_FREE(copy[i]);
  150.         }
  151.         XP_FREE(copy);
  152.     }
  153.  
  154.     /* we now have the maximum # of colors*/
  155.     /*
  156.     ** Step 2: apply median-cut to histogram, making the new colormap.
  157.     */
  158.     colormap = mediancut( chv, (int16)*colors, (int32)(imageheight * imagewidth), (pixval)maxval, (int16)*maxcolorvalue );
  159.     free( chv );
  160.     { /* Crank up colors in color map */
  161.         int i;
  162.         for(i = 0; i < *colors; i++ ) {
  163.             PPM_DEPTH( colormap[i].color, colormap[i].color, maxval, MAXCOLORS-1 );
  164.         }
  165.         maxval = MAXCOLORS-1;
  166.     }
  167.     /*
  168.     ** Step 3: map the colors in the image to their closest match in the
  169.     ** new colormap, and write 'em out.
  170.     */
  171.     cht = ppm_alloccolorhash( );
  172.     usehash = 1;
  173.     if ( floyd )
  174.     {
  175.         /* Initialize Floyd-Steinberg error vectors. */
  176.         thisrerr = (int32*) malloc( (imagewidth + 2)* sizeof(int32) );
  177.         nextrerr = (int32*) malloc( (imagewidth + 2)* sizeof(int32) );
  178.         thisgerr = (int32*) malloc( (imagewidth + 2)* sizeof(int32) );
  179.         nextgerr = (int32*) malloc( (imagewidth + 2)* sizeof(int32) );
  180.         thisberr = (int32*) malloc( (imagewidth + 2)* sizeof(int32) );
  181.         nextberr = (int32*) malloc( (imagewidth + 2)* sizeof(int32) );
  182.         if (!nextberr||!thisberr||!nextgerr||!thisgerr||!nextrerr||!thisrerr)
  183.             return CONVERR_OUTOFMEMORY; /*memory allocation failed*/
  184.         srandom( (int16) ( time( 0 ) ^ getpid( ) ) );
  185.         for ( col = 0; col < imagewidth + 2; ++col )
  186.         {
  187.             thisrerr[col] = random( ) % ( FS_SCALE * 2 ) - FS_SCALE;
  188.             thisgerr[col] = random( ) % ( FS_SCALE * 2 ) - FS_SCALE;
  189.             thisberr[col] = random( ) % ( FS_SCALE * 2 ) - FS_SCALE;
  190.             /* (random errors in [-1 .. 1]) */
  191.         }
  192.         fs_direction = 1;
  193.     }
  194.     for ( row = 0; row < imageheight; ++row )
  195.     {
  196.         if ( floyd )
  197.             for ( col = 0; col < imagewidth + 2; ++col )
  198.                 nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
  199.         if ( ( ! floyd ) || fs_direction )
  200.         {
  201.             col = 0;
  202.             limitcol = imagewidth;
  203.             pP = (pixel *)imagearray[row];
  204.         }
  205.         else
  206.         {
  207.             col = imagewidth - 1;
  208.             limitcol = -1;
  209.             pP = &((pixel **)imagearray)[row][col]; /*(pixel *)&(imagearray[row][col*3]); times 3 because a CONV_IMAGE_ARRAY IS A char ** not a pixel ** */
  210.         }
  211.         do
  212.         {
  213.             if ( floyd )
  214.             {
  215.                 /* Use Floyd-Steinberg errors to adjust actual color. */
  216.                 sr = PPM_GETR(*pP) + thisrerr[col + 1] / FS_SCALE;
  217.                 sg = PPM_GETG(*pP) + thisgerr[col + 1] / FS_SCALE;
  218.                 sb = PPM_GETB(*pP) + thisberr[col + 1] / FS_SCALE;
  219.                 if ( sr < 0 ) sr = 0;
  220.                 else if ( sr > maxval ) sr = maxval;
  221.                 if ( sg < 0 ) sg = 0;
  222.                 else if ( sg > maxval ) sg = maxval;
  223.                 if ( sb < 0 ) sb = 0;
  224.                 else if ( sb > maxval ) sb = maxval;
  225.                 PPM_ASSIGN( *pP, (pixval)sr, (pixval)sg, (pixval)sb );
  226.             }
  227.  
  228.             /* Check hash table to see if we have already matched this color. */
  229.             ind = ppm_lookupcolor( cht, pP );
  230.             if ( ind == -1 )
  231.             { /* No; search colormap for closest match. */
  232.                 register int16 i, r1, g1, b1, r2, g2, b2;
  233.                 register int32 dist, newdist;
  234.                 r1 = PPM_GETR( *pP );
  235.                 g1 = PPM_GETG( *pP );
  236.                 b1 = PPM_GETB( *pP );
  237.                 dist = 2000000000;
  238.                 for ( i = 0; i < *maxcolorvalue; ++i )
  239.                 {
  240.                     r2 = PPM_GETR( colormap[i].color );
  241.                     g2 = PPM_GETG( colormap[i].color );
  242.                     b2 = PPM_GETB( colormap[i].color );
  243.                     newdist = ( r1 - r2 ) * ( r1 - r2 ) +
  244.                         ( g1 - g2 ) * ( g1 - g2 ) +
  245.                         ( b1 - b2 ) * ( b1 - b2 );
  246.                     if ( newdist < dist )
  247.                     {
  248.                         ind = i;
  249.                         dist = newdist;
  250.                     }
  251.                 }
  252.                 if ( usehash )
  253.                 {
  254.                     if ( ppm_addtocolorhash( cht, pP, ind ) < 0 )
  255.                     {
  256.                         usehash = 0;
  257.                     }
  258.                 }
  259.             }
  260.  
  261.             if ( floyd )
  262.             {
  263.                 /* Propagate Floyd-Steinberg error terms. */
  264.                 if ( fs_direction )
  265.                 {
  266.                     err = ( sr - (int32) PPM_GETR( colormap[ind].color ) ) * FS_SCALE;
  267.                     thisrerr[col + 2] += ( err * 7 ) / 16;
  268.                     nextrerr[col    ] += ( err * 3 ) / 16;
  269.                     nextrerr[col + 1] += ( err * 5 ) / 16;
  270.                     nextrerr[col + 2] += ( err     ) / 16;
  271.                     err = ( sg - (int32) PPM_GETG( colormap[ind].color ) ) * FS_SCALE;
  272.                     thisgerr[col + 2] += ( err * 7 ) / 16;
  273.                     nextgerr[col    ] += ( err * 3 ) / 16;
  274.                     nextgerr[col + 1] += ( err * 5 ) / 16;
  275.                     nextgerr[col + 2] += ( err     ) / 16;
  276.                     err = ( sb - (int32) PPM_GETB( colormap[ind].color ) ) * FS_SCALE;
  277.                     thisberr[col + 2] += ( err * 7 ) / 16;
  278.                     nextberr[col    ] += ( err * 3 ) / 16;
  279.                     nextberr[col + 1] += ( err * 5 ) / 16;
  280.                     nextberr[col + 2] += ( err     ) / 16;
  281.                 }
  282.                 else
  283.                 {
  284.                     err = ( sr - (int32) PPM_GETR( colormap[ind].color ) ) * FS_SCALE;
  285.                     thisrerr[col    ] += ( err * 7 ) / 16;
  286.                     nextrerr[col + 2] += ( err * 3 ) / 16;
  287.                     nextrerr[col + 1] += ( err * 5 ) / 16;
  288.                     nextrerr[col    ] += ( err     ) / 16;
  289.                     err = ( sg - (int32) PPM_GETG( colormap[ind].color ) ) * FS_SCALE;
  290.                     thisgerr[col    ] += ( err * 7 ) / 16;
  291.                     nextgerr[col + 2] += ( err * 3 ) / 16;
  292.                     nextgerr[col + 1] += ( err * 5 ) / 16;
  293.                     nextgerr[col    ] += ( err     ) / 16;
  294.                     err = ( sb - (int32) PPM_GETB( colormap[ind].color ) ) * FS_SCALE;
  295.                     thisberr[col    ] += ( err * 7 ) / 16;
  296.                     nextberr[col + 2] += ( err * 3 ) / 16;
  297.                     nextberr[col + 1] += ( err * 5 ) / 16;
  298.                     nextberr[col    ] += ( err     ) / 16;
  299.                 }
  300.             }
  301.  
  302.             *pP = colormap[ind].color;
  303.  
  304.             if ( ( ! floyd ) || fs_direction )
  305.             {
  306.                 ++col;
  307.                 ++pP;
  308.             }
  309.             else
  310.             {
  311.                 --col;
  312.                 --pP;
  313.             }
  314.         }
  315.         while ( col != limitcol );
  316.  
  317.         if ( floyd )
  318.         {
  319.             temperr = thisrerr;
  320.             thisrerr = nextrerr;
  321.             nextrerr = temperr;
  322.             temperr = thisgerr;
  323.             thisgerr = nextgerr;
  324.             nextgerr = temperr;
  325.             temperr = thisberr;
  326.             thisberr = nextberr;
  327.             nextberr = temperr;
  328.             fs_direction = ! fs_direction;
  329.         }
  330.  
  331. /*        ppm_writeppmrow( stdout, (pixel *)imagearray[row], imagewidth, maxval, 0 );*/
  332.     }
  333.     ppm_freecolorhash(cht);
  334.     free(thisrerr);
  335.     free(nextrerr);
  336.     free(thisgerr);
  337.     free(nextgerr);
  338.     free(thisberr);
  339.     free(nextberr);
  340.     (*maxcolorvalue)=maxval;
  341.     (*pchv)=colormap;
  342.     return CONV_OK;
  343. }
  344.  
  345. /*
  346. ** Here is the fun part, the median-cut colormap generator.  This is based
  347. ** on Paul Heckbert's paper "Color Image Quantization for Frame Buffer
  348. ** Display", SIGGRAPH '82 Proceedings, page 297.
  349. */
  350.  
  351. static colorhist_vector
  352. mediancut( colorhist_vector chv, int16 colors, int32 sum, pixval maxval, int16 newcolors )
  353. {
  354.     colorhist_vector colormap;
  355.     box_vector bv;
  356.     register int16 bi, i;
  357.     int16 boxes;
  358.  
  359.     bv = (box_vector) malloc( sizeof(struct box) * newcolors );
  360.     colormap = (colorhist_vector) malloc( sizeof(struct colorhist_item) * newcolors );
  361.     if ( bv == (box_vector) 0 || colormap == (colorhist_vector) 0 )
  362.         return NULL;
  363.     for ( i = 0; i < newcolors; ++i )
  364.         PPM_ASSIGN( colormap[i].color, 0, 0, 0 );
  365.  
  366.         /*
  367.         ** Set up the initial box.
  368.     */
  369.     bv[0].ind = 0;
  370.     bv[0].colors = colors;
  371.     bv[0].sum = sum;
  372.     boxes = 1;
  373.  
  374.     /*
  375.     ** Main loop: split boxes until we have enough.
  376.     */
  377.     while ( boxes < newcolors )
  378.     {
  379.         register int32 indx, clrs;
  380.         int32 sm;
  381.         register int32 minr, maxr, ming, maxg, minb, maxb, v;
  382.         int32 halfsum, lowersum;
  383.  
  384.         /*
  385.         ** Find the first splittable box.
  386.         */
  387.         for ( bi = 0; bi < boxes; ++bi )
  388.             if ( bv[bi].colors >= 2 )
  389.             break;
  390.         if ( bi == boxes )
  391.             break;    /* ran out of colors! */
  392.         indx = bv[bi].ind;
  393.         clrs = bv[bi].colors;
  394.         sm = bv[bi].sum;
  395.  
  396.         /*
  397.         ** Go through the box finding the minimum and maximum of each
  398.         ** component - the boundaries of the box.
  399.         */
  400.         minr = maxr = PPM_GETR( chv[indx].color );
  401.         ming = maxg = PPM_GETG( chv[indx].color );
  402.         minb = maxb = PPM_GETB( chv[indx].color );
  403.         for ( i = 1; i < clrs; ++i )
  404.         {
  405.             v = PPM_GETR( chv[indx + i].color );
  406.             if ( v < minr ) minr = v;
  407.             if ( v > maxr ) maxr = v;
  408.             v = PPM_GETG( chv[indx + i].color );
  409.             if ( v < ming ) ming = v;
  410.             if ( v > maxg ) maxg = v;
  411.             v = PPM_GETB( chv[indx + i].color );
  412.             if ( v < minb ) minb = v;
  413.             if ( v > maxb ) maxb = v;
  414.         }
  415.  
  416.         /*
  417.         ** Find the largest dimension, and sort by that component.  I have
  418.         ** included two methods for determining the "largest" dimension;
  419.         ** first by simply comparing the range in RGB space, and second
  420.         ** by transforming into luminosities before the comparison.  You
  421.         ** can switch which method is used by switching the commenting on
  422.         ** the LARGE_ defines at the beginning of this source file.
  423.         */
  424. #ifdef LARGE_NORM
  425.         if ( maxr - minr >= maxg - ming && maxr - minr >= maxb - minb )
  426.             XP_QSORT(
  427.             (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
  428.             (qsortprototype)redcompare );
  429.         else if ( maxg - ming >= maxb - minb )
  430.             XP_QSORT(
  431.             (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
  432.             (qsortprototype)greencompare );
  433.         else
  434.             XP_QSORT(
  435.             (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
  436.             (qsortprototype)bluecompare );
  437. #endif /*LARGE_NORM*/
  438. #ifdef LARGE_LUM
  439.         {
  440.             pixel p;
  441.             float rl, gl, bl;
  442.  
  443.             PPM_ASSIGN(p, maxr - minr, 0, 0);
  444.             rl = PPM_LUMIN(p);
  445.             PPM_ASSIGN(p, 0, maxg - ming, 0);
  446.             gl = PPM_LUMIN(p);
  447.             PPM_ASSIGN(p, 0, 0, maxb - minb);
  448.             bl = PPM_LUMIN(p);
  449.  
  450.             if ( rl >= gl && rl >= bl )
  451.                 XP_QSORT(
  452.                 (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
  453.                 redcompare );
  454.             else if ( gl >= bl )
  455.                 XP_QSORT(
  456.                 (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
  457.                 greencompare );
  458.             else
  459.                 XP_QSORT(
  460.                 (char*) &(chv[indx]), clrs, sizeof(struct colorhist_item),
  461.                 bluecompare );
  462.         }
  463. #endif /*LARGE_LUM*/
  464.         
  465.         /*
  466.         ** Now find the median based on the counts, so that about half the
  467.         ** pixels (not colors, pixels) are in each subdivision.
  468.         */
  469.         lowersum = chv[indx].value;
  470.         halfsum = sm / 2;
  471.         for ( i = 1; i < clrs - 1; ++i )
  472.         {
  473.             if ( lowersum >= halfsum )
  474.                 break;
  475.             lowersum += chv[indx + i].value;
  476.         }
  477.  
  478.         /*
  479.         ** Split the box, and sort to bring the biggest boxes to the top.
  480.         */
  481.         bv[bi].colors = i;
  482.         bv[bi].sum = lowersum;
  483.         bv[boxes].ind = indx + i;
  484.         bv[boxes].colors = clrs - i;
  485.         bv[boxes].sum = sm - lowersum;
  486.         ++boxes;
  487.         XP_QSORT( (char*) bv, boxes, sizeof(struct box), (qsortprototype)sumcompare );
  488.     }
  489.  
  490.     /*
  491.     ** Ok, we've got enough boxes.  Now choose a representative color for
  492.     ** each box.  There are a number of possible ways to make this choice.
  493.     ** One would be to choose the center of the box; this ignores any structure
  494.     ** within the boxes.  Another method would be to average all the colors in
  495.     ** the box - this is the method specified in Heckbert's paper.  A third
  496.     ** method is to average all the pixels in the box.  You can switch which
  497.     ** method is used by switching the commenting on the REP_ defines at
  498.     ** the beginning of this source file.
  499.     */
  500.     for ( bi = 0; bi < boxes; ++bi )
  501.     {
  502. #ifdef REP_CENTER_BOX
  503.         register int16 indx = bv[bi].ind;
  504.         register int16 clrs = bv[bi].colors;
  505.         register int16 minr, maxr, ming, maxg, minb, maxb, v;
  506.  
  507.         minr = maxr = PPM_GETR( chv[indx].color );
  508.         ming = maxg = PPM_GETG( chv[indx].color );
  509.         minb = maxb = PPM_GETB( chv[indx].color );
  510.         for ( i = 1; i < clrs; ++i )
  511.         {
  512.             v = PPM_GETR( chv[indx + i].color );
  513.             minr = min( minr, v );
  514.             maxr = max( maxr, v );
  515.             v = PPM_GETG( chv[indx + i].color );
  516.             ming = min( ming, v );
  517.             maxg = max( maxg, v );
  518.             v = PPM_GETB( chv[indx + i].color );
  519.             minb = min( minb, v );
  520.             maxb = max( maxb, v );
  521.         }
  522.         PPM_ASSIGN(
  523.             colormap[bi].color, ( minr + maxr ) / 2, ( ming + maxg ) / 2,
  524.             ( minb + maxb ) / 2 );
  525. #endif /*REP_CENTER_BOX*/
  526. #ifdef REP_AVERAGE_COLORS
  527.         register int16 indx = bv[bi].ind;
  528.         register int16 clrs = bv[bi].colors;
  529.         register int32 r = 0, g = 0, b = 0;
  530.  
  531.         for ( i = 0; i < clrs; ++i )
  532.         {
  533.             r += PPM_GETR( chv[indx + i].color );
  534.             g += PPM_GETG( chv[indx + i].color );
  535.             b += PPM_GETB( chv[indx + i].color );
  536.         }
  537.         r = r / clrs;
  538.         g = g / clrs;
  539.         b = b / clrs;
  540.         PPM_ASSIGN( colormap[bi].color, (pixval)r, (pixval)g, (pixval)b );
  541. #endif /*REP_AVERAGE_COLORS*/
  542. #ifdef REP_AVERAGE_PIXELS
  543.         register int16 indx = bv[bi].ind;
  544.         register int16 clrs = bv[bi].colors;
  545.         register int32 r = 0, g = 0, b = 0, sum = 0;
  546.  
  547.         for ( i = 0; i < clrs; ++i )
  548.         {
  549.             r += PPM_GETR( chv[indx + i].color ) * chv[indx + i].value;
  550.             g += PPM_GETG( chv[indx + i].color ) * chv[indx + i].value;
  551.             b += PPM_GETB( chv[indx + i].color ) * chv[indx + i].value;
  552.             sum += chv[indx + i].value;
  553.         }
  554.         r = r / sum;
  555.         if ( r > maxval ) r = maxval;    /* avoid math errors */
  556.         g = g / sum;
  557.         if ( g > maxval ) g = maxval;
  558.         b = b / sum;
  559.         if ( b > maxval ) b = maxval;
  560.         PPM_ASSIGN( colormap[bi].color, r, g, b );
  561. #endif /*REP_AVERAGE_PIXELS*/
  562.     }
  563.  
  564.     /*
  565.     ** All done.
  566.     */
  567.     free (bv);
  568.     return colormap;
  569. }
  570.  
  571. static int
  572. redcompare( ch1, ch2 )
  573. const colorhist_vector ch1, ch2;
  574. {
  575.     return (int16) PPM_GETR( ch1->color ) - (int16) PPM_GETR( ch2->color );
  576. }
  577.  
  578. static int
  579. greencompare( ch1, ch2 )
  580. const colorhist_vector ch1, ch2;
  581. {
  582.     return (int16) PPM_GETG( ch1->color ) - (int16) PPM_GETG( ch2->color );
  583. }
  584.  
  585. static int
  586. bluecompare( ch1, ch2 )
  587. const colorhist_vector ch1, ch2;
  588. {
  589.     return (int16) PPM_GETB( ch1->color ) - (int16) PPM_GETB( ch2->color );
  590. }
  591.  
  592. static int
  593. sumcompare( b1, b2 )
  594. const box_vector b1, b2;
  595. {
  596.     return b2->sum - b1->sum;
  597. }
  598.