/* * 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 */ #ifndef lint char rcsid[] = "$Header: /l/spencer/src/urt/tools/RCS/rleselect.c,v 3.0.1.2 1992/04/30 14:13:31 spencer Exp $"; #endif /* rleselect() Tag the file. */ #include #include "rle.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; FILE *outfile = stdout; /* Headers for input and output files. */ rle_hdr in_hdr, out_hdr; int *sorted_list; register int i, j; my_name = cmd_name( argv ); in_hdr = *rle_hdr_init( NULL ); out_hdr = *rle_hdr_init( NULL ); if ( scanargs( argc, argv, "% i%-infile%s o%-outfile!s v%- image-numbers!*d\n(\ \tSelect images from a file.\n\ \t-v\tEcho list of images selected.\n\ \tPositive numbers (1,...) select individual images. A negative\n\ \tnumber indicates a range from the previous number (or from 1 if \n\ \tat the beginning of the list), thus 3 -8 selects images 3, 4, 5,\n\ \t6, 7, 8. Zero means \"through the last\", so 5 0 selects images\n\ \t5 through the last one in the file. Image selections may be given in\n\ \tany order, they will be sorted and merged by the program.)", &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" ); rle_names( &in_hdr, my_name, infname, 0 ); rle_names( &out_hdr, in_hdr.cmd, outfname, 0 ); /* 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 ( i < nsorted && rle_cnt > sorted_list[i] ) i++; /* Quick out when all selected images have been copied. */ if ( thrulast < 0 && i >= nsorted ) break; /* Otherwise, if between selections, skip. */ 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. */ (void)rle_hdr_cp( &in_hdr, &out_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 ); /* Copy the image. */ rle_cp( &in_hdr, &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) ); RLE_CHECK_ALLOC( my_name, sorted_list, 0 ); *sorted_list = i; } else { sorted_list = (int *)realloc( sorted_list, (n + 1) * sizeof(int) ); RLE_CHECK_ALLOC( my_name, sorted_list, 0 ); 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; }