Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
rawtorle.c
Go to the documentation of this file.
1 
2 /*
3  * This software is copyrighted as noted below. It may be freely copied,
4  * modified, and redistributed, provided that the copyright notice is
5  * preserved on all copies.
6  *
7  * There is no warranty or other guarantee of fitness for this software,
8  * it is provided solely "as is". Bug reports or fixes may be sent
9  * to the author, who may or may not act on them as he desires.
10  *
11  * You may not include this software in a program or other software product
12  * without supplying the source, or without informing the end-user that the
13  * source is available for no extra charge.
14  *
15  * If you modify this software, you should include a notice giving the
16  * name of the person performing the modification, the date of modification,
17  * and the reason for such modification.
18  */
19 /*
20  * rawtorle.c - Convert the kitchen sink to RLE format.
21  *
22  * Author: Martin R. Friedmann while residing@media-lab
23  * Vision and Modeling Group/Media Lab
24  * Massachusetts Institute of Technology
25  * Date: Fri Feb 16 1990
26  * Copyright (c) 1990, Martin R. Friedmann
27  *
28  * usage : rawtorle [-{Ns}] [-r] [-w width] [-h height] [-f header-size]
29  * [-t tailer-size] [-n nchannels] [-a [alpha-value]]
30  * [-p scanline-pad] [-l left-scanline-pad] [-o outfile]
31  * [infile]
32  *
33  * -a [value] add a blank alpha channel to the rle file
34  * -s input data is in scanline interleaved order
35  * -N input is in non-interleaved order (eg. cat pic.r pic.g pic.b | rawtorle)
36  * -r reverse the channel order (e.g. read data as ABGR instead of
37  * the default RGBA order)
38  *
39  * Examples:
40  * 512x512 greyscale image: rawtorle -w 512 -h 512 -n 1
41  * 640x512 raw RGB file : rawtorle -w 640 -h 512 -n 3
42  * picture.[rgb] : cat picture.* | rawtorle -w 640 -h 512 -n 3 -N -r
43  * JPLs ODL voyager pics : rawtorle -w 800 -h 800 -f 2508 -t 1672 -n 1 -p 36
44  * 24bit rasterfile : rawtorle -f 32 -w ... -h ... -n 3
45  * 8 bit rasterfile w/cmap: Uh er Uh.... use rastorle anyway huh?
46  * pic.[000-100].[rgb] : cat pic.* | rawtorle -w ... -h ... -n 3 -s -r
47  */
48 
49 #include <stdio.h>
50 #include "rle.h"
51 
52 /* hey.. why spin normally! */
53 #define duff(counter, block) {
54  while (counter >= 4) {
55  { block; }
56  { block; }
57  { block; }
58  { block; }
59  counter -= 4;
60  }
61  switch (counter & 3) {
62  case 3: { block; }
63  case 2: { block; }
64  case 1: { block; }
65  case 0: counter = 0;
66  }\
67 }
68 
69 void
71 int argc;
72 char *argv[];
73 {
74  int i;
75  char *header_bytes = NULL, *trailer_bytes = NULL;
76  char *infname = NULL, *outfname = NULL;
77  FILE *infile, *outfile;
78  rle_hdr hdr;
79  int oflag = 0, wflag = 0, hflag = 0, nflag = 0;
80  int fflag = 0, tflag = 0, Nsflag = 0, rflag = 0;
81 #define Nflag (Nsflag & 2)
82 #define sflag (Nsflag & 1)
83  int header = 0, trailer = 0, alpha_value = 255;
84  int pflag= 0, right_pad = 0, lflag = 0, left_pad = 0;
85  int aflag = 0, input_alpha = 0;
86  int height = 512, width = 512, nochan = 3;
87  int red_pos, alpha_pos, green_pos = 0, blue_pos = 0;
88  int img_size;
89 
90  /* Default color values */
91  rle_pixel **outrows;
92  unsigned char *inrows;
93  int inrows_size;
94 
95  if ( scanargs( argc, argv,
96  "% Ns%- r%- w%-width!d h%-height!d f%-header-size!d \n\
97 \t\tt%-trailer-size!d n%-nchannels!d a%-alpha-value%d \n\
98 \t\tp%-scanline-pad!d l%-left-scanline-pad!d o%-outfile!s \n\
99 \t\tinfile%s\n(\
100 \t-a\tAdd an alpha channel to the rle file with given value.\n\
101 \t-f,-t\tEach input image is preceded (followed) by so many bytes.\n\
102 \t-l,-p\tScanlines are padded on left (right) end with so many bytes.\n\
103 \t-n\tNumber of channels in the input. If 2 or 4, presence of\n\
104 \t\talpha channel is assumed.\n\
105 \t-N\tinput is in non-interleaved order (e.g.\n\
106 \t\tcat pic.r pic.g pic.b | rawtorle)\n\
107 \t-r\treverse the channel order (e.g. read data as ABGR instead of\n\
108 \t\tthe default RGBA order)\n\
109 \t-s\tInput data is in scanline interleaved order.)",
110  &Nsflag, &rflag, &wflag, &width, &hflag, &height,
111  &fflag, &header, &tflag, &trailer, &nflag, &nochan,
112  &aflag, &alpha_value,
113  &pflag, &right_pad, &lflag, &left_pad,
114  &oflag, &outfname, &infname ) == 0)
115  exit( 1 );
116 
117  /* Initialize header. */
118  hdr = *rle_hdr_init( (rle_hdr *)NULL );
119  rle_names( &hdr, cmd_name( argv ), outfname, 0 );
120 
121  /* Error check arguments. */
122  if ( width <= 0 || height <= 0 ) {
123  fprintf(stderr, "%s: Invalid width or height arg (%d,%d)\n",
124  hdr.cmd, width, height);
125  exit(-2);
126  }
127 
128  if ( 0 > nochan || nochan > 4 ) {
129  fprintf(stderr, "%s: Invalid number of channels %d\n",
130  hdr.cmd, nochan);
131  exit(-2);
132  }
133 
134  /* For 2 channels we assume one is an alpha channel */
135  if ( nochan == 2 || nochan == 4 )
136  input_alpha = 1;
137 
138  /* either way, who cares */
139  if ( Nflag && nochan == 1 )
140  Nsflag = 0;
141 
142  if ( Nflag && (lflag || pflag))
143  fprintf( stderr,
144  "%s: -N with -l or -p is not supported, padding ignored.\n",
145  hdr.cmd );
146 
147  /* Open Raw file */
148  infile = rle_open_f( hdr.cmd, infname, "r" );
149  outfile = rle_open_f( hdr.cmd, outfname, "w" );
150 
151  /* for -Non-interleaved case, we need nochan-1 whole channels of buffer */
152  inrows_size = Nflag ? width * (height + 1) * (nochan - 1) : width * nochan;
153 
154  if ((inrows = (unsigned char *) malloc ( inrows_size )) == NULL) {
155  fprintf(stderr, "%s: No memory available for inrows malloc\n",
156  hdr.cmd);
157  exit(-2);
158  }
159  /* HACK: we allocate more memory; we jack the size for the first fread */
160  if ( Nflag )
161  inrows_size = width * height * (nochan - 1) + width;
162 
163  img_size = width * height;
164 
165  rle_dflt_hdr.rle_file = outfile;
167  rle_dflt_hdr.xmax = width - 1;
168  rle_dflt_hdr.ymax = height - 1;
169  rle_dflt_hdr.alpha = aflag || input_alpha;
170  switch ( nochan ) {
171  case 4: case 3:
173  break;
174  case 2: case 1:
176  break;
177  }
178  if ( aflag || input_alpha )
180  else
182  rle_addhist( argv, (rle_hdr *)NULL, &rle_dflt_hdr );
183 
184  /* maybe faster to malloc and fread than to do lots of GETCs, Idunno */
185  if (fflag)
186  header_bytes = (char *) malloc ( header );
187  if (tflag)
188  trailer_bytes = (char *) malloc ( trailer );
189 
190  if (rle_row_alloc( &rle_dflt_hdr, &outrows )) {
191  fprintf(stderr, "%s: No memory available for rle_row_alloc\n",
192  hdr.cmd);
193  exit(-2);
194  }
195 
196  /* insert alpha channel */
197  if ( aflag && !input_alpha )
198  for (i = 0; i < width; i++)
199  outrows[RLE_ALPHA][i] = alpha_value;
200 
201  /* setup byte positions for reversed colors or otherwise */
202  if ( rflag ) {
203  alpha_pos = 0;
204  /* alpha comes first if it's there */
205  if (nochan > 2) {
206  red_pos = 2 + input_alpha;
207  green_pos = 1 + input_alpha;
208  blue_pos = 0 + input_alpha;
209  } else
210  red_pos = 0 + input_alpha;
211  }
212  else {
213  alpha_pos = nochan - input_alpha;
214  red_pos = 0;
215  if (nochan > 2) {
216  green_pos = 1;
217  blue_pos = 2;
218  }
219  }
220 
221  if ( Nflag ) {
222  red_pos *= img_size;
223  green_pos *= img_size;
224  blue_pos *= img_size;
225  alpha_pos *= img_size;
226  }
227  if ( sflag ) {
228  red_pos *= width;
229  green_pos *= width;
230  blue_pos *= width;
231  alpha_pos *= width;
232  }
233  while ( !feof( infile ))
234  {
235  int y = height;
236  int ni_y = 0; /* only used in -N cases */
237  int first_line = 1;
238  int fread_len = inrows_size;
239  unsigned char *fread_pos = inrows;
240 
241  /* skip the header */
242  if (fflag)
243  fread( header_bytes, 1, header, infile );
244 
245  while (--y >= 0) {
246  register rle_pixel *p, *o;
247  register int stride = nochan, count;
248 
249  /* LEFT_PAD */
250  for (count = 0; count < left_pad; count++)
251  getc(infile);
252 
253  /* READ_SCANLINE */
254  if (fread( fread_pos, 1, fread_len, infile ) != fread_len) {
255  if (!first_line)
256  perror( "read error" );
257  exit (!first_line);
258  }
259 
260  /* RIGHT_PAD */
261  for (count = 0; count < right_pad; count++)
262  getc(infile);
263 
264  /* non-interleaved data is easier to compute than interleaved */
265  if ( Nflag ) {
266  /*
267  * This is a wierd case... We had to read in all of the
268  * scanlines for all but one of the channels... Then we can
269  * handle things scanline by scanline... We have to jack
270  * the fread parameters for all of the remaining scanlines
271  */
272  if ( first_line ) {
273  fread_len = width;
274  fread_pos = inrows + (img_size * (nochan - 1));
275  }
276 
277  if ( input_alpha )
278  outrows[RLE_ALPHA] = (rflag ? inrows + ni_y : fread_pos);
279 
280  if ( rflag )
281  outrows[RLE_RED] = fread_pos;
282  else
283  outrows[RLE_RED] = inrows + red_pos + ni_y;
284 
285  if (nochan > 2) {
286  outrows[RLE_GREEN] = inrows + green_pos + ni_y;
287  if ( rflag || input_alpha )
288  outrows[RLE_BLUE] = inrows + blue_pos + ni_y;
289  else
290  outrows[RLE_BLUE] = fread_pos;
291  }
292  ni_y += width;
293  } else if ( sflag ) {
294  /* scanline interleaved! Like the rle_putrow format.. cake */
295  /* we only need to jack the pointers on the first scanline */
296  if (first_line) {
297  if ( input_alpha )
298  outrows[RLE_ALPHA] = inrows + alpha_pos;
299 
300  outrows[RLE_RED] = inrows + red_pos;
301 
302  if (nochan > 2) {
303  outrows[RLE_GREEN] = inrows + green_pos;
304  outrows[RLE_BLUE] = inrows + blue_pos;
305  }
306  }
307  }
308  else {
309  /* ahhh... the default. interleaved data */
310  if ( input_alpha ) {
311  o = outrows[RLE_ALPHA];
312  p = inrows + alpha_pos;
313  count = width;
314  duff(count, *o++ = *p; p += stride);
315  }
316 
317  o = outrows[RLE_RED];
318  p = inrows + red_pos;
319  count = width;
320  duff( count, *o++ = *p; p += stride);
321 
322  if (nochan > 2) {
323  o = outrows[RLE_GREEN];
324  p = inrows + green_pos;
325  count = width;
326  duff( count, *o++ = *p; p += stride);
327 
328  o = outrows[RLE_BLUE];
329  p = inrows + blue_pos;
330  count = width;
331  duff( count, *o++ = *p; p += stride);
332  }
333  }
334  /* start the file */
335  if (first_line) {
337  first_line = 0;
338  }
339  rle_putrow( outrows, width, &rle_dflt_hdr );
340  }
342 
343  /* skip the trailer */
344  if (tflag)
345  fread( trailer_bytes, 1, trailer, infile );
346  }
347  exit(0);
348 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
#define RLE_SET_BIT(glob, bit)
Definition: rle.h:122
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_row_alloc(rle_hdr *the_hdr, rle_pixel ***scanp)
Definition: rle_row_alc.c:56
#define RLE_GREEN
Definition: rle.h:63
int ymin
Definition: rle.h:100
#define RLE_BLUE
Definition: rle.h:64
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 sflag
#define RLE_RED
Definition: rle.h:62
void rle_putrow(rows, int rowlen, rle_hdr *the_hdr)
Definition: rle_putrow.c:96
int xmax
Definition: rle.h:100
#define duff(counter, block)
Definition: rawtorle.c:53
void rle_addhist(argv, rle_hdr *in_hdr, rle_hdr *out_hdr)
Definition: rle_addhist.c:54
#define RLE_CLR_BIT(glob, bit)
Definition: rle.h:124
int ymax
Definition: rle.h:100
unsigned char rle_pixel
Definition: rle.h:56
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
#define Nflag
int alpha
Definition: rle.h:100
#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