tools/unexp.c
/*
* unexp.c - take an exponential RLE file and make an integer file.
*
* Author: John W. Peterson
* Computer Science Dept.
* University of Utah
* Date: Wed Aug 21 17:02:45 1985
*
* Based on code by Spencer Thomas
*/
#include <stdio.h>
#include <math.h>
#include "rle.h"
#define MAX(i,j) ( (i) > (j) ? (i) : (j) )
#define RLE_EXPONENT (in_hdr.ncolors-1) /* Assume last channel is exp */
rle_pixel **in_rows;
rle_pixel **out_rows;
int truncations = 0;
rle_hdr in_hdr, out_hdr;
rle_pixel r_in, g_in, b_in;
void
main(argc,argv)
int argc;
char *argv[];
{
register int x, chan;
int y;
int scan_flag = 0;
int max_flag = 0;
int verbose_flag = 0;
int print_flag = 0;
int oflag = 0;
float maxval, tmp, expnt, tmp_max;
char *infilename = NULL, *outfilename = NULL;
FILE *outfile = stdout;
int rle_cnt, rle_err;
long start;
if (scanargs(argc, argv, "% v%- p%- s%- m%-maxval!f o%-outfile!s infile!s",
&verbose_flag, &print_flag, &scan_flag, &max_flag, &maxval,
&oflag, &outfilename, &infilename ) == 0)
{
exit(-1);
}
(void)rle_hdr_init( &in_hdr );
in_hdr.rle_file = rle_open_f(cmd_name( argv ), infilename, "r");
rle_names( &in_hdr, cmd_name( argv ), infilename, 0 );
rle_names( &out_hdr, in_hdr.cmd, outfilename, 0 );
for ( rle_cnt = 0; ; rle_cnt++ )
{
start = ftell( in_hdr.rle_file );
if ( start < 0 && !max_flag && !scan_flag )
{
fprintf( stderr,
"%s: Can't pipe input unless either -m or -s is given.\n",
cmd_name( argv ) );
exit( 1 );
}
if ( (rle_err = rle_get_setup( &in_hdr )) != RLE_SUCCESS )
break;
if (! rle_getcom( "exponential_data", &in_hdr ))
fprintf(stderr, "%s: warning - no exponential_data comment\n",
cmd_name( argv ));
if (in_hdr.ncolors < 2)
{
fprintf(stderr,
"%s: File does not contain exponent channel.\n",
cmd_name( argv ));
exit(-4);
}
if ( rle_row_alloc( &in_hdr, &in_rows ) < 0 )
RLE_CHECK_ALLOC( cmd_name( argv ), 0, 0 );
/* If maximum value isn't given, slosh through file to find it */
if (! max_flag)
{
maxval = 0.0;
for (y = in_hdr.ymin; y <= in_hdr.ymax; y++)
{
if ((verbose_flag) && (y % 100) == 0)
fprintf(stderr, "Scanning row %d...\n", y);
rle_getrow( &in_hdr, in_rows );
for (x = in_hdr.xmin; x <= in_hdr.xmax; x++)
{
expnt = ldexp( 1/256.0, in_rows[RLE_EXPONENT][x] - 127);
tmp = -2000.0;
for (chan = 0; chan < RLE_EXPONENT; chan++)
tmp = MAX( tmp, (float)in_rows[chan][x] );
tmp *= expnt;
maxval = MAX( maxval, tmp );
}
}
if (scan_flag || print_flag || verbose_flag)
fprintf(stderr, "Maximum value: %1.8g\n", maxval);
if (scan_flag) exit(0);
fseek( in_hdr.rle_file, start, 0 );
rle_get_setup( &in_hdr );
}
/* Open output file */
(void)rle_hdr_cp( &in_hdr, &out_hdr );
rle_delcom( "exponential_data", &out_hdr );
out_hdr.ncolors = in_hdr.ncolors - 1;
if ( rle_cnt == 0 )
outfile = rle_open_f( cmd_name( argv ), outfilename, "w" );
out_hdr.rle_file = outfile;
rle_addhist( argv, &in_hdr, &out_hdr );
rle_put_setup( &out_hdr );
out_hdr.xmin = 0;
out_hdr.xmax -= in_hdr.xmin;
if (rle_row_alloc( &out_hdr, &out_rows ) < 0)
RLE_CHECK_ALLOC( cmd_name( argv ), 0, 0 );
/*
* Convert byte/exponent form into straight RLE.
* Alpha is passed straight through.
*/
if ( maxval == 0.0 )
maxval = 1.0;
else
maxval /= 255; /* Pre-scale to 0-255 */
for (y = in_hdr.ymin; y <= in_hdr.ymax; y++)
{
if (((y % 100) == 0) && verbose_flag)
fprintf(stderr, "Processing row %d...\n", y);
rle_getrow( &in_hdr, in_rows );
for (x = in_hdr.xmin; x <= in_hdr.xmax; x++)
{
/* Only bother with pixels with coverage */
if (in_rows[RLE_ALPHA][x])
{
expnt = ldexp( 1/256.0, in_rows[RLE_EXPONENT][x] - 127 );
tmp_max = -1000;
for( chan = 0; chan < RLE_EXPONENT; chan++ )
tmp_max = MAX( tmp_max, in_rows[chan][x] );
tmp = expnt / maxval * tmp_max;
if (tmp > 255)
{
tmp = 255 / tmp;
truncations++;
}
else
tmp = 1.0;
tmp *= expnt / maxval;
for( chan = 0; chan < RLE_EXPONENT; chan++ )
out_rows[chan][x-in_hdr.xmin] = (rle_pixel) (int)
(in_rows[chan][x] * tmp);
out_rows[RLE_ALPHA][x-in_hdr.xmin] =
in_rows[RLE_ALPHA][x];
}
else
for( chan = RLE_ALPHA; chan < RLE_EXPONENT; chan++ )
out_rows[chan][x-in_hdr.xmin] = 0;
}
rle_putrow( out_rows, (in_hdr.xmax - in_hdr.xmin) + 1,
&out_hdr );
}
rle_puteof( &out_hdr );
if (truncations)
fprintf(stderr,"%s: %d bytes truncated (sorry...)\n",
cmd_name( argv ), truncations);
rle_row_free( &in_hdr, in_rows );
rle_row_free( &out_hdr, out_rows );
}
/* Check for an error. EOF or EMPTY is ok if at least one image
* has been read. Otherwise, print an error message.
*/
if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
rle_get_error( rle_err, cmd_name( argv ), infilename );
exit( 0 );
}