Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
rlecat.c
Go to the documentation of this file.
1 /*
2  * rlecat.c - Concatenate RLE files.
3  *
4  * Author: Spencer W. Thomas
5  * EECS Dept.
6  * University of Michigan
7  * Date: Mon Nov 5 1990
8  * Copyright (c) 1990, University of Michigan
9  */
10 #ifndef lint
11 static char rcsid[] = "$Header: /l/spencer/src/urt/tools/RCS/rlecat.c,v 3.0.1.4 1992/04/30 14:11:43 spencer Exp $";
12 #endif
13 /*
14 rlecat() Make a tag.
15 */
16 
17 #include "rle.h"
18 #ifndef _XOPEN_SOURCE
19 #define _XOPEN_SOURCE /* For mkstemp */
20 #endif /* !_XOPEN_SOURCE */
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include "rle_raw.h"
26 
27 #ifdef USE_PROTOTYPES
28 static void rep_file(rle_hdr *, rle_hdr *, int);
29 #else
30 static void rep_file();
31 #endif
32 
33 /*
34  * rlecat
35  *
36  * Concatenate RLE files, adding title comments, and/or repeating files.
37  *
38  * Usage:
39  * rlecat [-c] [-n repeat-count] [-o outfile] [files...]
40  * Inputs:
41  * -c: "Collated" Multiple input images will be repeated
42  * (see -n) in sequence 1 2 3 ... 1 2 3 ... The default
43  * is uncolllated, 1 1 ... 2 2 ... 3 3 ...
44  *
45  * -n repeat-count:
46  * Repeat each input image 'repeat-count' times. The -c
47  * flag controls the ordering of the repeats. Repeating
48  * creates a temporary file in the "/tmp" directory that
49  * is the size of a single "repeat unit". In collated
50  * mode, a repeat unit consists of the concatenation of
51  * all the input images, otherwise it is just a single
52  * image.
53  *
54  * files: Input file names. If none specified, input will be
55  * read from the standard input.
56  *
57  * Outputs:
58  * -o outfile:
59  * Output file. If not specified, output is written to
60  * the standard output.
61  *
62  * Algorithm:
63  * Reads each input image, adds a 'title' comment to it based on
64  * the input file name (no title is added to images read from the
65  * standard input), and writes it to the output. If a repeat
66  * count is specified, the image is written to a temporary file,
67  * and this is repeatedly copied to the output according to the
68  * repeat count. If the collation flag (-c) is specified, then
69  * all images will be read before starting to repeat.
70  */
71 void
73 int argc;
74 char **argv;
75 {
76  CONST_DECL char **infname = NULL,
77  *outfname = NULL;
78  CONST_DECL char *dash = "-"; /* Used to fake a request for stdin. */
79  static char temp[] = "rlecatXXXXXX";
80  int cflag = 0,
81  nflag = 0,
82  rep_cnt = 0,
83  oflag = 0,
84  nfiles = 0;
85  int rle_cnt, rle_err, y, nskip;
86  int file_cnt;
87  FILE *outfile, *tmpfile = NULL;
88  rle_hdr in_hdr, out_hdr;
89  rle_hdr tmp_hdr; /* Header for temp file for repeats. */
90  char buf[BUFSIZ]; /* For building title comment. */
91  rle_op **rows; /* Storage for input data. */
92  int *n_op; /* Number of ops per row. */
93 
94  in_hdr = *rle_hdr_init( NULL );
95  out_hdr = *rle_hdr_init( NULL );
96 
97  if ( scanargs( argc, argv, "% c%- n%-repeat-count!d o%-outfile!s files%*s",
98  &cflag, &nflag, &rep_cnt,
99  &oflag, &outfname, &nfiles, &infname ) == 0 )
100  exit( 1 );
101 
102  /* If no input, use standard input. */
103  if ( nfiles == 0 )
104  {
105  nfiles = 1;
106  infname = &dash;
107  }
108 
109  /* Open the output file now, to make sure we can. */
110  outfile = rle_open_f_noexit( cmd_name( argv ), outfname, "w" );
111 
112  /* If requesting repeats, create temp file. */
113  if ( nflag )
114  {
115  if ( rep_cnt < 2 )
116  nflag = 0; /* Not really repeating! */
117  else
118  {
119  /* we dont have to use rle_open_f() because all it does in
120  * this case is run fopen() ... we're creating a file so all
121  * the checks for opening an existing file aren't needed */
122  int fd = mkstemp(temp);
123  if (fd == -1 || (tmpfile = fdopen(fd, "w+")) == NULL) {
124  perror("Unable to open tempfile");
125  exit(-1);
126  }
127  }
128  }
129 
130  /* For each file, read it and write it. */
131  rle_names( &out_hdr, cmd_name( argv ), outfname, 0 );
132  for ( file_cnt = 0; file_cnt < nfiles; file_cnt++ )
133  {
134  /* Open the input file. */
135  rle_names( &in_hdr, out_hdr.cmd, infname[file_cnt], 0 );
136  in_hdr.rle_file =
137  rle_open_f_noexit( in_hdr.cmd, infname[file_cnt], "r" );
138  if ( in_hdr.rle_file == NULL )
139  continue;
140 
141  /* Count the input images. */
142  for ( rle_cnt = 0;
143  (rle_err = rle_get_setup( &in_hdr )) == RLE_SUCCESS;
144  rle_cnt++ )
145  {
146  /* The output header is a copy of the input header. The only
147  * difference is the FILE pointer.
148  */
149  (void)rle_hdr_cp( &in_hdr, &out_hdr );
150  out_hdr.rle_file = outfile;
151 
152  /* Add to the history comment. */
153  rle_addhist( argv, &in_hdr, &out_hdr );
154 
155  /* Build the title comment. */
156  if ( rle_getcom( "title", &in_hdr ) ||
157  rle_getcom( "TITLE", &in_hdr ) )
158  ; /* Don't disturb existing title. */
159  else
160  if ( in_hdr.rle_file != stdin )
161  {
162  if ( rle_cnt == 0 )
163  sprintf( buf, "TITLE=%s", infname[file_cnt] );
164  else
165  sprintf( buf, "TITLE=%s(%d)", infname[file_cnt],
166  rle_cnt+1 );
167  rle_putcom( buf, &out_hdr );
168  }
169 
170  /* Write the output image header. */
171  rle_put_setup( &out_hdr );
172 
173  if ( nflag )
174  {
175  (void)rle_hdr_cp( &out_hdr, &tmp_hdr );
176  tmp_hdr.rle_file = tmpfile;
177  rle_put_setup( &tmp_hdr );
178  }
179 
180  /* Allocate memory into which the image scanlines can be read.
181  * This should happen after the above adjustment, to minimize
182  * the amount of memory allocated.
183  */
184  if ( rle_raw_alloc( &in_hdr, &rows, &n_op ) < 0 )
185  RLE_CHECK_ALLOC( cmd_name( argv ), 0, "image memory" );
186 
187  /* Read the input image and copy it to the output file. */
188  y = in_hdr.ymin - 1;
189  while ( (nskip = rle_getraw( &in_hdr, rows, n_op )) != 32768 )
190  {
191  nskip -= y;
192  y += nskip;
193  if ( nskip > 1 )
194  rle_skiprow( &out_hdr, nskip - 1 );
195 
196  /* Write the processed scanline. */
197  rle_putraw( rows, n_op, &out_hdr );
198  if ( nflag )
199  {
200  if ( nskip > 1 )
201  rle_skiprow( &tmp_hdr, nskip - 1 );
202  rle_putraw( rows, n_op, &tmp_hdr );
203  }
204 
205  rle_freeraw( &in_hdr, rows, n_op );
206  }
207 
208  /* Free memory. */
209  rle_raw_free( &in_hdr, rows, n_op );
210 
211  /* Write an end-of-image code. */
212  rle_puteof( &out_hdr );
213  if ( nflag )
214  rle_puteof( &tmp_hdr );
215 
216  /* If not collating, do the repeats now. */
217  if ( !cflag && nflag )
218  rep_file( &tmp_hdr, &out_hdr, rep_cnt );
219  }
220 
221  /* Close the input file. */
222  fclose( in_hdr.rle_file );
223 
224  /* Check for an error. EOF or EMPTY is ok if at least one image
225  * has been read. Otherwise, print an error message.
226  */
227  if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
228  rle_get_error( rle_err, in_hdr.cmd, in_hdr.file_name );
229  }
230 
231  /* If collating, do the repeats here. */
232  if ( cflag && nflag )
233  rep_file( &tmp_hdr, &out_hdr, rep_cnt );
234 
235  /* If repeating, delete the temp file. */
236  if ( nflag )
237  unlink( temp );
238 
239  exit( 0 ); /* All ok. */
240 }
241 
242 /*****************************************************************
243  * TAG( rep_file )
244  *
245  * Copy an rle file repeatedly to the output file.
246  * Inputs:
247  * in_hdr: Header for the file to copy from.
248  * rep_cnt: Number of times to repeat + 1 (one copy has
249  * already been written at this point.)
250  * Outputs:
251  * out_hdr: Header for the output file.
252  * Assumptions:
253  * in_hdr refers to a seekable file, file "cursor" is at the end
254  * of the image(s) to be copied.
255  * Algorithm:
256  * Save current file position in nbytes.
257  * Repeat rep_cnt-1 times:
258  * Rewind the input.
259  * Copy nbytes bytes from the input to the output.
260  * Rewind the input.
261  */
262 static void
264 rle_hdr *in_hdr, *out_hdr;
265 int rep_cnt;
266 {
267  long int pos = ftell( in_hdr->rle_file );
268  char buf[BUFSIZ];
269  int n, nr;
270 
271  while ( --rep_cnt > 0 )
272  {
273  rewind( in_hdr->rle_file );
274  for ( n = 0;
275  n < pos && (nr = fread( buf, 1, BUFSIZ, in_hdr->rle_file )) > 0;
276  n += nr )
277  {
278  if ( pos - n < nr )
279  nr = pos - n;
280  fwrite( buf, 1, nr, out_hdr->rle_file );
281  }
282  }
283 
284  rewind( in_hdr->rle_file );
285 }
rle_hdr * rle_hdr_cp(rle_hdr *from_hdr, rle_hdr *to_hdr)
Definition: rle_hdr.c:119
void rle_freeraw(rle_hdr *the_hdr, scanraw, nraw)
Definition: rle_getraw.c:268
#define USE_PROTOTYPES
Definition: rle_config.h:22
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
int rle_raw_alloc(rle_hdr *the_hdr, rle_op ***scanp, int **nrawp)
Definition: rle_raw_alc.c:60
#define RLE_EMPTY
Definition: rle.h:73
char * cmd_name(char **argv)
Definition: cmd_name.c:31
void main(int argc, char **argv)
Definition: aliastorle.c:121
int rle_get_setup(rle_hdr *the_hdr)
Definition: rle_getrow.c:74
void rle_putraw(rle_op **scanraw, int *nraw, rle_hdr *the_hdr)
Definition: rle_putraw.c:60
#define RLE_SUCCESS
Definition: rle.h:70
int ymin
Definition: rle.h:100
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
void rle_puteof(rle_hdr *the_hdr)
Definition: rle_putrow.c:474
#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
FILE * rle_open_f_noexit(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:57
void rle_skiprow(rle_hdr *the_hdr, int nrow)
Definition: rle_putrow.c:393
char * rle_getcom(char *name, rle_hdr *the_hdr) const
Definition: rle_getcom.c:81
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
const char * rle_putcom(char *value, rle_hdr *the_hdr) const
Definition: rle_putcom.c:82
void rle_raw_free(rle_hdr *the_hdr, rle_op **scanp, nrawp)
Definition: rle_raw_alc.c:131
const char * file_name
Definition: rle.h:134
static void rep_file(rle_hdr *in_hdr, rle_hdr *out_hdr, int rep_cnt)
Definition: rlecat.c:263
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
FILE * rle_file
Definition: rle.h:114
unsigned int rle_getraw(rle_hdr *the_hdr, scanraw, nraw)
Definition: rle_getraw.c:78
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86
static char rcsid[]
Definition: rlecat.c:11