home *** CD-ROM | disk | FTP | other *** search
- /* libppm4.c - ppm utility library part 4
- **
- ** Copyright (C) 1989 by Jef Poskanzer.
- **
- ** Permission to use, copy, modify, and distribute this software and its
- ** documentation for any purpose and without fee is hereby granted, provided
- ** that the above copyright notice appear in all copies and that both that
- ** copyright notice and this permission notice appear in supporting
- ** documentation. This software is provided "as is" without express or
- ** implied warranty.
- */
-
- #include "ppm.h"
-
- static void
- canonstr( str )
- char* str;
- {
- while ( *str != '\0' )
- {
- if ( *str == ' ' )
- {
- (void) strcpy( str, &(str[1]) );
- continue;
- }
- if ( isupper( *str ) )
- *str = tolower( *str );
- ++str;
- }
- }
-
- static long
- rgbnorm( rgb, lmaxval, n, colorname )
- long rgb, lmaxval;
- int n;
- char* colorname;
- {
- switch ( n )
- {
- case 1:
- if ( lmaxval != 15 )
- rgb = rgb * lmaxval / 15;
- break;
- case 2:
- if ( lmaxval != 255 )
- rgb = rgb * lmaxval / 255;
- break;
- case 3:
- if ( lmaxval != 4095 )
- rgb = rgb * lmaxval / 4095;
- break;
- case 4:
- if ( lmaxval != 65535L )
- rgb = rgb * lmaxval / 65535L;
- break;
- default:
- pm_error( "invalid color specifier - \"%s\"", colorname );
- }
- return rgb;
- }
-
- #if __STDC__
- pixel
- ppm_parsecolor( char* colorname, pixval maxval )
- #else /*__STDC__*/
- pixel
- ppm_parsecolor( colorname, maxval )
- char* colorname;
- pixval maxval;
- #endif /*__STDC__*/
- {
- int hexit[256], i;
- pixel p;
- long lmaxval, r, g, b;
- char* inval = "invalid color specifier - \"%s\"";
-
- for ( i = 0; i < 256; ++i )
- hexit[i] = 1234567890;
- hexit['0'] = 0;
- hexit['1'] = 1;
- hexit['2'] = 2;
- hexit['3'] = 3;
- hexit['4'] = 4;
- hexit['5'] = 5;
- hexit['6'] = 6;
- hexit['7'] = 7;
- hexit['8'] = 8;
- hexit['9'] = 9;
- hexit['a'] = hexit['A'] = 10;
- hexit['b'] = hexit['B'] = 11;
- hexit['c'] = hexit['C'] = 12;
- hexit['d'] = hexit['D'] = 13;
- hexit['e'] = hexit['E'] = 14;
- hexit['f'] = hexit['F'] = 15;
-
- lmaxval = maxval;
- if ( strncmp( colorname, "rgb:", 4 ) == 0 )
- {
- /* It's a new-X11-style hexadecimal rgb specifier. */
- char* cp;
-
- cp = colorname + 4;
- r = g = b = 0;
- for ( i = 0; *cp != '/'; ++i, ++cp )
- r = r * 16 + hexit[*cp];
- r = rgbnorm( r, lmaxval, i, colorname );
- for ( i = 0, ++cp; *cp != '/'; ++i, ++cp )
- g = g * 16 + hexit[*cp];
- g = rgbnorm( g, lmaxval, i, colorname );
- for ( i = 0, ++cp; *cp != '\0'; ++i, ++cp )
- b = b * 16 + hexit[*cp];
- b = rgbnorm( b, lmaxval, i, colorname );
- if ( r < 0 || r > lmaxval || g < 0 || g > lmaxval || b < 0 || b > lmaxval )
- pm_error( inval, colorname );
- }
- else if ( strncmp( colorname, "rgbi:", 5 ) == 0 )
- {
- /* It's a new-X11-style decimal/float rgb specifier. */
- float fr, fg, fb;
-
- if ( sscanf( colorname, "rgbi:%f/%f/%f", &fr, &fg, &fb ) != 3 )
- pm_error( inval, colorname );
- if ( fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 || fb < 0.0 || fb > 1.0 )
- pm_error( "invalid color specifier - \"%s\" - values must be between 0.0 and 1.0", colorname );
- r = fr * lmaxval;
- g = fg * lmaxval;
- b = fb * lmaxval;
- }
- else if ( colorname[0] == '#' )
- {
- /* It's an old-X11-style hexadecimal rgb specifier. */
- switch ( strlen( colorname ) )
- {
- case 4:
- r = hexit[colorname[1]];
- g = hexit[colorname[2]];
- b = hexit[colorname[3]];
- r = rgbnorm( r, lmaxval, 1, colorname );
- g = rgbnorm( g, lmaxval, 1, colorname );
- b = rgbnorm( b, lmaxval, 1, colorname );
- break;
-
- case 7:
- r = ( hexit[colorname[1]] << 4 ) + hexit[colorname[2]];
- g = ( hexit[colorname[3]] << 4 ) + hexit[colorname[4]];
- b = ( hexit[colorname[5]] << 4 ) + hexit[colorname[6]];
- r = rgbnorm( r, lmaxval, 2, colorname );
- g = rgbnorm( g, lmaxval, 2, colorname );
- b = rgbnorm( b, lmaxval, 2, colorname );
- break;
-
- case 10:
- r = ( hexit[colorname[1]] << 8 ) + ( hexit[colorname[2]] << 4 ) +
- hexit[colorname[3]];
- g = ( hexit[colorname[4]] << 8 ) + ( hexit[colorname[5]] << 4 ) +
- hexit[colorname[6]];
- b = ( hexit[colorname[7]] << 8 ) + ( hexit[colorname[8]] << 4 ) +
- hexit[colorname[9]];
- r = rgbnorm( r, lmaxval, 3, colorname );
- g = rgbnorm( g, lmaxval, 3, colorname );
- b = rgbnorm( b, lmaxval, 3, colorname );
- break;
-
- case 13:
- r = ( hexit[colorname[1]] << 12 ) + ( hexit[colorname[2]] << 8 ) +
- ( hexit[colorname[3]] << 4 ) + hexit[colorname[4]];
- g = ( hexit[colorname[5]] << 12 ) + ( hexit[colorname[6]] << 8 ) +
- ( hexit[colorname[7]] << 4 ) + hexit[colorname[8]];
- b = ( hexit[colorname[9]] << 12 ) + ( hexit[colorname[10]] << 8 ) +
- ( hexit[colorname[11]] << 4 ) + hexit[colorname[12]];
- r = rgbnorm( r, lmaxval, 4, colorname );
- g = rgbnorm( g, lmaxval, 4, colorname );
- b = rgbnorm( b, lmaxval, 4, colorname );
- break;
-
- default:
- pm_error( inval, colorname );
- }
- if ( r < 0 || r > lmaxval || g < 0 || g > lmaxval || b < 0 || b > lmaxval )
- pm_error( inval, colorname );
- }
- else if ( ( colorname[0] >= '0' && colorname[0] <= '9' ) ||
- colorname[0] == '.' )
- {
- /* It's an old-style decimal/float rgb specifier. */
- float fr, fg, fb;
-
- if ( sscanf( colorname, "%f,%f,%f", &fr, &fg, &fb ) != 3 )
- pm_error( inval, colorname );
- if ( fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 || fb < 0.0 || fb > 1.0 )
- pm_error( "invalid color specifier - \"%s\" - values must be between 0.0 and 1.0", colorname );
- r = fr * lmaxval;
- g = fg * lmaxval;
- b = fb * lmaxval;
- }
- else
- {
- /* Must be a name from the X-style rgb file. */
- #ifndef RGB_DB
- pm_error( "color names database required - please reconfigure with RGBDEF" );
- #else /*RGB_DB*/
- FILE* f;
- char buf1[200], buf2[200];
-
- (void) sprintf( buf1, "%s.txt", RGB_DB );
- if ( ( f = fopen( buf1, "r" ) ) == NULL )
- pm_error( "can't open color names database - reconfigure with correct RGBDEF" );
- canonstr( colorname );
- while ( fgets( buf1, sizeof(buf1), f ) != NULL )
- {
- if ( sscanf( buf1, "%ld %ld %ld %[^\n]", &r, &g, &b, buf2 ) != 4 )
- {
- pm_message(
- "can't parse color names database line - \"%s\"", buf1 );
- continue;
- }
- canonstr( buf2 );
- if ( strcmp( colorname, buf2 ) == 0 )
- goto gotit;
- }
- (void) fclose( f );
- pm_error( "unknown color - \"%s\"", colorname );
-
- gotit:
- (void) fclose( f );
- /* Rescale from [0..255] if necessary. */
- if ( lmaxval != 255 )
- {
- r = r * lmaxval / 255;
- g = g * lmaxval / 255;
- b = b * lmaxval / 255;
- }
- #endif /*RGB_DB*/
- }
-
- PPM_ASSIGN( p, r, g, b );
- return p;
- }
-
- static char colorname[200];
-
- #if __STDC__
- char*
- ppm_colorname( pixel* colorP, pixval maxval, int hexok )
- #else /*__STDC__*/
- char*
- ppm_colorname( colorP, maxval, hexok )
- pixel* colorP;
- pixval maxval;
- int hexok;
- #endif /*__STDC__*/
- {
- int r, g, b;
- #ifdef RGB_DB
- FILE* f;
- char buf[200];
- int this_r, this_g, this_b;
- int best_diff, this_diff;
- char this_colorname[200];
- #endif /*RGB_DB*/
-
- if ( maxval == 255 )
- {
- r = PPM_GETR( *colorP );
- g = PPM_GETG( *colorP );
- b = PPM_GETB( *colorP );
- }
- else
- {
- r = (int) PPM_GETR( *colorP ) * 255 / (int) maxval;
- g = (int) PPM_GETG( *colorP ) * 255 / (int) maxval;
- b = (int) PPM_GETB( *colorP ) * 255 / (int) maxval;
- }
-
- #ifdef RGB_DB
- (void) sprintf( buf, "%s.txt", RGB_DB );
- if ( ( f = fopen( buf, "r" ) ) == NULL )
- pm_error( "can't open color names database - reconfigure with correct RGBDEF" );
- best_diff = 32767;
- while ( fgets( buf, sizeof(buf), f ) != NULL )
- {
- if ( sscanf( buf, "%d %d %d %[^\n]", &this_r, &this_g, &this_b,
- this_colorname ) != 4 )
- {
- pm_message(
- "can't parse color names database line - \"%s\"",
- buf );
- continue;
- }
- this_diff = abs( r - this_r ) + abs( g - this_g ) + abs( b - this_b );
- if ( this_diff < best_diff )
- {
- best_diff = this_diff;
- (void) strcpy( colorname, this_colorname );
- }
- }
- (void) fclose( f );
- if ( best_diff != 32767 && ( best_diff == 0 || ! hexok ) )
- return colorname;
- #endif /*RGB_DB*/
-
- /* Color lookup failed; generate an X11-style hex specifier. */
- if ( ! hexok )
- pm_error(
- "color names database required - please reconfigure with RGBDEF" );
- sprintf( colorname, "#%02x%02x%02x", r, g, b );
- return colorname;
- }
-