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

  1. /* pnmgamma.c - perform gamma correction on a portable pixmap
  2. **
  3. ** Copyright (C) 1991 by Bill Davidson and 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 <math.h>
  14. #include <ctype.h>
  15. #include "pnm.h"
  16.  
  17. static void buildgamma ARGS(( xelval table[], xelval maxval, double gamma ));
  18.  
  19. int
  20. main( argc, argv )
  21.     int argc;
  22.     char* argv[];
  23.     {
  24.     FILE* ifp;
  25.     xel* xelrow;
  26.     register xel* xP;
  27.     xelval maxval;
  28.     int argn, rows, cols, format, newformat, row;
  29.     register int col;
  30.     double rgamma, ggamma, bgamma;
  31.     xelval* rtable;
  32.     xelval* gtable;
  33.     xelval* btable;
  34.     char *usage = "<value> [pnmfile]\n\t\t<redvalue> <greenvalue> <bluevalue> [pnmfile]";
  35.  
  36.     pnm_init( &argc, argv );
  37.  
  38.     argn = 1;
  39.  
  40.     /* Parse gamma args. */
  41.     if ( argc == 2 || argc == 3 )
  42.     {
  43.     rgamma = ggamma = bgamma = atof( argv[argn] );
  44.     ++argn;
  45.     }
  46.     else if ( argc == 4 || argc == 5 )
  47.     {
  48.     rgamma = atof( argv[argn] );
  49.     ++argn;
  50.     ggamma = atof( argv[argn] );
  51.     ++argn;
  52.     bgamma = atof( argv[argn] );
  53.     ++argn;
  54.     }
  55.     else
  56.     pm_usage( usage );
  57.  
  58.     if ( rgamma <= 0.0 || ggamma <= 0.0 || bgamma <= 0.0 )
  59.     pm_usage( usage );
  60.  
  61.     if ( argn != argc )
  62.     {
  63.         ifp = pm_openr( argv[argn] );
  64.         ++argn;
  65.     }
  66.     else 
  67.     ifp = stdin;
  68.  
  69.     if ( argn != argc )
  70.     pm_usage( usage );
  71.  
  72.     pnm_pbmmaxval = PNM_MAXMAXVAL;  /* use larger value for better results */
  73.     pnm_readpnminit( ifp, &cols, &rows, &maxval, &format );
  74.     xelrow = pnm_allocrow( cols );
  75.  
  76.     /* Promote PBM files to PGM.  Not that it makes much sense to
  77.     ** gamma-correct PBM files. */
  78.     if ( PNM_FORMAT_TYPE(format) == PBM_TYPE )
  79.     {
  80.         newformat = PGM_TYPE;
  81.     pm_message( "promoting to PGM" );
  82.     }
  83.     else
  84.         newformat = format;
  85.  
  86.     if ( rgamma != ggamma || ggamma != bgamma )
  87.     if ( PNM_FORMAT_TYPE(newformat) == PGM_TYPE )
  88.         {
  89.         newformat = PPM_TYPE;
  90.         pm_message( "promoting to PPM" );
  91.         }
  92.  
  93.     /* Allocate space for the tables. */
  94.     rtable = (xelval*) malloc( (maxval+1) * sizeof(xelval) );
  95.     gtable = (xelval*) malloc( (maxval+1) * sizeof(xelval) );
  96.     btable = (xelval*) malloc( (maxval+1) * sizeof(xelval) );
  97.     if ( rtable == 0 || gtable == 0 || btable == 0 )
  98.     pm_error( "out of memory" );
  99.  
  100.     /* Build the gamma corection tables. */
  101.     buildgamma( rtable, maxval, rgamma );
  102.     buildgamma( gtable, maxval, ggamma );
  103.     buildgamma( btable, maxval, bgamma );
  104.  
  105.     pnm_writepnminit( stdout, cols, rows, maxval, newformat, 0 );
  106.     for ( row = 0; row < rows; ++row )
  107.     {
  108.     pnm_readpnmrow( ifp, xelrow, cols, maxval, format );
  109.  
  110.     /* Promote to PPM if differing gammas were specified. */
  111.     if ( rgamma != ggamma || ggamma != bgamma )
  112.         if ( PNM_FORMAT_TYPE(format) != PPM_TYPE &&
  113.          PNM_FORMAT_TYPE(newformat) == PPM_TYPE )
  114.         pnm_promoteformatrow(
  115.             xelrow, cols, maxval, format, maxval, newformat );
  116.  
  117.     switch ( PNM_FORMAT_TYPE(newformat) )
  118.         {
  119.         case PPM_TYPE:
  120.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  121.         {
  122.         register xelval r, g, b;
  123.  
  124.         r = PPM_GETR( *xP );
  125.         g = PPM_GETG( *xP );
  126.         b = PPM_GETB( *xP );
  127.         r = rtable[r];
  128.         g = gtable[g];
  129.         b = btable[b];
  130.         PPM_ASSIGN( *xP, r, g, b );
  131.         }
  132.         break;
  133.  
  134.         default:
  135.         for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
  136.         {
  137.         register xelval g;
  138.  
  139.         g = PNM_GET1( *xP );
  140.         g = gtable[g];
  141.         PNM_ASSIGN1( *xP, g );
  142.         }
  143.         break;
  144.         }
  145.  
  146.     pnm_writepnmrow( stdout, xelrow, cols, maxval, newformat, 0 );
  147.     }
  148.  
  149.     pm_close( ifp );
  150.     pm_close( stdout );
  151.  
  152.     exit( 0 );
  153.     }
  154.  
  155. /*
  156. ** Builds a gamma table of size maxval+1 for the given gamma value.
  157. **
  158. ** This function depends on pow(3m).  If you don't have it, you can
  159. ** simulate it with '#define pow(x,y) exp((y)*log(x))' provided that
  160. ** you have the exponential function exp(3m) and the natural logarithm
  161. ** function log(3m).  I can't believe I actually remembered my log
  162. ** identities.
  163. */
  164.  
  165. #if __STDC__
  166. static void
  167. buildgamma( xelval table[], xelval maxval, double gamma )
  168. #else /*__STDC__*/
  169. static void
  170. buildgamma( table, maxval, gamma )
  171.     xelval table[], maxval;
  172.     double gamma;
  173. #endif /*__STDC__*/
  174.     {
  175.     register int i, v;
  176.     double one_over_gamma, ind, q;
  177.  
  178.     one_over_gamma = 1.0 / gamma;
  179.     q = (double) maxval;
  180.     for ( i = 0 ; i <= (int) maxval; ++i )
  181.     {
  182.     ind = ( (double) i ) / q;
  183.     v = ( q * pow( ind, one_over_gamma ) ) + 0.5;
  184.     if ( v > (int) maxval )
  185.         v = maxval;
  186.     table[i] = v;
  187.     }
  188.     }
  189.