Mercurial > hg > minc-tools
annotate conversion/scxtominc/scx_file.c @ 618:9de05be4c965
Pre-release
author | neelin <neelin> |
---|---|
date | Wed, 28 Sep 1994 10:32:02 +0000 |
parents | 4023ad64bae5 |
children | 96821ec9dfac |
rev | line source |
---|---|
72 | 1 /* ----------------------------- MNI Header ----------------------------------- |
2 @NAME : scx_file.c | |
3 @DESCRIPTION: File containing routines to read scanditronix image files | |
4 @GLOBALS : | |
5 @CREATED : January 8, 1993 (Peter Neelin) | |
314 | 6 @MODIFIED : $Log: scx_file.c,v $ |
618 | 7 @MODIFIED : Revision 1.9 1994-09-28 10:33:28 neelin |
8 @MODIFIED : Pre-release | |
314 | 9 @MODIFIED : |
618 | 10 * Revision 1.8 93/11/03 17:16:19 neelin |
11 * Removed check for DPR==1 when getting images (this applies only to data). | |
12 * | |
433
4023ad64bae5
Removed check for DPR==1 when getting images (this applies only to data).
neelin <neelin>
parents:
374
diff
changeset
|
13 * Revision 1.7 93/10/06 10:15:46 neelin |
4023ad64bae5
Removed check for DPR==1 when getting images (this applies only to data).
neelin <neelin>
parents:
374
diff
changeset
|
14 * Added include of memory.h for compilation on SUNs |
4023ad64bae5
Removed check for DPR==1 when getting images (this applies only to data).
neelin <neelin>
parents:
374
diff
changeset
|
15 * |
374
3816e24a7935
Added include of memory.h for compilation on SUNs
neelin <neelin>
parents:
367
diff
changeset
|
16 * Revision 1.6 93/09/22 14:50:32 neelin |
3816e24a7935
Added include of memory.h for compilation on SUNs
neelin <neelin>
parents:
367
diff
changeset
|
17 * Added DTYP = 2 for short values in scx_get_image (this isn't documented, |
3816e24a7935
Added include of memory.h for compilation on SUNs
neelin <neelin>
parents:
367
diff
changeset
|
18 * but seems to occur for version 6 files sometimes). |
3816e24a7935
Added include of memory.h for compilation on SUNs
neelin <neelin>
parents:
367
diff
changeset
|
19 * |
367
96a886088b4d
Added DTYP = 2 for short values in scx_get_image (this isn't documented,
neelin <neelin>
parents:
334
diff
changeset
|
20 * Revision 1.5 93/08/31 12:08:28 neelin |
96a886088b4d
Added DTYP = 2 for short values in scx_get_image (this isn't documented,
neelin <neelin>
parents:
334
diff
changeset
|
21 * Added conditional definition of SEEK_SET. |
96a886088b4d
Added DTYP = 2 for short values in scx_get_image (this isn't documented,
neelin <neelin>
parents:
334
diff
changeset
|
22 * |
334 | 23 * Revision 1.4 93/08/11 15:27:42 neelin |
24 * Added RCS logging in source. | |
25 * | |
259 | 26 @COPYRIGHT : |
27 Copyright 1993 Peter Neelin, McConnell Brain Imaging Centre, | |
28 Montreal Neurological Institute, McGill University. | |
29 Permission to use, copy, modify, and distribute this | |
30 software and its documentation for any purpose and without | |
31 fee is hereby granted, provided that the above copyright | |
32 notice appear in all copies. The author and McGill University | |
33 make no representations about the suitability of this | |
34 software for any purpose. It is provided "as is" without | |
35 express or implied warranty. | |
72 | 36 ---------------------------------------------------------------------------- */ |
37 | |
38 #ifndef lint | |
618 | 39 static char rcsid[]="$Header: /private-cvsroot/minc/conversion/scxtominc/scx_file.c,v 1.9 1994-09-28 10:33:28 neelin Exp $"; |
72 | 40 #endif |
41 | |
42 #include <stdlib.h> | |
43 #include <stdio.h> | |
44 #include <string.h> | |
374
3816e24a7935
Added include of memory.h for compilation on SUNs
neelin <neelin>
parents:
367
diff
changeset
|
45 #include <memory.h> |
72 | 46 #include <scx_header_def.h> |
47 #include <scx_file.h> | |
48 #include <vax_conversions.h> | |
49 | |
334 | 50 #ifndef SEEK_SET |
51 # define SEEK_SET 0 | |
52 #endif | |
53 | |
72 | 54 /* Private functions */ |
55 private void scx_get_value(unsigned char *header, long position, | |
56 scx_mnem_types type, int length, | |
57 long *lvalue, float *fvalue, char *svalue); | |
58 | |
59 /* Constants */ | |
60 #define TRUE 1 | |
61 #define FALSE 0 | |
62 #define HEADER_SIZE 2048 | |
63 #define FILE_TYPE_POSITION 0 | |
64 #define FILE_TYPE_TYPE scx_word | |
65 #define SCX_NCS "NCS" | |
66 #define SCX_SPOS "SPOS" | |
67 #define SCX_DPR "DPR" | |
68 #define SCX_FHS "FHS" | |
69 #define SCX_REC "REC" | |
70 #define SCX_DTYP "DTYP" | |
71 #define SCX_IMFM "IMFM" | |
72 #define SCX_SPOS "SPOS" | |
73 #define MAX_PIX_SIZE 2 | |
74 | |
75 | |
76 /* ----------------------------- MNI Header ----------------------------------- | |
77 @NAME : scx_open | |
78 @INPUT : filename - name of file to open | |
79 @OUTPUT : (none) | |
80 @RETURNS : Pointer to scanditronix file descriptor or NULL if an error | |
81 occurs. | |
82 @DESCRIPTION: Routine to open a scanditronix file (for reading only), given | |
83 its pathname. | |
84 @METHOD : | |
85 @GLOBALS : | |
86 @CALLS : | |
87 @CREATED : January 8, 1993 (Peter Neelin) | |
88 @MODIFIED : | |
89 ---------------------------------------------------------------------------- */ | |
90 public scx_file *scx_open(char *filename) | |
91 { | |
92 scx_file *file; | |
93 long file_type, nslice, spos; | |
94 int i; | |
95 | |
96 /* Allocate space for a scx file structure */ | |
237
bff58e671d2e
Changed includes, malloc, free and return from main.
neelin <neelin>
parents:
72
diff
changeset
|
97 file = (void *) malloc(sizeof(scx_file)); |
72 | 98 |
99 /* Open the file */ | |
100 if ((file->file_pointer=fopen(filename, "rb")) == NULL) { | |
101 free(file); | |
102 return NULL; | |
103 } | |
104 | |
105 /* Read in the header */ | |
237
bff58e671d2e
Changed includes, malloc, free and return from main.
neelin <neelin>
parents:
72
diff
changeset
|
106 file->header = (void *) malloc(HEADER_SIZE); |
72 | 107 if (fread(file->header, sizeof(char), (size_t) HEADER_SIZE, |
108 file->file_pointer) != HEADER_SIZE) { | |
109 free(file->header); | |
110 free(file); | |
111 return NULL; | |
112 } | |
113 | |
114 /* Get the file type from the header */ | |
115 scx_get_value(file->header, FILE_TYPE_POSITION, FILE_TYPE_TYPE, 1, | |
116 &file_type, NULL, NULL); | |
117 | |
118 /* Search for the file type */ | |
119 for (i=0; (scx_file_types[i].file_type!=0) && | |
120 (file_type!=scx_file_types[i].file_type); i++) {} | |
121 if (scx_file_types[i].file_type==0) { | |
122 free(file->header); | |
123 free(file); | |
124 return NULL; | |
125 } | |
126 file->blocks = scx_file_types[i].block_list; | |
127 file->mnemonics = scx_file_types[i].mnemonic_list; | |
128 | |
129 /* Get the number of mnemonics in the header */ | |
130 for (i=0; file->mnemonics[i].name!=NULL; i++) {} | |
131 file->num_mnemonics = i; | |
132 | |
133 /* Check for a consistent header by looking at the slice positions */ | |
134 if (scx_get_mnem(file, SCX_NCS, 0, &nslice, NULL, NULL) || (nslice<=0)) { | |
135 free(file->header); | |
136 free(file); | |
137 return NULL; | |
138 } | |
139 for (i=0; i<nslice; i++) { | |
140 if (scx_get_mnem(file, SCX_SPOS, i, &spos, NULL, NULL) || | |
141 (spos<0) || (spos>nslice)) { | |
142 free(file->header); | |
143 free(file); | |
144 return NULL; | |
145 } | |
146 } | |
147 | |
148 return file; | |
149 } | |
150 | |
151 /* ----------------------------- MNI Header ----------------------------------- | |
152 @NAME : scx_close | |
153 @INPUT : file - scanditronix file descriptor to close | |
154 @OUTPUT : (none) | |
155 @RETURNS : (nothing) | |
156 @DESCRIPTION: Routine to close a scanditronix file. | |
157 @METHOD : | |
158 @GLOBALS : | |
159 @CALLS : | |
160 @CREATED : January 8, 1993 (Peter Neelin) | |
161 @MODIFIED : | |
162 ---------------------------------------------------------------------------- */ | |
163 public void scx_close(scx_file *file) | |
164 { | |
165 if (file==NULL) return; | |
166 (void) fclose(file->file_pointer); | |
167 free(file->header); | |
168 free(file); | |
169 | |
170 return; | |
171 } | |
172 | |
173 /* ----------------------------- MNI Header ----------------------------------- | |
174 @NAME : scx_get_mnem | |
175 @INPUT : file - scanditronix file descriptor | |
176 mnem - mnemonic to find | |
177 multiplicity - index of value to get | |
178 @OUTPUT : lvalue - long integer value to return | |
179 fvalue - floating point value to return | |
180 svalue - string value to return | |
181 @RETURNS : TRUE if an error occurs, FALSE otherwise | |
182 @DESCRIPTION: Routine to get a mnemonic's value from a scanditronix file | |
183 header. | |
184 @METHOD : | |
185 @GLOBALS : | |
186 @CALLS : | |
187 @CREATED : January 8, 1993 (Peter Neelin) | |
188 @MODIFIED : | |
189 ---------------------------------------------------------------------------- */ | |
190 public int scx_get_mnem(scx_file *file, char *mnem, int multiplicity, | |
191 long *lvalue, float *fvalue, char *svalue) | |
192 { | |
193 scx_block_type *block_ptr; | |
194 scx_mnemonic_type *mnem_ptr; | |
195 long position; | |
196 | |
197 /* Check file pointer */ | |
198 if (file==NULL) return TRUE; | |
199 | |
200 /* Check for negative multiplicity */ | |
201 if (multiplicity < 0) return TRUE; | |
202 | |
203 /* Search for the mnemonic */ | |
204 for (mnem_ptr=file->mnemonics; | |
205 (mnem_ptr->name!=NULL) && (strcmp(mnem_ptr->name, mnem)!=0); | |
206 mnem_ptr++) {} | |
207 if (mnem_ptr->name==NULL) return TRUE; | |
208 | |
209 /* Check for a mnemonic not in the file (a constant). We only handle | |
210 integer constants */ | |
211 if (!mnem_ptr->in_file) { | |
212 switch (mnem_ptr->type) { | |
213 case scx_byte: | |
214 case scx_word: | |
215 case scx_long: | |
216 if (lvalue!=NULL) *lvalue = mnem_ptr->mdefault; | |
217 if (fvalue!=NULL) *fvalue = mnem_ptr->mdefault; | |
218 if (svalue!=NULL) | |
219 (void) sprintf(svalue, "%d", (int) mnem_ptr->mdefault); | |
220 break; | |
221 default: | |
222 return TRUE; | |
223 } | |
224 } | |
225 | |
226 /* Mnemonic is in file header */ | |
227 else { | |
228 | |
229 /* Calculate the position of the mnemonic by looping through | |
230 the list of parent blocks */ | |
231 position = mnem_ptr->start; | |
232 for (block_ptr = mnem_ptr->block; | |
233 (multiplicity>0) && (block_ptr!=NULL); | |
234 block_ptr = block_ptr->parent) { | |
235 position += block_ptr->length * | |
236 (multiplicity % block_ptr->multiplicity); | |
237 multiplicity /= block_ptr->multiplicity; | |
238 } | |
239 if (multiplicity > 0) return TRUE; | |
240 | |
241 /* Get the value */ | |
242 scx_get_value(file->header, position, mnem_ptr->type, mnem_ptr->length, | |
243 lvalue, fvalue, svalue); | |
244 | |
245 } | |
246 | |
247 return FALSE; | |
248 } | |
249 | |
250 /* ----------------------------- MNI Header ----------------------------------- | |
251 @NAME : scx_get_value | |
252 @INPUT : header - pointer to header data | |
253 position - postion of value to read | |
254 type - type of value to get | |
255 length - number of values to get | |
256 @OUTPUT : lvalue - long integer value to return | |
257 fvalue - floating point value to return | |
258 svalue - string value to return | |
259 @RETURNS : (nothing) | |
260 @DESCRIPTION: Routine to get a mnemonic's value from a scanditronix file | |
261 header, given the position and type. | |
262 @METHOD : | |
263 @GLOBALS : | |
264 @CALLS : | |
265 @CREATED : January 8, 1993 (Peter Neelin) | |
266 @MODIFIED : | |
267 ---------------------------------------------------------------------------- */ | |
268 private void scx_get_value(unsigned char *header, long position, | |
269 scx_mnem_types type, int length, | |
270 long *lvalue, float *fvalue, char *svalue) | |
271 { | |
272 void *data; | |
273 unsigned char *bdata; | |
274 short *idata; | |
275 long *ldata; | |
276 float *fdata; | |
277 | |
278 /* Check length */ | |
279 if (length<=0) return; | |
280 | |
281 /* Get the values */ | |
237
bff58e671d2e
Changed includes, malloc, free and return from main.
neelin <neelin>
parents:
72
diff
changeset
|
282 data = (void *) malloc(length * scx_mnem_type_size[type]); |
72 | 283 bdata = data; idata = data; ldata = data; fdata = data; |
284 switch (type) { | |
285 case scx_byte: | |
286 case scx_string: | |
287 case scx_time: | |
288 case scx_date: | |
289 (void) memcpy(bdata, &header[position], length); | |
290 break; | |
291 case scx_word: | |
292 case scx_short_float: | |
293 get_vax_short(length, &header[position], idata); | |
294 break; | |
295 case scx_long: | |
296 get_vax_long(length, &header[position], ldata); | |
297 break; | |
298 case scx_float: | |
299 get_vax_float(length, &header[position], fdata); | |
300 } | |
301 | |
302 /* Convert the values */ | |
303 switch (type) { | |
304 case scx_byte: | |
305 if (lvalue!=NULL) *lvalue = bdata[0]; | |
306 if (fvalue!=NULL) *fvalue = bdata[0]; | |
307 if (svalue!=NULL) (void) sprintf(svalue, "%d", (int) bdata[0]); | |
308 break; | |
309 case scx_string: | |
310 if (lvalue!=NULL) *lvalue = 0; | |
311 if (fvalue!=NULL) *fvalue = 0; | |
312 if (svalue!=NULL) { | |
313 (void) memcpy(svalue, bdata, length); | |
314 svalue[length]='\0'; | |
315 } | |
316 break; | |
317 case scx_time: | |
318 if (lvalue!=NULL) *lvalue = 0; | |
319 if (fvalue!=NULL) *fvalue = 0; | |
320 if (svalue!=NULL) { | |
321 if (length==3) | |
322 (void) sprintf(svalue, "%02d:%02d:%02d", | |
323 (int) bdata[0], (int) bdata[1], (int) bdata[2]); | |
324 else if (length==4) | |
325 (void) sprintf(svalue, "%02d:%02d:%02d.%02d", | |
326 (int) bdata[0], (int) bdata[1], | |
327 (int) bdata[2], (int) bdata[3]); | |
328 else | |
329 svalue[0]='\0'; | |
330 } | |
331 break; | |
332 case scx_date: | |
333 if (lvalue!=NULL) *lvalue = 0; | |
334 if (fvalue!=NULL) *fvalue = 0; | |
335 if (svalue!=NULL) { | |
336 if (length==3) | |
337 (void) sprintf(svalue, "%02d-%02d-%02d", | |
338 (int) bdata[0], (int) bdata[1], (int) bdata[2]); | |
339 else | |
340 svalue[0]='\0'; | |
341 } | |
342 break; | |
343 case scx_word: | |
344 if (lvalue!=NULL) *lvalue = idata[0]; | |
345 if (fvalue!=NULL) *fvalue = idata[0]; | |
346 if (svalue!=NULL) (void) sprintf(svalue, "%d", (int) idata[0]); | |
347 break; | |
348 case scx_short_float: | |
349 if (lvalue!=NULL) *lvalue = idata[0]/100.0; | |
350 if (fvalue!=NULL) *fvalue = idata[0]/100.0; | |
351 if (svalue!=NULL) (void) sprintf(svalue, "%8g", (double) idata[0]/100.0); | |
352 break; | |
353 case scx_long: | |
354 if (lvalue!=NULL) *lvalue = ldata[0]; | |
355 if (fvalue!=NULL) *fvalue = ldata[0]; | |
356 if (svalue!=NULL) (void) sprintf(svalue, "%d", (int) ldata[0]); | |
357 break; | |
358 case scx_float: | |
359 if (lvalue!=NULL) *lvalue = fdata[0]; | |
360 if (fvalue!=NULL) *fvalue = fdata[0]; | |
361 if (svalue!=NULL) (void) sprintf(svalue, "%8g", (double) fdata[0]); | |
362 break; | |
363 } | |
364 | |
365 free(data); | |
366 | |
367 return; | |
368 | |
369 } | |
370 | |
371 /* ----------------------------- MNI Header ----------------------------------- | |
372 @NAME : scx_get_image | |
373 @INPUT : file - scanditronix file pointer | |
374 image_num - image to get (first image is zero) | |
375 @OUTPUT : image - pointer to array into which image should be written. | |
376 @RETURNS : TRUE if an error occurs, false otherwise. | |
377 @DESCRIPTION: Routine to get an image from a scanditronix image file. | |
378 @METHOD : | |
379 @GLOBALS : | |
380 @CALLS : | |
381 @CREATED : January 11, 1993 (Peter Neelin) | |
382 @MODIFIED : | |
383 ---------------------------------------------------------------------------- */ | |
384 public int scx_get_image(scx_file *file, int image_num, short *image) | |
385 { | |
433
4023ad64bae5
Removed check for DPR==1 when getting images (this applies only to data).
neelin <neelin>
parents:
374
diff
changeset
|
386 long header_size, record_size, data_type; |
72 | 387 long image_width, image_pos, image_npix, image_size; |
388 long file_offset, array_offset, ipix; | |
389 int pix_size; | |
390 unsigned char *bimage; | |
391 | |
392 /* Check file pointer */ | |
393 if (file==NULL) return TRUE; | |
394 | |
395 /* Parameters for calculating image position */ | |
396 if (scx_get_mnem(file, SCX_FHS, 0, &header_size, NULL, NULL) || | |
397 scx_get_mnem(file, SCX_REC, 0, &record_size, NULL, NULL) || | |
398 scx_get_mnem(file, SCX_DTYP, 0, &data_type, NULL, NULL) || | |
399 scx_get_mnem(file, SCX_IMFM, 0, &image_width, NULL, NULL) || | |
400 scx_get_mnem(file, SCX_SPOS, image_num, &image_pos, NULL, NULL) || | |
401 (header_size<0) || (record_size<0) || (image_width<0) || | |
402 (image_pos<0)) { | |
403 return TRUE; | |
404 } | |
405 | |
406 /* Check that image is in file */ | |
407 if (image_pos<1) return TRUE; | |
408 | |
409 /* Check data type */ | |
410 switch (data_type) { | |
411 case 0: pix_size=2; break; | |
412 case 1: pix_size=1; break; | |
367
96a886088b4d
Added DTYP = 2 for short values in scx_get_image (this isn't documented,
neelin <neelin>
parents:
334
diff
changeset
|
413 case 2: pix_size=2; break; |
72 | 414 default: return TRUE; |
415 } | |
416 | |
417 /* Calculate image size and offsets */ | |
418 image_npix = image_width * image_width; | |
419 image_size = image_npix * pix_size; | |
420 file_offset = header_size * record_size + (image_pos-1) * image_size; | |
421 array_offset = image_npix * (MAX_PIX_SIZE - pix_size); | |
422 bimage = (unsigned char *) image; | |
423 | |
424 /* Read in the image */ | |
425 if (fseek(file->file_pointer, file_offset, SEEK_SET) || | |
426 (fread(&bimage[array_offset], (size_t) pix_size, (size_t) image_npix, | |
427 file->file_pointer) != image_npix)) { | |
428 return TRUE; | |
429 } | |
430 | |
431 /* Transform the image to the right type */ | |
432 switch (pix_size) { | |
433 case 1: | |
434 for (ipix=0; ipix<image_npix; ipix++) { | |
435 image[ipix] = bimage[array_offset+ipix]; | |
436 } | |
437 break; | |
438 case 2: | |
439 get_vax_short(image_npix, image, image); | |
440 break; | |
441 default: | |
442 return TRUE; | |
443 } | |
444 | |
445 return FALSE; | |
446 | |
447 } | |
448 | |
449 /* ----------------------------- MNI Header ----------------------------------- | |
450 @NAME : scx_list_mnems | |
451 @INPUT : file - pointer to an open scanditronix file | |
452 index - counter to identify next mnemonic | |
453 @OUTPUT : mname - pointer to array into which name should be written | |
454 mmult - multiplicity of mnemonic | |
455 mtype - type of mnemonic (can be scx_long, scx_float or | |
456 scx_string) | |
457 @RETURNS : Value of mname or NULL if index out of range. | |
458 @DESCRIPTION: Routine to list the mnemonics that can be found in a scanditronix | |
459 file. | |
460 @METHOD : | |
461 @GLOBALS : | |
462 @CALLS : | |
463 @CREATED : January 19, 1993 (Peter Neelin) | |
464 @MODIFIED : | |
465 ---------------------------------------------------------------------------- */ | |
466 public char *scx_list_mnems(scx_file *file,int index, char *mname, | |
467 int *mmult, scx_mnem_types *mtype) | |
468 { | |
469 scx_block_type *block_ptr; | |
470 | |
471 /* Check file pointer and index */ | |
472 if ((file == NULL) || (index < 0) || (index >= file->num_mnemonics)) | |
473 return NULL; | |
474 | |
475 /* Copy the name */ | |
476 (void) strcpy(mname, file->mnemonics[index].name); | |
477 | |
478 /* Get the multiplicity */ | |
479 *mmult = 1; | |
480 for (block_ptr = file->mnemonics[index].block; | |
481 block_ptr!=NULL; | |
482 block_ptr = block_ptr->parent) { | |
483 *mmult *= block_ptr->multiplicity; | |
484 } | |
485 | |
486 /* Get the mnemonic type */ | |
487 switch (file->mnemonics[index].type) { | |
488 case scx_byte: *mtype = scx_long; break; | |
489 case scx_string: *mtype = scx_string; break; | |
490 case scx_time: *mtype = scx_string; break; | |
491 case scx_date: *mtype = scx_string; break; | |
492 case scx_word: *mtype = scx_long; break; | |
493 case scx_short_float: *mtype = scx_float; break; | |
494 case scx_long: *mtype = scx_long; break; | |
495 case scx_float: *mtype = scx_float; break; | |
496 } | |
497 | |
498 return mname; | |
499 | |
500 } | |
501 |