Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
rleselect.c
Go to the documentation of this file.
1 /*
2  * This software is copyrighted as noted below. It may be freely copied,
3  * modified, and redistributed, provided that the copyright notice is
4  * preserved on all copies.
5  *
6  * There is no warranty or other guarantee of fitness for this software,
7  * it is provided solely "as is". Bug reports or fixes may be sent
8  * to the author, who may or may not act on them as he desires.
9  *
10  * You may not include this software in a program or other software product
11  * without supplying the source, or without informing the end-user that the
12  * source is available for no extra charge.
13  *
14  * If you modify this software, you should include a notice giving the
15  * name of the person performing the modification, the date of modification,
16  * and the reason for such modification.
17  */
18 /*
19  * rleselect.c - Select images from an RLE file.
20  *
21  * Author: Spencer W. Thomas
22  * EECS Dept.
23  * University of Michigan
24  * Date: Wed Jul 11 1990
25  * Copyright (c) 1990, University of Michigan
26  */
27 #ifndef lint
28 char rcsid[] = "$Header: /l/spencer/src/urt/tools/RCS/rleselect.c,v 3.0.1.2 1992/04/30 14:13:31 spencer Exp $";
29 #endif
30 /*
31 rleselect() Tag the file.
32 */
33 
34 #include <stdio.h>
35 #include "rle.h"
36 
37 static void insert();
38 
39 static CONST_DECL char *my_name = "rleselect";
40 
41 /*****************************************************************
42  * TAG( rleselect )
43  *
44  * Select images from an RLE file.
45  * Usage:
46  * rleselect [-i infile] [-o outfile] image-numbers ...
47  * Inputs:
48  * -i infile: The input RLE file. Default stdin.
49  * "-" means stdin.
50  * image-numbers: A space-separated list of image numbers.
51  * Images are numbered from 1 in the input file.
52  * Images in this list will be included in the
53  * output.
54  * A negative number in the list means that all
55  * images from the previous number to the
56  * absolute value of this number should be
57  * included. A number of 0 is taken to mean
58  * '-infinity' (i.e., all images from the
59  * previous through the end).
60  * Examples:
61  * rleselect 1 4 5
62  * Selects images 1, 4, and 5.
63  * rleselect 4 1 5
64  * Does the same.
65  * rleselect 1 -4 5
66  * Selects images 1 through 5.
67  * rleselect 3 0
68  * Selects images 3 through the last.
69  * rleselect -4
70  * Selects images 1 through 4.
71  * Outputs:
72  * -o outfile: The output RLE file. Default stdout.
73  * "-" means stdout.
74  * Assumptions:
75  * [None]
76  * Algorithm:
77  * Sort the list of desired image numbers. (Treat N - infinity
78  * specially.) Read images, skipping if they are not in the
79  * list, and copying if they are.
80  */
81 void
83 int argc;
84 char **argv;
85 {
86  char *infname = NULL,
87  *outfname = NULL;
88  int *image_list = NULL;
89  int oflag = 0,
90  iflag = 0,
91  verbose = 0;
92  int nimage = 0;
93  int nsorted = 0;
94  int thrulast = -1; /* If > 0, take this through last. */
95  int rle_cnt, rle_err;
96  FILE *outfile = stdout;
97  /* Headers for input and output files. */
98  rle_hdr in_hdr, out_hdr;
99  int *sorted_list;
100  register int i, j;
101 
102  my_name = cmd_name( argv );
103  in_hdr = *rle_hdr_init( NULL );
104  out_hdr = *rle_hdr_init( NULL );
105 
106 
107  if ( scanargs( argc, argv,
108  "% i%-infile%s o%-outfile!s v%- image-numbers!*d\n(\
109 \tSelect images from a file.\n\
110 \t-v\tEcho list of images selected.\n\
111 \tPositive numbers (1,...) select individual images. A negative\n\
112 \tnumber indicates a range from the previous number (or from 1 if \n\
113 \tat the beginning of the list), thus 3 -8 selects images 3, 4, 5,\n\
114 \t6, 7, 8. Zero means \"through the last\", so 5 0 selects images\n\
115 \t5 through the last one in the file. Image selections may be given in\n\
116 \tany order, they will be sorted and merged by the program.)",
117  &iflag, &infname, &oflag, &outfname, &verbose,
118  &nimage, &image_list ) == 0 )
119  exit( 1 );
120 
121  if ( nimage == 0 )
122  {
123  fprintf( stderr, "%s: No images selected.\n", my_name );
124  exit( 0 );
125  }
126 
127  /*
128  * Scan the image list, expanding "through" specifications. Then
129  * sort the result.
130  */
131  for ( i = 0; i < nimage; i++ )
132  {
133  if ( image_list[i] < 0 )
134  {
135  image_list[i] = abs( image_list[i] );
136  if ( i == 0 )
137  j = 1;
138  else
139  j = image_list[i-1] + 1;
140  for ( ; j <= image_list[i]; j++ )
141  insert( &sorted_list, j, nsorted++ );
142  }
143  else if ( image_list[i] == 0 )
144  {
145  if ( i == 0 )
146  thrulast = 1;
147  else
148  thrulast = image_list[i-1];
149  }
150  else
151  insert( &sorted_list, image_list[i], nsorted++ );
152  }
153  /* Optimize list. */
154  if ( thrulast >= 0 )
155  {
156  for ( i = nsorted - 1; i >= 0 && sorted_list[i] >= thrulast; i-- )
157  ;
158  nsorted = i + 1;
159  }
160 
161  if ( verbose )
162  {
163  fprintf( stderr, "%s: Selecting images", my_name );
164  for ( i = 0; i < nsorted; i++ )
165  {
166  if ( i % 14 == 0 )
167  fprintf( stderr, "\n\t" );
168  fprintf( stderr, "%d%s", sorted_list[i],
169  ((i < nsorted - 1) || thrulast >= 0) ? ", " : "" );
170  }
171  if ( thrulast > 0 )
172  fprintf( stderr, "%s%d - last", i % 14 == 0 ? "\n\t" : "",
173  thrulast );
174  putc( '\n', stderr );
175  fflush( stderr );
176  }
177 
178 
179  /* Open the input file.
180  * The output file won't be opened until the first image header
181  * has been read. This avoids unnecessarily wiping out a
182  * pre-existing file if the input is garbage.
183  */
184  in_hdr.rle_file = rle_open_f( my_name, infname, "r" );
185  rle_names( &in_hdr, my_name, infname, 0 );
186  rle_names( &out_hdr, in_hdr.cmd, outfname, 0 );
187 
188  /* Read images from the input file until the end of file is
189  * encountered or an error occurs.
190  */
191  rle_cnt = 0;
192  i = 0;
193  while ( (rle_err = rle_get_setup( &in_hdr )) == RLE_SUCCESS )
194  {
195  /* Open the output file when the first header is successfully read. */
196  if ( rle_cnt == 0 )
197  outfile = rle_open_f( my_name, outfname, "w" );
198 
199  /* Count the input images. */
200  rle_cnt++;
201 
202  /* If it's not in the list, skip it. */
203  while ( i < nsorted && rle_cnt > sorted_list[i] )
204  i++;
205  /* Quick out when all selected images have been copied. */
206  if ( thrulast < 0 && i >= nsorted )
207  break;
208  /* Otherwise, if between selections, skip. */
209  if ( ! (thrulast >= 0 && rle_cnt >= thrulast) &&
210  (i >= nsorted || rle_cnt < sorted_list[i]) )
211  {
212  while ( rle_getskip( &in_hdr ) != 32768 )
213  ;
214  continue;
215  }
216 
217  /* The output header is a copy of the input header. The only
218  * difference is the FILE pointer.
219  */
220  (void)rle_hdr_cp( &in_hdr, &out_hdr );
221  out_hdr.rle_file = outfile;
222 
223  /* Add to the history comment. */
224  rle_addhist( argv, &in_hdr, &out_hdr );
225 
226  /* Write the output image header. */
227  rle_put_setup( &out_hdr );
228 
229  /* Copy the image. */
230  rle_cp( &in_hdr, &out_hdr );
231  }
232 
233  /* Check for an error. EOF or EMPTY is ok if at least one image
234  * has been read. Otherwise, print an error message.
235  */
236  if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
237  rle_get_error( rle_err, my_name, infname );
238 
239  exit( 0 );
240 }
241 
242 
243 static void
245 int **sorted_list_p;
246 int i, n;
247 {
248  register int *sorted_list = *sorted_list_p;
249  register int j;
250 
251  if ( n == 0 )
252  {
253  sorted_list = (int *)malloc( sizeof(int) );
254  RLE_CHECK_ALLOC( my_name, sorted_list, 0 );
255  *sorted_list = i;
256  }
257  else
258  {
259  sorted_list = (int *)realloc( sorted_list, (n + 1) * sizeof(int) );
260  RLE_CHECK_ALLOC( my_name, sorted_list, 0 );
261 
262  for ( j = n - 1; j >= 0 && sorted_list[j] > i; j-- )
263  sorted_list[j+1] = sorted_list[j];
264  sorted_list[j+1] = i;
265  }
266 
267  *sorted_list_p = sorted_list;
268 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
char rcsid[]
Definition: rleswap.c:28
rle_hdr * rle_hdr_cp(rle_hdr *from_hdr, rle_hdr *to_hdr)
Definition: rle_hdr.c:119
void rle_cp(rle_hdr *in_hdr, rle_hdr *the_hdr)
Definition: rle_cp.c:69
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
#define RLE_EMPTY
Definition: rle.h:73
char * cmd_name(char **argv)
Definition: cmd_name.c:31
static const char * my_name
Definition: rleselect.c:39
void main(int argc, char **argv)
Definition: aliastorle.c:121
int rle_get_setup(rle_hdr *the_hdr)
Definition: rle_getrow.c:74
#define RLE_SUCCESS
Definition: rle.h:70
int rle_get_error(int code, const char *pgmname, const char *fname)
Definition: rle_error.c:76
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
const char * cmd
Definition: rle.h:133
#define RLE_EOF
Definition: rle.h:74
#define CONST_DECL
Definition: rle_config.h:42
void rle_addhist(argv, rle_hdr *in_hdr, rle_hdr *out_hdr)
Definition: rle_addhist.c:54
unsigned int rle_getskip(rle_hdr *the_hdr)
Definition: rle_getskip.c:57
static void insert(int **sorted_list_p, int i, int n)
Definition: rleselect.c:244
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
FILE * rle_file
Definition: rle.h:114
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86