Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
rletocgm.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  * rletocgm.c - Tool to convert RLE files to ANSI/ISO CGM metafiles.
20  *
21  * Author: Joel Welling
22  * Pittsburgh Supercomputing Center
23  * Carnegie Mellon University
24  * welling@psc.edu
25  * (derived from rleskel.c)
26  * Date: Thursday, April 11, 1991
27  * Copyright (c) 1990, University of Michigan
28  * Copyright (c) 1991, Carnegie Mellon University (derived from rleskel.c)
29  */
30 #ifndef lint
31 static char rcs_id[] = "$Header: /l/spencer/src/urt/cnv/RCS/rletocgm.c,v 3.0.1.1 1992/04/30 13:59:08 spencer Exp $";
32 #endif
33 #if 0
34 rletocgm() /* TAG */
35 #endif
36 
37 #include <stdio.h>
38 #include <rle.h>
39 
40 /* This module recognizes what type of machine it's on by the presence
41 of the symbol VMS, unix, CRAY, or ardent. The following makes the machine
42 assignment less ambiguous.
43 */
44 #if ( unix && ( !CRAY && !ardent ) )
45 #define USE_UNIX
46 #endif
47 
48 /* Include defs files that allow linkage to Fortran on various systems */
49 #ifdef USE_UNIX
50 #include "unix_defs.h"
51 #endif
52 #ifdef CRAY
53 #include "unicos_defs.h"
54 #endif
55 #ifdef ardent
56 #include "unicos_defs.h" /* these are also appropriate on Ardent Titan */
57 #endif
58 #ifdef _IBMR2
59 /* include nothing */
60 #endif
61 
62 /* Flag to produce verbose output */
63 static int verboseflag= 0;
64 
65 static void open_output(outfname)
66 char *outfname;
67 /* This routine opens the output file. */
68 {
69  int ierr= 0, i256= 256;
70 
71  wrcopn(outfname,&ierr);
72  if (ierr) {
73  fprintf(stderr,"rletocgm: Error opening file <%s> for output!\n",outfname);
74  exit(2);
75  }
76  wrmxci(&i256,&ierr);
77  if (ierr) {
78  fprintf(stderr,"rletocgm: Error writing to file!\n");
79  exit(2);
80  }
81 }
82 
83 static void close_output()
84 /* This routine closes the output file. */
85 {
86  int ierr= 0;
87 
88  wrtend(&ierr);
89  if (ierr) {
90  fprintf(stderr,"rletocgm: Error closing output!\n");
91  exit(2);
92  }
93 }
94 
95 static void begin_direct_page(in_hdr)
96 rle_hdr *in_hdr;
97 /* This routine begins a direct color page */
98 {
99  int ierr= 0, one= 1;
100  float red, green, blue;
101 
102  if (in_hdr->background) {
103  red= ((float)in_hdr->bg_color[0])/255.0;
104  green= ((float)in_hdr->bg_color[1])/255.0;
105  blue= ((float)in_hdr->bg_color[2])/255.0;
106  }
107  else {
108  red= 0.0;
109  green= 0.0;
110  blue= 0.0;
111  }
112 
113  wrbegp(&ierr);
114  if (ierr) {
115  fprintf(stderr,"rletocgm: Error writing begin page!\n");
116  exit(2);
117  }
118  wrtcsm(&one,&ierr);
119  if (ierr) {
120  fprintf(stderr,"rletocgm: Error writing color selection mode!\n");
121  exit(2);
122  }
123  wrbgdc(&red, &green, &blue, &ierr);
124  if (ierr) {
125  fprintf(stderr,"rletocgm: Error writing background color!\n");
126  exit(2);
127  }
128  wrbgpb(&ierr);
129  if (ierr) {
130  fprintf(stderr,"rletocgm: Error writing begin picture body!\n");
131  exit(2);
132  }
133 }
134 
135 static void handle_color_table(in_hdr,cmap)
136 rle_hdr *in_hdr;
137 rle_pixel **cmap;
138 /* This routine extracts color table information for the image, or
139  * makes it up if need be.
140  */
141 {
142  int tablesize, i, zero= 0, ierr= 0;
143  float *rarray, *garray, *barray;
144  char *comstring;
145 
146  /* Calculate table size, then reset it if there is a comment to that
147  * effect in the RLE file.
148  */
149  if (in_hdr->cmaplen)
150  tablesize= 2<<(in_hdr->cmaplen-1);
151  else tablesize= 2;
152  comstring= rle_getcom( "color_map_length", in_hdr );
153  if (!comstring) comstring= rle_getcom( "colormap_length", in_hdr );
154  if (comstring) sscanf( comstring, "%d", &tablesize );
155 
156  if ( !(rarray= (float *)malloc( tablesize*sizeof(float) )) ) {
157  fprintf(stderr,
158  "rletocgm: unable to allocate %d floats for color table reds!\n",
159  tablesize);
160  exit(2);
161  }
162  if ( !(garray= (float *)malloc( tablesize*sizeof(float) )) ) {
163  fprintf(stderr,
164  "rletocgm: unable to allocate %d floats for color table greens!\n",
165  tablesize);
166  exit(2);
167  }
168  if ( !(barray= (float *)malloc( tablesize*sizeof(float) )) ) {
169  fprintf(stderr,
170  "rletocgm: unable to allocate %d floats for color table blues!\n",
171  tablesize);
172  exit(2);
173  }
174 
175  /* Transcribe the color map into the float arrays */
176  for (i=0; i<tablesize; i++) {
177  rarray[i]= (float)cmap[0][i]/255.0;
178  garray[i]= (float)cmap[1][i]/255.0;
179  barray[i]= (float)cmap[2][i]/255.0;
180  }
181 
182  /* Actually write the map */
183  wrctbl(rarray, garray, barray, &zero, &tablesize, &ierr);
184  if (ierr) {
185  fprintf(stderr,"rletocgm: Error writing color map!\n");
186  exit(2);
187  }
188 
189  /* Clean up */
190  free( (char *)rarray );
191  free( (char *)garray );
192  free( (char *)barray );
193 }
194 
195 static void begin_indexed_page(in_hdr)
196 rle_hdr *in_hdr;
197 /* This routine begins an indexed color page */
198 {
199  int ierr= 0;
200  rle_pixel **cmap;
201  float red, green, blue;
202 
203  /* Load the color table, and write background color information */
204  cmap= buildmap( in_hdr, 3, 0.0, 1.0 );
205  if (in_hdr->background) {
206  red= (float)cmap[0][in_hdr->bg_color[0]]/255.0;
207  green= (float)cmap[1][in_hdr->bg_color[0]]/255.0;
208  blue= (float)cmap[2][in_hdr->bg_color[0]]/255.0;
209  }
210  else {
211  red= 0.0;
212  green= 0.0;
213  blue= 0.0;
214  }
215 
216  /* Preliminary CGM stuff */
217  wrbegp(&ierr);
218  if (ierr) {
219  fprintf(stderr,"rletocgm: Error writing begin page!\n");
220  exit(2);
221  }
222  wrbgdc(&red, &green, &blue, &ierr);
223  if (ierr) {
224  fprintf(stderr,"rletocgm: Error writing background color!\n");
225  exit(2);
226  }
227  wrbgpb(&ierr);
228  if (ierr) {
229  fprintf(stderr,"rletocgm: Error writing begin picture body!\n");
230  exit(2);
231  }
232 
233  /* Produce a color table */
234  handle_color_table(in_hdr, cmap);
235 
236  /* Clean up */
237  free( (char *)cmap[0] );
238 }
239 
240 static void end_page()
241 /* This routine ends a page. */
242 {
243  int ierr= 0;
244 
245  wrendp(&ierr);
246  if (ierr) {
247  fprintf(stderr,"rletocgm: Error ending output page!\n");
248  exit(2);
249  }
250 }
251 
252 static void center_image(in_hdr, px, py, qx, qy, rx, ry)
253 rle_hdr *in_hdr;
254 float *px, *py, *qx, *qy, *rx, *ry;
255 /* This routine centers the image in DrawCGM's unit square coordinates. */
256 {
257  float xrange, yrange;
258 
259  xrange= (float)(in_hdr->xmax - in_hdr->xmin + 1);
260  yrange= (float)(in_hdr->ymax - in_hdr->ymin + 1);
261  if (xrange>=yrange) {
262  *px= 0.0;
263  *qx= 1.0;
264  *rx= *qx;
265  *py= 0.5 * (1.0 - yrange/xrange);
266  *qy= 1.0 - *py;
267  *ry= *py;
268  }
269  else {
270  *py= 0.0;
271  *qy= 1.0;
272  *ry= *py;
273  *px= 0.5 * (1.0 - xrange/yrange);
274  *qx= 1.0 - *px;
275  *rx= *qy;
276  }
277 }
278 
279 static void process_indexed_page(in_hdr)
280 rle_hdr *in_hdr;
281 /* This routine handles one page of a file, assuming indexed color. */
282 {
283  int x, y;
284  rle_pixel **rows; /* Will be used for scanline storage. */
285  static int *iarray= (int *)0; /* Stores the CGM integer image */
286  int *iptr;
287  static int nx, ny; /* dimensions of iarray */
288  float px, py, qx, qy, rx, ry; /* CGM array boundaries */
289  int ierr= 0;
290 
291  /* Be verbose if requested */
292  if (verboseflag) fprintf(stderr,"Found indexed color (1 channel) page\n");
293 
294  /* Begin an output page, including the color table */
295  begin_indexed_page(in_hdr);
296 
297  /* Calculate array boundaries */
298  center_image(in_hdr, &px, &py, &qx, &qy, &rx, &ry);
299 
300  /* Allocate the CGM image array, if it's not already there */
301  if (!iarray ||
302  !(nx == in_hdr->xmax - in_hdr->xmin + 1) ||
303  !(ny == in_hdr->ymax - in_hdr->ymin + 1)) {
304  if (iarray) free( (char *)iarray );
305  nx= in_hdr->xmax - in_hdr->xmin + 1;
306  ny= in_hdr->ymax - in_hdr->ymin + 1;
307  if ( !(iarray= (int *)malloc( nx*ny*sizeof(int) )) ) {
308  fprintf(stderr,"rletocgm: cannot allocate %d ints!\n",nx*ny);
309  exit(2);
310  }
311  }
312 
313  /* Allocate memory into which the image scanlines can be read. */
314  if ( rle_row_alloc( in_hdr, &rows ) < 0 ) {
315  fprintf( stderr, "rletocgm: Unable to allocate image memory.\n" );
316  exit( RLE_NO_SPACE );
317  }
318 
319  /* Read the input image and copy it to the output file. */
320  iptr= iarray;
321  for ( y = in_hdr->ymin; y <= in_hdr->ymax; y++ )
322  {
323  /* Read a scanline. */
324  rle_getrow( in_hdr, rows );
325 
326  for (x=0; x<nx; x++) *iptr++= rows[0][x];
327  }
328 
329  /* Write the CGM cell array */
330  wrtcla( iarray, &nx, &ny, &px, &py, &qx, &qy, &rx, &ry, &ierr );
331  if (ierr) {
332  fprintf(stderr,"rletocgm: Error writing indexed cell array!\n");
333  exit(2);
334  }
335 
336  /* Protect from bad input. */
337  while ( rle_getskip( in_hdr ) != 32768 );
338 
339  /* Free memory. */
340  rle_row_free( in_hdr, rows );
341 
342  /* End the page */
343  end_page();
344 }
345 
346 static void process_direct_page(in_hdr)
347 rle_hdr *in_hdr;
348 /* This routine handles one page of a file, assuming direct color. */
349 {
350  int x, y;
351  rle_pixel **rows; /* Will be used for scanline storage. */
352  static float *rarray= (float *)0; /* red CGM image */
353  static float *garray= (float *)0; /* green CGM image */
354  static float *barray= (float *)0; /* blue CGM image */
355  float *rptr, *gptr, *bptr;
356  static int nx, ny; /* dimensions of image */
357  float px, py, qx, qy, rx, ry; /* CGM array boundaries */
358  int ierr= 0;
359 
360  /* Be verbose if requested */
361  if (verboseflag) fprintf(stderr,"Found direct color (3 channel) page\n");
362 
363  /* Begin an output page */
364  begin_direct_page(in_hdr);
365 
366  /* Calculate array boundaries */
367  center_image(in_hdr, &px, &py, &qx, &qy, &rx, &ry);
368 
369  /* Allocate the CGM image array, if it's not already there */
370  if (!rarray ||
371  !(nx == in_hdr->xmax - in_hdr->xmin + 1) ||
372  !(ny == in_hdr->ymax - in_hdr->ymin + 1)) {
373  if (rarray) free( (char *)rarray );
374  if (garray) free( (char *)garray );
375  if (barray) free( (char *)barray );
376  nx= in_hdr->xmax - in_hdr->xmin + 1;
377  ny= in_hdr->ymax - in_hdr->ymin + 1;
378  if ( !(rarray= (float *)malloc( nx*ny*sizeof(float) )) ) {
379  fprintf(stderr,"rletocgm: cannot allocate %d floats for red!\n",nx*ny);
380  exit(2);
381  }
382  if ( !(garray= (float *)malloc( nx*ny*sizeof(float) )) ) {
383  fprintf(stderr,"rletocgm: cannot allocate %d floats for green!\n",nx*ny);
384  exit(2);
385  }
386  if ( !(barray= (float *)malloc( nx*ny*sizeof(float) )) ) {
387  fprintf(stderr,"rletocgm: cannot allocate %d floats for blue!\n",nx*ny);
388  exit(2);
389  }
390  }
391 
392  /* Allocate memory into which the image scanlines can be read. */
393  if ( rle_row_alloc( in_hdr, &rows ) < 0 ) {
394  fprintf( stderr, "rletocgm: Unable to allocate image memory.\n" );
395  exit( RLE_NO_SPACE );
396  }
397 
398  /* Read the input image and copy it to the output file. */
399  rptr= rarray;
400  gptr= garray;
401  bptr= barray;
402  for ( y = in_hdr->ymin; y <= in_hdr->ymax; y++ )
403  {
404  /* Read a scanline. */
405  rle_getrow( in_hdr, rows );
406 
407  for (x=0; x<nx; x++) {
408  *rptr++= (float)rows[0][x]/255.0;
409  *gptr++= (float)rows[1][x]/255.0;
410  *bptr++= (float)rows[2][x]/255.0;
411  }
412  }
413 
414  /* Write the CGM cell array */
415  wcladc( rarray, garray, barray,
416  &nx, &ny, &px, &py, &qx, &qy, &rx, &ry, &ierr );
417  if (ierr) {
418  fprintf(stderr,"rletocgm: Error writing direct color cell array!\n");
419  exit(2);
420  }
421 
422  /* Protect from bad input. */
423  while ( rle_getskip( in_hdr ) != 32768 );
424 
425  /* Free memory. */
426  rle_row_free( in_hdr, rows );
427 
428  /* End the page */
429  end_page();
430 }
431 
432 /*****************************************************************
433  * TAG( main )
434  *
435  * A skeleton RLE tool. Demonstrates argument parsing, opening,
436  * reading, and writing RLE files. Includes support for files
437  * consisting of concatenated images.
438  * Usage:
439  * rletocgm [-o outfile] [infile]
440  * Inputs:
441  * infile: The input RLE file. Default stdin.
442  * "-" means stdin.
443  * Outputs:
444  * -o outfile: The output RLE file. Default stdout.
445  * "-" means stdout.
446  * Assumptions:
447  * [None]
448  * Algorithm:
449  * Repeatedly read from the input until the file EOF or an
450  * error is encountered.
451  */
453 int argc;
454 char **argv;
455 {
456  char *infname = NULL,
457  *outfname = NULL;
458  int rle_cnt, rle_err;
459  int oflag = 0, debugflag= 0;
460  FILE *outfile;
461  rle_hdr in_hdr; /* Headers for input file. */
462 
463  in_hdr = *rle_init_hdr( (rle_hdr *)NULL );
464  if ( scanargs( argc, argv, "% o%-outfile!s d%- v%- infile%s",
465  &oflag, &outfname, &debugflag, &verboseflag, &infname ) == 0 )
466  exit( 1 );
467 
468  /* Turn on debugging if requested. */
469  if (debugflag) {
470  int ierr= 0;
471  rle_debug(1);
472  tgldbg(&ierr);
473  if (ierr) fprintf(stderr,"rletocgm: couldn't set debugging!\n");
474  }
475 
476  /* Open the input file.
477  * The output file won't be opened until the first image header
478  * has been read. This avoids unnecessarily wiping out a
479  * pre-existing file if the input is garbage.
480  */
481  rle_names( &in_hdr, cmd_name( argv ), infname, 0 );
482  in_hdr.rle_file = rle_open_f( in_hdr.cmd, infname, "r" );
483 
484  /* Read images from the input file until the end of file is
485  * encountered or an error occurs.
486  */
487  rle_cnt = 0;
488  while ( (rle_err = rle_get_setup( &in_hdr )) == RLE_SUCCESS )
489  {
490 
491  /* Open the CGM output file */
492  if (rle_cnt==0) open_output(oflag ? outfname : "-");
493 
494  /* Count the input images. */
495  rle_cnt++;
496 
497  /* Be verbose if requested */
498  if (verboseflag) fprintf(stderr,"image %d: ",rle_cnt);
499 
500  /* Based on the number of colors in the header, select either indexed
501  * or direct color processing for the images in the file.
502  */
503  switch (in_hdr.ncolors) {
504  case 1: process_indexed_page(&in_hdr); break;
505  case 3: process_direct_page(&in_hdr); break;
506  default: fprintf(stderr,
507  "rletocgm: %d is an invalid number of color planes!\n",
508  in_hdr.ncolors);
509  }
510  }
511 
512  /* Close the CGM output file */
513  close_output();
514 
515  /* Check for an error. EOF or EMPTY is ok if at least one image
516  * has been read. Otherwise, print an error message.
517  */
518  if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
519  rle_get_error( rle_err, in_hdr.cmd, infname );
520 
521  exit( 0 );
522 }
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
void rle_debug(int on_off)
Definition: rle_getrow.c:293
void rle_row_free(rle_hdr *the_hdr, rle_pixel **scanp)
Definition: rle_row_alc.c:114
#define RLE_EMPTY
Definition: rle.h:73
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
int rle_getrow(rle_hdr *the_hdr, scanline)
Definition: rle_getrow.c:333
int * bg_color
Definition: rle.h:100
#define RLE_SUCCESS
Definition: rle.h:70
int ymin
Definition: rle.h:100
int rle_get_error(int code, const char *pgmname, const char *fname)
Definition: rle_error.c:76
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
rle_pixel ** buildmap(rle_hdr *the_hdr, int minmap, double orig_gamma, double new_gamma)
Definition: buildmap.c:56
const char * cmd
Definition: rle.h:133
int xmax
Definition: rle.h:100
#define RLE_NO_SPACE
Definition: rle.h:72
#define RLE_EOF
Definition: rle.h:74
unsigned int rle_getskip(rle_hdr *the_hdr)
Definition: rle_getskip.c:57
char * rle_getcom(char *name, rle_hdr *the_hdr) const
Definition: rle_getcom.c:81
int background
Definition: rle.h:100
int ymax
Definition: rle.h:100
unsigned char rle_pixel
Definition: rle.h:56
int cmaplen
Definition: rle.h:100
static char rcs_id[]
Definition: rletocgm.c:31
FILE * rle_file
Definition: rle.h:114
int ncolors
Definition: rle.h:100
static int verboseflag
Definition: rletocgm.c:63