Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
rle_getraw.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  * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
19  * to have all "void" functions so declared.
20  */
21 /*
22  * rle_getraw.c -
23  *
24  * Author: Spencer W. Thomas
25  * Computer Science Dept.
26  * University of Utah
27  * Date: Mon Nov 10 1986
28  * Copyright (c) 1986, University of Utah
29  */
30 #ifndef lint
31 static char rcs_ident[] = "$Id: rle_getraw.c,v 3.0.1.1 1992/01/28 18:20:36 spencer Exp spencer $";
32 #endif
33 
34 #include <stdio.h>
35 #include "rle.h"
36 #include "rle_raw.h"
37 
38 /* Read a two-byte "short" that started in VAX (LITTLE_ENDIAN) order */
39 #define VAXSHORT( var, fp )
40  { var = fgetc(fp)&0xFF; var |= (fgetc(fp)) << 8; }
41 
42 /* Instruction format -- first byte is opcode, second is datum. */
43 
44 #define OPCODE(inst) (inst[0] & ~LONG)
45 #define LONGP(inst) (inst[0] & LONG)
46 #define DATUM(inst) (inst[1] & 0xff) /* Make sure it's unsigned. */
47 
48 /*****************************************************************
49  * TAG( rle_getraw )
50  *
51  * Get a raw scanline from the input file.
52  * Inputs:
53  * the_hdr: rle_hdr structure containing information about
54  * the input file.
55  * Outputs:
56  * scanraw: an array of pointers to the individual color
57  * scanlines. Scanraw is assumed to have
58  * the_hdr->ncolors pointers to arrays of rle_op,
59  * each of which with enough elements, at least
60  * 1 + (the_hdr->xmax - the_hdr->xmin) / 3.
61  * nraw: an array of integers giving the number of rle_ops for
62  * each color channel.
63  * Returns the current scanline number. Returns 32768 at EOF.
64  * Assumptions:
65  * rle_get_setup has already been called.
66  * Algorithm:
67  * Read input until a vertical skip is encountered,
68  * decoding the instructions into the scanraw array.
69  * Vertical skips that separate scanlines with no data do not
70  * cause a return. In other words, the only reason for returning
71  * with an empty scanline is end of file.
72  *
73  * When the scan_y reaches or exceeds the ymax, the rest of the
74  * input image is skipped. This avoids problems with malformed
75  * input files.
76  */
77 unsigned int
79 rle_hdr *the_hdr;
80 rle_op *scanraw[];
81 int nraw[];
82 {
83  register int channel;
84  register rle_op * rawp = NULL;
85  FILE *infile = the_hdr->rle_file;
86  char inst[2];
87  int scan_x = the_hdr->xmin;
88  register int was_data;
89  short word, long_data, nc, been_some = 0;
90 
91  /* Add in vertical skip from last scanline */
92  if ( the_hdr->priv.get.vert_skip > 0 )
93  the_hdr->priv.get.scan_y += the_hdr->priv.get.vert_skip;
94 
95  /* Set run lengths to 0 */
96  for ( channel = (the_hdr->alpha ? -1 : 0);
97  channel < the_hdr->ncolors;
98  channel++ )
99  if ( RLE_BIT( *the_hdr, channel ) )
100  nraw[channel] = 0;
101  channel = 0;
102 
103  if ( the_hdr->priv.get.is_eof )
104  return 32768; /* too big for 16 bits, signal EOF */
105 
106  /* Otherwise, read and interpret instructions until a skipLines
107  * instruction is encountered.
108  */
109  for (was_data = 0;;)
110  {
111  inst[0] = getc( infile );
112  inst[1] = getc( infile );
113  if ( feof(infile) )
114  {
115  the_hdr->priv.get.is_eof = 1;
116  break; /* <--- one of the exits */
117  }
118 
119  switch( OPCODE(inst) )
120  {
121  case RSkipLinesOp:
122  was_data = 1;
123  if ( LONGP(inst) )
124  {
125  VAXSHORT( the_hdr->priv.get.vert_skip, infile );
126  }
127  else
128  the_hdr->priv.get.vert_skip = DATUM(inst);
129  break; /* need to break for() here, too */
130 
131  case RSetColorOp:
132  was_data = 1;
133  channel = DATUM(inst); /* select color channel */
134  if ( channel == 255 )
135  channel = -1;
136  scan_x = the_hdr->xmin;
137  if ( RLE_BIT( *the_hdr, channel ) )
138  rawp = scanraw[channel];
139  else
140  rawp = NULL;
141  break;
142 
143  case RSkipPixelsOp:
144  was_data = 1;
145  if ( LONGP(inst) )
146  {
147  VAXSHORT( long_data, infile );
148  scan_x += long_data;
149  }
150  else
151  {
152  scan_x += DATUM(inst);
153  }
154  break;
155 
156  case RByteDataOp:
157  was_data = 1;
158  if ( LONGP(inst) )
159  {
160  VAXSHORT( nc, infile );
161  }
162  else
163  nc = DATUM(inst);
164  nc++;
165  if ( rawp != NULL )
166  {
167  rawp->opcode = RByteDataOp;
168  rawp->xloc = scan_x;
169  rawp->length = nc;
170  rawp->u.pixels = (rle_pixel *)malloc( (unsigned)nc );
171  fread( (char *)rawp->u.pixels, 1, nc, infile );
172  if ( nc & 1 )
173  (void)getc( infile ); /* throw away odd byte */
174  rawp++;
175  nraw[channel]++;
176  }
177  else
178  if ( the_hdr->priv.get.is_seek )
179  fseek( infile, ((nc + 1) / 2) * 2, 1 );
180  else
181  {
182  register int ii;
183  for ( ii = ((nc + 1) / 2) * 2; ii > 0; ii-- )
184  (void) getc( infile ); /* discard it */
185  }
186 
187  scan_x += nc;
188  been_some = 1;
189  break;
190 
191  case RRunDataOp:
192  was_data = 1;
193  if ( LONGP(inst) )
194  {
195  VAXSHORT( nc, infile );
196  }
197  else
198  nc = DATUM(inst);
199 
200  nc++;
201  VAXSHORT( word, infile );
202  if ( rawp != NULL )
203  {
204  rawp->opcode = RRunDataOp;
205  rawp->xloc = scan_x;
206  rawp->length = nc;
207  rawp->u.run_val = word;
208  rawp++;
209  nraw[channel]++;
210  }
211  scan_x += nc;
212  been_some = 1;
213  break;
214 
215  case REOFOp:
216  the_hdr->priv.get.is_eof = 1;
217  break;
218 
219  default:
220  fprintf( stderr,
221  "%s: rle_getraw: Unrecognized opcode: %d, reading %s\n",
222  the_hdr->cmd, OPCODE(inst), the_hdr->file_name );
223  exit(1);
224  }
225  if ( OPCODE(inst) == REOFOp )
226  break; /* <--- the other loop exit */
227  if ( OPCODE(inst) == RSkipLinesOp )
228  {
229  if ( been_some )
230  break; /* <--- the other loop exit */
231  else
232  /* No data on that scanline, so move up to this scanline */
233  the_hdr->priv.get.scan_y +=
234  the_hdr->priv.get.vert_skip;
235  }
236  }
237 
238  /* If at top of image, skip any remaining. */
239  if ( the_hdr->priv.get.scan_y >= the_hdr->ymax )
240  {
241  int y = the_hdr->priv.get.scan_y;
242  while ( rle_getskip( the_hdr ) != 32768 )
243  ;
244  return y;
245  }
246 
247  /* Return current Y value */
248  return (was_data == 0) ? 32768 : the_hdr->priv.get.scan_y;
249 }
250 
251 /*****************************************************************
252  * TAG( rle_freeraw )
253  *
254  * Free all the pixel arrays in the raw scan struct.
255  * Inputs:
256  * the_hdr: Header struct corresponding to this RLE data.
257  * scanraw: Array of pointers to array of rle_op, as above.
258  * nraw: Array of lengths (as above)
259  * Outputs:
260  * Frees the areas pointed to by the pixels elements of any
261  * RByteDataOp type rle_op structs.
262  * Assumptions:
263  * [None]
264  * Algorithm:
265  * [None]
266  */
267 void
269 rle_hdr * the_hdr;
270 int nraw[];
271 rle_op *scanraw[] ;
272 {
273  int c, i;
274  register rle_op * raw_p;
275 
276  for ( c = -the_hdr->alpha; c < the_hdr->ncolors; c++ )
277  if ( RLE_BIT( *the_hdr, c ) )
278  for ( i = nraw[c], raw_p = scanraw[c]; i > 0; i--, raw_p++ )
279  if ( raw_p->opcode == RByteDataOp )
280  {
281  if ( raw_p->u.pixels )
282  free( raw_p->u.pixels );
283  else
284  fprintf( stderr,
285  "%s(%s): rle_freeraw given NULL pixel pointer, %d[%d].\n",
286  the_hdr->cmd, the_hdr->file_name,
287  c, nraw[c] - i );
288  raw_p->u.pixels = NULL;
289  }
290 }
#define RSetColorOp
Definition: rle_code.h:38
#define RRunDataOp
Definition: rle_code.h:41
int xmin
Definition: rle.h:100
void rle_freeraw(rle_hdr *the_hdr, scanraw, nraw)
Definition: rle_getraw.c:268
int length
Definition: rle_raw.h:51
int opcode
Definition: rle_raw.h:49
#define RSkipLinesOp
Definition: rle_code.h:37
#define LONGP(inst)
Definition: XtndRunget.c:85
#define REOFOp
Definition: rle_code.h:42
int xloc
Definition: rle_raw.h:50
const char * cmd
Definition: rle.h:133
static char rcs_ident[]
Definition: rle_getraw.c:31
#define RSkipPixelsOp
Definition: rle_code.h:39
unsigned int rle_getskip(rle_hdr *the_hdr)
Definition: rle_getskip.c:57
#define LONG
Definition: rle_code.h:36
#define VAXSHORT(var, fp)
Definition: rle_cp.c:33
#define DATUM(inst)
Definition: XtndRunget.c:86
int ymax
Definition: rle.h:100
unsigned char rle_pixel
Definition: rle.h:56
int alpha
Definition: rle.h:100
const char * file_name
Definition: rle.h:134
#define OPCODE(inst)
Definition: XtndRunget.c:84
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 RByteDataOp
Definition: rle_code.h:40
#define RLE_BIT(glob, bit)
Definition: rle.h:126