The netpbm-1mar1994 release of ppmquant suffers from an overflow bug.
(The "distance" between colors is computed as a long, but it won't
fit in a 32-bit long if maxval is 65535.)
You can test for this bug by running
ppmmake red 10 10 | ppmquant 256 | ppmhist
If you get this output:
r g b lum count
--- --- --- --- -----
0 0 0 0 100
then you've got the bug. The fixed version will
produce the correct output (all red):
r g b lum count
--- --- --- --- -----
65535 0 0 19595 100
- Darrell Kindred (dkindred@cmu.edu), 15 March 1997
--- ppm/ppmquant.c.orig Mon Oct 4 05:12:30 1993
+++ ppm/ppmquant.c Sat Mar 15 15:39:54 1997
@@ -247,20 +247,22 @@
ind = ppm_lookupcolor( cht, pP );
if ( ind == -1 )
{ /* No; search colormap for closest match. */
- register int i, r1, g1, b1, r2, g2, b2;
- register long dist, newdist;
+ int i;
+ pixval r1, g1, b1, r2, g2, b2;
+ double dist, newdist;
r1 = PPM_GETR( *pP );
g1 = PPM_GETG( *pP );
b1 = PPM_GETB( *pP );
- dist = 2000000000;
+ /* 3 * maxval^2 is the largest distance possible */
+ dist = (double) maxval * maxval * 4;
for ( i = 0; i < newcolors; ++i )
{
r2 = PPM_GETR( colormap[i].color );
g2 = PPM_GETG( colormap[i].color );
b2 = PPM_GETB( colormap[i].color );
- newdist = ( r1 - r2 ) * ( r1 - r2 ) +
- ( g1 - g2 ) * ( g1 - g2 ) +
- ( b1 - b2 ) * ( b1 - b2 );
+ newdist = (double) ( r1 - r2 ) * ( r1 - r2 ) +
+ (double) ( g1 - g2 ) * ( g1 - g2 ) +
+ (double) ( b1 - b2 ) * ( b1 - b2 );
if ( newdist < dist )
{
ind = i;