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  * rletovcr.c - Convert RLE to VICAR format.
20  *
21  * Author:	Spencer W. Thomas
22  * 		Information Technology and Networking
23  * 		University of Michigan Medical Center
24  * Date:	Tue Feb 18 1992
25  * Copyright (c) 1992, University of Michigan
26  */
27 
28 /*
29 Based on.
30   File: wff2vcr.c
31   Author: K.R. Sloan
32   Last Modified: 17 February 1992
33   Purpose: convert a .wff file to VICAR
34 
35  NOTE: this program is based on bare minimum specifications for VICAR
36        images.  It works on the images that I have seen, and on the images
37        produced by wff2vcr (of course?).  It is not to be taken as a
38        specification of VICAR images.  If you spot an obvious error, or
39        know enough to provide guidance on further extensions, please
40        contact <sloan@cis.uab.edu>
41 
42   NOTE: the VICAR files have 8 bits per sample
43 
44         the .wff files must be I.  If the BitsPerSample is less than
45         8, then samples are extended to 8 bits (correctly!).  If the
46         BitsPerSample is greater than 8, the samples are truncated.
47  */
48 
49 #include <stdio.h>
50 #include <math.h>
51 #include "rle.h"
52 
53 int VERBOSE = 0;
54 
55 
56 /* VICAR stuff */
57  /* tags, and guesses as to meaning... */
58 static int  LBLSIZE;       /* size of header, must be int mult of NS */
59 #if 0
60 /* These aren't used by the program, but are kept for documentation. */
61 static char FORMAT[80];    /* 'BYTE' is OK */
62 static char TYPE[80];      /* 'IMAGE' is OK */
63 static int  BUFSIZe;       /* integer multiple of NS ? */
64 static int  DIM;           /* == 3? */
65 static int  EOL;           /* == 0? */
66 static int  RECSIZE;       /* == LBLSIZE? */
67 static char ORG[80];       /* `BSQ` is OK */
68 static int  NL;            /* height */
69 static int  NS;            /* width */
70 static int  NB;            /* samples per pixel? */
71 static int  N1;            /* == NL? */
72 static int  N2;            /* == NS? */
73 static int  N3;            /* == NB? */
74 static int  N4;            /* 0 is OK */
75 static int  NBB;           /* 0 is OK */
76 static int  NLB;           /* 0 is OK */
77 static char HOST[80];      /* machine type? */
78 static char INTFMT[80];    /* integer format? */
79 static char REALFMT[80];   /* read format? */
80 static char TASK[80];      /* processing applied? */
81 static char USER[80];      /* who was responsible? */
82 static char DAT_TIM[80];   /* when? */
83 static char COMMENT[80];   /* comment! */
84 #endif
85 
WriteVICARHeader(fd,width,height,BandsPerPixel)86 void WriteVICARHeader(fd, width, height, BandsPerPixel)
87 FILE *fd;
88 int width, height, BandsPerPixel;
89 {
90     char *buffer, *bp;
91 
92     /*
93       LBLSIZE must be an integer multiple of width.
94       It also needs to be large enough for everything below to fit.
95       We use 1024 as a reasonable minimum size, and pick the first integer
96       multiple of 'width' to be the LBLSIZE.
97 
98       Look - I don't really understand VICAR format.  We're just hacking...
99 
100       */
101     LBLSIZE = width;  while(LBLSIZE < 1024) LBLSIZE += width;
102     /* Allocate a buffer. */
103     buffer = (char *)malloc( LBLSIZE );
104     bp = buffer;
105 
106 #define incr(bp,fudge) \
107     bp += strlen( bp ); \
108     if ( bp - buffer + fudge > LBLSIZE ) \
109     { \
110 	bp = buffer = realloc( buffer, LBLSIZE += width ); \
111 	bp += strlen( bp ); \
112     }
113 
114     sprintf(bp,"LBLSIZE=%-d ",LBLSIZE);	/* see above */
115     incr( bp, 20 );
116     sprintf(bp," FORMAT='BYTE'");
117     incr( bp, 20 );
118     sprintf(bp," TYPE='IMAGE'");
119     incr( bp, 20 );
120     sprintf(bp," BUFSIZ=%-d",20*LBLSIZE);
121     incr( bp, 20 );
122     sprintf(bp," DIM=3");
123     incr( bp, 20 );
124     sprintf(bp," EOL=0");
125     incr( bp, 20 );
126     sprintf(bp," RECSIZE=%-d",LBLSIZE);
127     incr( bp, 20 );
128     sprintf(bp," ORG='BSQ'");
129     incr( bp, 20 );
130     sprintf(bp," NL=%-d",height);
131     incr( bp, 20 );
132     sprintf(bp," NS=%-d",width);
133     incr( bp, 20 );
134     sprintf(bp," NB=1");
135     incr( bp, 20 );
136     sprintf(bp," N1=%-d",height);
137     incr( bp, 20 );
138     sprintf(bp," N2=%-d",width);
139     incr( bp, 20 );
140     sprintf(bp," N3=1");
141     incr( bp, 20 );
142     sprintf(bp," N4=0");
143     incr( bp, 20 );
144     sprintf(bp," NBB=0");
145     incr( bp, 20 );
146     sprintf(bp," NLB=0");
147     incr( bp, 100 );
148     sprintf(bp," COMMENT='created by rletovcr'");
149     bp += strlen( bp );
150 
151 #undef incr
152 
153     /* Rewrite LBLSIZE in case it changed (unlikely). */
154     sprintf( buffer, "LBLSIZE=%-d", LBLSIZE );
155 
156     while ( bp < buffer + LBLSIZE )
157 	*bp++ = 0;
158 
159     fwrite( buffer, 1, LBLSIZE, fd );
160     free( buffer );
161 }
162 
WriteVICARScanLine(fd,VICARScanLine,VICARScanLineLength)163 static void WriteVICARScanLine(fd, VICARScanLine, VICARScanLineLength)
164 FILE *fd;
165 unsigned char *VICARScanLine;
166 int VICARScanLineLength;
167 {
168     (void)fwrite(VICARScanLine, 1, VICARScanLineLength, fd);
169 }
170 
171 static unsigned char *
read_image(the_hdr)172 read_image( the_hdr )
173 rle_hdr *the_hdr;
174 {
175     int y,width,height;
176     unsigned char *VICARImage;
177     rle_pixel **rows;
178 
179     /* Read the RLE file header. */
180     rle_get_setup_ok( the_hdr, NULL, NULL );
181     /* Don't read alpha channel. */
182     RLE_CLR_BIT( *the_hdr, RLE_ALPHA );
183 
184     /* Sanity check. */
185     if ( the_hdr->ncolors > 1 || the_hdr->cmap )
186     {
187 	fprintf( stderr,
188 		 "%s: Only black & white images can be converted to VICAR.\n",
189 		 the_hdr->cmd );
190 	if ( the_hdr->ncolors > 1 )
191 	    fprintf( stderr, "\t%s has %d colors.\n",
192 		     the_hdr->file_name, the_hdr->ncolors );
193 	else
194 	    fprintf( stderr, "\t%s has a color map.\n",
195 		     the_hdr->file_name );
196 	exit( 1 );
197     }
198 
199     /* Shift image over to save space. */
200     the_hdr->xmax -= the_hdr->xmin;
201     the_hdr->xmin = 0;
202     width = the_hdr->xmax + 1;
203     height = the_hdr->ymax - the_hdr->ymin + 1;
204 
205     VICARImage = (unsigned char *) malloc(width * height);
206     RLE_CHECK_ALLOC( the_hdr->cmd, VICARImage, "image" );
207     rows = (rle_pixel **)malloc( the_hdr->ncolors * sizeof(rle_pixel *));
208 
209     for ( y = the_hdr->ymin; y <= the_hdr->ymax; y++ )
210     {
211 	rows[0] = VICARImage + width * (the_hdr->ymax - y);
212 	rle_getrow( the_hdr, rows );
213     }
214     free( rows );
215 
216     return VICARImage;
217 }
218 
219 static void
write_image(the_hdr,outFD,VICARImage)220 write_image( the_hdr, outFD, VICARImage )
221 rle_hdr *the_hdr;
222 FILE *outFD;
223 unsigned char *VICARImage;
224 {
225     int width, height, y;
226 
227     if (VERBOSE) fprintf(stderr,"%s: Writing VICARHeader\n", the_hdr->cmd);
228 
229     width = the_hdr->xmax - the_hdr->xmin + 1;
230     height = the_hdr->ymax - the_hdr->ymin + 1;
231     WriteVICARHeader(outFD, width, height, the_hdr->ncolors);
232 
233     if (VERBOSE) fprintf(stderr,"%s: Writing VICAR image", the_hdr->cmd);
234 
235     for ( y = 0; y < height; y++ )
236     {
237 	WriteVICARScanLine(outFD, VICARImage + y * width, width);
238 	if (VERBOSE) fprintf(stderr,".");
239     }
240 
241     if (VERBOSE) fprintf(stderr,"\n");
242 
243     if (ferror(outFD))
244 	fprintf(stderr,"%s: Error writing image\n", the_hdr->cmd);
245 
246     if (VERBOSE)
247 	fprintf(stderr,"%s: finished writing the image\n", the_hdr->cmd);
248 
249     fflush(outFD);
250 }
251 
main(argc,argv)252 int main(argc,argv)
253 int argc;
254 char *argv[];
255 {
256     char *infname = NULL, *outfname = NULL;
257     int oflag = 0;
258     unsigned char *VICARImage;
259     rle_hdr the_hdr;
260     FILE *outFD;
261 
262     if ( scanargs( argc, argv, "% v%- o%-outfile!s infile%s\n(\
263 \tConvert URT image to VICAR format (as currently understood).)",
264 		   &VERBOSE, &oflag, &outfname, &infname ) == 0 )
265 	exit( 1 );
266 
267     the_hdr = *rle_hdr_init( (rle_hdr *)NULL );
268     rle_names( &the_hdr, cmd_name( argv ), infname );
269 
270     the_hdr.rle_file = rle_open_f( the_hdr.cmd, infname, "r" );
271 
272     VICARImage = read_image( &the_hdr );
273 
274     outFD = rle_open_f( the_hdr.cmd, outfname, "w" );
275 
276     write_image( &the_hdr, outFD, VICARImage );
277 
278     exit(0);
279 }
280