Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
vcrtorle.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  * vcrtorle.c - Convert from VICAR to RLE.
20  *
21  * Author: Spencer W. Thomas
22  * Information Technology and Networking
23  * University of Michigan Medical Center
24  * Date: Mon Feb 17 1992
25  * Copyright (c) 1992, University of Michigan
26  *
27  * From: vcr2wff.c
28  * Author: K.R. Sloan
29  */
30 
31 /*
32  * The VICAR file starts with a bunch of labels in ASCII of the form
33  * "keyword=value", separated by spaces. The entire label string is
34  * terminated by a 0 byte. The very first label is always LBLSIZE,
35  * which tells you the size in bytes of the space that has been set
36  * aside for the label. The actual size of the label (to the 0
37  * terminator byte) may be shorter than the space allocated for it.
38  * So, the first characters of the file are always "LBLSIZE=" followed
39  * by an integer in ASCII format. The other items in the label you
40  * need to look for are NL (number of lines) and NS (number of
41  * samples). The keywords are always upper case.
42  *
43  * The image data itself starts immediately after the space allocated
44  * for the label. So, skip LBLSIZE bytes at the beginning of the file
45  * to find the start of the image. The image is stored in binary (not
46  * ASCII), one byte per pixel (gray scale), with 0 being black and 255
47  * being white. It is stored in a simple matrix of NS samples (X
48  * dimension) by NL lines (Y dimension), with X varying the fastest.
49  * So, the first NS bytes contain the entire first line of the image,
50  * the second NS bytes contain the entire second line, etc. The order
51  * goes left-to-right, top-to-bottom.
52  *
53  * The full VICAR format can be more complex than this, but this
54  * description will hold for most files. If you want to do a sanity
55  * check, then the following have to be true for this description to
56  * work: FORMAT='BYTE' ORG='BSQ' NB=1 NBB=0 NLB=0.
57  *
58  * For example, here's the beginning of the file from an actual image,
59  * dumped in ASCII format (the newlines are artificial for this
60  * message, and are not in the file):
61  *
62  * LBLSIZE=1024 FORMAT='BYTE' TYPE='IMAGE' BUFSIZ=20480 DIM=3 EOL=0
63  * RECSIZE=1024 ORG='BSQ' NL=1024 NS=1024 NB=1 N1=1024 N2=1024 N3=1
64  * N4=0 NBB=0 NLB=0 HOST='VAX-VMS' INTFMT='LOW' REALFMT='VAX' TASK= ...
65  *
66  * This says the image is 1024 samples (NS, X dimension) by 1024 lines
67  * (NL, Y dimension). The space allocated for the label is 1024
68  * bytes. So, the image data starts at byte number 1024 (0-based) in
69  * the file. That first byte is the upper left pixel of the image.
70  * The first 1024 bytes in the image are the first horizontal line of
71  * the image. The next 1024 bytes are the second line, and so on.
72  * There is no data compression.
73  *
74  * Note that items in the label do not have to be in the same order
75  * (except LBLSIZE is always first), so don't count on that. Also,
76  * LBLSIZE does not have to equal NS, although it does have to be an
77  * integer multiple of NS. NL and NS do not have to be equal, i.e.
78  * the image does not have to be square.
79  *
80  * Ron Baalke baalke@mars.jpl.nasa.gov
81  * Jet Propulsion Lab
82  *
83  */
84 #ifndef lint
85 static char rcs_id[] = "$Header:$";
86 #endif
87 #if 0
88 vcrtorle() /* Tag. */
89 #endif
90 
91 #include <assert.h>
92 #include <stdio.h>
93 #include "rle.h"
94 
95 
96 static int VERBOSE = 0;
97 static char *RoutineName;
98 
99 static long int VICARpos; /* Position in file for reading w/o fseek. */
100 
101 static void FatalError(s)
102  char *s;
103  {
104  fprintf(stderr,"%s\n",s); exit(1);
105  }
106 
107 /* VICAR stuff */
108  /* tags, and guesses as to meaning... */
109 static int LBLSIZE; /* size of header, must be int mult of NS */
110 static char FORMAT[80]; /* 'BYTE' is OK */
111 static char TYPE[80]; /* 'IMAGE' is OK */
112 static int BUFSIZe; /* integer multiple of NS ? */
113 static int DIM; /* == 3? */
114 static int EOL; /* == 0? */
115 static int RECSIZE; /* == LBLSIZE? */
116 static char ORG[80]; /* `BSQ` is OK */
117 static int NL; /* height */
118 static int NS; /* width */
119 static int NB; /* samples per pixel? */
120 static int N1; /* == NL? */
121 static int N2; /* == NS? */
122 static int N3; /* == NB? */
123 static int N4; /* 0 is OK */
124 static int NBB; /* 0 is OK */
125 static int NLB; /* 0 is OK */
126 static char HOST[80]; /* machine type? */
127 static char INTFMT[80]; /* integer format? */
128 static char REALFMT[80]; /* real format? */
129 static char TASK[80]; /* processing applied? */
130 static char USER[80]; /* who was responsible? */
131 static char DAT_TIM[80]; /* when? */
132 static char COMMENT[80]; /* comment! */
133 
134 static void ParseVICARHeader(fd)
135 FILE *fd;
136 {
137  char Name[81],Value[1024];
138  int n;
139 
140  for ( n = 0; ; n++ )
141  {
142  Value[n] = fgetc( fd );
143  if ( Value[n] == ' ' )
144  break;
145  }
146  Value[n++] = 0;
147 
148  sscanf(Value,"%80[^=]=%d",Name,&LBLSIZE);
149  if (VERBOSE) fprintf(stderr,"[%s = %d]\n",Name,LBLSIZE);
150  if (0 != strcmp("LBLSIZE",Name)) FatalError("This is not a VICAR file");
151 
152  /* There must be a better way to read the header. This is gross. */
153  while(n < LBLSIZE)
154  {
155  register char *cp;
156  register char c = ' ';
157  int done;
158 
159  /* Skip spaces. */
160  while ( c == ' ' && n < LBLSIZE )
161  {
162  c = fgetc( fd );
163  n++;
164  }
165 
166  /* Get Name. */
167  cp = &Name[0];
168  while ( c != '=' && c != '\0' && n < LBLSIZE )
169  {
170  *cp++ = c;
171  c = fgetc( fd );
172  n++;
173  }
174  *cp = 0;
175 
176  if ( n >= LBLSIZE )
177  break;
178 
179  if ('\0' == Name[0] || c == '\0')
180  break;
181 
182  /* At this point, c is '='. Get the next character. */
183  Value[0] = fgetc( fd );
184  n++;
185 
186  cp = &Value[1];
187  if ('\'' == Value[0])
188  for(;n < LBLSIZE;cp++)
189  {
190  *cp = fgetc( fd );
191  n++;
192  if ('\'' == *cp)
193  {
194  *++cp = '\0';
195  break;
196  }
197  }
198  else
199  for(;n < LBLSIZE;cp++)
200  {
201  *cp = fgetc(fd);
202  n++;
203  if (' ' == *cp)
204  {
205  *cp = '\0';
206  done = 0;
207  break;
208  }
209  if ('\0' == *cp)
210  {
211  done = -1;
212  break;
213  }
214  }
215 
216  if (VERBOSE) fprintf(stderr,"[%s = %s]\n",Name,Value);
217  Value[80] = '\0'; /* for our own protection... */
218 
219  if (0 == strcmp("FORMAT" ,Name)) {strcpy(FORMAT ,Value); continue;}
220  if (0 == strcmp("TYPE" ,Name)) {strcpy(TYPE ,Value); continue;}
221  if (0 == strcmp("BUFSIZ" ,Name)) {BUFSIZe = atoi(Value); continue;}
222  if (0 == strcmp("DIM" ,Name)) {DIM = atoi(Value); continue;}
223  if (0 == strcmp("EOL" ,Name)) {EOL = atoi(Value); continue;}
224  if (0 == strcmp("RECSIZE",Name)) {RECSIZE = atoi(Value); continue;}
225  if (0 == strcmp("ORG" ,Name)) {strcpy(ORG ,Value); continue;}
226  if (0 == strcmp("NL" ,Name)) {NL = atoi(Value); continue;}
227  if (0 == strcmp("NS" ,Name)) {NS = atoi(Value); continue;}
228  if (0 == strcmp("NB" ,Name)) {NB = atoi(Value); continue;}
229  if (0 == strcmp("N1" ,Name)) {N1 = atoi(Value); continue;}
230  if (0 == strcmp("N2" ,Name)) {N2 = atoi(Value); continue;}
231  if (0 == strcmp("N3" ,Name)) {N3 = atoi(Value); continue;}
232  if (0 == strcmp("N4" ,Name)) {N4 = atoi(Value); continue;}
233  if (0 == strcmp("NBB" ,Name)) {NBB = atoi(Value); continue;}
234  if (0 == strcmp("NLB" ,Name)) {NLB = atoi(Value); continue;}
235  if (0 == strcmp("HOST" ,Name)) {strcpy(HOST ,Value); continue;}
236  if (0 == strcmp("INTFMT" ,Name)) {strcpy(INTFMT ,Value); continue;}
237  if (0 == strcmp("REALFMT",Name)) {strcpy(REALFMT,Value); continue;}
238  if (0 == strcmp("TASK" ,Name)) {strcpy(TASK ,Value); continue;}
239  if (0 == strcmp("USER" ,Name)) {strcpy(USER ,Value); continue;}
240  if (0 == strcmp("DAT_TIM",Name)) {strcpy(DAT_TIM,Value); continue;}
241  if (0 == strcmp("COMMENT",Name)) {strcpy(COMMENT,Value); continue;}
242  if (done) break;
243  }
244 
245  /* Skip the rest of the label. */
246  while ( n < LBLSIZE )
247  {
248  (void)fgetc( fd );
249  n++;
250  }
251 
252  VICARpos = n;
253 }
254 
255 /* RLE stuff */
256 void
257 addVICARcomment( the_hdr, label, value )
258 rle_hdr *the_hdr;
259 char *label, *value;
260 {
261  char *comment;
262 
263  if ( *value == 0 )
264  return;
265  /* 8 = length of "VICAR" + "=" + nul byte. */
266  comment = (char *)malloc( 8 + strlen( label ) + strlen( value ) );
267  sprintf( comment, "VICAR-%s=%s", label, value );
268  rle_putcom( comment, the_hdr );
269 }
270 
271 void SetUpRLEFile(the_hdr, xsize, ysize, zsize)
272 rle_hdr *the_hdr;
273 int xsize, ysize, zsize;
274 {
275 
276  the_hdr->xmin = 0;
277  the_hdr->xmax = xsize - 1;
278  the_hdr->ymin = 0;
279  the_hdr->ymax = ysize - 1;
280 
281  /* 1=B&W, 3=RGB? */
282  the_hdr->ncolors = zsize;
283 
284  /* Carry over info from VICAR file as comments. */
285  addVICARcomment( the_hdr, "USER", USER );
286  addVICARcomment( the_hdr, "DAT_TIM", DAT_TIM );
287  addVICARcomment( the_hdr, "TASK", TASK );
288  addVICARcomment( the_hdr, "COMMENT", COMMENT );
289 }
290 
292 int argc;
293 char *argv[];
294 {
295  char *VICARFileName = NULL;
296  FILE *fd;
297  unsigned char *VICARImage;
298  char *outfname = NULL;
299  int oflag = 0;
300  int x,y,z;
301  long int nread;
302  rle_hdr the_hdr;
303  rle_pixel **rows;
304 
305  the_hdr = *rle_hdr_init( (rle_hdr *)NULL );
306  if ( scanargs( argc, argv, "% v%- o%-outfile!s infile%s\n(\
307 \tConvert VICAR format image to URT.\n\
308 \t-v\tVerbose -- print out VICAR header information.)",
309  &VERBOSE, &oflag, &outfname, &VICARFileName ) == 0 )
310  exit( 1 );
311  rle_names( &the_hdr, cmd_name( argv ), outfname );
312  rle_addhist( argv, NULL, &the_hdr );
313 
314  fd = rle_open_f(the_hdr.cmd,VICARFileName,"r");
315 
316  ParseVICARHeader(fd);
317 
318  /* Check for what we know how to handle. */
319  if ( NB != 1 )
320  {
321  fprintf( stderr, "%s: Can't handle NB (%d) != 1 in %s.\n",
322  the_hdr.cmd, NB, the_hdr.file_name );
323  exit( 1 );
324  }
325  if ( strcmp( FORMAT, "'BYTE'" ) != 0 )
326  {
327  fprintf( stderr, "%s: Can't handle FORMAT (%s) != 'BYTE' in %s.\n",
328  the_hdr.cmd, FORMAT, the_hdr.file_name );
329  exit( 1 );
330  }
331 
332  /* !!! Will have to be modified when we handle NB>1. !!! */
333  VICARImage = (unsigned char *)malloc( NS * NL );
334  RLE_CHECK_ALLOC(the_hdr.cmd, VICARImage, "image");
335 
336  the_hdr.rle_file = rle_open_f( the_hdr.cmd, outfname, "w" );
337 
338  SetUpRLEFile(&the_hdr, NS, NL, NB);
339  rle_put_setup( &the_hdr );
340 
341  rows = (rle_pixel **)malloc( NB * sizeof(rle_pixel *) );
342 
343  /* !!! Will have to be modified when we handle NB>1. !!! */
344  nread = fread( VICARImage, 1, NS*NL, fd );
345  if ( nread < NS*NL )
346  fprintf( stderr, "%s: Short read from %s (%d bytes missing)\n",
347  the_hdr.cmd, the_hdr.file_name, NS*NL - nread );
348  for(y=(NL-1);y>=0;y--) /* flip in y */
349  {
350  /* !!! Loop somehow if NB > 1. !!! */
351  rows[0] = VICARImage + NS * y;
352 
353  rle_putrow( rows, NS, &the_hdr );
354  }
355  rle_puteof( &the_hdr );
356  exit(0);
357 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
static int DIM
Definition: vcrtorle.c:113
static int NB
Definition: vcrtorle.c:119
int xmin
Definition: rle.h:100
static char HOST[80]
Definition: vcrtorle.c:126
static char rcs_id[]
Definition: vcrtorle.c:85
static char FORMAT[80]
Definition: vcrtorle.c:110
void main(int argc, char **argv)
Definition: aliastorle.c:121
static char DAT_TIM[80]
Definition: vcrtorle.c:131
static char ORG[80]
Definition: vcrtorle.c:116
static int N2
Definition: vcrtorle.c:121
static int BUFSIZe
Definition: vcrtorle.c:112
static int NL
Definition: vcrtorle.c:117
static int EOL
Definition: vcrtorle.c:114
int ymin
Definition: rle.h:100
static int N3
Definition: vcrtorle.c:122
static int NS
Definition: vcrtorle.c:118
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
static int RECSIZE
Definition: vcrtorle.c:115
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
static int NLB
Definition: vcrtorle.c:125
void rle_addhist(argv, rle_hdr *in_hdr, rle_hdr *out_hdr)
Definition: rle_addhist.c:54
static int VERBOSE
Definition: vcrtorle.c:96
static char USER[80]
Definition: vcrtorle.c:130
static char INTFMT[80]
Definition: vcrtorle.c:127
int ymax
Definition: rle.h:100
static long int VICARpos
Definition: vcrtorle.c:99
static char REALFMT[80]
Definition: vcrtorle.c:128
static int LBLSIZE
Definition: vcrtorle.c:109
static char * RoutineName
Definition: vcrtorle.c:97
unsigned char rle_pixel
Definition: rle.h:56
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
const char * rle_putcom(char *value, rle_hdr *the_hdr) const
Definition: rle_putcom.c:82
static int N4
Definition: vcrtorle.c:123
static int N1
Definition: vcrtorle.c:120
static char TASK[80]
Definition: vcrtorle.c:129
static int NBB
Definition: vcrtorle.c:124
static char COMMENT[80]
Definition: vcrtorle.c:132
const char * file_name
Definition: rle.h:134
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
static char TYPE[80]
Definition: vcrtorle.c:111
FILE * rle_file
Definition: rle.h:114
int ncolors
Definition: rle.h:100
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86