Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
rletoraw.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  * rletoraw.c - Convert the RLE format to the kitchen sink.
20  *
21  * Author: Martin R. Friedmann
22  * Vision and Modeling Group/Media Lab
23  * Massachusetts Institute of Technology
24  * Date: Thu Sep 13 1990
25  * Copyright (c) 1990, Martin R. Friedmann
26  *
27  * usage : rletoraw [-{Ns}] [-r] [-w width] [-h height] [-f header-size]
28  * [-t tailer-size] [-n nchannels] [-a]
29  * [-p scanline-pad] [-l left-scanline-pad] [-o outfile]
30  * [infile]
31  *
32  * -a dont strip the alpha channel from the rle file
33  * -s output data in scanline interleaved order
34  * -N output data in non-interleaved order (eg. | split -Wid*Height -)
35  * -r reverse the channel order (e.g. write data as ABGR instead of
36  * the default RGBA order)
37  *
38  */
39 
40 #include <stdio.h>
41 #include "rle.h"
42 
43 /* hey.. why spin normally! */
44 #define duff(counter, block) {
45  while (counter >= 4) {
46  { block; }
47  { block; }
48  { block; }
49  { block; }
50  counter -= 4;
51  }
52  switch (counter & 3) {
53  case 3: { block; }
54  case 2: { block; }
55  case 1: { block; }
56  case 0: counter = 0;
57  }\
58 }
59 
60 
61 #define WRITE_DATA()
62  if (fwrite( outrows, 1, fwrite_len, outfile ) != fwrite_len) {
63  perror( "write error" );
64  exit(-2);
65  }
66 
67 
68 void
70 int argc;
71 char *argv[];
72 {
73  int i, rle_err;
74  char *nullbytes = NULL;
75  char *infname = NULL, *outfname = NULL, *progname;
76  FILE *infile, *outfile;
77  rle_hdr hdr;
78  int oflag = 0;
79  int fflag = 0, tflag = 0, Nflag = 0, rflag = 0;
80  int header = 0, trailer = 0;
81  int pflag= 0, right_pad = 0, lflag = 0, left_pad = 0;
82  int aflag = 0, output_alpha = 0, sflag = 0;
83 
84  int height, width, nochan;
85  int red_pos, alpha_pos, green_pos = 0, blue_pos = 0;
86  int img_size;
87 
88  /* Default color values */
89  unsigned char *outrows;
90  rle_pixel **inrows;
91  int outrows_size;
92  int y;
93  int line_pos;
94  int fwrite_len;
95  unsigned char *fwrite_pos;
96 
97  progname = cmd_name( argv );
98 
99  if ( scanargs( argc, argv,
100  "% Ns%- r%- a%- f%-header-size!d t%-trailer-size!d \n\
101 \t\tp%-scanline-pad!d l%-left-scanline-pad!d o%-outfile!s \n\
102 \t\tinfile%s\n(\
103 \t-a\tDon't strip the alpha channel from the rle file.\n\
104 \t-f,-t\tEach output image is preceded (followed) by so many bytes.\n\
105 \t-l,-p\tScanlines are padded on left (right) end with so many bytes.\n\
106 \t\tAll padding is with null (0) bytes.\n\
107 \t-s\tOutput data in scanline interleaved order\n\
108 \t-N\tOutput data in non-interleaved order (eg. | split -Wid*Height -)\n\
109 \t-r\treverse the channel order (e.g. write data as ABGR instead of\n\
110 \t\tthe default RGBA order).)",
111  &Nflag, &rflag, &aflag, &fflag, &header,
112  &tflag, &trailer, &pflag, &right_pad, &lflag, &left_pad,
113  &oflag, &outfname, &infname ) == 0)
114  exit( 1 );
115 
116  /* Initialize header. */
117  hdr = *rle_hdr_init( (rle_hdr *)NULL );
118  rle_names( &hdr, cmd_name( argv ), infname, 0 );
119 
120  if (Nflag) {
121  if (Nflag & 1) {
122  Nflag = 0;
123  sflag = 1;
124  } else {
125  Nflag = 1;
126  sflag = 0;
127  }
128  }
129 
130 
131  /* Open Raw file */
132  infile = rle_open_f( progname, infname, "r" );
133  outfile = rle_open_f( progname, outfname, "w" );
134 
135 
136  rle_dflt_hdr.rle_file = infile;
137 
138  if ( (rle_err = rle_get_setup(&rle_dflt_hdr)) < 0) {
139  rle_get_error( rle_err, progname, infname );
140  exit ( rle_err );
141  }
142 
144  rle_dflt_hdr.xmin = 0;
146  rle_dflt_hdr.ymin = 0;
147 
148  width = rle_dflt_hdr.xmax + 1;
149  height = rle_dflt_hdr.ymax + 1;
150  nochan = rle_dflt_hdr.ncolors;
151 
152  fprintf(stderr, "width %d, height %d, channels %d\n", width, height, nochan);
153 
154  if (! aflag)
156  output_alpha = (aflag && RLE_BIT(rle_dflt_hdr, RLE_ALPHA)) ? 1 : 0;
157 
158  /* for -Non-interleaved case, we need nochan-1 whole channels of buffer */
159  /* HACK: we allocate more memory; we jack the size for the first fread */
160  outrows_size = width * (nochan + output_alpha);
161  if ( Nflag )
162  outrows_size *= height;
163  if ((outrows = (unsigned char *) malloc ( outrows_size )) == NULL ) {
164  fprintf(stderr, "%s: No memory available for rows malloc\n", progname);
165  exit(-2);
166  }
167 
168  img_size = width * height;
169 
170  /* Were only interested in R, G, & B */
171  for (i = 3; i < rle_dflt_hdr.ncolors; i++)
173 
174  if (rle_row_alloc( &rle_dflt_hdr, &inrows )) {
175  fprintf(stderr, "%s: No memory available for rle_row_alloc\n", progname);
176  exit(-2);
177  }
178 
179  /* maybe faster to malloc and fwrite than to do lots of GETCs, Idunno */
180  if (fflag || tflag) {
181  nullbytes = (char *) malloc ( (header > trailer) ? header : trailer );
182  if (! nullbytes)
183  fprintf(stderr, "%s: No memory for nullbytes\n", progname);
184  else
185  for( i = (header > trailer) ? header : trailer; i > 0; )
186  nullbytes[--i] = 0;
187  }
188 
189  /* setup byte positions for reversed colors or otherwise */
190  if ( rflag ) {
191  alpha_pos = 0;
192  /* alpha comes first if it's there */
193  if (nochan > 2) {
194  red_pos = 2 + output_alpha;
195  green_pos = 1 + output_alpha;
196  blue_pos = 0 + output_alpha;
197  } else
198  red_pos = 0 + output_alpha;
199  }
200  else {
201  alpha_pos = nochan;
202  red_pos = 0;
203  if (nochan > 2) {
204  green_pos = 1;
205  blue_pos = 2;
206  }
207  }
208 
209  if ( Nflag ) {
210  red_pos *= img_size;
211  green_pos *= img_size;
212  blue_pos *= img_size;
213  alpha_pos *= img_size;
214  } else if ( sflag ) {
215  red_pos *= width;
216  green_pos *= width;
217  blue_pos *= width;
218  alpha_pos *= width;
219  }
220 
221  y = height;
222  line_pos = 0;
223  fwrite_len = outrows_size;
224  fwrite_pos = outrows;
225 
226  /* write the header */
227  if (fflag)
228  fwrite( nullbytes, 1, header, outfile );
229 
230  while (--y >= 0) {
231  register rle_pixel *p, *o;
232  register int stride = nochan + output_alpha, count;
233 
235  /* non-interleaved data is easier to compute than interleaved */
236  if ( Nflag ) {
237  /*
238  * This is a wierd case... We had to read in all of the
239  * scanlines for all but one of the channels... Then we can
240  * handle things scanline by scanline... We have to jack
241  * the fread parameters for all of the remaining scanlines
242  */
243 
244  if ( output_alpha )
245  bcopy(inrows[RLE_ALPHA], outrows + alpha_pos + line_pos,width);
246 
247  bcopy(inrows[RLE_RED], outrows + red_pos + line_pos, width);
248 
249  if (nochan > 2) {
250  bcopy(inrows[RLE_GREEN], outrows + green_pos + line_pos,width);
251  bcopy(inrows[RLE_BLUE], outrows + blue_pos + line_pos,width);
252  }
253  line_pos += width;
254  } else if (sflag) {
255  /* scanline interleaved: we only need to copy the data */
256  if ( output_alpha )
257  bcopy (inrows[RLE_ALPHA], outrows + alpha_pos, width);
258 
259  bcopy (inrows[RLE_RED], outrows + red_pos, width);
260 
261  if (nochan > 2) {
262  bcopy(inrows[RLE_GREEN], outrows + green_pos, width);
263  bcopy(inrows[RLE_BLUE], outrows + blue_pos, width);
264  }
265  }
266  else
267  {
268 #define COPY_LINE() duff(count, *o = *p++; o += stride);
269 
270  /* ahhh... the default. interleaved data */
271  if ( output_alpha ) {
272  o = outrows + alpha_pos;
273  p = inrows[RLE_ALPHA];
274  count = width;
275  COPY_LINE();
276  }
277 
278  o = outrows + red_pos;
279  p = inrows[RLE_RED];
280  count = width;
281  COPY_LINE();
282 
283  if (nochan > 2) {
284  o = outrows + green_pos;
285  p = inrows[RLE_GREEN];
286  count = width;
287  COPY_LINE();
288 
289  o = outrows + blue_pos;
290  p = inrows[RLE_BLUE];
291  count = width;
292  COPY_LINE();
293  }
294  }
295 
296  /* LEFT_PAD */
297  for (count = 0; count < left_pad; count++)
298  putc('\0', outfile);
299 
300  /* WRITE_SCANLINE */
301  if (! Nflag)
302  WRITE_DATA();
303 
304  /* RIGHT_PAD */
305  for (count = 0; count < right_pad; count++)
306  putc('\0', outfile);
307 
308  }
309  if ( Nflag )
310  WRITE_DATA();
311 
312  /* write the trailer */
313  if (tflag)
314  fwrite( nullbytes, 1, trailer, outfile );
315 
316  exit(0);
317 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
int xmin
Definition: rle.h:100
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
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
int rle_row_alloc(rle_hdr *the_hdr, rle_pixel ***scanp)
Definition: rle_row_alc.c:56
#define RLE_GREEN
Definition: rle.h:63
int rle_getrow(rle_hdr *the_hdr, scanline)
Definition: rle_getrow.c:333
int ymin
Definition: rle.h:100
#define WRITE_DATA()
Definition: rletoraw.c:61
int rle_get_error(int code, const char *pgmname, const char *fname)
Definition: rle_error.c:76
#define RLE_BLUE
Definition: rle.h:64
#define COPY_LINE()
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
#define RLE_RED
Definition: rle.h:62
int xmax
Definition: rle.h:100
#define duff(counter, block)
Definition: rawtorle.c:53
#define RLE_CLR_BIT(glob, bit)
Definition: rle.h:124
int ymax
Definition: rle.h:100
unsigned char rle_pixel
Definition: rle.h:56
#define RLE_ALPHA
Definition: rle.h:65
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
rle_hdr rle_dflt_hdr
Definition: rle_global.c:66
FILE * rle_file
Definition: rle.h:114
int ncolors
Definition: rle.h:100
#define RLE_BIT(glob, bit)
Definition: rle.h:126