ftp.nice.ch/pub/next/unix/graphics/urt.3.0.s.tar.gz#/urt.3.0.s/tools/rleselect.c

This is rleselect.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.
 */
/* 
 * rleselect.c - Select images from an RLE file.
 * 
 * Author:	Spencer W. Thomas
 * 		EECS Dept.
 * 		University of Michigan
 * Date:	Wed Jul 11 1990
 * Copyright (c) 1990, University of Michigan
 */

#include <stdio.h>
#include <rle.h>

#ifdef USE_STDLIB_H
#include <stdlib.h>
#else

#ifdef VOID_STAR
extern void *malloc(), *realloc();
#else
extern char *malloc(), *realloc();
#endif
extern void free();

#endif /* USE_STDLIB_H */

static void insert();

static CONST_DECL char *my_name = "rleselect";

/*****************************************************************
 * TAG( rleselect )
 *
 * Select images from an RLE file.
 * Usage:
 * 	rleselect [-i infile] [-o outfile] image-numbers ...
 * Inputs:
 * 	-i infile:	The input RLE file.  Default stdin.
 * 			"-" means stdin.
 * 	image-numbers:	A space-separated list of image numbers.
 * 			Images are numbered from 1 in the input file.
 * 			Images in this list will be included in the
 * 			output. 
 * 			A negative number in the list means that all
 * 			images from the previous number to the
 * 			absolute value of this number should be
 * 			included.  A number of 0 is taken to mean
 * 			'-infinity' (i.e., all images from the
 * 			previous through the end).
 * Examples:
 * 	rleselect 1 4 5
 * 			Selects images 1, 4, and 5.
 * 	rleselect 4 1 5
 * 			Does the same.
 * 	rleselect 1 -4 5
 * 			Selects images 1 through 5.
 * 	rleselect 3 0
 * 			Selects images 3 through the last.
 * 	rleselect -4
 * 			Selects images 1 through 4.
 * Outputs:
 * 	-o outfile:	The output RLE file.  Default stdout.
 * 			"-" means stdout.
 * Assumptions:
 *	[None]
 * Algorithm:
 * 	Sort the list of desired image numbers.  (Treat N - infinity
 * 	specially.)  Read images, skipping if they are not in the
 * 	list, and copying if they are.
 */
