Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
mergechan.c
Go to the documentation of this file.
1 /*
2  * mergechan.c - Merge channels from multiple RLE images
3  *
4  * Author: John W. Peterson
5  * Computer Science Dept.
6  * University of Utah
7  * Date: Mon Nov 9 1987
8  * Copyright (c) 1987, University of Utah
9  *
10  * Warning: this code does not intelligently deal with color maps!
11  *
12  */
13 
14 #include <stdio.h>
15 #include "rle.h"
16 #include "rle_raw.h"
17 
18 #define MIN(i,j) ( (i) < (j) ? (i) : (j) )
19 
20 #define RLE_END 32768 /* This should be in rle.h */
21 
22 void
24 int argc;
25 char ** argv;
26 {
27  int nfiles;
28  rle_hdr * in_hdr;
29  rle_hdr out_hdr;
30  int alpha_flag = 0, oflag = 0;
31  rle_op *** in_rows; /* A Carl Sagan pointer. */
32  int ** in_counts; /* nraw */
33  rle_op ** out_rows;
34  int * out_count;
35  int * skips;
36  CONST_DECL char **filenames, *out_fname = NULL, *cmd_nm;
37  FILE *outfile = stdout;
38  int minskip = 0, y;
39  register int i;
40  int rle_cnt, rle_err, stdin_used = -1;
41 
42  if (! scanargs( argc, argv, "% a%- o%-outfile!s files%*s",
43  &alpha_flag, &oflag, &out_fname, &nfiles, &filenames ))
44  exit( -1 );
45  cmd_nm = cmd_name( argv );
46 
47  if (alpha_flag) alpha_flag = 1; /* So indexing's right. */
48 
49  in_hdr = (rle_hdr *) malloc( sizeof( rle_hdr )
50  * nfiles );
51  RLE_CHECK_ALLOC( cmd_nm, in_hdr, "file headers" );
52 
53  in_rows = (rle_op ***) malloc( sizeof( rle_op ** ) * nfiles );
54  RLE_CHECK_ALLOC( cmd_nm, in_rows, "input data" );
55  in_counts = (int **) malloc( sizeof( int * ) * nfiles );
56  RLE_CHECK_ALLOC( cmd_nm, in_counts, 0 );
57  skips = (int *) malloc( sizeof( int ) * nfiles );
58  RLE_CHECK_ALLOC( cmd_nm, skips, 0 );
59 
60  out_rows = (rle_op **) malloc( sizeof( rle_op * ) * nfiles );
61  RLE_CHECK_ALLOC( cmd_nm, out_rows, "output data" );
62  out_count = (int *) malloc( sizeof( int ) * nfiles );
63  RLE_CHECK_ALLOC( cmd_nm, out_count, 0 );
64 
65  /* Open all the files, and check consistancy */
66 
67  for (i = 0; i < nfiles; i++)
68  {
69  in_hdr[i] = *rle_hdr_init( NULL );
70  rle_names( &in_hdr[i], cmd_name( argv ), filenames[i], 0 );
71  in_hdr[i].rle_file = rle_open_f( in_hdr[i].cmd, filenames[i], "r");
72  if ( in_hdr[i].rle_file == stdin )
73  if ( stdin_used < 0 )
74  {
75  filenames[i] = "Standard Input";
76  stdin_used = i;
77  }
78  else
79  {
80  fprintf( stderr,
81  "Images %d and %d are both from the standard input\n",
82  stdin_used, i );
83  exit( -1 );
84  }
85  }
86  out_hdr = *rle_hdr_init( NULL );
87  rle_names( &out_hdr, in_hdr[0].cmd, out_fname, 0 );
88 
89  /* Note: the only way out of this loop is via one of the two exit
90  * calls below.
91  */
92  for ( rle_cnt = 0; ; rle_cnt++ )
93  {
94  for (i = 0; i < nfiles; i++)
95  {
96  /* Check for an error. EOF or EMPTY is ok if at least one image
97  * has been read. Otherwise, print an error message. EOF
98  * or EMPTY after first image means end of input.
99  */
100  if ( (rle_err = rle_get_setup( &in_hdr[i])) != RLE_SUCCESS )
101  if ( rle_cnt == 0 || (rle_err != RLE_EOF &&
102  rle_err != RLE_EMPTY) )
103  {
104  rle_get_error( rle_err, cmd_name( argv ), filenames[i] );
105  exit( 1 );
106  }
107  else if ( rle_err == RLE_EOF || rle_err == RLE_EMPTY )
108  exit( 0 );
109 
110 
111  /* Check that the channel's really there */
112  if (((in_hdr[i].ncolors-1) < (i-alpha_flag)) ||
113  (! RLE_BIT( in_hdr[i], i-alpha_flag )))
114  {
115  fprintf(stderr, "mergechan: channel %d not in file %s\n",
116  i-alpha_flag, filenames[i] );
117  exit( -2 );
118  }
119 
120  /* Check to make sure all images have the same size */
121  if (i > 0)
122  {
123  if (! ((in_hdr[0].xmin == in_hdr[i].xmin) &&
124  (in_hdr[0].xmax == in_hdr[i].xmax) &&
125  (in_hdr[0].ymin == in_hdr[i].ymin) &&
126  (in_hdr[0].ymax == in_hdr[i].ymax)) )
127  {
128  fprintf(stderr,
129  "mergechan: image %s is not the same size as image %s\n",
130  filenames[i], filenames[0] );
131  exit( -2 );
132  }
133  }
134 
135  if ( rle_raw_alloc( &in_hdr[i], &in_rows[i], &in_counts[i] ) < 0 )
136  RLE_CHECK_ALLOC( cmd_nm, 0, "input image data" );
137  }
138 
139  /* Setup output stuff */
140 
141  (void)rle_hdr_cp( &in_hdr[0], &out_hdr );
142  rle_addhist( argv, &in_hdr[0], &out_hdr );
143 
144  if ( rle_cnt == 0 )
145  outfile = rle_open_f("mergechan", out_fname, "w");
146  out_hdr.rle_file = outfile;
147 
148  out_hdr.ncolors = nfiles - alpha_flag;
149  out_hdr.alpha = alpha_flag;
150 
151  /* Set background color appropriately. */
152  if ( out_hdr.ncolors > 0 )
153  {
154  out_hdr.background = 2;
155  out_hdr.bg_color = (int *)malloc(out_hdr.ncolors * sizeof(int));
156  RLE_CHECK_ALLOC( cmd_nm, out_hdr.bg_color,
157  "output background color" );
158  for ( i = 0; i < out_hdr.ncolors; i++ )
159  if ( in_hdr[i + alpha_flag].background > 0 )
160  out_hdr.bg_color[i] = in_hdr[i + alpha_flag].bg_color[i];
161  else
162  out_hdr.bg_color[i] = 0;
163  }
164  else
165  out_hdr.background = 0;
166 
167  /* Enable all output channels. */
168  for (i = -alpha_flag; i < out_hdr.ncolors; i++)
169  RLE_SET_BIT( out_hdr, i );
170 
171  rle_put_setup( &out_hdr );
172 
173 
174  if (alpha_flag) /* So indexing's right (alpha == -1) */
175  {
176  in_hdr++;
177  in_rows++;
178  in_counts++;
179 
180  out_rows++;
181  out_count++;
182  skips++;
183  }
184 
185  /* Initialize counters */
186  for (i = -alpha_flag; i < out_hdr.ncolors; i++)
187  {
188  skips[i] = 0;
189  out_rows[i] = in_rows[i][i];
190  }
191  y = out_hdr.ymin - 1; /* -1 'cuz we haven't read data yet */
192 
193  /*
194  * Do the actual work. Since rle_getraw may "skip" several lines
195  * ahead, we need to keep track of the Y position of each channel
196  * independently with skips[]. The output moves ahead by the
197  * minimum of these skip values (minskip).
198  */
199  while (1) /* Stops at EOF on all files */
200  {
201  for (i = -alpha_flag; i < out_hdr.ncolors; i++)
202  {
203  if (! skips[i])
204  {
205  skips[i] = rle_getraw( &(in_hdr[i]),
206  in_rows[i], in_counts[i] );
207  if (skips[i] != RLE_END)
208  skips[i] -= y; /* Store delta to next data */
209  }
210 
211  /* Find smallest skip distance until a channel has data again */
212  if (i == -alpha_flag)
213  minskip = skips[i];
214  else
215  minskip = MIN( skips[i], minskip );
216  }
217 
218  if (minskip == RLE_END)
219  break; /* Hit the end of all input files */
220 
221  if (minskip > 1)
222  rle_skiprow( &out_hdr, minskip-1 );
223 
224  y += minskip;
225 
226  for (i = -alpha_flag; i < out_hdr.ncolors; i++)
227  {
228  if (skips[i] != RLE_END) skips[i] -= minskip;
229 
230  if (skips[i] == 0) /* Has data to go out */
231  {
232  out_count[i] = in_counts[i][i];
233  }
234  else
235  {
236  out_count[i] = 0;
237  }
238  }
239 
240  rle_putraw( out_rows, out_count, &out_hdr );
241 
242  for (i = -alpha_flag; i < out_hdr.ncolors; i++)
243  {
244  if (skips[i] == 0) /* Data is written, so free the raws */
245  {
246  rle_freeraw( &(in_hdr[i]), in_rows[i], in_counts[i] );
247  }
248  }
249  }
250 
251  rle_puteof( &out_hdr );
252 
253  /* Free storage. */
254  if (alpha_flag)
255  {
256  in_hdr--;
257  in_rows--;
258  in_counts--;
259 
260  out_rows--;
261  out_count--;
262  skips--;
263  }
264  for ( i = 0; i < nfiles; i++ )
265  rle_raw_free( &in_hdr[i], in_rows[i], in_counts[i] );
266  }
267  /* NOTREACHED */
268 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
#define MIN(x, y)
Definition: rletopaint.c:53
#define RLE_SET_BIT(glob, bit)
Definition: rle.h:122
int xmin
Definition: rle.h:100
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
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
int * bg_color
Definition: rle.h:100
#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
#define RLE_END
Definition: mergechan.c:20
void rle_puteof(rle_hdr *the_hdr)
Definition: rle_putrow.c:474
int xmax
Definition: rle.h:100
#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
void rle_skiprow(rle_hdr *the_hdr, int nrow)
Definition: rle_putrow.c:393
int background
Definition: rle.h:100
int ymax
Definition: rle.h:100
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
int alpha
Definition: rle.h:100
void rle_raw_free(rle_hdr *the_hdr, rle_op **scanp, nrawp)
Definition: rle_raw_alc.c:131
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
int ncolors
Definition: rle.h:100
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86
#define RLE_BIT(glob, bit)
Definition: rle.h:126