Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
aliastorle.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  * aliastorle.c - Convert Alias "pix" format to Utah's rle images
20  *
21  * Author: Raul Rivero
22  * Mathematics Dept.
23  * University of Oviedo
24  * Date: Fri Dec 27 1991
25  * Copyright (c) 1991, Raul Rivero
26  *
27  */
28 #ifndef lint
29 static char rcs_id[] = "$Header: /l/spencer/src/urt/cnv/RCS/aliastorle.c,v 3.0.1.1 1992/04/29 20:01:12 spencer Exp $";
30 #endif
31 /*
32  aliastorle() Tag the file.
33 */
34 
35 #include <stdio.h>
36 #include <math.h>
37 #include "rle.h"
38 
39 #define byte unsigned char
40 #define Fread(p, s, n, f) if ( fread(p, s, n, f) != n ) error(3)
41 #define Fwrite(p, s, n, f) if ( fwrite(p, s, n, f) != n ) error(4)
42 #define VPRINTF if (verbose) fprintf
43 
44 /*
45  * Alias header.
46  */
47 typedef struct {
48  short xsize, ysize;
49  short xinit, yinit;
50  short depth;
51 } alias_hdr;
52 
53 /*
54  * I use a intermediate format ( a simple bitmap ) with
55  * this format ...
56  */
57 typedef struct {
58  int xsize, ysize; /* sizes */
59  int depth; /* # of colors */
60  int colors; /* # of colors */
61  byte *r, *g, *b; /* components or bitmap (planes < 8) */
62  byte *cmap; /* cmap if planes < 8 */
63 } bitmap_hdr;
64 
65 /*
66  * Prototypes ( only what is necesary ).
67  */
68 #ifdef USE_PROTOTYPES
69 static char *Malloc(long int);
70 static char *read_file(FILE *, int *);
71 static long filelen(FILE *);
72 static int read_alias(FILE *, bitmap_hdr *);
73 static void write_rle(FILE *, bitmap_hdr *);
74 static void read_alias_header(FILE *, alias_hdr *);
75 static void create_alias_cmap(bitmap_hdr *);
76 static void uncode_alias24(byte *, byte *, byte *, byte *, byte *);
77 static void uncode_alias(byte *, byte *, byte *);
78 static int read_line_alias24(FILE *, byte *, byte *, byte *, int);
79 static int read_line_alias(FILE *, byte *, int);
80 static void error( int );
81 #else
82 static char *Malloc();
83 static char *read_file();
84 static long filelen();
85 static int read_alias();
86 static void write_rle(), read_alias_header();
87 static void create_alias_cmap(), uncode_alias24(), uncode_alias();
88 static int read_line_alias24(), read_line_alias();
89 static void error();
90 #endif
91 
92 
93 /*
94  * The flag for verbose.
95  */
96 int verbose= 0;
97 /*
98  * RLE file header (put here so can be initialized with cmd and file names).
99  */
100 rle_hdr the_hdr;
101 
102 /*****************************************************************
103  * TAG( main )
104  *
105  * Usage: aliastorle [-v] [-o outfile] [infile]
106  *
107  * Inputs:
108  * -v: Verbose switch.
109  * infile: Input Alias pix file. Stdin used if not
110  * specified.
111  * Outputs:
112  * outfile: Output a RLE file. Stdout used if not
113  * specified.
114  * Assumptions:
115  * [None]
116  * Algorithm:
117  * [None]
118  */
119 
120 void
122 int argc;
123 char **argv;
124 {
125  char *inname = NULL;
126  char *outname = NULL;
127  FILE *infile;
128  FILE *outfile;
129  int oflag = 0;
130  bitmap_hdr bitmap;
131 
132  the_hdr = *rle_hdr_init( (rle_hdr *)NULL );
133  /*
134  * Get options
135  */
136  if ( !scanargs( argc, argv, "% v%- o%-outfile!s infile%s",
137  &verbose, &oflag, &outname, &inname ))
138  exit( 1 );
139 
140  /* An input file name ? */
141  rle_names( &the_hdr, cmd_name( argv ), inname, 0 );
142  infile= rle_open_f(the_hdr.cmd, inname, "r");
143 
144 
145  /*
146  * Translate Alias "pix" format into my bitmap.
147  */
148  read_alias(infile, &bitmap);
149  rle_close_f(infile); /* We finish with this file */
150 
151  /*
152  * We have a bitmap with the image, so we open the
153  * new rle file and write it.
154  */
155  outfile = rle_open_f(cmd_name(argv), outname, "w");
156  write_rle(outfile, &bitmap);
157  fclose(outfile); /* it is not necesary, but ... */
158 
159  exit(0);
160 }
161 
162 static int
163 read_alias(handle, image)
164 FILE *handle;
165 bitmap_hdr *image;
166 {
167  register int i;
168  alias_hdr header;
169  int total_size;
170  register int xsize;
171  byte *end;
172  byte *r, *g = 0, *b = 0;
173  int can_read_all;
174  byte *buffer = 0, *ptr = 0;
175  int filesize;
176  int allplanes = 0;
177  int error;
178  int cmapsize;
179 
180  /*
181  * Alias "pix" is a bad format to read line per line. If every
182  * triplet is different to its next, then we read 2 bytes, 2 bytes ...
183  * ... and read a file of 1 Mb. with this form ... hmmmmmm !!!
184  * This is necesary if we are reading from stdin, but if we have
185  * a file, we'll read the file into memory ( one access to disk ).
186  */
187  can_read_all = (handle != stdin); /* a regular file ? */
188  VPRINTF(stderr, "Reading Alias from %s\n",
189  (can_read_all ? "file" : "stdin"));
190 
191  if (can_read_all) {
192  /*
193  * We are using a regular file ( not a pipe ), so we can
194  * read it into memory.
195  */
196  ptr= buffer= (byte *) read_file(handle, &filesize);
197  VPRINTF(stderr, "File size: %d\n", filesize);
198  /* Copy the header */
199  bcopy(ptr, &header, sizeof(alias_hdr));
200  ptr += sizeof(alias_hdr); /* skip the header */
201  }else {
202  /*
203  * We are using stdin so ...
204  */
205  /* We need the header of Alias pix */
206  VPRINTF(stderr, "Reading Alias header\n");
207  read_alias_header(handle, &header);
208  }
209 
210  /* Size in pixels */
211  total_size = header.xsize * header.ysize;
212 
213  /* Fill our header */
214  image->xsize = header.xsize;
215  image->ysize = header.ysize;
216  image->depth = header.depth;
217  image->colors = 1 << image->depth;
218  allplanes = ( image->depth > 8 ); /* an image with 24 planes ? */
219  VPRINTF(stderr, "Image size: %dx%d\n", image->xsize, image->ysize);
220  VPRINTF(stderr, "Depth: %d\n", image->depth);
221 
222  /* Get some memory */
223  if ( allplanes ) {
224  /*
225  * We have a image with 24 planes, so we need three buffers to
226  * store it.
227  */
228  r= image->r = (byte *) Malloc(total_size);
229  g= image->g = (byte *) Malloc(total_size);
230  b= image->b = (byte *) Malloc(total_size);
231  }else {
232  /*
233  * The image has less than 256 colors, so we use one plane,
234  * for the bitmap, and the cmap.
235  */
236  r= image->r = (byte *) Malloc(total_size);
237  cmapsize= image->colors * 3; /* size in bytes */
238  image->cmap = (byte *) Malloc(cmapsize);
239  /* Creating the cmap from file */
240  VPRINTF(stderr, "Creating cmap\n");
241  create_alias_cmap(image);
242  }
243 
244  /*
245  * We are ready to uncompress Alias file.
246  */
247  VPRINTF(stderr, "Uncompressing Alias file\n");
248  if (can_read_all) {
249  /*
250  * We have the file into memory so we uncode it directly.
251  */
252  end = r + total_size; /* the end of main buffer */
253  if ( allplanes )
254  uncode_alias24(ptr, r, g, b, end);
255  else uncode_alias(ptr, r, end);
256  /*
257  * We have read the file and uncompressed, so we can
258  * free the memory ( and exit ).
259  */
260  free(buffer);
261  }else {
262  /*
263  * We'll read each line from Alias file ( stdin ) until we
264  * fill our buffers or we get an error.
265  */
266  xsize = image->xsize;
267  for (i= 0; i< image->ysize; i++) {
268  /*
269  * Read and decode the Alias raster information, two cases:
270  * with planes > 8 => a triplet (RGB), else a index.
271  */
272  if ( allplanes ) {
273  /* An image with 24 planes */
274  error= read_line_alias24(handle, r, b, g, xsize);
275  }else {
276  /* An image with indexes to cmap */
277  error= read_line_alias(handle, r, xsize);
278  }
279  if (error) {
280  /* An error, so we exit */
281  fprintf(stderr, "Error while reading line %d\n", i);
282  return 1;
283  }else {
284  /* A line has been read, so we increment theirs pointers */
285  r += xsize;
286  if ( allplanes ) {
287  g += xsize;
288  b += xsize;
289  }
290  }
291  }
292  } /* end of reading from stdin */
293 
294  /* Finish with no problems */
295  return 0;
296 }
297 
298 static void
299 read_alias_header(handle, header)
300 FILE *handle;
301 alias_hdr *header;
302 {
303  /* Read the header */
304  Fread(header, sizeof(alias_hdr), 1, handle);
305 
306  /* Check some things */
307  if ( header->xsize < 1 || header -> xsize > 2560 ||
308  header->ysize < 1 || header -> ysize > 2560 )
309  error(5);
310  if ( header->depth > 24 || header->depth < 1 )
311  error(5);
312 }
313 
314 static int
315 read_line_alias24(handle, r, g, b, size)
316 FILE *handle;
317 byte *r, *g, *b;
318 register int size;
319 {
320  register int i;
321  register int count = 0;
322  byte *end;
323  byte buffer[4];
324 
325  end = r + size;
326  while (count < size) {
327  /*
328  * Alias code format: <repeat>BGR => 4 bytes.
329  */
330  if ( !fread(buffer, 4, 1, handle) ) /* read next buffer */
331  return 1; /* hey !, an EOF here ?. Hmmmm, this is an error ! */
332 
333  count += buffer[0]; /* # of repetitions */
334  /* repeat 'buffer[0]' times these triplet */
335  for (i= 0; i< buffer[0]; i++) {
336  *r++ = buffer[3];
337  *g++ = buffer[1];
338  *b++ = buffer[2];
339  }
340  if ( r > end )
341  error(6); /* uncompress more bytes than size */
342  }
343 
344  /* No problems */
345  return 0;
346 }
347 
348 static int
349 read_line_alias(handle, r, size)
350 FILE *handle;
351 byte *r;
352 register int size;
353 {
354  register int i;
355  register int count = 0;
356  byte *end;
357  byte buffer[2];
358 
359  end = r + size;
360  while (count < size) {
361  /*
362  * Alias code format: <repeat><index> => 2 bytes.
363  */
364  if ( !fread(buffer, 2, 1, handle) ) /* read next buffer */
365  return 1; /* hey !, an EOF here ?. Hmmmm, this is an error ! */
366 
367  count += buffer[0]; /* # of repetitions */
368  /* repeat 'buffer[0]' times these index */
369  for (i= 0; i< buffer[0]; i++) {
370  *r++ = buffer[1];
371  }
372  if ( r > end )
373  error(6); /* uncompress more bytes than size */
374  }
375 
376  /* No problems */
377  return 0;
378 }
379 
380 static void
381 create_alias_cmap(image)
382 bitmap_hdr *image;
383 {
384  register int i;
385  byte *ptr;
386 
387  /*
388  * Alias 8 bits files are b&w, so ...
389  */
390  ptr = (byte *) image->cmap;
391  for (i= 0; i< image->colors; i++) {
392  *ptr++ = i;
393  *ptr++ = i;
394  *ptr++ = i;
395  }
396 }
397 
398 static void
399 bitmapcmap_to_rlecmap(bitmap, rle)
400 bitmap_hdr *bitmap;
401 rle_hdr *rle;
402 {
403  register int i;
404  rle_map *rch, *gch, *bch;
405  byte *ptr;
406 
407  /* Allocate memory */
408  rle->cmap= (rle_map *) Malloc(bitmap->colors * 3 * sizeof(rle_map));
409 
410  /*
411  * We'll use 3 ptrs, first to R channel, second to G channel, ...
412  */
413  ptr = bitmap->cmap;
414  rch = rle->cmap;
415  gch = &(rle->cmap[bitmap->colors]);
416  bch = &(rle->cmap[2 * bitmap->colors]);
417  for (i= 0; i< bitmap->colors; i++) {
418  *rch++ = (*ptr++ << 8);
419  *gch++ = (*ptr++ << 8);
420  *bch++ = (*ptr++ << 8);
421  }
422 }
423 
424 static void
425 uncode_alias24(ptr, rbuf, gbuf, bbuf, end)
426 byte *ptr;
427 byte *rbuf, *gbuf, *bbuf;
428 byte *end;
429 {
430  register int i;
431  byte r, g, b;
432 
433  while ( rbuf < end ) { /* while not end of buffer */
434  if ( (i= *ptr++) > 1 ) { /* how mary repetitions ? */
435  b= *ptr++;
436  g= *ptr++;
437  r= *ptr++;
438  while( i-- ) { /* copy these triplet 'i' times */
439  *rbuf++ = r;
440  *gbuf++ = g;
441  *bbuf++ = b;
442  }
443  }else { /* else, copy these triplet */
444  *bbuf++ = *ptr++;
445  *gbuf++ = *ptr++;
446  *rbuf++ = *ptr++;
447  }
448  }
449 }
450 
451 static void
452 uncode_alias(ptr, rbuf, end)
453 byte *ptr;
454 byte *rbuf;
455 byte *end;
456 {
457  register int i;
458  byte r;
459 
460  while ( rbuf < end ) { /* while not end of buffer */
461  if ( (i= *ptr++) > 1 ) { /* how mary repetitions ? */
462  r= *ptr++;
463  while( i-- ) { /* copy these index 'i' times */
464  *rbuf++ = r;
465  }
466  }else { /* else, copy these index */
467  *rbuf++ = *ptr++;
468  }
469  }
470 }
471 
472 static void
473 write_rle(handle, image)
474 FILE *handle;
475 bitmap_hdr *image;
476 {
477  register int i, j;
478  rle_pixel **row;
479  byte *r;
480  int offset_last;
481 
482  VPRINTF(stderr, "Writing RLE file\n");
483  /*
484  * Fill the rle header with our ( little ) information.
485  */
486  the_hdr.rle_file = handle;
487  the_hdr.xmin = 0;
488  the_hdr.ymin = 0;
489  the_hdr.xmax = image->xsize - 1;
490  the_hdr.ymax = image->ysize - 1;
491  if (image->depth > 8) {
492  the_hdr.ncolors = 3; /* 24 planes */
493  the_hdr.ncmap = 0;
494  }else {
495  the_hdr.ncolors = 1;
496  the_hdr.ncmap = 3;
497  the_hdr.cmaplen = image->depth;
498  /* Convert our cmap to rle cmap */
499  bitmapcmap_to_rlecmap(image, &the_hdr);
500  }
501  the_hdr.alpha = 0; /* we don't use alpha channels */
502 
503  /* Write the header */
505 
506  /*
507  * RLE write raster lines in reverse order, so we'll put
508  * pointers to the last line.
509  */
510  offset_last = image->xsize * image->ysize - image->xsize;
511 
512  VPRINTF(stderr, "Compressing RLE lines\n");
513  if (image->depth > 8) {
514  /*
515  * 24 planes, rle_putrow functions use a buffer which contains
516  * a line, so we need do it.
517  */
518  /* Allocate some memory */
519  row = (rle_pixel **)Malloc( 3 * sizeof(rle_pixel *) );
520  if ( row == 0 )
521  error(2);
522 
523  /* Pointers to last line */
524  row[0] = image->r + offset_last;
525  row[1] = image->g + offset_last;
526  row[2] = image->b + offset_last;
527 
528  /* Write each line */
529  for (i= 0; i< image->ysize; i++) {
530  rle_putrow(row, image->xsize, &the_hdr);
531  /*
532  * Back up to the previous line.
533  */
534  for ( j = 0; j < 3; j++ )
535  row[0] -= image->xsize;
536  }
537  /* free rle row buffer */
538  free(row);
539 
540  }else {
541  /*
542  * A image with cmap.
543  */
544  /* if a simple plane => stored on R component */
545  r = image->r + offset_last;
546  for (i= 0; i< image->ysize; i++) {
548  r -= image->xsize;
549  }
550  }
551 
552  /*
553  * Put an EOF into the RLE file ( and THE END ! )
554  */
556 }
557 
558 static void
559 error(code)
560 int code;
561 {
562  fprintf(stderr, "%s: ", the_hdr.cmd);
563  switch (code) {
564  case 0:
565  break;
566  case 1: fprintf(stderr, "Cannot open file\n");
567  break;
568  case 2: fprintf(stderr, "Out of memory\n");
569  break;
570  case 3: fprintf(stderr, "Error while reading input file\n");
571  break;
572  case 4: fprintf(stderr, "Error while writing output file\n");
573  break;
574  case 5: fprintf(stderr, "Input file is not an Alias pix\n");
575  break;
576  case 6: fprintf(stderr, "File corrupt ( uncompress too bytes )\n");
577  break;
578  case 99: fprintf(stderr, "Not ready\n");
579  break;
580  default: fprintf(stderr, "Unknow error code (%d)\n", code);
581  break;
582  }
583  exit(1);
584 }
585 
586 /*
587  * My standard functions.
588  */
589 
590 static char *Malloc(size)
591 long int size;
592 {
593  char *ptr;
594 
595  if ((ptr = (char *) malloc(size)) == NULL)
596  error(2);
597 
598  /*
599  * Usually compilers fill buffers with zeros,
600  * but ...
601  */
602  bzero( ptr, size );
603  return ptr;
604 }
605 
606 
607 static char *read_file(handle, bytes)
608 FILE *handle;
609 int *bytes;
610 {
611  char *buffer;
612 
613  /* Get size of file and allocate memory */
614  *bytes= (int) filelen(handle);
615  if ( *bytes > 0 ) /* Ok, it's a regular file. */
616  {
617  buffer= (char *) Malloc(*bytes);
618 
619  /* Read it */
620  Fread(buffer, (int) (*bytes), 1, handle);
621  }
622  else /* Oops! It's a pipe. */
623  {
624  int n = 0, bufsize = 0;
625  /* Read in chunks of BUFSIZ. */
626  buffer = Malloc( BUFSIZ );
627  while ( (n = fread( buffer + bufsize, 1, BUFSIZ, handle )) == BUFSIZ )
628  {
629  bufsize += BUFSIZ;
630  buffer = realloc( buffer, bufsize + BUFSIZ );
631  RLE_CHECK_ALLOC( the_hdr.cmd, buffer, "input image" );
632  }
633  if ( n >= 0 )
634  n += bufsize;
635  else
636  n = bufsize;
637  }
638 
639  /* Return the buffer */
640  return buffer;
641 }
642 
643 static long filelen(handle)
644 FILE *handle;
645 {
646  long current_pos;
647  long len;
648 
649  /* Save current position */
650  current_pos= ftell(handle);
651 
652  /* Get len of file */
653  fseek(handle, 0, 2);
654  len= ftell(handle);
655 
656  /* Restore position */
657  fseek(handle, current_pos, 0);
658 
659  return len;
660 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
int xmin
Definition: rle.h:100
short xsize
Definition: aliastorle.c:48
#define USE_PROTOTYPES
Definition: rle_config.h:22
short depth
Definition: aliastorle.c:50
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 rle_close_f(FILE *fd)
Definition: rle_open_f.c:244
void main(int argc, char **argv)
Definition: aliastorle.c:121
rle_map * cmap
Definition: rle.h:112
short xinit
Definition: aliastorle.c:49
int ymin
Definition: rle.h:100
int verbose
Definition: rletorla.c:81
unsigned char * r
Definition: aliastorle.c:61
short yinit
Definition: aliastorle.c:49
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
void rle_putrow(rows, int rowlen, rle_hdr *the_hdr)
Definition: rle_putrow.c:96
int xmax
Definition: rle.h:100
#define byte
Definition: aliastorle.c:39
unsigned char * g
Definition: aliastorle.c:61
#define Fread(p, s, n, f)
Definition: aliastorle.c:40
static char rcs_id[]
Definition: aliastorle.c:29
#define VPRINTF
Definition: aliastorle.c:42
int ncmap
Definition: rle.h:100
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
int cmaplen
Definition: rle.h:100
int alpha
Definition: rle.h:100
rle_hdr the_hdr
Definition: rletoalias.c:78
unsigned short rle_map
Definition: rle.h:57
short ysize
Definition: aliastorle.c:48
unsigned char * cmap
Definition: aliastorle.c:62
int colors
Definition: aliastorle.c:60
unsigned char * b
Definition: aliastorle.c:61
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
FILE * rle_file
Definition: rle.h:114
int ncolors
Definition: rle.h:100
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86