home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / ppm / libppm4.c < prev    next >
C/C++ Source or Header  |  1993-10-04  |  11KB  |  329 lines

  1. /* libppm4.c - ppm utility library part 4
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "ppm.h"
  14.  
  15. static void canonstr ARGS((char* str));
  16. static long rgbnorm ARGS((long rgb, long lmaxval, int n, char* colorname));
  17. static void
  18. canonstr( str )
  19.     char* str;
  20.     {
  21.     while ( *str != '\0' )
  22.         {
  23.         if ( *str == ' ' )
  24.             {
  25.             (void) strcpy( str, &(str[1]) );
  26.             continue;
  27.             }
  28.         if ( isupper( *str ) )
  29.             *str = tolower( *str );
  30.         ++str;
  31.         }
  32.     }
  33.  
  34. static long
  35. rgbnorm( rgb, lmaxval, n, colorname )
  36.     long rgb, lmaxval;
  37.     int n;
  38.     char* colorname;
  39.     {
  40.     switch ( n )
  41.         {
  42.         case 1:
  43.         if ( lmaxval != 15 )
  44.             rgb = rgb * lmaxval / 15;
  45.         break;
  46.         case 2:
  47.         if ( lmaxval != 255 )
  48.             rgb = rgb * lmaxval / 255;
  49.         break;
  50.         case 3:
  51.         if ( lmaxval != 4095 )
  52.             rgb = rgb * lmaxval / 4095;
  53.         break;
  54.         case 4:
  55.         if ( lmaxval != 65535L )
  56.             rgb = rgb * lmaxval / 65535L;
  57.         break;
  58.         default:
  59.         pm_error( "invalid color specifier - \"%s\"", colorname );
  60.         }
  61.     return rgb;
  62.     }
  63.  
  64. #if __STDC__
  65. pixel
  66. ppm_parsecolor( char* colorname, pixval maxval )
  67. #else /*__STDC__*/
  68. pixel
  69. ppm_parsecolor( colorname, maxval )
  70.     char* colorname;
  71.     pixval maxval;
  72. #endif /*__STDC__*/
  73.     {
  74.     int hexit[256], i;
  75.     pixel p;
  76.     long lmaxval, r, g, b;
  77.     char* inval = "invalid color specifier - \"%s\"";
  78.  
  79.     for ( i = 0; i < 256; ++i )
  80.         hexit[i] = 1234567890;
  81.     hexit['0'] = 0;
  82.     hexit['1'] = 1;
  83.     hexit['2'] = 2;
  84.     hexit['3'] = 3;
  85.     hexit['4'] = 4;
  86.     hexit['5'] = 5;
  87.     hexit['6'] = 6;
  88.     hexit['7'] = 7;
  89.     hexit['8'] = 8;
  90.     hexit['9'] = 9;
  91.     hexit['a'] = hexit['A'] = 10;
  92.     hexit['b'] = hexit['B'] = 11;
  93.     hexit['c'] = hexit['C'] = 12;
  94.     hexit['d'] = hexit['D'] = 13;
  95.     hexit['e'] = hexit['E'] = 14;
  96.     hexit['f'] = hexit['F'] = 15;
  97.  
  98.     lmaxval = maxval;
  99.     if ( strncmp( colorname, "rgb:", 4 ) == 0 )
  100.         {
  101.         /* It's a new-X11-style hexadecimal rgb specifier. */
  102.         char* cp;
  103.  
  104.         cp = colorname + 4;
  105.         r = g = b = 0;
  106.         for ( i = 0; *cp != '/'; ++i, ++cp )
  107.             r = r * 16 + hexit[*cp];
  108.         r = rgbnorm( r, lmaxval, i, colorname );
  109.         for ( i = 0, ++cp; *cp != '/'; ++i, ++cp )
  110.             g = g * 16 + hexit[*cp];
  111.         g = rgbnorm( g, lmaxval, i, colorname );
  112.         for ( i = 0, ++cp; *cp != '\0'; ++i, ++cp )
  113.             b = b * 16 + hexit[*cp];
  114.         b = rgbnorm( b, lmaxval, i, colorname );
  115.         if ( r < 0 || r > lmaxval || g < 0 || g > lmaxval || b < 0 || b > lmaxval )
  116.             pm_error( inval, colorname );
  117.         }
  118.     else if ( strncmp( colorname, "rgbi:", 5 ) == 0 )
  119.         {
  120.         /* It's a new-X11-style decimal/float rgb specifier. */
  121.         float fr, fg, fb;
  122.  
  123.         if ( sscanf( colorname, "rgbi:%f/%f/%f", &fr, &fg, &fb ) != 3 )
  124.             pm_error( inval, colorname );
  125.         if ( fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 || fb < 0.0 || fb > 1.0 )
  126.             pm_error( "invalid color specifier - \"%s\" - values must be between 0.0 and 1.0", colorname );
  127.         r = fr * lmaxval;
  128.         g = fg * lmaxval;
  129.         b = fb * lmaxval;
  130.         }
  131.     else if ( colorname[0] == '#' )
  132.         {
  133.         /* It's an old-X11-style hexadecimal rgb specifier. */
  134.         switch ( strlen( colorname ) )
  135.             {
  136.             case 4:
  137.             r = hexit[colorname[1]];
  138.             g = hexit[colorname[2]];
  139.             b = hexit[colorname[3]];
  140.             r = rgbnorm( r, lmaxval, 1, colorname );
  141.             g = rgbnorm( g, lmaxval, 1, colorname );
  142.             b = rgbnorm( b, lmaxval, 1, colorname );
  143.             break;
  144.  
  145.             case 7:
  146.             r = ( hexit[colorname[1]] << 4 ) + hexit[colorname[2]];
  147.             g = ( hexit[colorname[3]] << 4 ) + hexit[colorname[4]];
  148.             b = ( hexit[colorname[5]] << 4 ) + hexit[colorname[6]];
  149.             r = rgbnorm( r, lmaxval, 2, colorname );
  150.             g = rgbnorm( g, lmaxval, 2, colorname );
  151.             b = rgbnorm( b, lmaxval, 2, colorname );
  152.             break;
  153.  
  154.             case 10:
  155.             r = ( hexit[colorname[1]] << 8 ) + ( hexit[colorname[2]] << 4 ) +
  156.                 hexit[colorname[3]];
  157.             g = ( hexit[colorname[4]] << 8 ) + ( hexit[colorname[5]] << 4 ) +
  158.                 hexit[colorname[6]];
  159.             b = ( hexit[colorname[7]] << 8 ) + ( hexit[colorname[8]] << 4 ) +
  160.                 hexit[colorname[9]];
  161.             r = rgbnorm( r, lmaxval, 3, colorname );
  162.             g = rgbnorm( g, lmaxval, 3, colorname );
  163.             b = rgbnorm( b, lmaxval, 3, colorname );
  164.             break;
  165.  
  166.             case 13:
  167.             r = ( hexit[colorname[1]] << 12 ) + ( hexit[colorname[2]] << 8 ) +
  168.                 ( hexit[colorname[3]] << 4 ) + hexit[colorname[4]];
  169.             g = ( hexit[colorname[5]] << 12 ) + ( hexit[colorname[6]] << 8 ) +
  170.                 ( hexit[colorname[7]] << 4 ) + hexit[colorname[8]];
  171.             b = ( hexit[colorname[9]] << 12 ) + ( hexit[colorname[10]] << 8 ) +
  172.                 ( hexit[colorname[11]] << 4 ) + hexit[colorname[12]];
  173.             r = rgbnorm( r, lmaxval, 4, colorname );
  174.             g = rgbnorm( g, lmaxval, 4, colorname );
  175.             b = rgbnorm( b, lmaxval, 4, colorname );
  176.             break;
  177.  
  178.             default:
  179.             pm_error( inval, colorname );
  180.             }
  181.         if ( r < 0 || r > lmaxval || g < 0 || g > lmaxval || b < 0 || b > lmaxval )
  182.             pm_error( inval, colorname );
  183.         }
  184.     else if ( ( colorname[0] >= '0' && colorname[0] <= '9' ) ||
  185.               colorname[0] == '.' )
  186.         {
  187.         /* It's an old-style decimal/float rgb specifier. */
  188.         float fr, fg, fb;
  189.  
  190.         if ( sscanf( colorname, "%f,%f,%f", &fr, &fg, &fb ) != 3 )
  191.             pm_error( inval, colorname );
  192.         if ( fr < 0.0 || fr > 1.0 || fg < 0.0 || fg > 1.0 || fb < 0.0 || fb > 1.0 )
  193.             pm_error( "invalid color specifier - \"%s\" - values must be between 0.0 and 1.0", colorname );
  194.         r = fr * lmaxval;
  195.         g = fg * lmaxval;
  196.         b = fb * lmaxval;
  197.         }
  198.     else
  199.         {
  200.         /* Must be a name from the X-style rgb file. */
  201. #ifndef RGB_DB
  202.         pm_error( "color names database required - please reconfigure with RGBDEF" );
  203. #else /*RGB_DB*/
  204.         FILE* f;
  205.         char buf1[200], buf2[200];
  206.  
  207. #ifndef A_RGBENV
  208.         (void) sprintf( buf1, "%s.txt", RGB_DB );
  209.         if ( ( f = fopen( buf1, "r" ) ) == NULL )
  210.             pm_error( "can't open color names database - reconfigure with correct RGBDEF" );
  211. #else /* A_RGBENV */
  212.         char *rgbdef;
  213.         if( (rgbdef = getenv(RGB_DB))==NULL )
  214.             pm_error( "can't get path to color names database - %s not set", RGB_DB );
  215.         if ( ( f = fopen( rgbdef, "r" ) ) == NULL )
  216.             pm_error( "can't open color names database - set %s to correct path", RGB_DB );
  217. #endif /* A_RGBENV */
  218.         canonstr( colorname );
  219.         while ( fgets( buf1, sizeof(buf1), f ) != NULL )
  220.             {
  221.             if ( sscanf( buf1, "%ld %ld %ld %[^\n]", &r, &g, &b, buf2 ) != 4 )
  222.                 {
  223.                 pm_message(
  224.                     "can't parse color names database line - \"%s\"", buf1 );
  225.                 continue;
  226.                 }
  227.             canonstr( buf2 );
  228.             if ( strcmp( colorname, buf2 ) == 0 )
  229.                 goto gotit;
  230.             }
  231.         (void) fclose( f );
  232.         pm_error( "unknown color - \"%s\"", colorname );
  233.  
  234. gotit:
  235.         (void) fclose( f );
  236.         /* Rescale from [0..255] if necessary. */
  237.         if ( lmaxval != 255 )
  238.             {
  239.             r = r * lmaxval / 255;
  240.             g = g * lmaxval / 255;
  241.             b = b * lmaxval / 255;
  242.             }
  243. #endif /*RGB_DB*/
  244.         }
  245.  
  246.     PPM_ASSIGN( p, r, g, b );
  247.     return p;
  248.     }
  249.  
  250. static char colorname[200];
  251.  
  252. #if __STDC__
  253. char*
  254. ppm_colorname( pixel* colorP, pixval maxval, int hexok )
  255. #else /*__STDC__*/
  256. char*
  257. ppm_colorname( colorP, maxval, hexok )
  258.     pixel* colorP;
  259.     pixval maxval;
  260.     int hexok;
  261. #endif /*__STDC__*/
  262.     {
  263.     int r, g, b;
  264. #ifdef RGB_DB
  265.     FILE* f;
  266.     char buf[200];
  267.     int this_r, this_g, this_b;
  268.     int best_diff, this_diff;
  269.     char this_colorname[200];
  270. #ifdef A_RGBENV
  271.     char *rgbdef;
  272. #endif /* A_RGBENV */
  273. #endif /*RGB_DB*/
  274.  
  275.     if ( maxval == 255 )
  276.         {
  277.         r = PPM_GETR( *colorP );
  278.         g = PPM_GETG( *colorP );
  279.         b = PPM_GETB( *colorP );
  280.         }
  281.     else
  282.         {
  283.         r = (int) PPM_GETR( *colorP ) * 255 / (int) maxval;
  284.         g = (int) PPM_GETG( *colorP ) * 255 / (int) maxval;
  285.         b = (int) PPM_GETB( *colorP ) * 255 / (int) maxval;
  286.         }
  287.  
  288. #ifdef RGB_DB
  289. #ifndef A_RGBENV
  290.     (void) sprintf( buf, "%s.txt", RGB_DB );
  291.     if ( ( f = fopen( buf, "r" ) ) == NULL )
  292.         pm_error( "can't open color names database - reconfigure with correct RGBDEF" );
  293. #else /* A_RGBENV */
  294.     if( (rgbdef = getenv(RGB_DB))==NULL )
  295.         pm_error( "can't get path to color names database - %s not set", RGB_DB );
  296.     if ( ( f = fopen( rgbdef, "r" ) ) == NULL )
  297.         pm_error( "can't open color names database - set %s to correct path", RGB_DB );
  298. #endif /* A_RGBENV */
  299.     best_diff = 32767;
  300.     while ( fgets( buf, sizeof(buf), f ) != NULL )
  301.         {
  302.         if ( sscanf( buf, "%d %d %d %[^\n]", &this_r, &this_g, &this_b,
  303.                      this_colorname ) != 4 )
  304.             {
  305.             pm_message(
  306.                 "can't parse color names database line - \"%s\"",
  307.                 buf );
  308.             continue;
  309.             }
  310.         this_diff = abs( r - this_r ) + abs( g - this_g ) + abs( b - this_b );
  311.         if ( this_diff < best_diff )
  312.             {
  313.             best_diff = this_diff;
  314.             (void) strcpy( colorname, this_colorname );
  315.             }
  316.         }
  317.     (void) fclose( f );
  318.     if ( best_diff != 32767 && ( best_diff == 0 || ! hexok ) )
  319.         return colorname;
  320. #endif /*RGB_DB*/
  321.  
  322.     /* Color lookup failed; generate an X11-style hex specifier. */
  323.     if ( ! hexok )
  324.         pm_error(
  325.             "color names database required - please reconfigure with RGBDEF" );
  326.     sprintf( colorname, "#%02x%02x%02x", r, g, b );
  327.     return colorname;
  328.     }
  329.