home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
NETWORK
/
netpbm_src.lzh
/
NETPBM
/
PNM
/
pnmgamma.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-18
|
5KB
|
189 lines
/* pnmgamma.c - perform gamma correction on a portable pixmap
**
** Copyright (C) 1991 by Bill Davidson and 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 <math.h>
#include <ctype.h>
#include "pnm.h"
static void buildgamma ARGS(( xelval table[], xelval maxval, double gamma ));
int
main( argc, argv )
int argc;
char* argv[];
{
FILE* ifp;
xel* xelrow;
register xel* xP;
xelval maxval;
int argn, rows, cols, format, newformat, row;
register int col;
double rgamma, ggamma, bgamma;
xelval* rtable;
xelval* gtable;
xelval* btable;
char *usage = "<value> [pnmfile]\n\t\t<redvalue> <greenvalue> <bluevalue> [pnmfile]";
pnm_init( &argc, argv );
argn = 1;
/* Parse gamma args. */
if ( argc == 2 || argc == 3 )
{
rgamma = ggamma = bgamma = atof( argv[argn] );
++argn;
}
else if ( argc == 4 || argc == 5 )
{
rgamma = atof( argv[argn] );
++argn;
ggamma = atof( argv[argn] );
++argn;
bgamma = atof( argv[argn] );
++argn;
}
else
pm_usage( usage );
if ( rgamma <= 0.0 || ggamma <= 0.0 || bgamma <= 0.0 )
pm_usage( usage );
if ( argn != argc )
{
ifp = pm_openr( argv[argn] );
++argn;
}
else
ifp = stdin;
if ( argn != argc )
pm_usage( usage );
pnm_pbmmaxval = PNM_MAXMAXVAL; /* use larger value for better results */
pnm_readpnminit( ifp, &cols, &rows, &maxval, &format );
xelrow = pnm_allocrow( cols );
/* Promote PBM files to PGM. Not that it makes much sense to
** gamma-correct PBM files. */
if ( PNM_FORMAT_TYPE(format) == PBM_TYPE )
{
newformat = PGM_TYPE;
pm_message( "promoting to PGM" );
}
else
newformat = format;
if ( rgamma != ggamma || ggamma != bgamma )
if ( PNM_FORMAT_TYPE(newformat) == PGM_TYPE )
{
newformat = PPM_TYPE;
pm_message( "promoting to PPM" );
}
/* Allocate space for the tables. */
rtable = (xelval*) malloc( (maxval+1) * sizeof(xelval) );
gtable = (xelval*) malloc( (maxval+1) * sizeof(xelval) );
btable = (xelval*) malloc( (maxval+1) * sizeof(xelval) );
if ( rtable == 0 || gtable == 0 || btable == 0 )
pm_error( "out of memory" );
/* Build the gamma corection tables. */
buildgamma( rtable, maxval, rgamma );
buildgamma( gtable, maxval, ggamma );
buildgamma( btable, maxval, bgamma );
pnm_writepnminit( stdout, cols, rows, maxval, newformat, 0 );
for ( row = 0; row < rows; ++row )
{
pnm_readpnmrow( ifp, xelrow, cols, maxval, format );
/* Promote to PPM if differing gammas were specified. */
if ( rgamma != ggamma || ggamma != bgamma )
if ( PNM_FORMAT_TYPE(format) != PPM_TYPE &&
PNM_FORMAT_TYPE(newformat) == PPM_TYPE )
pnm_promoteformatrow(
xelrow, cols, maxval, format, maxval, newformat );
switch ( PNM_FORMAT_TYPE(newformat) )
{
case PPM_TYPE:
for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
{
register xelval r, g, b;
r = PPM_GETR( *xP );
g = PPM_GETG( *xP );
b = PPM_GETB( *xP );
r = rtable[r];
g = gtable[g];
b = btable[b];
PPM_ASSIGN( *xP, r, g, b );
}
break;
default:
for ( col = 0, xP = xelrow; col < cols; ++col, ++xP )
{
register xelval g;
g = PNM_GET1( *xP );
g = gtable[g];
PNM_ASSIGN1( *xP, g );
}
break;
}
pnm_writepnmrow( stdout, xelrow, cols, maxval, newformat, 0 );
}
pm_close( ifp );
pm_close( stdout );
exit( 0 );
}
/*
** Builds a gamma table of size maxval+1 for the given gamma value.
**
** This function depends on pow(3m). If you don't have it, you can
** simulate it with '#define pow(x,y) exp((y)*log(x))' provided that
** you have the exponential function exp(3m) and the natural logarithm
** function log(3m). I can't believe I actually remembered my log
** identities.
*/
#if __STDC__
static void
buildgamma( xelval table[], xelval maxval, double gamma )
#else /*__STDC__*/
static void
buildgamma( table, maxval, gamma )
xelval table[], maxval;
double gamma;
#endif /*__STDC__*/
{
register int i, v;
double one_over_gamma, ind, q;
one_over_gamma = 1.0 / gamma;
q = (double) maxval;
for ( i = 0 ; i <= (int) maxval; ++i )
{
ind = ( (double) i ) / q;
v = ( q * pow( ind, one_over_gamma ) ) + 0.5;
if ( v > (int) maxval )
v = maxval;
table[i] = v;
}
}