1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * filename: m-files.c *
3 * *
4 * UTIL C-source: Medical Image Conversion Utility *
5 * *
6 * purpose : Files edit, file I/O, image buffers *
7 * *
8 * project : (X)MedCon by Erik Nolf *
9 * *
10 * Functions : MdcOpenFile() - Open file *
11 * MdcReadFile() - Read file *
12 * MdcWriteFile() - Write file *
13 * MdcLoadFile() - Load file *
14 * MdcSaveFile() - Save file *
15 * MdcLoadPlane() - Load one plane *
16 * MdcSavePlane() - Save one plane *
17 * MdcDecompressFile() - Decompress file *
18 * MdcStringCopy() - Copy a string *
19 * MdcFileSize() - Get the size of a file *
20 * MdcFileExists() - Check if file exists *
21 * MdcKeepFile() - Prevent overwrite existing file *
22 * MdcGetFrmt() - Get format of imagefile *
23 * MdcGetImgBuffer() - Malloc a buffer *
24 * MdcHandleTruncated() - Reset FILEINFO for truncated file*
25 * MdcWriteLine() - Write image line *
26 * MdcWriteDoublePixel() - Write single pixel double input *
27 * MdcGetFname() - Get filename *
28 * MdcSetExt() - Set filename extension *
29 * MdcNewExt() - Create filename extension *
30 * MdcPrefix() - Create filename prefix *
31 * MdcGetPrefixNr() - Get proper filename prefix *
32 * MdcGetLastPathDelim() - Get pointer last path delimiter *
33 * MdcMySplitPath() - Split path from filename *
34 * MdcMyMergePath() - Merge path to filename *
35 * MdcNewName() - Create new filename *
36 * MdcAliasName() - Create alias name based on ID's *
37 * MdcEchoAliasName() - Echo alias name based on ID's *
38 * MdcDefaultName() - Create new filename for format *
39 * MdcRenameFile() - Let user give a new name *
40 * MdcFillImgPos() - Fill the image_pos(_dev/_pat) *
41 * MdcFillImgOrient() - Fill the image_orient(_dev/_pat) *
42 * MdcGetOrthogonalInt() - Get orthogonal direction cosine *
43 * MdcGetPatSliceOrient()- Get patient_slice_orient *
44 * MdcTryPatSliceOrient()- Try to get it from pat_orient *
45 * MdcCheckQuantitation()- Check quantitation preservation *
46 * MdcGetHeartRate() - Get heart rate from gated data *
47 * *
48 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49 /*
50 */
51
52 /*
53 Copyright (C) 1997-2021 by Erik Nolf
54
55 This program is free software; you can redistribute it and/or modify it
56 under the terms of the GNU General Public License as published by the
57 Free Software Foundation; either version 2, or (at your option) any later
58 version.
59
60 This program is distributed in the hope that it will be useful, but
61 WITHOUT ANY WARRANTY; without even the implied warranty of
62 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
63 Public License for more details.
64
65 You should have received a copy of the GNU General Public License along
66 with this program; if not, write to the Free Software Foundation, Inc.,
67 59 Place - Suite 330, Boston, MA 02111-1307, USA. */
68
69 /****************************************************************************
70 H E A D E R S
71 ****************************************************************************/
72
73 #include "m-depend.h"
74
75 #include <stdio.h>
76 #include <ctype.h>
77 #ifdef HAVE_STDLIB_H
78 #include <stdlib.h>
79 #endif
80 #ifdef HAVE_STRING_H
81 #include <string.h>
82 #endif
83 #ifdef HAVE_STRINGS_H
84 #ifndef _WIN32
85 #include <strings.h>
86 #endif
87 #endif
88 #ifdef HAVE_UNISTD_H
89 #include <unistd.h>
90 #endif
91
92 #include "medcon.h"
93
94 /****************************************************************************
95 F U N C T I O N S
96 ****************************************************************************/
MdcOpenFile(FILEINFO * fi,const char * path)97 int MdcOpenFile(FILEINFO *fi, const char *path)
98 {
99 int ctype;
100
101 if (MDC_FILE_STDIN == MDC_NO) {
102 if ( (ctype = MdcWhichCompression(path)) != MDC_NO ) {
103 if ((MdcDecompressFile(path)) != MDC_OK) {
104
105 MdcPrntWarn("Decompression failed");
106
107 /* no longer quit, because NIFTI */
108 /* can read .gz files directly */
109 /* return(MDC_BAD_OPEN); */
110
111 /* prevent unwanted unlink later */
112 ctype = MDC_NO;
113 }
114 }
115 }else{
116 ctype = MDC_NO;
117 }
118
119 MdcInitFI(fi, path); fi->compression = (Int8)ctype;
120
121 if (MDC_FILE_STDIN == MDC_NO) {
122 if ( (fi->ifp=fopen(fi->ipath,"rb")) == NULL) {
123 MdcPrntWarn("Couldn't open <%s> for reading",fi->ipath);
124 return(MDC_BAD_OPEN);
125 }
126 }else{
127 fi->ifp = stdin; strcpy(fi->ipath,"stdin");
128 }
129
130 if (ctype != MDC_NO) unlink(path);
131
132 MdcSplitPath(fi->ipath,fi->idir,fi->ifname);
133
134 return(MDC_OK);
135
136 }
137
MdcReadFile(FILEINFO * fi,int filenr,char * (* ReadFunc)(FILEINFO * fi))138 int MdcReadFile(FILEINFO *fi, int filenr, char *(*ReadFunc)(FILEINFO *fi))
139 {
140 int FORMAT=MDC_FRMT_NONE;
141 const char *msg=NULL;
142
143 if (ReadFunc == NULL) {
144 /* get the format or fallback */
145 if ( (FORMAT=MdcGetFrmt(fi) ) == MDC_FRMT_NONE ) {
146 MdcCloseFile(fi->ifp);
147 MdcPrntWarn("Unsupported format in <%s>",fi->ifname);
148 return(MDC_BAD_CODE);
149 }else if (FORMAT < 0) {
150 MdcCloseFile(fi->ifp);
151 MdcPrntWarn("Unsuccessful read from <%s>",fi->ifname);
152 return(MDC_BAD_READ);
153 }
154 }
155
156 /* print a header message */
157 if (MDC_INFO && !MDC_INTERACTIVE) {
158 MdcPrntScrn("\n");
159 MdcPrintLine('*',MDC_FULL_LENGTH);
160 MdcPrntScrn("FILE %03d : %s\t\t\t",filenr,fi->ifname);
161 MdcPrntScrn("FORMAT: %s\n",FrmtString[fi->iformat]);
162 MdcPrintLine('*',MDC_FULL_LENGTH);
163 MdcPrntScrn("\n");
164 }
165
166 /* read the appropriate format */
167 switch (FORMAT) {
168
169 case MDC_FRMT_RAW: msg=MdcReadRAW(fi); break;
170 #if MDC_INCLUDE_ACR
171 case MDC_FRMT_ACR: msg=MdcReadACR(fi); break;
172 #endif
173 #if MDC_INCLUDE_GIF
174 case MDC_FRMT_GIF: msg=MdcReadGIF(fi); break;
175 #endif
176 #if MDC_INCLUDE_INW
177 case MDC_FRMT_INW: msg=MdcReadINW(fi); break;
178 #endif
179 #if MDC_INCLUDE_ECAT
180 case MDC_FRMT_ECAT6: msg=MdcReadECAT6(fi); break;
181
182 case MDC_FRMT_ECAT7: msg=MdcReadECAT7(fi); break;
183 #endif
184 #if MDC_INCLUDE_INTF
185 case MDC_FRMT_INTF: msg=MdcReadINTF(fi); break;
186 #endif
187 #if MDC_INCLUDE_ANLZ
188 case MDC_FRMT_ANLZ: msg=MdcReadANLZ(fi); break;
189 #endif
190 #if MDC_INCLUDE_DICM
191 case MDC_FRMT_DICM: msg=MdcReadDICM(fi); break;
192 #endif
193 #if MDC_INCLUDE_PNG
194 case MDC_FRMT_PNG: msg=MdcReadPNG(fi); break;
195 #endif
196 #if MDC_INCLUDE_CONC
197 case MDC_FRMT_CONC: msg=MdcReadCONC(fi); break;
198 #endif
199 #if MDC_INCLUDE_NIFTI
200 case MDC_FRMT_NIFTI: msg=MdcReadNIFTI(fi); break;
201 #endif
202 default:
203 if (ReadFunc != NULL) {
204 msg = ReadFunc(fi);
205 }else{
206 MdcPrntWarn("Reading: Unsupported format");
207 return(MDC_BAD_FILE);
208 }
209 }
210
211 /* read error handling */
212 if (msg != NULL) {
213 MdcPrntWarn("Reading: %s",msg);
214 if (strstr(msg,"Truncated image") == NULL) {
215 MdcCleanUpFI(fi);
216 return(MDC_BAD_READ);
217 }else{
218 MdcCloseFile(fi->ifp);
219 }
220 }
221
222 /* database info | dangerous: not all image info read */
223 if (MDC_INFO_DB == MDC_YES) return(MDC_OK);
224
225 /* echo alias, quickly leave */
226 if (MDC_ECHO_ALIAS == MDC_YES) return(MDC_OK);
227
228 /* set the proper color map */
229 if (fi->map == MDC_MAP_GRAY) {
230 /* gray scale images, set selected colormap */
231 if (MDC_COLOR_MAP < MDC_MAP_GRAY) MDC_COLOR_MAP = MDC_MAP_GRAY;
232 fi->map = MDC_COLOR_MAP;
233 }else{
234 /* colored images, preserve map */
235 fi->map = (Uint8)MdcSetPresentMap(fi->palette);
236 }
237
238 /* get the proper color map */
239 MdcGetColorMap((int)fi->map,fi->palette);
240
241 /* the obligated pixel handling */
242 msg = MdcImagesPixelFiddle(fi);
243 if (msg != NULL) {
244 MdcCleanUpFI(fi);
245 MdcPrntWarn("Reading: %s",msg);
246 return(MDC_BAD_CODE);
247 }
248
249 /* do some requested transformations */
250 msg = NULL;
251 if (MDC_INFO == MDC_NO) {
252 if ((msg == NULL) && (MDC_CONTRAST_REMAP == MDC_YES))
253 msg=MdcContrastRemap(fi);
254 if ((msg == NULL) && (MDC_MAKE_SQUARE != MDC_NO))
255 msg=MdcMakeSquare(fi,MDC_MAKE_SQUARE);
256 if ((msg == NULL) && (MDC_FLIP_HORIZONTAL == MDC_YES))
257 msg=MdcFlipHorizontal(fi);
258 if ((msg == NULL) && (MDC_FLIP_VERTICAL == MDC_YES))
259 msg=MdcFlipVertical(fi);
260 if ((msg == NULL) && (MDC_SORT_REVERSE == MDC_YES))
261 msg=MdcSortReverse(fi);
262 if ((msg == NULL) && (MDC_SORT_CINE_APPLY == MDC_YES))
263 msg=MdcSortCineApply(fi);
264 if ((msg == NULL) && (MDC_SORT_CINE_UNDO == MDC_YES))
265 msg=MdcSortCineUndo(fi);
266 if ((msg == NULL) && (MDC_CROP_IMAGES == MDC_YES))
267 msg=MdcCropImages(fi,NULL);
268
269 if (msg != NULL) {
270 MdcCleanUpFI(fi);
271 MdcPrntWarn("Transform: %s",msg);
272 return(MDC_BAD_CODE);
273 }
274 }
275
276 return(MDC_OK);
277
278 }
279
MdcWriteFile(FILEINFO * fi,int format,int prefixnr,char * (* WriteFunc)())280 int MdcWriteFile(FILEINFO *fi, int format, int prefixnr, char *(*WriteFunc)())
281 {
282 const char *msg=NULL;
283 Int8 INTERNAL_ENDIAN;
284
285 if (WriteFunc != NULL) format = MDC_FRMT_NONE;
286
287 /* reset ID's rescaled stuff from any previous write */
288 MdcResetIDs(fi);
289
290 /* negative value = self made prefix */
291 if (prefixnr >= 0 ) MdcPrefix(prefixnr);
292
293 /* preserve internal file endian - global var issue */
294 INTERNAL_ENDIAN = MDC_FILE_ENDIAN;
295
296 switch (format) {
297 case MDC_FRMT_RAW : fi->rawconv = MDC_FRMT_RAW;
298 msg=MdcWriteRAW(fi);
299 break;
300 case MDC_FRMT_ASCII: fi->rawconv = MDC_FRMT_ASCII;
301 msg=MdcWriteRAW(fi);
302 break;
303 #if MDC_INCLUDE_ACR
304 case MDC_FRMT_ACR : msg=MdcWriteACR(fi); break;
305 #endif
306 #if MDC_INCLUDE_GIF
307 case MDC_FRMT_GIF : msg=MdcWriteGIF(fi); break;
308 #endif
309 #if MDC_INCLUDE_INW
310 case MDC_FRMT_INW : msg=MdcWriteINW(fi); break;
311 #endif
312 #if MDC_INCLUDE_ECAT
313 case MDC_FRMT_ECAT6: msg=MdcWriteECAT6(fi); break;
314 #if MDC_INCLUDE_TPC
315 case MDC_FRMT_ECAT7: msg=MdcWriteECAT7(fi); break;
316 #endif
317 #endif
318 #if MDC_INCLUDE_INTF
319 case MDC_FRMT_INTF : msg=MdcWriteINTF(fi); break;
320 #endif
321 #if MDC_INCLUDE_ANLZ
322 case MDC_FRMT_ANLZ : msg=MdcWriteANLZ(fi); break;
323 #endif
324 #if MDC_INCLUDE_DICM
325 case MDC_FRMT_DICM : msg=MdcWriteDICM(fi); break;
326 #endif
327 #if MDC_INCLUDE_PNG
328 case MDC_FRMT_PNG : msg=MdcWritePNG(fi); break;
329 #endif
330 #if MDC_INCLUDE_CONC
331 case MDC_FRMT_CONC : msg=MdcWriteCONC(fi); break;
332 #endif
333 #if MDC_INCLUDE_NIFTI
334 case MDC_FRMT_NIFTI: msg=MdcWriteNIFTI(fi); break;
335 #endif
336 default:
337 if (WriteFunc != NULL) {
338 msg = WriteFunc(fi);
339 }else{
340 MdcPrntWarn("Writing: Unsupported format");
341 return(MDC_BAD_FILE);
342 }
343 }
344
345 /* restore internal file endian - global var issue */
346 MDC_FILE_ENDIAN = INTERNAL_ENDIAN;
347
348 MdcCloseFile(fi->ofp);
349
350 if (msg != NULL) {
351 MdcPrntWarn("Writing: %s",msg);
352 return(MDC_BAD_WRITE);
353 }
354
355 return(MDC_OK);
356
357 }
358
MdcLoadFile(FILEINFO * fi)359 int MdcLoadFile(FILEINFO *fi)
360 {
361 int FORMAT=MDC_FRMT_NONE;
362 const char *msg=NULL;
363
364 /* get the format or fallback */
365 if ( (FORMAT=MdcGetFrmt(fi) ) == MDC_FRMT_NONE ) {
366 MdcCloseFile(fi->ifp);
367 return(MDC_BAD_READ);
368 }
369
370 /* read the appropriate format */
371 switch (FORMAT) {
372
373 case MDC_FRMT_RAW: msg=MdcReadRAW(fi); break;
374 #if MDC_INCLUDE_ACR
375 case MDC_FRMT_ACR: msg=MdcReadACR(fi); break;
376 #endif
377 #if MDC_INCLUDE_GIF
378 case MDC_FRMT_GIF: msg=MdcReadGIF(fi); break;
379 #endif
380 #if MDC_INCLUDE_INW
381 case MDC_FRMT_INW: msg=MdcReadINW(fi); break;
382 #endif
383 #if MDC_INCLUDE_ECAT
384 case MDC_FRMT_ECAT6: msg=MdcReadECAT6(fi); break;
385
386 case MDC_FRMT_ECAT7: msg=MdcReadECAT7(fi); break;
387 #endif
388 #if MDC_INCLUDE_INTF
389 case MDC_FRMT_INTF: msg=MdcReadINTF(fi); break;
390 #endif
391 #if MDC_INCLUDE_ANLZ
392 case MDC_FRMT_ANLZ: msg=MdcReadANLZ(fi); break;
393 #endif
394 #if MDC_INCLUDE_DICM
395 case MDC_FRMT_DICM: msg=MdcReadDICM(fi); break;
396 #endif
397 #if MDC_INCLUDE_PNG
398 case MDC_FRMT_PNG: msg=MdcReadPNG(fi); break;
399 #endif
400 #if MDC_INCLUDE_CONC
401 case MDC_FRMT_CONC: msg=MdcLoadCONC(fi); break;
402 #endif
403 #if MDC_INCLUDE_NIFTI
404 case MDC_FRMT_NIFTI: msg=MdcReadNIFTI(fi); break;
405 #endif
406 default:
407 MdcPrntWarn("Loading: unsupported format");
408 return(MDC_BAD_FILE);
409 }
410
411 /* read error handling */
412 if (msg != NULL) {
413 MdcPrntWarn("Loading: %s",msg);
414 return(MDC_BAD_READ);
415 }
416
417 return(MDC_OK);
418 }
419
MdcSaveFile(FILEINFO * fi,int format,int prefixnr)420 int MdcSaveFile(FILEINFO *fi, int format, int prefixnr)
421 {
422 const char *msg=NULL;
423 Int8 INTERNAL_ENDIAN;
424
425 /* reset ID's rescaled stuff from any previous write */
426 MdcResetIDs(fi);
427
428 /* negative value = self made prefix */
429 if (prefixnr >= 0 ) MdcPrefix(prefixnr);
430
431 /* preserve internal file endian - global var issue */
432 INTERNAL_ENDIAN = MDC_FILE_ENDIAN;
433
434 switch (format) {
435 case MDC_FRMT_RAW : fi->rawconv = MDC_FRMT_RAW;
436 msg=MdcWriteRAW(fi);
437 break;
438 case MDC_FRMT_ASCII: fi->rawconv = MDC_FRMT_ASCII;
439 msg=MdcWriteRAW(fi);
440 break;
441 #if MDC_INCLUDE_ACR
442 case MDC_FRMT_ACR : msg=MdcWriteACR(fi); break;
443 #endif
444 #if MDC_INCLUDE_GIF
445 case MDC_FRMT_GIF : msg=MdcWriteGIF(fi); break;
446 #endif
447 #if MDC_INCLUDE_INW
448 case MDC_FRMT_INW : msg=MdcWriteINW(fi); break;
449 #endif
450 #if MDC_INCLUDE_ECAT
451 case MDC_FRMT_ECAT6: msg=MdcWriteECAT6(fi); break;
452 #if MDC_INCLUDE_TPC
453 case MDC_FRMT_ECAT7: msg=MdcWriteECAT7(fi); break;
454 #endif
455 #endif
456 #if MDC_INCLUDE_INTF
457 case MDC_FRMT_INTF : msg=MdcWriteINTF(fi); break;
458 #endif
459 #if MDC_INCLUDE_ANLZ
460 case MDC_FRMT_ANLZ : msg=MdcWriteANLZ(fi); break;
461 #endif
462 #if MDC_INCLUDE_DICM
463 case MDC_FRMT_DICM : msg=MdcWriteDICM(fi); break;
464 #endif
465 #if MDC_INCLUDE_PNG
466 case MDC_FRMT_PNG : msg=MdcWritePNG(fi); break;
467 #endif
468 #if MDC_INCLUDE_CONC
469 case MDC_FRMT_CONC : msg=MdcSaveCONC(fi); break;
470 #endif
471 #if MDC_INCLUDE_NIFTI
472 case MDC_FRMT_NIFTI: msg=MdcWriteNIFTI(fi); break;
473 #endif
474 default:
475 MdcPrntWarn("Writing: Unsupported format");
476 return(MDC_BAD_FILE);
477
478 }
479
480 /* restore internal file endian - global var issue */
481 MDC_FILE_ENDIAN = INTERNAL_ENDIAN;
482
483 MdcCloseFile(fi->ofp);
484
485 if (msg != NULL) {
486 MdcPrntWarn("Saving: %s",msg);
487 return(MDC_BAD_WRITE);
488 }
489
490 return(MDC_OK);
491 }
492
MdcLoadPlane(FILEINFO * fi,Uint32 img)493 int MdcLoadPlane(FILEINFO *fi, Uint32 img)
494 {
495 const char *msg=NULL;
496
497 /* sanity check */
498 if (img >= fi->number) {
499 MdcPrntWarn("Loading plane %d: non-existent",img);
500 return(MDC_BAD_CODE);
501 }
502
503 /* check the format */
504 if (fi->iformat == MDC_FRMT_NONE) {
505 MdcPrntWarn("Loading plane %d: unsupported format",img);
506 return(MDC_BAD_CODE);
507 }
508
509 /* check for loaded planes */
510 if (fi->image[img].buf != NULL) {
511 MdcPrntWarn("Loading plane %d: already loaded",img);
512 return(MDC_OK);
513 }
514
515 /* read appropriate format */
516 switch (fi->iformat) {
517 case MDC_FRMT_RAW: /* msg=MdcLoadPlaneRAW(fi, img); */ break;
518 #if MDC_INCLUDE_ACR
519 case MDC_FRMT_ACR: /* msg=MdcLoadPlaneACR(fi, img); */ break;
520 #endif
521 #if MDC_INCLUDE_GIF
522 case MDC_FRMT_GIF: /* msg=MdcLoadPlaneGIF(fi, img); */ break;
523 #endif
524 #if MDC_INCLUDE_INW
525 case MDC_FRMT_INW: /* msg=MdcLoadPlaneINW(fi, img); */ break;
526 #endif
527 #if MDC_INCLUDE_ECAT
528 case MDC_FRMT_ECAT6: /* msg=MdcLoadPlaneECAT6(fi, img); */ break;
529
530 case MDC_FRMT_ECAT7: /* msg=MdcLoadPlaneECAT7(fi, img); */ break;
531 #endif
532 #if MDC_INCLUDE_INTF
533 case MDC_FRMT_INTF: /* msg=MdcLoadPlaneINTF(fi, img); */ break;
534 #endif
535 #if MDC_INCLUDE_ANLZ
536 case MDC_FRMT_ANLZ: /* msg=MdcLoadPlaneANLZ(fi, img); */ break;
537 #endif
538 #if MDC_INCLUDE_DICM
539 case MDC_FRMT_DICM: /* msg=MdcLoadPlaneDICM(fi, img); */ break;
540 #endif
541 #if MDC_INCLUDE_PNG
542 case MDC_FRMT_PNG: /* msg=MdcLoadPlanePNG(fi, img); */ break;
543 #endif
544 #if MDC_INCLUDE_CONC
545 case MDC_FRMT_CONC: msg=MdcLoadPlaneCONC(fi, (signed)img); break;
546 #endif
547 #if MDC_INCLUDE_NIFTI
548 case MDC_FRMT_NIFTI: /* msg=MdcLoadPlaneNIFTI(fi, img); */ break;
549 #endif
550 default:
551 MdcPrntWarn("Loading plane %d: unsupported format",img);
552 return(MDC_BAD_FILE);
553 }
554
555 /* error handling */
556 if (msg != NULL) {
557 MdcPrntWarn("Loading plane %d: %s",img,msg);
558 return(MDC_BAD_READ);
559 }
560
561 return(MDC_OK);
562 }
563
MdcDecompressFile(const char * path)564 int MdcDecompressFile(const char *path)
565 {
566 char *ext;
567
568 if (MDC_PROGRESS) MdcProgress(MDC_PROGRESS_BEGIN,0.,"Decompress (Waiting)");
569
570 if (MDC_VERBOSE) MdcPrntMesg("Decompression ...");
571
572 /* get last extension (.gz or .Z) */
573 ext = strrchr(path,'.');
574 /* build system call, put paths between quotes */
575 /* in order to catch at least some weird filenames */
576 sprintf(mdcbufr,"%s -c \"%s\" > \"",MDC_DECOMPRESS,path);
577 /* remove extension from filename */
578 *ext = '\0';
579 /* add to pipe of system call */
580 strcat(mdcbufr,path); strcat(mdcbufr,"\"");
581
582 /* check if decompressed file already exists */
583 if (MdcKeepFile(path)) {
584 MdcPrntWarn("Decompressed filename exists!!");
585
586 if (MDC_PROGRESS) MdcProgress(MDC_PROGRESS_END,0.,NULL);
587
588 /* no overwrite, restore orig path */
589 *ext = '.';
590
591 return(MDC_BAD_CODE);
592 }
593
594 if (system(mdcbufr)) {
595
596 if (MDC_PROGRESS) MdcProgress(MDC_PROGRESS_END,0.,NULL);
597
598 unlink(path);
599
600 /* no gunzip? restore orig path */
601 *ext = '.';
602
603 return(MDC_BAD_CODE);
604 }
605
606 return(MDC_OK);
607
608 }
609
MdcStringCopy(char * s1,char * s2,Uint32 length)610 void MdcStringCopy(char *s1, char *s2, Uint32 length)
611 {
612 if ( length < MDC_MAXSTR) {
613 memcpy(s1,s2,length);
614 s1[length] = '\0';
615 }else{
616 memcpy(s1,s2,MDC_MAXSTR);
617 s1[MDC_MAXSTR-1] = '\0';
618 }
619 }
620
621
MdcFileSize(FILE * fp)622 int MdcFileSize(FILE *fp)
623 {
624 int size;
625
626 fseek(fp,0,SEEK_END);
627
628 size=ftell(fp);
629
630 fseek(fp,0,SEEK_SET);
631
632 return(size);
633
634 }
635
MdcFileExists(const char * fname)636 int MdcFileExists(const char *fname)
637 {
638
639 FILE *fp;
640
641 if ((fp=fopen(fname,"rb")) == NULL) return MDC_NO;
642
643 MdcCloseFile(fp);
644
645 return MDC_YES;
646
647 }
648
MdcKeepFile(const char * fname)649 int MdcKeepFile(const char *fname)
650 {
651 if (MDC_FILE_OVERWRITE == MDC_YES) return(MDC_NO);
652
653 return(MdcFileExists(fname));
654 }
655
MdcGetFrmt(FILEINFO * fi)656 int MdcGetFrmt(FILEINFO *fi)
657 {
658 int i, format=MDC_FRMT_NONE;
659
660 if (MDC_FILE_STDIN == MDC_YES && MDC_FRMT_INPUT != MDC_FRMT_NONE) {
661 fi->iformat = MDC_FRMT_INPUT; return(MDC_FRMT_INPUT);
662 }
663
664 if (MDC_INTERACTIVE) { fi->iformat = MDC_FRMT_RAW; return(MDC_FRMT_RAW); }
665
666 for (i=MDC_MAX_FRMTS-1;i>=3; i--) {
667
668 /* MARK: checks reversed; NIFTI must come before ANLZ */
669 /* otherwise MdcReadANLZ() would handle NIFTI files */
670
671 switch (i) {
672
673 #if MDC_INCLUDE_ACR
674 case MDC_FRMT_ACR: format = MdcCheckACR(fi); break;
675 #endif
676 #if MDC_INCLUDE_GIF
677 case MDC_FRMT_GIF: format = MdcCheckGIF(fi); break;
678 #endif
679 #if MDC_INCLUDE_INW
680 case MDC_FRMT_INW: format = MdcCheckINW(fi); break;
681 #endif
682 #if MDC_INCLUDE_INTF
683 case MDC_FRMT_INTF: format = MdcCheckINTF(fi); break;
684 #endif
685 #if MDC_INCLUDE_ANLZ
686 case MDC_FRMT_ANLZ: format = MdcCheckANLZ(fi); break;
687 #endif
688 #if MDC_INCLUDE_ECAT
689 case MDC_FRMT_ECAT6: format = MdcCheckECAT6(fi); break;
690
691 case MDC_FRMT_ECAT7: format = MdcCheckECAT7(fi); break;
692 #endif
693 #if MDC_INCLUDE_DICM
694 case MDC_FRMT_DICM: format = MdcCheckDICM(fi); break;
695 #endif
696 #if MDC_INCLUDE_PNG
697 case MDC_FRMT_PNG: format = MdcCheckPNG(fi); break;
698 #endif
699 #if MDC_INCLUDE_CONC
700 case MDC_FRMT_CONC: format = MdcCheckCONC(fi); break;
701 #endif
702 #if MDC_INCLUDE_NIFTI
703 case MDC_FRMT_NIFTI: format = MdcCheckNIFTI(fi); break;
704 #endif
705 }
706
707 fseek(fi->ifp,0,SEEK_SET);
708
709 if ( format != MDC_FRMT_NONE ) break;
710
711 }
712
713 if (format == MDC_FRMT_NONE) {
714 if (MDC_FALLBACK_FRMT != MDC_FRMT_NONE) {
715 MdcPrntWarn("Image format unknown - trying fallback format");
716 format = MDC_FALLBACK_FRMT;
717 }
718 }
719
720 fi->iformat = format;
721
722 return(format);
723
724 }
725
726
MdcGetImgBuffer(Uint32 bytes)727 Uint8 *MdcGetImgBuffer(Uint32 bytes)
728 {
729 return((Uint8 *)calloc(1,bytes));
730 }
731
MdcHandleTruncated(FILEINFO * fi,Uint32 images,int remap)732 char *MdcHandleTruncated(FILEINFO *fi, Uint32 images, int remap)
733 {
734 Uint32 i;
735
736 if (images == 0) images = 1;
737 if ((remap == MDC_YES) && (images < fi->number)) {
738 if (!MdcGetStructID(fi,images)) {
739 return("Couldn't realloc truncated IMG_DATA structs");
740 }
741 }
742
743 fi->truncated = MDC_YES;
744 fi->dim[0] = 3;
745 fi->dim[3] = fi->number;
746 for (i=4; i<MDC_MAX_DIMS; i++) fi->dim[i] = 0;
747
748 return NULL;
749 }
750
751 /* put whole line but MdcSWAP if necessary */
752 /* on success 1 on error 0 */
MdcWriteLine(IMG_DATA * id,Uint8 * buf,int type,FILE * fp)753 int MdcWriteLine(IMG_DATA *id, Uint8 *buf, int type, FILE *fp)
754 {
755 Uint32 i, bytes = MdcType2Bytes(type);
756 Uint8 *pbuf;
757
758 if (bytes == 1) {
759
760 fwrite(buf,id->width,bytes,fp); /* no MdcSWAP necessary */
761
762 }else for (i=0; i<id->width; i++) {
763
764 pbuf = buf + (i * bytes);
765
766 switch (type) {
767 case BIT16_S:
768 {
769 Int16 pix;
770
771 memcpy(&pix,pbuf,bytes); MdcSWAP(pix);
772 fwrite((char *)&pix,1,bytes,fp);
773 }
774 break;
775 case BIT16_U:
776 {
777 Uint16 pix;
778
779 memcpy(&pix,pbuf,bytes); MdcSWAP(pix);
780 fwrite((char *)&pix,1,bytes,fp);
781 }
782 break;
783 case BIT32_S:
784 {
785 Int32 pix;
786
787 memcpy(&pix,pbuf,bytes); MdcSWAP(pix);
788 fwrite((char *)&pix,1,bytes,fp);
789 }
790 break;
791 case BIT32_U:
792 {
793 Uint32 pix;
794
795 memcpy(&pix,pbuf,bytes); MdcSWAP(pix);
796 fwrite((char *)&pix,1,bytes,fp);
797 }
798 break;
799 case BIT64_S:
800 {
801 Int64 pix;
802
803 memcpy(&pix,pbuf,bytes); MdcSWAP(pix);
804 fwrite((char *)&pix,1,bytes,fp);
805 }
806 break;
807 case BIT64_U:
808 {
809 Uint64 pix;
810
811 memcpy(&pix,pbuf,bytes); MdcSWAP(pix);
812 fwrite((char *)&pix,1,bytes,fp);
813 }
814 break;
815 case FLT32:
816 {
817 float pix;
818
819 memcpy(&pix,pbuf,bytes); MdcSWAP(pix);
820 fwrite((char *)&pix,1,bytes,fp);
821 }
822 break;
823 case FLT64:
824 {
825 double pix;
826
827 memcpy(&pix,pbuf,bytes); MdcSWAP(pix);
828 fwrite((char *)&pix,1,bytes,fp);
829 }
830 break;
831 case VAXFL32:
832 {
833 float flt;
834
835 memcpy(&flt,pbuf,bytes);
836 MdcMakeVAXfl(flt);
837 fwrite((char *)&flt,1,bytes,fp);
838
839 }
840 break;
841
842 }
843 }
844
845 if (ferror(fp)) return MDC_NO;
846
847 return MDC_YES;
848
849 }
850
851 /* Put pixel but MdcSWAP if necessary */
852 /* on success 1 on error 0 */
MdcWriteDoublePixel(double pix,int type,FILE * fp)853 int MdcWriteDoublePixel(double pix, int type, FILE *fp)
854 {
855 unsigned int bytes = (unsigned)MdcType2Bytes(type);
856
857 switch (type) {
858 case BIT8_S:
859 {
860 Int8 c = (Int8)pix;
861 fwrite((char *)&c,1,bytes,fp);
862 }
863 break;
864 case BIT8_U:
865 {
866 Uint8 c = (Uint8)pix;
867 fwrite((char *)&c,1,bytes,fp);
868 }
869 break;
870 case BIT16_S:
871 {
872 Int16 c = (Int16)pix;
873 MdcSWAP(c); fwrite((char *)&c,1,bytes,fp);
874 }
875 break;
876 case BIT16_U:
877 {
878 Uint16 c = (Uint16)pix;
879 MdcSWAP(c); fwrite((char *)&c,1,bytes,fp);
880 }
881 break;
882 case BIT32_S:
883 {
884 Int32 c = (Int32)pix;
885 MdcSWAP(c); fwrite((char *)&c,1,bytes,fp);
886 }
887 break;
888 case BIT32_U:
889 {
890 Uint32 c = (Uint32)pix;
891 MdcSWAP(c); fwrite((char *)&c,1,bytes,fp);
892 }
893 break;
894 case BIT64_S:
895 {
896 Int64 c = (Int64)pix;
897 MdcSWAP(c); fwrite((char *)&c,1,bytes,fp);
898 }
899 break;
900 case BIT64_U:
901 {
902 Uint64 c = (Uint64)pix;
903 MdcSWAP(c); fwrite((char *)&c,1,bytes,fp);
904 }
905 break;
906 case FLT32:
907 {
908 float c = (float)pix;
909 MdcSWAP(c); fwrite((char *)&c,1,bytes,fp);
910 }
911 break;
912 case VAXFL32:
913 {
914 float flt = (float)pix;
915
916 MdcMakeVAXfl(flt);
917 fwrite((char *)&flt,1,bytes,fp);
918
919 }
920 break;
921 case FLT64:
922 {
923 double c = (double)pix;
924 MdcSWAP(c); fwrite((char *)&c,1,bytes,fp);
925 }
926 break;
927 }
928
929 if (ferror(fp)) return MDC_NO;
930
931 return MDC_YES;
932
933 }
934
MdcGetFname(char path[])935 char *MdcGetFname(char path[])
936 {
937 char *p;
938
939 p = MdcGetLastPathDelim(path);
940
941 if ( p == NULL ) return(path);
942
943 return(p+1);
944 }
945
MdcSetExt(char path[],char * ext)946 void MdcSetExt(char path[], char *ext)
947 {
948 char *p;
949
950 if (path == NULL) return;
951
952 if (ext == NULL) return;
953
954 p=(char *)strrchr(path,'.');
955
956 if ( p != NULL ) *p = '\0';
957
958 strcat(path,".");
959 strcat(path,ext);
960 }
961
MdcNewExt(char dest[],char * src,char * ext)962 void MdcNewExt(char dest[], char *src, char *ext)
963 {
964 char *p, *s;
965
966 if (mdcbasename != NULL) {
967 /* forced output name/path */
968 s = MdcGetLastPathDelim(mdcbasename);
969 p = strrchr(mdcbasename,'.');
970 if (s != NULL) {
971 /* full pathname */
972 strncpy(dest,mdcbasename,MDC_MAX_PATH); dest[MDC_MAX_PATH-5]='\0';
973 if ((p != NULL) && (p < s)) {
974 /* prevent "(.)./filename" without . for extension */
975 strcat(dest,".ext");
976 }
977 }else{
978 /* single basename */
979 strncpy(dest,mdcbasename,MDC_MAX_PATH);
980 }
981 }else{
982 /* default output name */
983 if ((src != NULL) && (src[0] != '\0')) strcat(dest,src);
984 }
985
986 MdcSetExt(dest,ext);
987 }
988
989 /* create a prefix of the form: 000 ... ... 999,A00................ZZZ
990 <- normal -> | <----- extra ----->
991 (1000) (33696)
992
993 normal prefixes =
994 integers from 000 to 999 (1000)
995
996 extra prefixes = +
997 1st char: A...Z (26)
998 2nd char: 0...9,A...Z (36)
999 3rd char: 0...9,A...Z (36)
1000
1001 This construct gives at first numeric prefixes, extended with
1002 a lot more alphanumeric prefixes before overlap. A directory
1003 listing will thus show the filenames in sequence of creation. */
1004
MdcPrefix(int n)1005 void MdcPrefix(int n)
1006 {
1007 int t, c1, c2, c3, v1, v2, v3;
1008 int A='A', Zero='0'; /* ascii values for A and Zero */
1009 char cprefix[6];
1010
1011 if (MDC_PREFIX_DISABLED == MDC_YES) {
1012 strcpy(prefix,""); return;
1013 }
1014
1015 if (n < 1000) {
1016 sprintf(cprefix,"m%03d-",n);
1017 }else{
1018 t = n - 1000;
1019 v1 = t / 1296;
1020 v2 = (t % 1296) / 36;
1021 v3 = (t % 1296) % 36;
1022
1023
1024 if (n >= 34696) {
1025 MdcPrntWarn("%d-th conversion creates overlapping filenames", n);
1026 if (MDC_FILE_OVERWRITE == MDC_NO) return;
1027 }
1028
1029 /* first char */
1030 c1 = A + v1; /* A...Z */
1031 /* second char */
1032 if (v2 < 10) c2 = Zero + v2; /* 0...9 */
1033 else c2 = A + v2 - 10; /* A...Z */
1034 /* third char */
1035 if (v3 < 10) c3 = Zero + v3; /* 0...9 */
1036 else c3 = A + v3 - 10; /* A...Z */
1037
1038 sprintf(cprefix,"m%c%c%c-",(char)c1,(char)c2,(char)c3);
1039 }
1040
1041 if (MDC_FILE_SPLIT != MDC_NO) {
1042 /* special naming for splitted files */
1043 switch (MDC_FILE_SPLIT) {
1044 case MDC_SPLIT_PER_FRAME:
1045 sprintf(prefix,"%sf%04u-",cprefix,MdcGetNrSplit() + 1);
1046 break;
1047 case MDC_SPLIT_PER_SLICE:
1048 sprintf(prefix,"%ss%04d-",cprefix,MdcGetNrSplit() + 1);
1049 break;
1050 }
1051 }else if (MDC_FILE_STACK != MDC_NO) {
1052 /* special naming for stacked files */
1053 switch (MDC_FILE_STACK) {
1054 case MDC_STACK_SLICES:
1055 sprintf(prefix,"%sstacks-",cprefix);
1056 break;
1057 case MDC_STACK_FRAMES:
1058 sprintf(prefix,"%sstackf-",cprefix);
1059 break;
1060 }
1061 }else{
1062 /* default naming */
1063 strcpy(prefix,cprefix);
1064 }
1065 }
1066
MdcGetPrefixNr(FILEINFO * fi,int nummer)1067 int MdcGetPrefixNr(FILEINFO *fi, int nummer)
1068 {
1069 int prefixnr;
1070
1071 prefixnr = MDC_PREFIX_ACQ == MDC_YES ? fi->nr_acquisition :
1072 (MDC_PREFIX_SER == MDC_YES ? fi->nr_series : nummer) ;
1073
1074 return(prefixnr);
1075 }
1076
MdcNewName(char dest[],char * src,char * ext)1077 void MdcNewName(char dest[], char *src, char *ext)
1078 {
1079 strcpy(dest,prefix);
1080 MdcNewExt( dest, src, ext);
1081 }
1082
MdcAliasName(FILEINFO * fi,char alias[])1083 char *MdcAliasName(FILEINFO *fi, char alias[])
1084 {
1085 char unknown[]="unknown";
1086 char *c, *patient, *patient_id, *study;
1087 Int16 year, month, day;
1088 Int16 hour, minute, second;
1089 Int32 series, acquisition, instance;
1090
1091 patient = strlen(fi->patient_name) ? fi->patient_name : unknown;
1092 patient_id = strlen(fi->patient_id) ? fi->patient_id : unknown;
1093 study = strlen(fi->study_id) ? fi->study_id : unknown;
1094
1095 year = fi->study_date_year;
1096 month = fi->study_date_month;
1097 day = fi->study_date_day;
1098 hour = fi->study_time_hour;
1099 minute= fi->study_time_minute;
1100 second= fi->study_time_second;
1101
1102 switch (fi->iformat) {
1103 case MDC_FRMT_ACR:
1104 case MDC_FRMT_DICM: /* UID's */
1105 series = (fi->nr_series > 0) ? fi->nr_series : 0;
1106 acquisition = (fi->nr_acquisition > 0) ? fi->nr_acquisition : 0;
1107 instance = (fi->nr_instance > 0) ? fi->nr_instance : 0;
1108
1109 sprintf(alias,"%s+%s+%hd%02hd%02hd+%02hd%02hd%02hd+%010d+%010d+%010d.ext"
1110 ,patient,study
1111 ,year,month,day
1112 ,hour,minute,second
1113 ,series,acquisition,instance);
1114 break;
1115 case MDC_FRMT_ANLZ: /* patient_id */
1116 sprintf(alias,"%s+%s+%hd%02hd%02hd+%02hd%02hd%02hd.ext"
1117 ,patient_id,study
1118 ,year,month,day
1119 ,hour,minute,second);
1120
1121 break;
1122 default:
1123 sprintf(alias,"%s+%s+%hd%02hd%02hd+%02hd%02hd%02hd.ext"
1124 ,patient,study
1125 ,year,month,day
1126 ,hour,minute,second);
1127 }
1128
1129 /* change to lower and replace spaces */
1130 c=alias; while (*c) { *c=tolower((int)*c); if (isspace((int)*c)) *c='_'; c++;}
1131
1132 return(alias);
1133
1134 }
1135
1136 /* make alias in opath, splitted ipath assumed */
MdcEchoAliasName(FILEINFO * fi)1137 void MdcEchoAliasName(FILEINFO *fi)
1138 {
1139 MDC_ALIAS_NAME = MDC_YES; prefix[0]='\0';
1140
1141 MdcDefaultName(fi,fi->iformat,fi->opath,fi->ifname);
1142
1143 fprintf(stdout,"%s\n",fi->opath);
1144 }
1145
MdcDefaultName(FILEINFO * fi,int format,char dest[],char * src)1146 void MdcDefaultName(FILEINFO *fi, int format, char dest[], char *src)
1147 {
1148 char alias[MDC_MAX_PATH];
1149
1150 if (MDC_ALIAS_NAME == MDC_YES) src = MdcAliasName(fi,alias);
1151
1152 switch (format) {
1153 case MDC_FRMT_RAW : MdcNewName(dest,src,FrmtExt[MDC_FRMT_RAW]); break;
1154 case MDC_FRMT_ASCII: MdcNewName(dest,src,FrmtExt[MDC_FRMT_ASCII]); break;
1155 #if MDC_INCLUDE_ACR
1156 case MDC_FRMT_ACR : MdcNewName(dest,src,FrmtExt[MDC_FRMT_ACR]); break;
1157 #endif
1158 #if MDC_INCLUDE_GIF
1159 case MDC_FRMT_GIF : MdcNewName(dest,src,FrmtExt[MDC_FRMT_GIF]); break;
1160 #endif
1161 #if MDC_INCLUDE_INW
1162 case MDC_FRMT_INW : MdcNewName(dest,src,FrmtExt[MDC_FRMT_INW]); break;
1163 #endif
1164 #if MDC_INCLUDE_ECAT
1165 case MDC_FRMT_ECAT6: MdcNewName(dest,src,FrmtExt[MDC_FRMT_ECAT6]); break;
1166 #if MDC_INCLUDE_TPC
1167 case MDC_FRMT_ECAT7: MdcNewName(dest,src,FrmtExt[MDC_FRMT_ECAT7]); break;
1168 #endif
1169 #endif
1170 #if MDC_INCLUDE_INTF
1171 case MDC_FRMT_INTF : MdcNewName(dest,src,FrmtExt[MDC_FRMT_INTF]); break;
1172 #endif
1173 #if MDC_INCLUDE_ANLZ
1174 case MDC_FRMT_ANLZ : MdcNewName(dest,src,FrmtExt[MDC_FRMT_ANLZ]); break;
1175 #endif
1176 #if MDC_INCLUDE_DICM
1177 case MDC_FRMT_DICM : MdcNewName(dest,src,FrmtExt[MDC_FRMT_DICM]); break;
1178 #endif
1179 #if MDC_INCLUDE_PNG
1180 case MDC_FRMT_PNG : MdcNewName(dest,src,FrmtExt[MDC_FRMT_PNG]); break;
1181 #endif
1182 #if MDC_INCLUDE_CONC
1183 case MDC_FRMT_CONC : MdcNewName(dest,src,FrmtExt[MDC_FRMT_CONC]); break;
1184 #endif
1185 #if MDC_INCLUDE_NIFTI
1186 case MDC_FRMT_NIFTI: MdcNewName(dest,src,FrmtExt[MDC_FRMT_NIFTI]); break;
1187 #endif
1188 default : MdcNewName(dest,src,FrmtExt[MDC_FRMT_NONE]); break;
1189 }
1190
1191 }
1192
MdcRenameFile(char * name)1193 void MdcRenameFile(char *name)
1194 {
1195 char *pbegin = NULL, *pend = NULL;
1196
1197 MdcPrintLine('-',MDC_FULL_LENGTH);
1198 MdcPrntScrn("\tRENAME FILE\n");
1199 MdcPrintLine('-',MDC_FULL_LENGTH);
1200
1201 pbegin = MdcGetLastPathDelim(name); /* point to basename */
1202
1203 if (pbegin == NULL) pbegin = name;
1204 else pbegin = pbegin + 1;
1205
1206 strcpy(mdcbufr,pbegin);
1207 pend = (char *)strrchr(mdcbufr,'.'); /* without extension */
1208 if (pend != NULL) pend[0] = '\0';
1209
1210 MdcPrntScrn("\n\tOld Filename: %s\n",mdcbufr);
1211 MdcPrntScrn("\n\tNew Filename: ");
1212 MdcGetStrLine(mdcbufr,MDC_MAX_PATH-1,stdin);
1213 mdcbufr[MDC_MAX_PATH]='\0';
1214 MdcRemoveEnter(mdcbufr);
1215 strcpy(name,mdcbufr);
1216
1217 MdcPrintLine('-',MDC_FULL_LENGTH);
1218
1219 }
1220
1221 /* always check for both path delimiters */
MdcGetLastPathDelim(char * path)1222 char *MdcGetLastPathDelim(char *path)
1223 {
1224 char *p=NULL;
1225
1226 if (path == NULL) return NULL;
1227
1228 p = (char *)strrchr(path,'/');
1229 if (p != NULL) return(p);
1230
1231 p = (char *)strrchr(path,'\\');
1232 return(p);
1233
1234 }
1235
1236
MdcMySplitPath(char path[],char ** dir,char ** fname)1237 void MdcMySplitPath(char path[], char **dir, char **fname)
1238 {
1239 char *p=NULL;
1240
1241 p = MdcGetLastPathDelim(path); /* last path delim becomes '\0' */
1242
1243 if ( p == NULL ) {
1244 *fname=&path[0];
1245 *dir=NULL;
1246 } else {
1247 *p='\0';
1248 *dir=&path[0];
1249 *fname=p+1;
1250 }
1251
1252 }
1253
MdcMyMergePath(char path[],char * dir,char ** fname)1254 void MdcMyMergePath(char path[], char *dir, char **fname)
1255 /* first '\0' becomes path delim again */
1256 {
1257 char *p;
1258
1259 if ( dir != NULL ) {
1260 p=(char *)strchr(path,'\0');
1261 if ( p != NULL ) *p=MDC_PATH_DELIM_CHR;
1262 }
1263
1264 *fname = &path[0];
1265
1266 }
1267
MdcFillImgPos(FILEINFO * fi,Uint32 nr,Uint32 plane,float translation)1268 void MdcFillImgPos(FILEINFO *fi, Uint32 nr, Uint32 plane, float translation)
1269 {
1270 IMG_DATA *id = &fi->image[nr];
1271
1272 /* according to device coordinates */
1273
1274 switch (fi->pat_slice_orient) {
1275
1276 case MDC_SUPINE_HEADFIRST_TRANSAXIAL:
1277 case MDC_PRONE_HEADFIRST_TRANSAXIAL :
1278 case MDC_DECUBITUS_RIGHT_HEADFIRST_TRANSAXIAL:
1279 case MDC_DECUBITUS_LEFT_HEADFIRST_TRANSAXIAL :
1280 case MDC_SUPINE_FEETFIRST_TRANSAXIAL:
1281 case MDC_PRONE_FEETFIRST_TRANSAXIAL :
1282 case MDC_DECUBITUS_RIGHT_FEETFIRST_TRANSAXIAL:
1283 case MDC_DECUBITUS_LEFT_FEETFIRST_TRANSAXIAL :
1284 id->image_pos_dev[0]=-(id->pixel_xsize*(float)id->width);
1285 id->image_pos_dev[1]=-(id->pixel_ysize*(float)id->height);
1286 id->image_pos_dev[2]=-((id->slice_spacing*(float)(plane+1))+translation);
1287 break;
1288 case MDC_SUPINE_HEADFIRST_SAGITTAL :
1289 case MDC_PRONE_HEADFIRST_SAGITTAL :
1290 case MDC_DECUBITUS_RIGHT_HEADFIRST_SAGITTAL:
1291 case MDC_DECUBITUS_LEFT_HEADFIRST_SAGITTAL :
1292 case MDC_SUPINE_FEETFIRST_SAGITTAL :
1293 case MDC_PRONE_FEETFIRST_SAGITTAL :
1294 case MDC_DECUBITUS_RIGHT_FEETFIRST_SAGITTAL:
1295 case MDC_DECUBITUS_LEFT_FEETFIRST_SAGITTAL :
1296 id->image_pos_dev[0]=-((id->slice_spacing*(float)(plane+1))+translation);
1297 id->image_pos_dev[1]=-(id->pixel_xsize*(float)id->width);
1298 id->image_pos_dev[2]=-(id->pixel_ysize*(float)id->height);
1299 break;
1300 case MDC_SUPINE_HEADFIRST_CORONAL :
1301 case MDC_PRONE_HEADFIRST_CORONAL :
1302 case MDC_DECUBITUS_RIGHT_HEADFIRST_CORONAL:
1303 case MDC_DECUBITUS_LEFT_HEADFIRST_CORONAL :
1304 case MDC_SUPINE_FEETFIRST_CORONAL :
1305 case MDC_PRONE_FEETFIRST_CORONAL :
1306 case MDC_DECUBITUS_RIGHT_FEETFIRST_CORONAL:
1307 case MDC_DECUBITUS_LEFT_FEETFIRST_CORONAL :
1308 id->image_pos_dev[0]=-(id->pixel_xsize*(float)id->width);
1309 id->image_pos_dev[1]=-((id->slice_spacing*(float)(plane+1))+translation);
1310 id->image_pos_dev[2]=-(id->pixel_ysize*(float)id->height);
1311 break;
1312 default : { } /* do nothing */
1313
1314 }
1315
1316 /* according to the patient coordinate system */
1317
1318 switch (fi->pat_slice_orient) {
1319 case MDC_SUPINE_HEADFIRST_TRANSAXIAL:
1320 id->image_pos_pat[0]=-(id->pixel_xsize*(float)id->width);
1321 id->image_pos_pat[1]=-(id->pixel_ysize*(float)id->height);
1322 id->image_pos_pat[2]=-((id->slice_spacing*(float)(plane+1))+translation);
1323 break;
1324 case MDC_SUPINE_HEADFIRST_SAGITTAL :
1325 id->image_pos_pat[0]=-((id->slice_spacing*(float)(plane+1))+translation);
1326 id->image_pos_pat[1]=-(id->pixel_xsize*(float)id->width);
1327 id->image_pos_pat[2]=-(id->pixel_ysize*(float)id->height);
1328 break;
1329 case MDC_SUPINE_HEADFIRST_CORONAL :
1330 id->image_pos_pat[0]=-(id->pixel_xsize*(float)id->width);
1331 id->image_pos_pat[1]=-((id->slice_spacing*(float)(plane+1))+translation);
1332 id->image_pos_pat[2]=-(id->pixel_ysize*(float)id->height);
1333 break;
1334 case MDC_SUPINE_FEETFIRST_TRANSAXIAL:
1335 id->image_pos_pat[0]=+(id->pixel_xsize*(float)id->width);
1336 id->image_pos_pat[1]=-(id->pixel_ysize*(float)id->height);
1337 id->image_pos_pat[2]=+((id->slice_spacing*(float)(plane+1))+translation);
1338 break;
1339 case MDC_SUPINE_FEETFIRST_SAGITTAL :
1340 id->image_pos_pat[0]=+((id->slice_spacing*(float)(plane+1))+translation);
1341 id->image_pos_pat[1]=-(id->pixel_xsize*(float)id->width);
1342 id->image_pos_pat[2]=+(id->pixel_ysize*(float)id->height);
1343 break;
1344 case MDC_SUPINE_FEETFIRST_CORONAL :
1345 id->image_pos_pat[0]=+(id->pixel_xsize*(float)id->width);
1346 id->image_pos_pat[1]=-((id->slice_spacing*(float)(plane+1))+translation);
1347 id->image_pos_pat[2]=+(id->pixel_ysize*(float)id->height);
1348 break;
1349 case MDC_PRONE_HEADFIRST_TRANSAXIAL :
1350 id->image_pos_pat[0]=+(id->pixel_xsize*(float)id->width);
1351 id->image_pos_pat[1]=+(id->pixel_ysize*(float)id->height);
1352 id->image_pos_pat[2]=-((id->slice_spacing*(float)(plane+1))+translation);
1353 break;
1354 case MDC_PRONE_HEADFIRST_SAGITTAL :
1355 id->image_pos_pat[0]=+((id->slice_spacing*(float)(plane+1))+translation);
1356 id->image_pos_pat[1]=+(id->pixel_xsize*(float)id->width);
1357 id->image_pos_pat[2]=-(id->pixel_ysize*(float)id->height);
1358 break;
1359 case MDC_PRONE_HEADFIRST_CORONAL :
1360 id->image_pos_pat[0]=+(id->pixel_xsize*(float)id->width);
1361 id->image_pos_pat[1]=+((id->slice_spacing*(float)(plane+1))+translation);
1362 id->image_pos_pat[2]=-(id->pixel_ysize*(float)id->height);
1363 break;
1364 case MDC_PRONE_FEETFIRST_TRANSAXIAL :
1365 id->image_pos_pat[0]=-(id->pixel_xsize*(float)id->width);
1366 id->image_pos_pat[1]=+(id->pixel_ysize*(float)id->height);
1367 id->image_pos_pat[2]=+((id->slice_spacing*(float)(plane+1))+translation);
1368 break;
1369 case MDC_PRONE_FEETFIRST_SAGITTAL :
1370 id->image_pos_pat[0]=-((id->slice_spacing*(float)(plane+1))+translation);
1371 id->image_pos_pat[1]=+(id->pixel_xsize*(float)id->width);
1372 id->image_pos_pat[2]=+(id->pixel_ysize*(float)id->height);
1373 break;
1374 case MDC_PRONE_FEETFIRST_CORONAL :
1375 id->image_pos_pat[0]=-(id->pixel_xsize*(float)id->width);
1376 id->image_pos_pat[1]=+((id->slice_spacing*(float)(plane+1))+translation);
1377 id->image_pos_pat[2]=+(id->pixel_ysize*(float)id->height);
1378 break;
1379 case MDC_DECUBITUS_RIGHT_HEADFIRST_TRANSAXIAL:
1380 id->image_pos_pat[0]=+(id->pixel_ysize*(float)id->height);
1381 id->image_pos_pat[1]=-(id->pixel_xsize*(float)id->width);
1382 id->image_pos_pat[2]=-((id->slice_spacing*(float)(plane+1))+translation);
1383 break;
1384 case MDC_DECUBITUS_RIGHT_HEADFIRST_SAGITTAL:
1385 id->image_pos_pat[0]=-(id->pixel_xsize*(float)id->width);
1386 id->image_pos_pat[1]=-((id->slice_spacing*(float)(plane+1))+translation);
1387 id->image_pos_pat[2]=-(id->pixel_ysize*(float)id->height);
1388 break;
1389 case MDC_DECUBITUS_RIGHT_HEADFIRST_CORONAL:
1390 id->image_pos_pat[0]=+((id->slice_spacing*(float)(plane+1))+translation);
1391 id->image_pos_pat[1]=-(id->pixel_xsize*(float)id->width);
1392 id->image_pos_pat[2]=-(id->pixel_ysize*(float)id->height);
1393 break;
1394 case MDC_DECUBITUS_RIGHT_FEETFIRST_TRANSAXIAL:
1395 id->image_pos_pat[0]=+(id->pixel_ysize*(float)id->height);
1396 id->image_pos_pat[1]=+(id->pixel_xsize*(float)id->width);
1397 id->image_pos_pat[2]=+((id->slice_spacing*(float)(plane+1))+translation);
1398 break;
1399 case MDC_DECUBITUS_RIGHT_FEETFIRST_SAGITTAL:
1400 id->image_pos_pat[0]=+(id->pixel_xsize*(float)id->width);
1401 id->image_pos_pat[1]=+((id->slice_spacing*(float)(plane+1))+translation);
1402 id->image_pos_pat[2]=+(id->pixel_ysize*(float)id->height);
1403 break;
1404 case MDC_DECUBITUS_RIGHT_FEETFIRST_CORONAL:
1405 id->image_pos_pat[0]=+((id->slice_spacing*(float)(plane+1))+translation);
1406 id->image_pos_pat[1]=+(id->pixel_xsize*(float)id->width);
1407 id->image_pos_pat[2]=+(id->pixel_ysize*(float)id->height);
1408 break;
1409 case MDC_DECUBITUS_LEFT_HEADFIRST_TRANSAXIAL :
1410 id->image_pos_pat[0]=-(id->pixel_ysize*(float)id->height);
1411 id->image_pos_pat[1]=+(id->pixel_xsize*(float)id->width);
1412 id->image_pos_pat[2]=-((id->slice_spacing*(float)(plane+1))+translation);
1413 break;
1414 case MDC_DECUBITUS_LEFT_HEADFIRST_SAGITTAL :
1415 id->image_pos_pat[0]=-(id->pixel_xsize*(float)id->width);
1416 id->image_pos_pat[1]=+((id->slice_spacing*(float)(plane+1))+translation);
1417 id->image_pos_pat[2]=-(id->pixel_ysize*(float)id->height);
1418 break;
1419 case MDC_DECUBITUS_LEFT_HEADFIRST_CORONAL :
1420 id->image_pos_pat[0]=-((id->slice_spacing*(float)(plane+1))+translation);
1421 id->image_pos_pat[1]=+(id->pixel_xsize*(float)id->width);
1422 id->image_pos_pat[2]=-(id->pixel_ysize*(float)id->height);
1423 break;
1424 case MDC_DECUBITUS_LEFT_FEETFIRST_TRANSAXIAL :
1425 id->image_pos_pat[0]=-(id->pixel_ysize*(float)id->height);
1426 id->image_pos_pat[1]=-(id->pixel_xsize*(float)id->width);
1427 id->image_pos_pat[2]=+((id->slice_spacing*(float)(plane+1))+translation);
1428 break;
1429 case MDC_DECUBITUS_LEFT_FEETFIRST_SAGITTAL :
1430 id->image_pos_pat[0]=+(id->pixel_xsize*(float)id->width);
1431 id->image_pos_pat[0]=-((id->slice_spacing*(float)(plane+1))+translation);
1432 id->image_pos_pat[2]=+(id->pixel_ysize*(float)id->height);
1433 break;
1434 case MDC_DECUBITUS_LEFT_FEETFIRST_CORONAL :
1435 id->image_pos_pat[0]=-((id->slice_spacing*(float)(plane+1))+translation);
1436 id->image_pos_pat[1]=-(id->pixel_xsize*(float)id->width);
1437 id->image_pos_pat[2]=+(id->pixel_ysize*(float)id->height);
1438 break;
1439 default : { } /* do nothing */
1440 }
1441 }
1442
MdcFillImgOrient(FILEINFO * fi,Uint32 nr)1443 void MdcFillImgOrient(FILEINFO *fi, Uint32 nr)
1444 {
1445 IMG_DATA *id = &fi->image[nr];
1446
1447 /* according to device coordinate system */
1448
1449 switch (fi->pat_slice_orient) {
1450 case MDC_SUPINE_HEADFIRST_TRANSAXIAL:
1451 case MDC_PRONE_HEADFIRST_TRANSAXIAL :
1452 case MDC_DECUBITUS_RIGHT_HEADFIRST_TRANSAXIAL:
1453 case MDC_DECUBITUS_LEFT_HEADFIRST_TRANSAXIAL :
1454 case MDC_SUPINE_FEETFIRST_TRANSAXIAL:
1455 case MDC_PRONE_FEETFIRST_TRANSAXIAL :
1456 case MDC_DECUBITUS_RIGHT_FEETFIRST_TRANSAXIAL:
1457 case MDC_DECUBITUS_LEFT_FEETFIRST_TRANSAXIAL :
1458 id->image_orient_dev[0]=+1.0; id->image_orient_dev[3]=+0.0;
1459 id->image_orient_dev[1]=-0.0; id->image_orient_dev[4]=+1.0;
1460 id->image_orient_dev[2]=+0.0; id->image_orient_dev[5]=-0.0;
1461 break;
1462
1463 case MDC_SUPINE_HEADFIRST_SAGITTAL :
1464 case MDC_PRONE_HEADFIRST_SAGITTAL :
1465 case MDC_DECUBITUS_RIGHT_HEADFIRST_SAGITTAL:
1466 case MDC_DECUBITUS_LEFT_HEADFIRST_SAGITTAL :
1467 case MDC_SUPINE_FEETFIRST_SAGITTAL :
1468 case MDC_PRONE_FEETFIRST_SAGITTAL :
1469 case MDC_DECUBITUS_RIGHT_FEETFIRST_SAGITTAL:
1470 case MDC_DECUBITUS_LEFT_FEETFIRST_SAGITTAL :
1471 id->image_orient_dev[0]=+0.0; id->image_orient_dev[3]=+0.0;
1472 id->image_orient_dev[1]=+1.0; id->image_orient_dev[4]=-0.0;
1473 id->image_orient_dev[2]=-0.0; id->image_orient_dev[5]=-1.0;
1474 break;
1475
1476 case MDC_SUPINE_HEADFIRST_CORONAL :
1477 case MDC_PRONE_HEADFIRST_CORONAL :
1478 case MDC_DECUBITUS_RIGHT_HEADFIRST_CORONAL:
1479 case MDC_DECUBITUS_LEFT_HEADFIRST_CORONAL :
1480 case MDC_SUPINE_FEETFIRST_CORONAL :
1481 case MDC_PRONE_FEETFIRST_CORONAL :
1482 case MDC_DECUBITUS_RIGHT_FEETFIRST_CORONAL:
1483 case MDC_DECUBITUS_LEFT_FEETFIRST_CORONAL :
1484 id->image_orient_dev[0]=+1.0; id->image_orient_dev[3]=+0.0;
1485 id->image_orient_dev[1]=-0.0; id->image_orient_dev[4]=-0.0;
1486 id->image_orient_dev[2]=+0.0; id->image_orient_dev[5]=-1.0;
1487 break;
1488
1489 default : { }
1490 }
1491
1492 /* according to patient coordinate system */
1493
1494 switch (fi->pat_slice_orient) {
1495
1496 case MDC_SUPINE_HEADFIRST_TRANSAXIAL:
1497 id->image_orient_pat[0]=+1.0; id->image_orient_pat[3]=+0.0;
1498 id->image_orient_pat[1]=-0.0; id->image_orient_pat[4]=+1.0;
1499 id->image_orient_pat[2]=+0.0; id->image_orient_pat[5]=-0.0;
1500 break;
1501 case MDC_SUPINE_HEADFIRST_SAGITTAL :
1502 id->image_orient_pat[0]=+0.0; id->image_orient_pat[3]=+0.0;
1503 id->image_orient_pat[1]=+1.0; id->image_orient_pat[4]=-0.0;
1504 id->image_orient_pat[2]=-0.0; id->image_orient_pat[5]=-1.0;
1505 break;
1506 case MDC_SUPINE_HEADFIRST_CORONAL :
1507 id->image_orient_pat[0]=+1.0; id->image_orient_pat[3]=+0.0;
1508 id->image_orient_pat[1]=-0.0; id->image_orient_pat[4]=-0.0;
1509 id->image_orient_pat[2]=+0.0; id->image_orient_pat[5]=-1.0;
1510 break;
1511 case MDC_SUPINE_FEETFIRST_TRANSAXIAL:
1512 id->image_orient_pat[0]=-1.0; id->image_orient_pat[3]=+0.0;
1513 id->image_orient_pat[1]=+0.0; id->image_orient_pat[4]=+1.0;
1514 id->image_orient_pat[2]=-0.0; id->image_orient_pat[5]=-0.0;
1515 break;
1516 case MDC_SUPINE_FEETFIRST_SAGITTAL :
1517 id->image_orient_pat[0]=+0.0; id->image_orient_pat[3]=-0.0;
1518 id->image_orient_pat[1]=+1.0; id->image_orient_pat[4]=+0.0;
1519 id->image_orient_pat[2]=-0.0; id->image_orient_pat[5]=+1.0;
1520 break;
1521 case MDC_SUPINE_FEETFIRST_CORONAL :
1522 id->image_orient_pat[0]=-1.0; id->image_orient_pat[3]=-0.0;
1523 id->image_orient_pat[1]=+0.0; id->image_orient_pat[4]=+0.0;
1524 id->image_orient_pat[2]=-0.0; id->image_orient_pat[5]=+1.0;
1525 break;
1526 case MDC_PRONE_HEADFIRST_TRANSAXIAL :
1527 id->image_orient_pat[0]=-1.0; id->image_orient_pat[3]=-0.0;
1528 id->image_orient_pat[1]=+0.0; id->image_orient_pat[4]=-1.0;
1529 id->image_orient_pat[2]=-0.0; id->image_orient_pat[5]=+0.0;
1530 break;
1531 case MDC_PRONE_HEADFIRST_SAGITTAL :
1532 id->image_orient_pat[0]=-0.0; id->image_orient_pat[3]=+0.0;
1533 id->image_orient_pat[1]=-1.0; id->image_orient_pat[4]=-0.0;
1534 id->image_orient_pat[2]=+0.0; id->image_orient_pat[5]=-1.0;
1535 break;
1536 case MDC_PRONE_HEADFIRST_CORONAL :
1537 id->image_orient_pat[0]=-1.0; id->image_orient_pat[3]=+0.0;
1538 id->image_orient_pat[1]=+0.0; id->image_orient_pat[4]=-0.0;
1539 id->image_orient_pat[2]=-0.0; id->image_orient_pat[5]=-1.0;
1540 break;
1541 case MDC_PRONE_FEETFIRST_TRANSAXIAL :
1542 id->image_orient_pat[0]=+1.0; id->image_orient_pat[3]=-0.0;
1543 id->image_orient_pat[1]=-0.0; id->image_orient_pat[4]=-1.0;
1544 id->image_orient_pat[2]=+0.0; id->image_orient_pat[5]=+0.0;
1545 break;
1546 case MDC_PRONE_FEETFIRST_SAGITTAL :
1547 id->image_orient_pat[0]=-0.0; id->image_orient_pat[3]=-0.0;
1548 id->image_orient_pat[1]=-1.0; id->image_orient_pat[4]=+0.0;
1549 id->image_orient_pat[2]=+0.0; id->image_orient_pat[5]=+1.0;
1550 break;
1551 case MDC_PRONE_FEETFIRST_CORONAL :
1552 id->image_orient_pat[0]=+1.0; id->image_orient_pat[3]=-0.0;
1553 id->image_orient_pat[1]=-0.0; id->image_orient_pat[4]=+0.0;
1554 id->image_orient_pat[2]=+0.0; id->image_orient_pat[5]=+1.0;
1555 break;
1556 case MDC_DECUBITUS_RIGHT_HEADFIRST_TRANSAXIAL:
1557 id->image_orient_pat[0]=+1.0; id->image_orient_pat[3]=+0.0;
1558 id->image_orient_pat[1]=-0.0; id->image_orient_pat[4]=+1.0;
1559 id->image_orient_pat[2]=+0.0; id->image_orient_pat[5]=-0.0;
1560 break;
1561 case MDC_DECUBITUS_RIGHT_HEADFIRST_SAGITTAL:
1562 case MDC_DECUBITUS_RIGHT_HEADFIRST_CORONAL:
1563 case MDC_DECUBITUS_RIGHT_FEETFIRST_TRANSAXIAL:
1564 case MDC_DECUBITUS_RIGHT_FEETFIRST_SAGITTAL:
1565 case MDC_DECUBITUS_RIGHT_FEETFIRST_CORONAL:
1566 case MDC_DECUBITUS_LEFT_HEADFIRST_TRANSAXIAL :
1567 case MDC_DECUBITUS_LEFT_HEADFIRST_SAGITTAL :
1568 case MDC_DECUBITUS_LEFT_HEADFIRST_CORONAL :
1569 case MDC_DECUBITUS_LEFT_FEETFIRST_TRANSAXIAL :
1570 case MDC_DECUBITUS_LEFT_FEETFIRST_SAGITTAL :
1571 case MDC_DECUBITUS_LEFT_FEETFIRST_CORONAL :
1572 /* FIXME */
1573 /* MdcPrntWarn("Extra code needed in %s at line %d\n", __FILE__, __LINE__);*/
1574 default : { } /* do nothing */
1575 }
1576 }
1577
MdcGetOrthogonalInt(float f)1578 int MdcGetOrthogonalInt(float f)
1579 {
1580 int i;
1581
1582 if (f == 0.0) i = 0;
1583 else if (f == 1.0) i = 1;
1584 else if (f == -1.0) i = -1;
1585 else i = (f < 0) ? (int)(f - 0.5) : (int)(f + 0.5);
1586
1587 return(i);
1588
1589 }
1590
MdcGetPatSliceOrient(FILEINFO * fi,Uint32 i)1591 Int8 MdcGetPatSliceOrient(FILEINFO *fi, Uint32 i)
1592 {
1593 IMG_DATA *id = &fi->image[i];
1594 int i0,i1,i4,i5;
1595 int slice_orientation=MDC_UNKNOWN;
1596 int patient_orientation=MDC_UNKNOWN;
1597 int patient_rotation=MDC_UNKNOWN;
1598 Int8 pat_slice_orient=MDC_UNKNOWN;
1599
1600 i0 = MdcGetOrthogonalInt(id->image_orient_pat[0]);
1601 i1 = MdcGetOrthogonalInt(id->image_orient_pat[1]);
1602 i4 = MdcGetOrthogonalInt(id->image_orient_pat[4]);
1603 i5 = MdcGetOrthogonalInt(id->image_orient_pat[5]);
1604
1605 /* A) image orientation combined with patient position */
1606 if (strstr(fi->pat_pos,"Unknown") == NULL) {
1607
1608 /* patient orientation */
1609 if (strstr(fi->pat_pos,"HF") != NULL) {
1610 patient_orientation = MDC_HEADFIRST;
1611 }else if (strstr(fi->pat_pos,"FF") != NULL) {
1612 patient_orientation = MDC_FEETFIRST;
1613 }
1614
1615 /* patient rotation */
1616 if (strstr(fi->pat_pos,"S") != NULL) {
1617 patient_rotation = MDC_SUPINE;
1618 }else if (strstr(fi->pat_pos,"P") != NULL) {
1619 patient_rotation = MDC_PRONE;
1620 }else if (strstr(fi->pat_pos, "DR") != NULL) {
1621 patient_rotation = MDC_DECUBITUS_RIGHT;
1622 }else if (strstr(fi->pat_pos, "DL") != NULL) {
1623 patient_rotation = MDC_DECUBITUS_LEFT;
1624 }
1625
1626 /* slice orientation */
1627 if ((i0 == +1 || i0 == -1) && (i4 == +1 || i4 == -1)) {
1628 slice_orientation = MDC_TRANSAXIAL;
1629 }else if ((i1 == +1 || i1 == -1) && (i5 == +1 || i5 == -1)) {
1630 slice_orientation = MDC_SAGITTAL;
1631 }else if ((i0 == +1 || i0 == -1) && (i5 == +1 || i5 == -1)) {
1632 slice_orientation = MDC_CORONAL;
1633 }
1634
1635 /* combined result */
1636 switch (patient_rotation) {
1637 case MDC_SUPINE:
1638 switch (patient_orientation) {
1639 case MDC_HEADFIRST:
1640 switch (slice_orientation) {
1641 case MDC_TRANSAXIAL:
1642 pat_slice_orient = MDC_SUPINE_HEADFIRST_TRANSAXIAL;
1643 break;
1644 case MDC_SAGITTAL:
1645 pat_slice_orient = MDC_SUPINE_HEADFIRST_SAGITTAL;
1646 break;
1647 case MDC_CORONAL:
1648 pat_slice_orient = MDC_SUPINE_HEADFIRST_CORONAL;
1649 break;
1650 }
1651 break;
1652 case MDC_FEETFIRST:
1653 switch (slice_orientation) {
1654 case MDC_TRANSAXIAL:
1655 pat_slice_orient = MDC_SUPINE_FEETFIRST_TRANSAXIAL;
1656 break;
1657 case MDC_SAGITTAL:
1658 pat_slice_orient = MDC_SUPINE_FEETFIRST_SAGITTAL;
1659 break;
1660 case MDC_CORONAL:
1661 pat_slice_orient = MDC_SUPINE_FEETFIRST_CORONAL;
1662 break;
1663 }
1664 break;
1665 }
1666 break;
1667 case MDC_PRONE:
1668 switch (patient_orientation) {
1669 case MDC_HEADFIRST:
1670 switch (slice_orientation) {
1671 case MDC_TRANSAXIAL:
1672 pat_slice_orient = MDC_PRONE_HEADFIRST_TRANSAXIAL;
1673 break;
1674 case MDC_SAGITTAL:
1675 pat_slice_orient = MDC_PRONE_HEADFIRST_SAGITTAL;
1676 break;
1677 case MDC_CORONAL:
1678 pat_slice_orient = MDC_PRONE_HEADFIRST_CORONAL;
1679 break;
1680 }
1681 break;
1682 case MDC_FEETFIRST:
1683 switch (slice_orientation) {
1684 case MDC_TRANSAXIAL:
1685 pat_slice_orient = MDC_PRONE_FEETFIRST_TRANSAXIAL;
1686 break;
1687 case MDC_SAGITTAL:
1688 pat_slice_orient = MDC_PRONE_FEETFIRST_SAGITTAL;
1689 break;
1690 case MDC_CORONAL:
1691 pat_slice_orient = MDC_PRONE_FEETFIRST_CORONAL;
1692 break;
1693 }
1694 break;
1695 }
1696 break;
1697 case MDC_DECUBITUS_RIGHT:
1698 switch (patient_orientation) {
1699 case MDC_HEADFIRST:
1700 switch (slice_orientation) {
1701 case MDC_TRANSAXIAL:
1702 pat_slice_orient=MDC_DECUBITUS_RIGHT_HEADFIRST_TRANSAXIAL;
1703 break;
1704 case MDC_SAGITTAL:
1705 pat_slice_orient=MDC_DECUBITUS_RIGHT_HEADFIRST_SAGITTAL;
1706 break;
1707 case MDC_CORONAL:
1708 pat_slice_orient=MDC_DECUBITUS_RIGHT_HEADFIRST_CORONAL;
1709 break;
1710 }
1711 break;
1712 case MDC_FEETFIRST:
1713 switch (slice_orientation) {
1714 case MDC_TRANSAXIAL:
1715 pat_slice_orient=MDC_DECUBITUS_RIGHT_FEETFIRST_TRANSAXIAL;
1716 break;
1717 case MDC_SAGITTAL:
1718 pat_slice_orient=MDC_DECUBITUS_RIGHT_FEETFIRST_SAGITTAL;
1719 break;
1720 case MDC_CORONAL:
1721 pat_slice_orient=MDC_DECUBITUS_RIGHT_FEETFIRST_CORONAL;
1722 break;
1723 }
1724 break;
1725 }
1726 break;
1727 case MDC_DECUBITUS_LEFT:
1728 switch (patient_orientation) {
1729 case MDC_HEADFIRST:
1730 switch (slice_orientation) {
1731 case MDC_TRANSAXIAL:
1732 pat_slice_orient=MDC_DECUBITUS_LEFT_HEADFIRST_TRANSAXIAL;
1733 break;
1734 case MDC_SAGITTAL:
1735 pat_slice_orient=MDC_DECUBITUS_LEFT_HEADFIRST_SAGITTAL;
1736 break;
1737 case MDC_CORONAL:
1738 pat_slice_orient=MDC_DECUBITUS_LEFT_HEADFIRST_CORONAL;
1739 break;
1740 }
1741 break;
1742 case MDC_FEETFIRST:
1743 switch (slice_orientation) {
1744 case MDC_TRANSAXIAL:
1745 pat_slice_orient=MDC_DECUBITUS_LEFT_FEETFIRST_TRANSAXIAL;
1746 break;
1747 case MDC_SAGITTAL:
1748 pat_slice_orient=MDC_DECUBITUS_LEFT_FEETFIRST_SAGITTAL;
1749 break;
1750 case MDC_CORONAL:
1751 pat_slice_orient=MDC_DECUBITUS_LEFT_FEETFIRST_CORONAL;
1752 break;
1753 }
1754 break;
1755 }
1756 break;
1757 }
1758
1759 if (pat_slice_orient != MDC_UNKNOWN) return(pat_slice_orient);
1760
1761 }
1762
1763 /* B) image orientation alone */
1764
1765 if ((i0 == +1) && (i4 == +1)) return MDC_SUPINE_HEADFIRST_TRANSAXIAL;
1766 if ((i0 == -1) && (i4 == +1)) return MDC_SUPINE_FEETFIRST_TRANSAXIAL;
1767 if ((i0 == -1) && (i4 == -1)) return MDC_PRONE_HEADFIRST_TRANSAXIAL;
1768 if ((i0 == +1) && (i4 == -1)) return MDC_PRONE_FEETFIRST_TRANSAXIAL;
1769 /* FIXME - doesn't handle DECUBITUS positions */
1770
1771 if ((i1 == +1) && (i5 == -1)) return MDC_SUPINE_HEADFIRST_SAGITTAL;
1772 if ((i1 == +1) && (i5 == +1)) return MDC_SUPINE_FEETFIRST_SAGITTAL;
1773 if ((i1 == -1) && (i5 == -1)) return MDC_PRONE_HEADFIRST_SAGITTAL;
1774 if ((i1 == -1) && (i5 == +1)) return MDC_PRONE_FEETFIRST_SAGITTAL;
1775 /* FIXME - doesn't handle DECUBITUS positions */
1776
1777 if ((i0 == +1) && (i5 == -1)) return MDC_SUPINE_HEADFIRST_CORONAL;
1778 if ((i0 == -1) && (i5 == +1)) return MDC_SUPINE_FEETFIRST_CORONAL;
1779 if ((i0 == -1) && (i5 == -1)) return MDC_PRONE_HEADFIRST_CORONAL;
1780 if ((i0 == +1) && (i5 == +1)) return MDC_PRONE_FEETFIRST_CORONAL;
1781 /* FIXME - doesn't handle DECUBITUS positions */
1782
1783 return(MDC_UNKNOWN);
1784 }
1785
MdcTryPatSliceOrient(char * pat_orient)1786 Int8 MdcTryPatSliceOrient(char *pat_orient)
1787 {
1788 char buffer[MDC_MAXSTR], *p1, *p2;
1789 Int8 orient1=MDC_UNKNOWN, orient2=MDC_UNKNOWN;
1790
1791 MdcStringCopy(buffer,pat_orient,strlen(pat_orient));
1792
1793 p1 = buffer;
1794 p2 = strrchr(buffer, '\\');
1795
1796 if (p2 == NULL) return MDC_UNKNOWN;
1797
1798 p2[0] = '\0'; p2+=1;
1799
1800 if (strchr(p1,'L') != NULL) orient1 = MDC_LEFT;
1801 else if (strchr(p1,'R') != NULL) orient1 = MDC_RIGHT;
1802 else if (strchr(p1,'A') != NULL) orient1 = MDC_ANTERIOR;
1803 else if (strchr(p1,'P') != NULL) orient1 = MDC_POSTERIOR;
1804 else if (strchr(p1,'H') != NULL) orient1 = MDC_HEAD;
1805 else if (strchr(p1,'F') != NULL) orient1 = MDC_FEET;
1806
1807 if (strchr(p2,'L') != NULL) orient2 = MDC_LEFT;
1808 else if (strchr(p2,'R') != NULL) orient2 = MDC_RIGHT;
1809 else if (strchr(p2,'A') != NULL) orient2 = MDC_ANTERIOR;
1810 else if (strchr(p2,'P') != NULL) orient2 = MDC_POSTERIOR;
1811 else if (strchr(p2,'H') != NULL) orient2 = MDC_HEAD;
1812 else if (strchr(p2,'F') != NULL) orient2 = MDC_FEET;
1813
1814
1815 if (orient1 == MDC_LEFT && orient2 == MDC_POSTERIOR)
1816 return MDC_SUPINE_HEADFIRST_TRANSAXIAL;
1817 if (orient1 == MDC_POSTERIOR && orient2 == MDC_FEET)
1818 return MDC_SUPINE_HEADFIRST_SAGITTAL;
1819 if (orient1 == MDC_LEFT && orient2 == MDC_FEET)
1820 return MDC_SUPINE_HEADFIRST_CORONAL;
1821
1822 if (orient1 == MDC_RIGHT && orient2 == MDC_POSTERIOR)
1823 return MDC_SUPINE_FEETFIRST_TRANSAXIAL;
1824 if (orient1 == MDC_POSTERIOR && orient2 == MDC_HEAD)
1825 return MDC_SUPINE_FEETFIRST_SAGITTAL;
1826 if (orient1 == MDC_RIGHT && orient2 == MDC_HEAD)
1827 return MDC_SUPINE_FEETFIRST_CORONAL;
1828
1829 if (orient1 == MDC_RIGHT && orient2 == MDC_ANTERIOR)
1830 return MDC_PRONE_HEADFIRST_TRANSAXIAL;
1831 if (orient1 == MDC_ANTERIOR && orient2 == MDC_FEET)
1832 return MDC_PRONE_HEADFIRST_SAGITTAL;
1833 if (orient1 == MDC_RIGHT && orient2 == MDC_FEET)
1834 return MDC_PRONE_HEADFIRST_CORONAL;
1835
1836 if (orient1 == MDC_LEFT && orient2 == MDC_ANTERIOR)
1837 return MDC_PRONE_FEETFIRST_TRANSAXIAL;
1838 if (orient1 == MDC_ANTERIOR && orient2 == MDC_HEAD)
1839 return MDC_PRONE_FEETFIRST_SAGITTAL;
1840 if (orient1 == MDC_LEFT && orient2 == MDC_HEAD)
1841 return MDC_PRONE_FEETFIRST_CORONAL;
1842
1843 if (orient1 == MDC_POSTERIOR && orient2 == MDC_RIGHT)
1844 return MDC_DECUBITUS_RIGHT_HEADFIRST_TRANSAXIAL;
1845 if (orient1 == MDC_RIGHT && orient2 == MDC_FEET)
1846 return MDC_DECUBITUS_RIGHT_HEADFIRST_SAGITTAL;
1847 if (orient1 == MDC_POSTERIOR && orient2 == MDC_FEET)
1848 return MDC_DECUBITUS_RIGHT_HEADFIRST_CORONAL;
1849
1850 if (orient1 == MDC_ANTERIOR && orient2 == MDC_RIGHT)
1851 return MDC_DECUBITUS_RIGHT_FEETFIRST_TRANSAXIAL;
1852 if (orient1 == MDC_RIGHT && orient2 == MDC_HEAD)
1853 return MDC_DECUBITUS_RIGHT_FEETFIRST_SAGITTAL;
1854 if (orient1 == MDC_ANTERIOR && orient2 == MDC_HEAD)
1855 return MDC_DECUBITUS_RIGHT_FEETFIRST_CORONAL;
1856
1857 if (orient1 == MDC_ANTERIOR && orient2 == MDC_LEFT)
1858 return MDC_DECUBITUS_LEFT_HEADFIRST_TRANSAXIAL;
1859 if (orient1 == MDC_LEFT && orient2 == MDC_FEET)
1860 return MDC_DECUBITUS_LEFT_HEADFIRST_SAGITTAL;
1861 if (orient1 == MDC_ANTERIOR && orient2 == MDC_FEET)
1862 return MDC_DECUBITUS_LEFT_HEADFIRST_CORONAL;
1863
1864 if (orient1 == MDC_POSTERIOR && orient2 == MDC_LEFT)
1865 return MDC_DECUBITUS_LEFT_FEETFIRST_TRANSAXIAL;
1866 if (orient1 == MDC_LEFT && orient2 == MDC_FEET)
1867 return MDC_DECUBITUS_LEFT_FEETFIRST_SAGITTAL;
1868 if (orient1 == MDC_POSTERIOR && orient2 == MDC_FEET)
1869 return MDC_DECUBITUS_LEFT_FEETFIRST_CORONAL;
1870
1871
1872 return MDC_UNKNOWN;
1873 }
1874
1875 /* Formats that only support one rescale factor but no slope/intercept */
1876 /* sometimes can lose quantitation: during rescale, the rescaled_fctr */
1877 /* is put to one. Warn the user about the loss of quantitation */
1878 /* example: negatives and force Uint8 pixel output */
MdcCheckQuantitation(FILEINFO * fi)1879 Int8 MdcCheckQuantitation(FILEINFO *fi)
1880 {
1881 IMG_DATA *id;
1882 Uint32 i;
1883
1884 if (MDC_QUANTIFY || MDC_CALIBRATE) {
1885
1886 for (i=0; i<fi->number; i++) {
1887
1888 id = &fi->image[0];
1889
1890 if (id->rescaled && (id->rescaled_fctr != id->rescaled_slope)) {
1891 MdcPrntWarn("Quantitation was lost");
1892 return(MDC_YES);
1893 }
1894 }
1895 }
1896
1897 return(MDC_NO);
1898
1899 }
1900
1901 /* return heart rate in beats per minute */
MdcGetHeartRate(GATED_DATA * gd,Int16 type)1902 float MdcGetHeartRate(GATED_DATA *gd, Int16 type)
1903 {
1904 float heart_rate = 0.;
1905
1906 if (gd->study_duration > 0.) {
1907 switch (type) {
1908 case MDC_HEART_RATE_ACQUIRED:
1909 /* note: [ms] -> [min] */
1910 heart_rate = (gd->cycles_acquired * 60. * 1000.) / gd->study_duration;
1911 break;
1912 case MDC_HEART_RATE_OBSERVED:
1913 /* note: [ms] -> [min] */
1914 heart_rate = (gd->cycles_observed * 60. * 1000.) / gd->study_duration;
1915 break;
1916 }
1917 }
1918
1919 return(heart_rate);
1920 }
1921
1922