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
FatalError(s)98 static void FatalError(s)
99 char *s;
100 {
101 fprintf(stderr,"%s\n",s); exit(1);
102 }
103
104 /* VICAR stuff */
105 /* tags, and guesses as to meaning... */
106 static int LBLSIZE; /* size of header, must be int mult of NS */
107 static char FORMAT[80]; /* 'BYTE' is OK */
108 static char TYPE[80]; /* 'IMAGE' is OK */
109 static char ORG[80]; /* `BSQ` is OK */
110 static int NL; /* height */
111 static int NS; /* width */
112 static int NB; /* samples per pixel? */
113 static char HOST[80]; /* machine type? */
114 static char INTFMT[80]; /* integer format? */
115 static char REALFMT[80]; /* real format? */
116 static char TASK[80]; /* processing applied? */
117 static char USER[80]; /* who was responsible? */
118 static char DAT_TIM[80]; /* when? */
119 static char COMMENT[80]; /* comment! */
120
ParseVICARHeader(fd)121 static void ParseVICARHeader(fd)
122 FILE *fd;
123 {
124 char Name[81],Value[1024];
125 int n;
126
127 for ( n = 0; ; n++ )
128 {
129 Value[n] = fgetc( fd );
130 if ( Value[n] == ' ' )
131 break;
132 }
133 Value[n++] = 0;
134
135 sscanf(Value,"%80[^=]=%d",Name,&LBLSIZE);
136 if (VERBOSE) fprintf(stderr,"[%s = %d]\n",Name,LBLSIZE);
137 if (0 != strcmp("LBLSIZE",Name)) FatalError("This is not a VICAR file");
138
139 /* There must be a better way to read the header. This is gross. */
140 while(n < LBLSIZE)
141 {
142 register char *cp;
143 register char c = ' ';
144 int done;
145
146 /* Skip spaces. */
147 while ( c == ' ' && n < LBLSIZE )
148 {
149 c = fgetc( fd );
150 n++;
151 }
152
153 /* Get Name. */
154 cp = &Name[0];
155 while ( c != '=' && c != '\0' && n < LBLSIZE )
156 {
157 *cp++ = c;
158 c = fgetc( fd );
159 n++;
160 }
161 *cp = 0;
162
163 if ( n >= LBLSIZE )
164 break;
165
166 if ('\0' == Name[0] || c == '\0')
167 break;
168
169 /* At this point, c is '='. Get the next character. */
170 Value[0] = fgetc( fd );
171 n++;
172
173 cp = &Value[1];
174 if ('\'' == Value[0])
175 for(;n < LBLSIZE;cp++)
176 {
177 *cp = fgetc( fd );
178 n++;
179 if ('\'' == *cp)
180 {
181 *++cp = '\0';
182 break;
183 }
184 }
185 else
186 for(;n < LBLSIZE;cp++)
187 {
188 *cp = fgetc(fd);
189 n++;
190 if (' ' == *cp)
191 {
192 *cp = '\0';
193 done = 0;
194 break;
195 }
196 if ('\0' == *cp)
197 {
198 done = -1;
199 break;
200 }
201 }
202
203 if (VERBOSE) fprintf(stderr,"[%s = %s]\n",Name,Value);
204 Value[80] = '\0'; /* for our own protection... */
205
206 if (0 == strcmp("FORMAT" ,Name)) {strcpy(FORMAT ,Value); continue;}
207 if (0 == strcmp("TYPE" ,Name)) {strcpy(TYPE ,Value); continue;}
208 if (0 == strcmp("BUFSIZ" ,Name)) { (void) atoi(Value); continue;}
209 if (0 == strcmp("DIM" ,Name)) { (void) atoi(Value); continue;}
210 if (0 == strcmp("EOL" ,Name)) { (void) atoi(Value); continue;}
211 if (0 == strcmp("RECSIZE",Name)) { (void) atoi(Value); continue;}
212 if (0 == strcmp("ORG" ,Name)) {strcpy(ORG ,Value); continue;}
213 if (0 == strcmp("NL" ,Name)) {NL = atoi(Value); continue;}
214 if (0 == strcmp("NS" ,Name)) {NS = atoi(Value); continue;}
215 if (0 == strcmp("NB" ,Name)) {NB = atoi(Value); continue;}
216 if (0 == strcmp("N1" ,Name)) { (void) atoi(Value); continue;}
217 if (0 == strcmp("N2" ,Name)) { (void) atoi(Value); continue;}
218 if (0 == strcmp("N3" ,Name)) { (void) atoi(Value); continue;}
219 if (0 == strcmp("N4" ,Name)) { (void) atoi(Value); continue;}
220 if (0 == strcmp("NBB" ,Name)) { (void) atoi(Value); continue;}
221 if (0 == strcmp("NLB" ,Name)) { (void) atoi(Value); continue;}
222 if (0 == strcmp("HOST" ,Name)) {strcpy(HOST ,Value); continue;}
223 if (0 == strcmp("INTFMT" ,Name)) {strcpy(INTFMT ,Value); continue;}
224 if (0 == strcmp("REALFMT",Name)) {strcpy(REALFMT,Value); continue;}
225 if (0 == strcmp("TASK" ,Name)) {strcpy(TASK ,Value); continue;}
226 if (0 == strcmp("USER" ,Name)) {strcpy(USER ,Value); continue;}
227 if (0 == strcmp("DAT_TIM",Name)) {strcpy(DAT_TIM,Value); continue;}
228 if (0 == strcmp("COMMENT",Name)) {strcpy(COMMENT,Value); continue;}
229 if (done) break;
230 }
231
232 /* Skip the rest of the label. */
233 while ( n < LBLSIZE )
234 {
235 (void)fgetc( fd );
236 n++;
237 }
238
239 }
240
241 /* RLE stuff */
242 void
addVICARcomment(the_hdr,label,value)243 addVICARcomment( the_hdr, label, value )
244 rle_hdr *the_hdr;
245 char *label, *value;
246 {
247 char *comment;
248
249 if ( *value == 0 )
250 return;
251 /* 8 = length of "VICAR" + "=" + nul byte. */
252 comment = (char *)malloc( 8 + strlen( label ) + strlen( value ) );
253 sprintf( comment, "VICAR-%s=%s", label, value );
254 rle_putcom( comment, the_hdr );
255 }
256
SetUpRLEFile(the_hdr,xsize,ysize,zsize)257 void SetUpRLEFile(the_hdr, xsize, ysize, zsize)
258 rle_hdr *the_hdr;
259 int xsize, ysize, zsize;
260 {
261
262 the_hdr->xmin = 0;
263 the_hdr->xmax = xsize - 1;
264 the_hdr->ymin = 0;
265 the_hdr->ymax = ysize - 1;
266
267 /* 1=B&W, 3=RGB? */
268 the_hdr->ncolors = zsize;
269
270 /* Carry over info from VICAR file as comments. */
271 addVICARcomment( the_hdr, "USER", USER );
272 addVICARcomment( the_hdr, "DAT_TIM", DAT_TIM );
273 addVICARcomment( the_hdr, "TASK", TASK );
274 addVICARcomment( the_hdr, "COMMENT", COMMENT );
275 }
276
main(argc,argv)277 int main(argc,argv)
278 int argc;
279 char *argv[];
280 {
281 char *VICARFileName = NULL;
282 FILE *fd;
283 unsigned char *VICARImage;
284 char *outfname = NULL;
285 int oflag = 0;
286 int y;
287 long int nread;
288 rle_hdr the_hdr;
289 rle_pixel **rows;
290
291 the_hdr = *rle_hdr_init( (rle_hdr *)NULL );
292 if ( scanargs( argc, argv, "% v%- o%-outfile!s infile%s\n(\
293 \tConvert VICAR format image to URT.\n\
294 \t-v\tVerbose -- print out VICAR header information.)",
295 &VERBOSE, &oflag, &outfname, &VICARFileName ) == 0 )
296 exit( 1 );
297 rle_names( &the_hdr, cmd_name( argv ), outfname );
298 rle_addhist( argv, NULL, &the_hdr );
299
300 fd = rle_open_f(the_hdr.cmd,VICARFileName,"r");
301
302 ParseVICARHeader(fd);
303
304 /* Check for what we know how to handle. */
305 if ( NB != 1 )
306 {
307 fprintf( stderr, "%s: Can't handle NB (%d) != 1 in %s.\n",
308 the_hdr.cmd, NB, the_hdr.file_name );
309 exit( 1 );
310 }
311 if ( strcmp( FORMAT, "'BYTE'" ) != 0 )
312 {
313 fprintf( stderr, "%s: Can't handle FORMAT (%s) != 'BYTE' in %s.\n",
314 the_hdr.cmd, FORMAT, the_hdr.file_name );
315 exit( 1 );
316 }
317
318 /* !!! Will have to be modified when we handle NB>1. !!! */
319 VICARImage = (unsigned char *)malloc( NS * NL );
320 RLE_CHECK_ALLOC(the_hdr.cmd, VICARImage, "image");
321
322 the_hdr.rle_file = rle_open_f( the_hdr.cmd, outfname, "w" );
323
324 SetUpRLEFile(&the_hdr, NS, NL, NB);
325 rle_put_setup( &the_hdr );
326
327 rows = (rle_pixel **)malloc( NB * sizeof(rle_pixel *) );
328
329 /* !!! Will have to be modified when we handle NB>1. !!! */
330 nread = fread( VICARImage, 1, NS*NL, fd );
331 if ( nread < NS*NL )
332 fprintf( stderr, "%s: Short read from %s (%d bytes missing)\n",
333 the_hdr.cmd, the_hdr.file_name, NS*NL - nread );
334 for(y=(NL-1);y>=0;y--) /* flip in y */
335 {
336 /* !!! Loop somehow if NB > 1. !!! */
337 rows[0] = VICARImage + NS * y;
338
339 rle_putrow( rows, NS, &the_hdr );
340 }
341 rle_puteof( &the_hdr );
342 exit(0);
343 }
344