Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
rastorle.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  * rastorle --
20  * convert Sun Rasterfile to Utah RLE format
21  * reads Sun rasterfile or stdin and writes stdout.
22  *
23  * Author: Berry Kercheval (berry@mordor.s1.gov)
24  * Lawrence Livermore National Laboratory
25  * Livermore, CA.
26  * Date: 9 March 1987
27  * History:
28  * 27 March 1987: bbk: make it understand depth one (B&W) rasterfiles.
29  * 6 September 1990: Clark: make it understand RT_BYTE_ENCODED rasterfiles,
30  * add flag so alpha channel is done only if desired,
31  * and output a colormap for images of depth 8.
32  *
33  * Usage is:
34  * rastorle [-a] [-o outfile.rle] [ infile.ras ] >out.rle
35  *
36  * -a Fake an alpha channel.
37  *
38  * This will be difficult to compile on a non-sun, as it uses the pixrect
39  * library include files.
40  */
41 #ifndef lint
42 static char rcsid[] = "$Header: /l/spencer/src/urt/cnv/RCS/rastorle.c,v 3.0.1.6 1992/04/30 13:58:02 spencer Exp $";
43 #endif
44 #if 0
45 rastorle() /* Tag. */
46 #endif
47 
48 #include <stdio.h>
49 #include <rasterfile.h>
50 #include <sysexits.h>
51 #include "rle.h"
52 
53 #define MAXLINE 1280 /* max width of a line */
54 #define MAXVAL 255 /* max value for pixel */
55 #define CMAPSIZE 256 /* Max size of color map */
56 #define ESCAPE 128 /* Escape value for RT_BYTE_ENCODED rasterfiles */
57 /* #define DEBUG /* debug output turned on */
58 
59 int getbit();
60 
61 static rle_map out_map[3*(1<<8)];
62 
63 static unsigned char *outrows[4]; /* array of rows for RLE output */
64 static unsigned char *redline, /* rle red row values */
65  *grnline,
66  *bluline,
67  *alfline; /* alpha channel values */
68 static int depth, npix; /* Image size factors. */
69 static unsigned char *image;
70 
71 static unsigned char red[CMAPSIZE], /* red colormap entries */
72  green[CMAPSIZE], /* Green ditto */
73  blue[CMAPSIZE]; /* see a pattern? */
74 
75 void
77 int argc;
78 char *argv[];
79 {
80  char *outfname = NULL;
81  char *infname = NULL;
82  int aflag = 0, oflag = 0;
83  FILE *rasfile; /* where input comes from */
84  FILE *outfile; /* where output goes to */
85  int i; /* useful index */
86  int p = 0; /* pixel value read from a file --
87  * used to index rasterfile color map. */
88  int count = 9999; /* Holds current byte count for
89  * rasterfiles of type RT_BYTE_ENCODED */
90  int h; /* index for looping along a row */
91  struct rasterfile rashdr; /* standard header of a Sun rasterfile*/
92  rle_hdr rlehdr; /* Header of RLE file. */
93 
94  if ( scanargs( argc, argv, "% a%- o%-outfile!s infile%s\n(\
95 \tConvert a Sun Raster file to URT RLE format.\n\
96 \t-a\tFake an alpha channel: opaque when pixel non-zero.)",
97  &aflag, &oflag, &outfname, &infname ) == 0 )
98  exit( EX_USAGE );
99 
100  rlehdr = *rle_hdr_init( (rle_hdr *)NULL );
101  rle_names( &rlehdr, cmd_name( argv ), outfname, 0 );
102 
103  rasfile = rle_open_f( rlehdr.cmd, infname, "r" );
104  outfile = rle_open_f( rlehdr.cmd, outfname, "w" );
105 
106  rle_addhist( argv, (rle_hdr *)NULL, &rlehdr );
107 
108  /* first read the rasterfile header */
109  if(fread(&rashdr, sizeof(rashdr), 1, rasfile) != 1)
110  {
111  fprintf(stderr, "Can't read rasterfile header.\n");
112  exit(EX_DATAERR);
113  }
114  /* it has to start with the magic number... */
115  if (rashdr.ras_magic != RAS_MAGIC)
116  {
117  fprintf(stderr, "Error: \"%s\" is not a rasterfile.\n",
118  rasfile==stdin?"stdin":argv[1]);
119  exit(EX_DATAERR);
120  }
121 #ifdef DEBUG
122  fprintf (stderr, "rasterfile width = %d\n", rashdr.ras_width);
123  fprintf (stderr, "rasterfile height = %d\n", rashdr.ras_height);
124  fprintf (stderr, "rasterfile depth = %d\n", rashdr.ras_depth);
125  fprintf (stderr, "rasterfile length = %d\n", rashdr.ras_length);
126  fprintf (stderr, "rasterfile type = %d\n", rashdr.ras_type);
127  fprintf (stderr, "rasterfile maplength = %d\n", rashdr.ras_maplength);
128 #endif
129 
130  /* Allocate image memory. */
131  if ( rashdr.ras_depth == 32 )
132  aflag = 0; /* Alpha counted in depth for 32-bit image. */
133  depth = (rashdr.ras_depth + 7) / 8 + aflag;
134  npix = rashdr.ras_width * rashdr.ras_height;
135  image = (unsigned char *) malloc( depth * npix );
136  RLE_CHECK_ALLOC( rlehdr.cmd, image, "pixel" );
137  if ( rashdr.ras_depth == 32 )
138  aflag = 1; /* Always alpha channel from 32-bit image. */
139  if ( aflag )
140  alfline = image + depth * npix - rashdr.ras_width;
141  redline = image + npix - rashdr.ras_width;
142  /* Depth > 2 means RGB or RGBA, <= 2 means 8-bit w/ or w/o alpha. */
143  if ( depth > 2 )
144  {
145  grnline = image + 2 * npix - rashdr.ras_width;
146  bluline = image + 3 * npix - rashdr.ras_width;
147  }
148 
149  /* read in color map */
150  switch(rashdr.ras_maptype)
151  {
152  case RMT_NONE:
153 #ifdef DEBUG
154  fprintf (stderr, "No color map\n");
155 #endif
156  for (i = 0; i < 256; i++)
157  red[i] = green[i] = blue[i] = i ;
158  break;
159  case RMT_RAW:
160 #ifdef DEBUG
161  fprintf (stderr, "Raw color map\n");
162 #endif
163  for (i = 0; i < 256; i++)
164  red[i] = green[i] = blue[i] = i ;
165  for (i = 0; i < rashdr.ras_maplength; i++)
166  getc(rasfile);
167  break;
168  case RMT_EQUAL_RGB:
169 #ifdef DEBUG
170  fprintf (stderr, "RGB color map\n");
171 #endif
172  /* read red */
173  for (i = 0; i < rashdr.ras_maplength/3; i++)
174  red[i] = getc(rasfile);
175  /* read green */
176  for (i = 0; i < rashdr.ras_maplength/3; i++)
177  green[i] = getc(rasfile);
178  /* read blue */
179  for (i = 0; i < rashdr.ras_maplength/3; i++)
180  blue[i] = getc(rasfile);
181  break;
182  default:
183  fprintf (stderr, "Unknown color map type (%d)\n", rashdr.ras_maptype);
184  exit (EX_DATAERR);
185  }
186 
187  /* Read in the image. */
188  switch(rashdr.ras_depth)
189  {
190  default:
191  fprintf(stderr,
192  "Sorry, I can't deal with a rasterfile depth %d\n",rashdr.ras_depth);
193  break;
194 
195  case 1: /* black & white */
196  /* A one channel output seems most reasonable. */
197  RLE_SET_BIT(rlehdr, RLE_RED);
198  RLE_CLR_BIT(rlehdr, RLE_GREEN);
199  RLE_CLR_BIT(rlehdr, RLE_BLUE);
200  if ( aflag )
201  RLE_SET_BIT(rlehdr, RLE_ALPHA );
202  else
203  RLE_CLR_BIT(rlehdr, RLE_ALPHA );
204  rlehdr.ncolors = 1;
205  rlehdr.ncmap = 0 ;
206  for (i=0; i<rashdr.ras_height; i++)
207  {
208  for(h = 0; h < rashdr.ras_width; h++)
209  {
210  p = getbit(rasfile, 0);
211  redline[h] = p?0:MAXVAL;
212  if ( aflag )
213  alfline[h] = p?0:MAXVAL;
214  }
215  redline -= rashdr.ras_width;
216  if ( aflag )
217  alfline -= rashdr.ras_width;
218  getbit(NULL, 1);
219  }
220  break; /* end case 1: */
221 
222  case 8:
223  case 24:
224  case 32:
225  /* next few lines stolen from painttorle.c */
226  RLE_SET_BIT(rlehdr, RLE_RED);
227  RLE_SET_BIT(rlehdr, RLE_GREEN);
228  RLE_SET_BIT(rlehdr, RLE_BLUE);
229  if ( aflag )
230  RLE_SET_BIT(rlehdr, RLE_ALPHA );
231  else
232  RLE_CLR_BIT(rlehdr, RLE_ALPHA );
233 
234  if (rashdr.ras_depth == 8)
235  {
236  rlehdr.ncolors = 1;
237  rlehdr.ncmap = 3;
238  rlehdr.cmaplen = 8;
239  rlehdr.cmap = out_map;
240  for (i=0;i<(1<<8);i++)
241  {
242  out_map[i+(0<<8)] = red[i] << 8;
243  out_map[i+(1<<8)] = green[i] << 8;
244  out_map[i+(2<<8)] = blue[i] << 8;
245  }
246  }
247 
248  if (rashdr.ras_type == RT_BYTE_ENCODED)
249  count = 9999;
250  for (i=0; i<rashdr.ras_height; i++)
251  {
252  /* read a line from the rasterfile */
253  switch(rashdr.ras_depth)
254  {
255  case 8:
256  for (h=0; h < rashdr.ras_width; h++)
257  {
258  if (rashdr.ras_type != RT_BYTE_ENCODED)
259  p = getc(rasfile);
260  else
261  {
262  if (count == 9999)
263  {
264  p = getc(rasfile);
265  if (p == ESCAPE)
266  {
267  count = getc(rasfile);
268  if (count == 0)
269  count = 9999;
270  else
271  p = getc(rasfile);
272  }
273  }
274  else
275  {
276  if (--count == 0)
277  count = 9999;
278  }
279  }
280  redline[h] = p;
281  /* fake up an alpha channel */
282  if ( aflag )
283  {
284  if (redline[h])
285  alfline[h] = 255;
286  else
287  alfline[h] = 0;
288  }
289  }
290  /* Since records are an even number of bytes */
291  if (rashdr.ras_width & 1) p = getc(rasfile);
292  break ;
293 
294  case 24:
295  for (h=0; h < rashdr.ras_width; h++)
296  {
297  register int r,g,b ;
298  r = getc(rasfile);
299  g = getc(rasfile);
300  b = getc(rasfile);
301  redline[h] = red[r];
302  grnline[h] = green[g];
303  bluline[h] = blue[b];
304  /* fake up an alpha channel */
305  if ( aflag )
306  {
307  if (redline[h] || grnline[h] || bluline[h])
308  alfline[h] = 255;
309  else
310  alfline[h] = 0;
311  }
312  }
313  /* Since records are an even number of bytes */
314  if (rashdr.ras_width & 1) p = getc(rasfile);
315  break ;
316 
317  case 32:
318  for (h=0; h < rashdr.ras_width; h++)
319  {
320  register int r,g,b,a ;
321  a = getc(rasfile);
322  r = getc(rasfile);
323  g = getc(rasfile);
324  b = getc(rasfile);
325  redline[h] = red[r];
326  grnline[h] = green[g];
327  bluline[h] = blue[b];
328  alfline[h] = a;
329  }
330  break ;
331  }
332  if ( aflag )
333  alfline -= rashdr.ras_width;
334  redline -= rashdr.ras_width;
335  if ( depth > 2 )
336  {
337  grnline -= rashdr.ras_width;
338  bluline -= rashdr.ras_width;
339  }
340  }
341  break; /* end case 8: */
342  } /* end switch */
343 
344  /* Set up common output parameters. */
345  rlehdr.rle_file = outfile;
346  rlehdr.xmax = rashdr.ras_width-1;
347  rlehdr.ymax = rashdr.ras_height-1;
348  if ( aflag )
349  rlehdr.alpha = 1;
350  else
351  rlehdr.alpha = 0;
352 
353  /* Write the header. */
354  rle_put_setup( &rlehdr );
355 
356  /* Write the image. */
357  outrows[0] = alfline;
358  outrows[1] = redline;
359  outrows[2] = grnline;
360  outrows[3] = bluline;
361  for ( i = 0; i <= rlehdr.xmax; i++ )
362  {
363  for ( h = 1 - aflag; h < depth + 1 - aflag; h++ )
364  outrows[h] += rashdr.ras_width;
365  rle_putrow( &outrows[1], rashdr.ras_width, &rlehdr );
366  }
367 
368  rle_puteof( &rlehdr );
369 
370  /* Free memory. */
371  free( image );
372 }
373 
374 /*
375  * get a bit from the file fp. Read a byte and return its bits
376  * one at a time. (actually returns zero or non-zero).
377  */
378 int
379 getbit(fp, force)
380 FILE *fp;
381 int force; /* true if we should read a byte anyway */
382 {
383  static int c; /* the char we are picking apart */
384  static unsigned int mask
385  = 0x0; /* mask to get the next bit -- init to huge
386  * so that we get a byte the first time */
387  int val; /* value to be returned */
388  if (force) /* read a new byte next time */
389  {
390  mask = 0x0;
391  return 0;
392  }
393  if(mask == 0) /* time to get the next byte */
394  {
395  c = getc(fp);
396  mask = 0x80; /* reset the mask */
397  }
398  val = c & mask; /* true if this bit on */
399  mask >>= 1; /* shift mask over one bit */
400  return val; /* the bit we saved goes back to caller */
401 }
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
static unsigned char * outrows[4]
Definition: rastorle.c:63
static unsigned char blue[256]
Definition: rastorle.c:71
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
static unsigned char * grnline
Definition: rastorle.c:64
static unsigned char * bluline
Definition: rastorle.c:64
char * cmd_name(char **argv)
Definition: cmd_name.c:31
#define CMAPSIZE
Definition: rastorle.c:55
void main(int argc, char **argv)
Definition: aliastorle.c:121
static int depth
Definition: rastorle.c:68
#define RLE_GREEN
Definition: rle.h:63
#define RLE_BLUE
Definition: rle.h:64
static unsigned char * alfline
Definition: rastorle.c: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
static rle_map out_map[3 *(1<< 8)]
Definition: rastorle.c:61
#define RLE_RED
Definition: rle.h:62
int xmax
Definition: rle.h:100
static unsigned char green[256]
Definition: rastorle.c:71
void rle_addhist(argv, rle_hdr *in_hdr, rle_hdr *out_hdr)
Definition: rle_addhist.c:54
#define MAXVAL
Definition: rastorle.c:54
#define RLE_CLR_BIT(glob, bit)
Definition: rle.h:124
static unsigned char * redline
Definition: rastorle.c:64
static int npix
Definition: rastorle.c:68
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
int alpha
Definition: rle.h:100
#define RLE_ALPHA
Definition: rle.h:65
static char rcsid[]
Definition: rastorle.c:42
unsigned short rle_map
Definition: rle.h:57
#define ESCAPE
Definition: rastorle.c:56
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
static unsigned char red[256]
Definition: rastorle.c:71
FILE * rle_file
Definition: rle.h:114
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86
static unsigned char * image
Definition: rastorle.c:69