This is rleswap.c in view mode; [Download] [Up]
/*
* This software is copyrighted as noted below. It may be freely copied,
* modified, and redistributed, provided that the copyright notice is
* preserved on all copies.
*
* There is no warranty or other guarantee of fitness for this software,
* it is provided solely "as is". Bug reports or fixes may be sent
* to the author, who may or may not act on them as he desires.
*
* You may not include this software in a program or other software product
* without supplying the source, or without informing the end-user that the
* source is available for no extra charge.
*
* If you modify this software, you should include a notice giving the
* name of the person performing the modification, the date of modification,
* and the reason for such modification.
*/
/*
* rleswap.c - Swap the channels in an RLE file around
*
* Author: Spencer W. Thomas
* Computer Science Dept.
* University of Utah
* Date: Thu Jan 22 1987
* Copyright (c) 1987, University of Utah
*/
#include <stdio.h>
#include <rle.h>
#include <rle_raw.h>
#ifdef USE_STDLIB_H
#include <stdlib.h>
#else
#ifdef VOID_STAR
extern void *malloc();
#else
extern char *malloc();
#endif
extern void free();
#endif /* USE_STDLIB_H */
extern void scan_usage();
/*****************************************************************
* TAG( main )
*
* Usage:
* rleswap [-p channel-pairs,...] [-f from-channels,...]
* [-t to-channels,...] [-d delete-channels,...] [infile]
* Inputs:
* -p, -f, -t, -d: Only one of these may be specified, they indicate
* different ways of indicating the channel swapping
* from input to output.
*
* channel-pairs: A comma separated list of pairs of channel numbers
* The first channel of each pair indicates a channel
* in the input file that will be mapped to the
* the channel in the output file indicated by the
* second number in the pair. No output channel
* number may appear more than once. Any input channel
* not mentioned will not appear in the output file.
* Any output channel not mentioned will not receive
* image data.
*
* from-channels: A comma separated list of numbers indicating the
* input channel that maps to each output channel
* in sequence. I.e., the first number indicates
* the input channel mapping to output channel 0.
* The alpha channel will be passed through unchanged
* if present. Any input channels not mentioned
* in the list will not appear in the output.
*
* to-channels: A comma separated list of numbers indicating the
* output channel to which each input channel, in
* sequence, will map. I.e., the first number gives
* the output channel to which the first input channel
* will map. No number may be repeated in this list.
* The alpha channel will be passed through unchanged
* if present. Any output channel not mentioned in
* the list will not receive image data. If there
* are fewer numbers in the list than there are input
* channels, the excess input channels will be ignored.
* If there are more numbers than input channels, it
* is an error.
*
* delete-channels:A comma separated list of input channels that should
* not appear in the output. All other channels will
* be passed through unchanged.
*
* infile: Optional input file name specification.
* outfile: Optional output file name specification.
* Outputs:
* An RLE file similar to the input file, but with the color channels
* remapped as indicated, will be written to the output.
* Assumptions:
* [None]
* Algorithm:
* [None]
*/
void
main( argc, argv )
int argc;
char **argv;
{
int nspec, * specs;
int tflag = 0, fflag = 0, oflag = 0, dflag = 0, pflag = 0, verbose = 0;
char * fname = NULL, *out_fname = NULL;
FILE *outfile = stdout;
static CONST_DECL char * argfmt =
"% v%- f%-from-channels!,d t%-to-channels!,d \n\
\td%-delete-channels!,d p%-channel-pairs!,d o%-outfile!s infile%s";
register int i;
int j, errs = 0;
int * outchan = 0, noutput = 0, outalpha = -2;
rle_hdr out_hdr;
rle_op ** scanraw, ** outraw;
int * nraw, * outnraw, y, nskip;
int rle_cnt, rle_err;
if ( scanargs( argc, argv, argfmt, &verbose,
&fflag, &nspec, &specs,
&tflag, &nspec, &specs,
&dflag, &nspec, &specs,
&pflag, &nspec, &specs,
&oflag, &out_fname, &fname ) == 0 )
exit( 1 );
/* Do some sanity checks */
if ( fflag + tflag + dflag + pflag != 1 )
{
fprintf( stderr,
"%s: You must specify exactly one of -d, -f, -t, or -p\n",
argv[0] );
/*
* Generate usage message.
*/
scan_usage( argv, argfmt );
exit( 1 );
}
if ( pflag && (nspec % 2) != 0 )
{
fprintf( stderr, "%s: You must specify pairs of channels with -p\n",
cmd_name( argv ) );
exit( 1 );
}
/* More later, after we have the RLE header in hand */
/* Open input */
rle_dflt_hdr.rle_file = rle_open_f(cmd_name( argv ), fname, "r");
/* Read in header */
for ( rle_cnt = 0;
(rle_err = rle_get_setup( &rle_dflt_hdr )) == RLE_SUCCESS;
rle_cnt++ )
{
/* Set up mapping and sanity check simultaneously */
if ( fflag ) /* where does output come from? */
{
outchan = specs;
noutput = nspec;
/* Sanity check */
for ( i = 0; i < noutput; i++ )
if ( outchan[i] >= rle_dflt_hdr.ncolors ||
outchan[i] < -1 ||
outchan[i] < 0 && !rle_dflt_hdr.alpha )
{
fprintf( stderr, "%s: No input channel %d\n",
cmd_name( argv ), outchan[i] );
errs++;
}
if ( rle_dflt_hdr.alpha )
outalpha = -1; /* pass alpha channel through */
}
if ( tflag ) /* where does input go */
{
if ( nspec > rle_dflt_hdr.ncolors )
{
fprintf( stderr,
"%s: Input file has %d channels, can't swap %d channels\n",
cmd_name( argv ), rle_dflt_hdr.ncolors, nspec );
errs++;
}
else
{
/* Find highest output channel */
noutput = -1; /* assume none */
for ( i = 0; i < nspec; i++ )
if ( specs[i] > noutput )
noutput = specs[i];
noutput++;
/* Allocate space for output pointers */
outchan = (int *)malloc( noutput * sizeof( int ) );
if ( outchan == NULL )
{
fprintf( stderr, "%s: Malloc failed\n", cmd_name( argv ) );
exit( 1 );
}
/* Initialize to empty state */
for ( i = 0; i < noutput; i++ )
outchan[i] = -2;
/* Fill it in */
for ( i = 0; i < nspec; i++ )
{
if ( specs[i] < -1 )
{
fprintf( stderr, "%s: No channel %d in output\n",
cmd_name( argv ), specs[i] );
errs++;
}
else if ( specs[i] < 0 )
{
if ( outalpha > -2 )
{
fprintf( stderr,
"%s: Output alpha channel can't come from both inputs %d and %d.\n",
cmd_name( argv ), outalpha, i );
errs++;
}
else
outalpha = i;
}
else
{
if ( outchan[specs[i]] > -2 )
{
fprintf( stderr,
"%s: Output channel %d can't come from both inputs %d and %d.\n",
cmd_name( argv ), specs[i],
outchan[specs[i]], i );
errs++;
}
else
outchan[specs[i]] = i;
}
}
if ( outalpha < -1 && rle_dflt_hdr.alpha )
outalpha = -1; /* map alpha channel through */
}
}
if ( dflag ) /* Delete some input channels */
{
/* First, set up identity mapping from input to output */
noutput = rle_dflt_hdr.ncolors;
/* Allocate space for output pointers */
outchan = (int *)malloc( noutput * sizeof( int ) );
if ( outchan == NULL )
{
fprintf( stderr, "%s: Malloc failed\n", cmd_name( argv ) );
exit( 1 );
}
for ( i = 0; i < noutput; i++ )
outchan[i] = i;
if ( rle_dflt_hdr.alpha )
outalpha = -1;
/* Now, delete indicated channels from mapping */
for ( i = 0; i < nspec; i++ )
if ( specs[i] < -rle_dflt_hdr.alpha ||
specs[i] >= rle_dflt_hdr.ncolors )
fprintf( stderr, "%s: Warning: No channel %d in input\n",
cmd_name( argv ), specs[i] );
else if ( specs[i] == -1 && outalpha == -2 ||
outchan[specs[i]] == -2 )
fprintf( stderr, "%s: Warning: Deleted channel %d twice\n",
cmd_name( argv ), specs[i] );
else if ( specs[i] >= 0 )
outchan[specs[i]] = -2; /* null it out */
else
outalpha = -2;
/* Figure out how many output channels we really have */
while ( outchan[noutput - 1] == -2 )
noutput--;
}
if ( pflag ) /* Do pairs of mappings */
{
/* Find highest output channel */
noutput = -1; /* assume none */
for ( i = 1; i < nspec; i += 2 )
if ( specs[i] > noutput )
noutput = specs[i];
noutput++;
/* Allocate space for output pointers */
outchan = (int *)malloc( noutput * sizeof( int ) );
if ( outchan == NULL )
{
fprintf( stderr, "%s: Malloc failed\n", cmd_name( argv ) );
exit( 1 );
}
/* Initialize to empty state */
for ( i = 0; i < noutput; i++ )
outchan[i] = -2;
/* Fill it in */
for ( i = 0; i < nspec; i += 2 )
{
if ( specs[i] < -rle_dflt_hdr.alpha ||
specs[i] >= rle_dflt_hdr.ncolors )
{
fprintf( stderr, "%s: No channel %d in input\n",
cmd_name( argv ), specs[i] );
errs++;
}
if ( specs[i+1] < -1 )
{
fprintf( stderr, "%s: No channel %d in output\n",
cmd_name( argv ), specs[i+1] );
errs++;
}
else if ( specs[i+1] < 0 )
{
if ( outalpha > -2 )
{
fprintf( stderr,
"%s: Output alpha channel can't come from both inputs %d and %d.\n",
cmd_name( argv ), outalpha, specs[i] );
errs++;
}
else
outalpha = specs[i];
}
else
{
if ( outchan[specs[i+1]] > -2 )
{
fprintf( stderr,
"%s: Output channel %d can't come from both inputs %d and %d.\n",
cmd_name( argv ), specs[i+1],
outchan[specs[i+1]], specs[i] );
errs++;
}
else
outchan[specs[i+1]] = specs[i];
}
}
}
/* If errors, go away */
if ( errs )
exit( 1 );
/* Be verbose if requested */
if ( verbose )
{
fprintf( stderr, "Channel mapping from input to output:\n" );
if ( outalpha != -2 )
if ( outalpha < 0 )
fprintf( stderr, "alpha\t-> alpha\n" );
else
fprintf( stderr, "%d\t-> alpha\n", outalpha );
else
fprintf( stderr, "No output alpha channel\n" );
for ( i = 0; i < noutput; i++ )
if ( outchan[i] == -2 )
fprintf( stderr, "nothing\t-> %d\n", i );
else if ( outchan[i] == -1 )
fprintf( stderr, "alpha\t-> %d\n", i );
else
fprintf( stderr, "%d\t-> %d\n", outchan[i], i );
}
/* Set up output the_hdr now */
out_hdr = rle_dflt_hdr; /* same as input, basically */
/* Except for a few changes */
if ( rle_cnt == 0 )
outfile = rle_open_f(cmd_name( argv ), out_fname, "w");
out_hdr.rle_file = outfile;
out_hdr.ncolors = noutput;
rle_addhist( argv, &rle_dflt_hdr, &out_hdr );
if ( outalpha != -2 )
{
out_hdr.alpha = 1;
RLE_SET_BIT( out_hdr, RLE_ALPHA );
}
else
{
out_hdr.alpha = 0;
RLE_CLR_BIT( out_hdr, RLE_ALPHA );
}
for ( i = 0; i < noutput; i++ )
if ( outchan[i] != -2 )
RLE_SET_BIT( out_hdr, i );
else
RLE_CLR_BIT( out_hdr, i );
/* Do background color */
if ( out_hdr.background )
{
out_hdr.bg_color =
(int *)malloc( out_hdr.ncolors * sizeof(int) );
for ( i = 0; i < noutput; i++ )
if ( outchan[i] < 0 )
out_hdr.bg_color[i] = 0; /* got to be something */
else
out_hdr.bg_color[i] = rle_dflt_hdr.bg_color[outchan[i]];
}
/* And color map!? */
if ( rle_dflt_hdr.ncmap > 1 ) /* only one channel color map stays */
{
int cmaplen = 1 << out_hdr.cmaplen;
int cmapshift = 16 - out_hdr.cmaplen;
out_hdr.cmap = (rle_map *)malloc( noutput * cmaplen *
sizeof(rle_map) );
out_hdr.ncmap = noutput;
/* If input channel is in color map, copy it, else use identity? */
for ( i = 0; i < noutput; i++ )
if ( outchan[i] >= 0 && outchan[i] < rle_dflt_hdr.ncmap )
{
register rle_map * imap, * omap;
imap = &rle_dflt_hdr.cmap[outchan[i] * cmaplen];
omap = &out_hdr.cmap[i * cmaplen];
for ( j = 0; j < cmaplen; j++ )
*omap++ = *imap++;
}
else
{
register rle_map * omap;
omap = &out_hdr.cmap[i * cmaplen];
for ( j = 0; j < cmaplen; j++ )
*omap++ = j << cmapshift;
}
}
/* Write output header */
rle_put_setup( &out_hdr );
/* Allocate raw buffers for input */
rle_raw_alloc( &rle_dflt_hdr, &scanraw, &nraw );
/* Allocate buffer pointers for output */
rle_raw_alloc( &out_hdr, &outraw, &outnraw );
for ( i = -out_hdr.alpha; i < out_hdr.ncolors; i++ )
if ( outraw[i] )
{
free( (char *)outraw[i] ); /* don't need these */
break;
};
/* Finally, do the work */
y = rle_dflt_hdr.ymin - 1;
while ( (nskip = rle_getraw( &rle_dflt_hdr, scanraw, nraw )) != 32768 )
{
nskip -= y; /* difference from previous line */
y += nskip;
if ( nskip > 1 )
rle_skiprow( &out_hdr, nskip - 1 );
if ( outalpha != -2 )
{
outraw[-1] = scanraw[outalpha];
outnraw[-1] = nraw[outalpha];
}
for ( i = 0; i < noutput; i++ )
if ( outchan[i] != -2 )
{
outraw[i] = scanraw[outchan[i]];
outnraw[i] = nraw[outchan[i]];
}
else
outnraw[i] = 0;
rle_putraw( outraw, outnraw, &out_hdr );
rle_freeraw( &rle_dflt_hdr, scanraw, nraw );
}
rle_puteof( &out_hdr ); /* all done! */
/* Release memory. */
if ( outchan != specs )
free( outchan );
rle_raw_free( &rle_dflt_hdr, scanraw, nraw );
}
/* 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 ), fname );
exit( 0 );
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.