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