void
main( argc, argv )
int argc;
char **argv;
{
    char       *infname = NULL,
    	       *outfname = NULL;
    int        *image_list = NULL;
    int 	oflag = 0,
    		iflag = 0,
		verbose = 0;
    int		nimage = 0;
    int		nsorted = 0;
    int		thrulast = -1;	/* If > 0, take this through last. */
    int		rle_cnt, rle_err, width, y;
    FILE       *outfile = stdout;
    rle_hdr in_hdr, out_hdr;	/* Headers for input and output files. */
    rle_pixel **rows;		/* Will be used for scanline storage. */
    int	       *sorted_list;
    register int i, j;
    
    my_name = cmd_name( argv );

    if ( scanargs( argc, argv,
		   "% i%-infile%s o%-outfile!s v%- image-numbers!*d",
		   &iflag, &infname, &oflag, &outfname, &verbose,
		   &nimage, &image_list ) == 0 )
	exit( 1 );

    if ( nimage == 0 )
    {
	fprintf( stderr, "%s: No images selected.\n", my_name );
	exit( 0 );
    }

    /*
     * Scan the image list, expanding "through" specifications.  Then
     * sort the result.
     */
    for ( i = 0; i < nimage; i++ )
    {
	if ( image_list[i] < 0 )
	{
	    image_list[i] = abs( image_list[i] );
	    if ( i == 0 )
		j = 1;
	    else
		j = image_list[i-1] + 1;
	    for ( ; j <= image_list[i]; j++ )
		insert( &sorted_list, j, nsorted++ );
	}
	else if ( image_list[i] == 0 )
	{
	    if ( i == 0 )
		thrulast = 1;
	    else
		thrulast = image_list[i-1];
	}
	else
	    insert( &sorted_list, image_list[i], nsorted++ );
    }
    /* Optimize list. */
    if ( thrulast >= 0 )
    {
	for ( i = nsorted - 1; i >= 0 && sorted_list[i] >= thrulast; i-- )
	    ;
	nsorted = i + 1;
    }

    if ( verbose )
    {
	fprintf( stderr, "%s: Selecting images", my_name );
	for ( i = 0; i < nsorted; i++ )
	{
	    if ( i % 14 == 0 )
		fprintf( stderr, "\n\t" );
	    fprintf( stderr, "%d%s", sorted_list[i],
		     ((i < nsorted - 1) || thrulast >= 0)  ? ", " : "" );
	}
	if ( thrulast > 0 )
	    fprintf( stderr, "%s%d - last", i % 14 == 0 ? "\n\t" : "",
		     thrulast );
	putc( '\n', stderr );
	fflush( stderr );
    }

	
    /* Open the input file.
     * The output file won't be opened until the first image header
     * has been read.  This avoids unnecessarily wiping out a
     * pre-existing file if the input is garbage.
     */
    in_hdr.rle_file = rle_open_f( my_name, infname, "r" );

    /* Read images from the input file until the end of file is
     * encountered or an error occurs.
     */
    rle_cnt = 0;
    i = 0;
    while ( (rle_err = rle_get_setup( &in_hdr )) == RLE_SUCCESS )
    {
	/* Open the output file when the first header is successfully read. */
	if ( rle_cnt == 0 )
	    outfile = rle_open_f( my_name, outfname, "w" );

	/* Count the input images. */
	rle_cnt++;

	/* If it's not in the list, skip it. */
	while ( rle_cnt > sorted_list[i] && i < nsorted )
	    i++;
	if ( ! (thrulast >= 0 && rle_cnt >= thrulast) &&
	     (i >= nsorted || rle_cnt < sorted_list[i]) )
	{
	    while ( rle_getskip( &in_hdr ) != 32768 )
		;
	    continue;
	}

	/* The output header is a copy of the input header.  The only
	 * difference is the FILE pointer.
	 */
	out_hdr = in_hdr;
	out_hdr.rle_file = outfile;

	/* Add to the history comment. */
	rle_addhist( argv, &in_hdr, &out_hdr );

	/* Write the output image header. */
	rle_put_setup( &out_hdr );

	/* Since rle_getrow and rle_putrow use different array origins,
	 * we will compensate by adjusting the xmin and xmax values in
	 * the input header.  [rle_getrow assumes that the scanline
	 * array starts at pixel 0, while rle_putrow assumes that the
	 * scanline array starts at pixel xmin.  This is a botch, but
	 * it's too late to change it now.]
	 */
	in_hdr.xmax -= in_hdr.xmin;
	in_hdr.xmin = 0;
	width = in_hdr.xmax + 1;	/* Width of a scanline. */

	/* Allocate memory into which the image scanlines can be read.
	 * This should happen after the above adjustment, to minimize
	 * the amount of memory allocated.
	 */
	if ( rle_row_alloc( &out_hdr, &rows ) < 0 )
	{
	    fprintf( stderr, "rleskel: Unable to allocate image memory.\n" );
	    exit( RLE_NO_SPACE );
	}
	
	/* Read the input image and copy it to the output file. */
	for ( y = in_hdr.ymin; y <= in_hdr.ymax; y++ )
	{
	    /* Read a scanline. */
	    rle_getrow( &in_hdr, rows );
	    
	    /* Process the scanline as desired here. */

	    /* Write the processed scanline. */
	    rle_putrow( rows, width, &out_hdr );
	}

	/* Free memory. */
	rle_row_free( &in_hdr, rows );

	/* Write an end-of-image code. */
	rle_puteof( &out_hdr );
    }
    
    /* 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, my_name, infname );

    exit( 0 );
}


static void 
insert( sorted_list_p, i, n )
int **sorted_list_p;
int i, n;
{
    register int *sorted_list = *sorted_list_p;
    register int j;

    if ( n == 0 )
    {
	sorted_list = (int *)malloc( sizeof(int) );
	if ( sorted_list == NULL )
	{
	    fprintf( stderr, "%s: Out of memory\n", my_name );
	    exit( RLE_NO_SPACE );
	}
	*sorted_list = i;
    }
    else
    {
	sorted_list = (int *)realloc( sorted_list, (n + 1) * sizeof(int) );
	if ( sorted_list == NULL )
	{
	    fprintf( stderr, "%s: Out of memory\n", my_name );
	    exit( RLE_NO_SPACE );
	}

	for ( j = n - 1; j >= 0 && sorted_list[j] > i; j-- )
	    sorted_list[j+1] = sorted_list[j];
	sorted_list[j+1] = i;
    }

    *sorted_list_p = sorted_list;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.