1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 #include "mrilib.h"
8 #include "thd.h"
9 
10 extern THD_3dim_dataset *THD_3dim_G_from_ROIstring(char *shar);
11 
12 #undef  CHECK_FOR_DATA     /* 06 Jan 2005: message about empty files */
13 #define CHECK_FOR_DATA(fn)                                                \
14  do{ if( fsize == 0 ){                                                    \
15        if( isfile )                                                       \
16          fprintf(stderr,"** Can't read ANY data from file '%s'\n",(fn));  \
17        RETURN(NULL) ;                                                     \
18      }} while(0)
19 
20 
21 /*-----------------------------------------------------------------
22  * this is a list of known filename extensions
23    (as found in THD_open_one_dataset())         28 Jun 2006 [rickr]
24 -------------------------------------------------------------------*/
25 static char * file_extension_list[] = {
26     ".HEAD", ".BRIK", ".BRIK.gz",
27     ".mnc",
28     ".mri",
29     ".svl",
30     ".1D", ".1D.dset", ".1D.do", ".txt",
31     ".3D",
32     ".nii", ".nii.gz", ".nia", ".hdr", ".img",
33     ".mpg", ".mpeg", ".MPG", ".MPEG",
34     ".niml", ".niml.dset", ".niml.do",
35     ".gii", ".gii.dset", ".niml.tract" , ".jpg" , ".jpeg" , ".png" , ".heic"
36 };
37 
38 /*
39    Return a plausible path to a pathless filename,
40    returns NULL if no file was found.
41 */
Add_plausible_path(char * fname)42 char * Add_plausible_path(char *fname)
43 {
44    char dname[THD_MAX_NAME], ename[THD_MAX_NAME],
45          *elocal=NULL, *eee=NULL, *pp=NULL, *epath=NULL;
46    int epos=0, ll=0, ii=0, id = 0, kk=0;
47    FILE *fp=NULL;
48 
49    ENTRY("Add_plausible_path");
50 
51    if (!fname) RETURN(NULL);
52 
53    /* If file exists as is, go back */
54    if ((fp = fopen( fname , "r"))) {
55       pp = (char *)malloc(sizeof(char)*(strlen(fname)+1));
56       pp = strcpy(pp, fname);
57       fclose(fp);
58       RETURN(pp);
59    }
60 
61    ii = strlen(fname);
62    while (ii >=0) {
63       if (fname[ii] == '/') { /* Have path in name, return whole thing,
64                                  if file exists! */
65          if ((fp = fopen( fname , "r"))) {
66             pp = (char *)malloc(sizeof(char)*(strlen(fname)+1));
67             pp = strcpy(pp, fname);
68             fclose(fp);
69             RETURN(pp);
70          } else {
71             RETURN(NULL);
72          }
73       }
74       --ii;
75    }
76 
77    /* have name, try different paths */
78                        epath = getenv("AFNI_R_PATH") ;
79    if( epath == NULL ) epath = getenv("AFNI_PLUGINPATH") ;
80    if( epath == NULL ) epath = getenv("AFNI_PLUGIN_PATH") ;
81    if( epath == NULL ) epath = getenv("PATH") ;
82 
83 
84    /* Next block is based on one in thd_ttatlas_query.c */
85    /*----- copy path list into local memory -----*/
86 
87    ll = strlen(epath) ;
88    elocal = AFMALL(char, sizeof(char) * (ll+2) ) ;
89 
90    /*----- put a blank at the end -----*/
91 
92    strcpy( elocal , epath ) ; elocal[ll] = ' ' ; elocal[ll+1] = '\0' ;
93 
94    /*----- replace colons with blanks -----*/
95 
96    for( ii=0 ; ii < ll ; ii++ )
97      if( elocal[ii] == ':' ) elocal[ii] = ' ' ;
98 
99    /*----- extract blank delimited strings;
100            use as directory names to look for atlas -----*/
101 
102    epos = 0 ;
103 
104    do{
105       ii = sscanf( elocal+epos , "%s%n" , ename , &id ); /* next substring */
106       if( ii < 1 ) break ;                               /* none -> done   */
107 
108       epos += id ;                                 /* char after last scanned */
109 
110       ii = strlen(ename) ;                         /* make sure name has   */
111       if( ename[ii-1] != '/' ){                    /* a trailing '/' on it */
112           ename[ii]  = '/' ; ename[ii+1] = '\0' ;
113       }
114       strcpy(dname,ename) ;
115       strcat(dname,fname) ;               /* add file name */
116 
117       if ((fp = fopen( dname , "r"))) {
118          pp = (char *)malloc(sizeof(char)*(strlen(dname)+1));
119          pp = strcpy(pp, dname);
120          fclose(fp);
121          RETURN(pp);
122       }
123 
124    } while( epos < ll ) ;  /* scan until 'epos' is after end of epath */
125 
126 
127    RETURN(pp);
128 }
129 
130 /*----------------------------------------------------------------
131    simply given a pathname, try to open it as a dataset
132    [allow for .HEAD, .BRIK, or just prefix+viewcode filenames]
133 ------------------------------------------------------------------*/
134 
THD_open_one_dataset(char * pathname)135 THD_3dim_dataset * THD_open_one_dataset( char *pathname )
136 {
137    int ii , plen ;
138    char dirname[THD_MAX_NAME] , fullname[THD_MAX_NAME] ;
139    THD_3dim_dataset *dset=NULL ;  /* NULL added 23 Feb 2007, from Bernd Feige */
140    THD_datablock    *dblk ;
141    char *sub ;
142    char *fname ;   /* to skip directory during HEAD/BRIK search in filename */
143    int   offset ;  /*                                 - [rickr 20 Sep 2002] */
144    long long fsize ;     /* 06 Jan 2005, to unsigned 20 Feb 2006 [rickr] */
145                                       /* to long long 22 Mar 2007 [RWC] */
146    int   isfile = 1;
147    static char qname[THD_MAX_NAME+222] ;
148 
149 ENTRY("THD_open_one_dataset") ;
150 
151    /*-- sanity check --*/
152 
153    if( pathname == NULL              ||
154        (plen=strlen(pathname)) == 0  ||
155        pathname[plen-1]        == '/'  ) RETURN(NULL) ;
156 
157 
158    if( pathname[0] == '~' && pathname[1] == '/' ){  /* 13 Feb 2008 */
159      char *eee = getenv("HOME") ;
160      if( eee != NULL ){
161        strcpy(qname,eee); strcat(qname,pathname+1);
162        pathname = qname ;
163      }
164    }
165 
166    /*-- perhaps open the new-fangled way [22 May 2000] --*/
167    if( getenv("AFNI_USE_THD_open_dataset") != NULL &&
168        strstr(pathname,"[")                != NULL   ){
169       dset = THD_open_dataset(pathname) ;
170       THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
171       RETURN(dset) ;
172    }
173 
174    /*-- other cases that require new-fangled way   23 Jul 2012 [rickr] --*/
175    if( ! strncmp(pathname,"filelist:",9) ){
176       dset = THD_open_dataset(pathname) ;
177       THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
178       RETURN(dset) ;
179    }
180 
181    fsize = THD_filesize(pathname) ;                         /* 06 Jan 2005 */
182 
183    /* replace fsize == -1 use with isfile variable   28 Feb 2007 [rickr] */
184    if( fsize == 0 && !THD_is_file(pathname) ) isfile = 0;
185 
186    /*-- perhaps the MINC way --*/
187 
188    if( STRING_HAS_SUFFIX(pathname,".mnc") ){
189      static int first=1 ;
190      if( first ){
191        ERROR_message("MINC-1 dataset open disabled: %s",pathname) ;
192        first = 0 ; RETURN(NULL) ;
193      }
194    }
195 
196    /*-- perhaps the ANALYZE way --*/
197 
198    if( STRING_HAS_SUFFIX(pathname,".hdr") ){
199      CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
200      dset = THD_open_analyze(pathname) ;
201      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
202      RETURN(dset) ;
203    }
204 
205    /*-- perhaps the CTF way [04 Dec 2002] --*/
206 
207    if( STRING_HAS_SUFFIX(pathname,".mri") ){
208      CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
209      dset = THD_open_ctfmri(pathname) ;
210      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
211      RETURN(dset) ;
212    } else if( STRING_HAS_SUFFIX(pathname,".svl") ){
213      CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
214      dset = THD_open_ctfsam(pathname) ;
215      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
216      RETURN(dset) ;
217    }
218 
219    /*-- 04 Mar 2003: allow input of .1D files --*/
220 
221    if( STRING_HAS_SUFFIX(pathname,".1D") ||
222        STRING_HAS_SUFFIX(pathname,".1D.dset") ){
223      CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
224      dset = THD_open_1D(pathname) ;
225      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
226      RETURN(dset) ;
227    } else if( STRING_HAS_SUFFIX(pathname,".3D") ){  /* 21 Mar 2003 */
228      CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
229      dset = THD_open_3D(pathname) ;
230      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
231      RETURN(dset) ;
232    }
233 
234    /*-- 28 Aug 2003: the NIFTI way! --*/
235 
236    if( STRING_HAS_SUFFIX(pathname,".nii")    ||
237        STRING_HAS_SUFFIX(pathname,".nii.gz") ||
238        STRING_HAS_SUFFIX(pathname,".nia")      ){
239 
240      /* let NIFTI decide if the dataset is there   10 Jun 2015 [ricrk] */
241      /* CHECK_FOR_DATA(pathname) ; */              /* 06 Jan 2005 */
242      dset = THD_open_nifti(pathname) ;
243      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
244      THD_report_obliquity(dset) ;  /* 20 Dec 2007 */
245      RETURN(dset) ;
246    }
247 
248    /*-- 03 Dec 2003: the MPEG way! --*/
249 
250    if( STRING_HAS_SUFFIX_CASE(pathname,".mpg") ||
251        STRING_HAS_SUFFIX_CASE(pathname,".mpeg")  ){
252 
253      CHECK_FOR_DATA(pathname) ;               /* 06 Jan 2005 */
254      dset = THD_open_mpeg(pathname) ;
255      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
256      RETURN(dset) ;
257    }
258 
259    if( STRING_HAS_SUFFIX_CASE(pathname,".jpg")  ||
260        STRING_HAS_SUFFIX_CASE(pathname,".png")  ||
261        STRING_HAS_SUFFIX_CASE(pathname,".jpeg") ||
262        STRING_HAS_SUFFIX_CASE(pathname,".heic")   ){  /* 06 Jul 2016 */
263 
264      CHECK_FOR_DATA(pathname) ;
265      dset = THD_open_image(pathname) ;  /* will be loaded, too */
266      THD_patch_brickim(dset) ;
267      RETURN(dset) ;
268    }
269 
270    /*-- 26 May 2006 [rickr]: the NIML way! --*/
271 
272    if( STRING_HAS_SUFFIX(pathname,".niml") ){
273 
274      CHECK_FOR_DATA(pathname) ;
275      dset = THD_open_niml(pathname) ;
276      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
277      RETURN(dset) ;
278    }
279 
280    /*-- 26 May 2006 [rickr]: the NI_SURF_DSET way! --*/
281 
282    if( STRING_HAS_SUFFIX(pathname,".niml.dset") ){
283 
284      CHECK_FOR_DATA(pathname) ;
285      dset = THD_open_niml(pathname) ;
286      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
287      RETURN(dset) ;
288    }
289 
290    /*-- 13 Feb 2008 [rickr]: the GIFTI way! --*/
291 
292    if( STRING_HAS_SUFFIX(pathname,".gii") ||
293        STRING_HAS_SUFFIX(pathname,".gii.dset") ){
294 
295      CHECK_FOR_DATA(pathname) ;
296      dset = THD_open_gifti(pathname) ;
297      THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
298      RETURN(dset) ;
299    }
300 
301    /* -- Try to read an AFNI dataset and if that fails,
302          there is one more chance                 -- */
303 
304    /*-- Must be an AFNI-formatted dataset! -------------*/
305    /*-- find directory and last names in the pathname --*/
306 
307    for( ii=plen-1 ; ii >= 0 ; ii-- ) if( pathname[ii] == '/' ) break ;
308 
309    if( ii < 0 ){
310      strcpy( dirname , "./" ) ;      /* fake directory name */
311    } else {
312      strcpy( dirname , pathname ) ;
313      dirname[ii+1] = '\0' ;
314    }
315    offset = ii + 1 ;  /* offset of file within pathname - rickr [20 Sep 2002] */
316 
317    /*-- perform surgery on the name to make it a valid .HEAD --*/
318 
319    strcpy( fullname , pathname ) ;
320    fname = fullname + offset ; /* trailing filename (past directory) - rickr */
321 
322    /* note: e.g. DATASET_HEADER_SUFFIX does not start with '.' */
323    /* (REPLACE) sub = strstr( fullname , DATASET_HEADER_SUFFIX ) ;  * .HEAD ? */
324    sub = strstr( fname , DATASET_DOT_HEADER_SUFFIX ) ;   /* .HEAD ?  r:fname */
325 
326    if( sub == NULL ){                                   /* no! */
327       sub = strstr( fname , DATASET_DOT_BRICK_SUFFIX ) ; /* .BRIK ?  r:fname */
328 
329       if( sub == NULL ){                               /* no! */
330          ii = strlen(fullname) ;
331          if( fullname[ii-1] != '.' ) strcat( fullname , "." ) ; /* tack .HEAD */
332          strcat( fullname , DATASET_HEADER_SUFFIX ) ;           /* onto end */
333 
334       } else {                                     /* yes! */
335          strcpy( sub , DATASET_DOT_HEADER_SUFFIX ) ; /* replace .BRIK with .HEAD */
336       }
337    }
338 
339    /*-- open it up? --*/
340 
341    fsize = THD_filesize(fullname) ;                         /* 06 Jan 2005 */
342    if( fsize == 0 && !THD_is_file(fullname) ) isfile = 0;
343    else                                       isfile = 1;
344 
345    /* if it is not a file, check the ROI case   28 Feb 2007 [rickr] */
346    if( isfile ) {
347       dblk = THD_init_one_datablock( dirname , fullname ) ;
348       if( dblk != NULL ) {
349          dset = THD_3dim_from_block( dblk ) ;
350          THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
351          THD_report_obliquity(dset) ;  /* 20 Dec 2007 */
352          RETURN(dset) ;
353       }
354    } else {
355       /*-- Nothing worked, see if name is that of an atlas based ROI -- */
356       /* fprintf(stderr,"Here's your moment %s\n", pathname); */
357       dset = THD_3dim_G_from_ROIstring(pathname) ;
358       THD_patch_brickim(dset) ;  /* 20 Oct 2006 */
359       RETURN(dset) ;
360    }
361 
362    /* all else failed, give them the famed message */
363    CHECK_FOR_DATA(fullname) ;
364 
365    RETURN(dset) ; /* not destined to get here */
366 }
367 
368 /*--------------------------------------------------------------------
369    Returns -1 if no dataset, otherwise returns view_type.
370    * If sname==NULL, then "./" is used.
371    * pname mustn't be NULL.
372    * If vt is a good view type (>= 0), then we only check that,
373        otherwise we check all possible view types (smallest one
374        found wins).
375 ----------------------------------------------------------------------*/
376 
THD_is_dataset(char * sname,char * pname,int vt)377 int THD_is_dataset( char *sname , char *pname , int vt ) /* 17 Mar 2000 */
378 {
379    THD_3dim_dataset *dset ;
380    int ii , vv ;
381 
382 ENTRY("THD_is_dataset") ;
383 
384    if( pname == NULL ) RETURN(-1) ;
385 
386    dset = EDIT_empty_copy(NULL) ;
387    EDIT_dset_items( dset , ADN_prefix , pname , ADN_none ) ;
388 
389    if( sname != NULL )
390      EDIT_dset_items( dset , ADN_directory_name , sname , ADN_none ) ;
391 
392    if( vt >= FIRST_VIEW_TYPE && vt <= LAST_VIEW_TYPE ){
393      EDIT_dset_items( dset , ADN_view_type , vt , ADN_none ) ;
394      ii = THD_is_file(dset->dblk->diskptr->header_name);
395      THD_delete_3dim_dataset(dset,False) ;
396      if( ii ) RETURN(vt) ;
397      RETURN(-1) ;
398    }
399 
400    for( vv=FIRST_VIEW_TYPE ; vv <= LAST_VIEW_TYPE ; vv++ ){
401      EDIT_dset_items( dset , ADN_view_type , vv , ADN_none ) ;
402      ii = THD_is_file(dset->dblk->diskptr->header_name);
403      if( ii ){ THD_delete_3dim_dataset(dset,False); RETURN(vv); }
404    }
405 
406    THD_delete_3dim_dataset( dset , False ) ;
407    RETURN(-1) ;
408 }
409 
410 /*--------------------------------------------------------------------*/
411 
THD_deconflict_nifti(char * brick_name)412 static int THD_deconflict_nifti( char *brick_name )
413 {
414    int lp , ls ; char suf[9] ;
415    char aa,bb,cc ;
416 
417    if( !THD_is_file(brick_name) ) return 0 ;
418 
419    lp = strlen(brick_name) ;
420    if( STRING_HAS_SUFFIX(brick_name,".nii") ){
421      ls = lp-4 ; strcpy(suf,".nii") ;
422    } else if( STRING_HAS_SUFFIX(brick_name,".nii.gz") ){
423      ls = lp-7 ; strcpy(suf,".nii.gz") ;
424    } else if( STRING_HAS_SUFFIX(brick_name,".hdr") ){
425      ls = lp-4 ; strcpy(suf,".hdr") ;
426    } else {
427      ls = lp   ; strcpy(suf,"\0") ;
428    }
429 
430    for( aa='A' ; aa <= 'Z' ; aa++ ){
431     for( bb='A' ; bb <= 'Z' ; bb++ ){
432      for( cc='1' ; cc <= '9' ; cc++ ){
433        brick_name[ls  ] = '_' ;
434        brick_name[ls+1] = aa  ;
435        brick_name[ls+2] = bb  ;
436        brick_name[ls+3] = cc  ;
437        brick_name[ls+4] = '\0';
438        strcat(brick_name,suf) ;
439        if( ! THD_is_file(brick_name) ) return 1 ;
440    }}}
441 
442    if( ls > THD_MAX_NAME-45 ) ls = THD_MAX_NAME-45 ;
443    brick_name[ls++] = '_' ;
444    UNIQ_idcode_fill( brick_name+ls ) ;
445    strcat(brick_name,suf) ;
446    return 1;
447 }
448 
449 /*--------------------------------------------------------------------*/
450 /*! Modify the prefix of a dataset to make sure it doesn't conflict
451     with an existing file.  Return value is 0 if no change was
452     needed, 1 if a change was made.
453 ----------------------------------------------------------------------*/
454 
THD_deconflict_prefix(THD_3dim_dataset * dset)455 int THD_deconflict_prefix( THD_3dim_dataset *dset )
456 {
457    char pfx[THD_MAX_PREFIX] ; int lp  ;
458    char aa,bb,cc ;
459 
460 ENTRY("THD_deconflict_prefix") ;
461 
462    if( !ISVALID_DSET(dset) ) RETURN(0) ;
463 
464    MCW_strncpy( pfx , DSET_PREFIX(dset) , THD_MAX_PREFIX ) ;
465 
466    if( PREFIX_IS_NIFTI(pfx) ){
467      /* adjust brick_name */
468      EDIT_dset_items( dset , ADN_prefix , pfx , ADN_none ) ;
469 
470      /* deconflict brick_name (to include path) */
471      lp = THD_deconflict_nifti( dset->dblk->diskptr->brick_name ) ;
472 
473      /* reset names from adjusted brick_name */
474      if( lp > 0 ) EDIT_dset_items( dset , ADN_prefix ,
475                                    dset->dblk->diskptr->brick_name , ADN_none );
476      RETURN(lp) ;
477    }
478 
479    if( ! THD_is_file(dset->dblk->diskptr->header_name) ) RETURN(0) ;
480 
481    lp = strlen(pfx) ;
482    if( lp > THD_MAX_PREFIX-5 ) lp = THD_MAX_PREFIX-5 ;
483 
484    for( aa='A' ; aa <= 'Z' ; aa++ ){
485     for( bb='A' ; bb <= 'Z' ; bb++ ){
486      for( cc='1' ; cc <= '9' ; cc++ ){
487        pfx[lp  ] = '_' ;
488        pfx[lp+1] = aa  ;
489        pfx[lp+2] = bb  ;
490        pfx[lp+3] = cc  ;
491        pfx[lp+4] = '\0';
492        EDIT_dset_items( dset , ADN_prefix , pfx , ADN_none ) ;
493        if( ! THD_is_file(dset->dblk->diskptr->header_name) ) RETURN(1) ;
494    }}}
495 
496    /** ugly brute force final solution: should never happen! **/
497 
498    if( lp > THD_MAX_PREFIX-35 ) lp = THD_MAX_PREFIX-35 ;
499    pfx[lp++] = '_' ; UNIQ_idcode_fill( pfx+lp ) ;
500    EDIT_dset_items( dset , ADN_prefix , pfx , ADN_none ) ;
501    RETURN(1) ;
502 }
503 
504 /*--------------------------------------------------------------------*/
505 
THD_dataset_headname(char * sname,char * pname,int vt)506 char * THD_dataset_headname( char *sname , char *pname , int vt )
507 {
508    THD_3dim_dataset *dset ;
509    char *str ; int ll ;
510 
511 ENTRY("THD_dataset_headname") ;
512 
513    if( pname == NULL ) RETURN(NULL) ;
514 
515    dset = EDIT_empty_copy(NULL) ;
516    EDIT_dset_items( dset , ADN_prefix , pname , ADN_none ) ;
517 
518    if( sname != NULL )
519       EDIT_dset_items( dset , ADN_directory_name , sname , ADN_none ) ;
520 
521    if( vt >= FIRST_VIEW_TYPE && vt <= LAST_VIEW_TYPE )
522       EDIT_dset_items( dset , ADN_view_type , vt , ADN_none ) ;
523 
524    ll = strlen(dset->dblk->diskptr->header_name) + 1 ;
525    str = (char *) malloc(sizeof(char)*ll ) ;
526    strcpy( str , dset->dblk->diskptr->header_name ) ;
527 
528    THD_delete_3dim_dataset( dset , False ) ;
529    RETURN(str) ;
530 }
531 
532 
533 /* ------------------------------------------------------------- */
534 /* given a filename, return one STORAGE_BY_* value from 3ddata.h
535  *                                           20 Apr 2006 [rickr] */
storage_mode_from_filename(char * fname)536 int storage_mode_from_filename( char * fname )
537 
538 {
539 ENTRY("storage_mode_from_filename");
540 
541     if( !fname || !*fname )                     RETURN(STORAGE_UNDEFINED);
542 
543     /* STORAGE_BY_SLICES was never implemented   :'( */
544 
545     if( STRING_HAS_SUFFIX(fname, ".HEAD") ||
546         STRING_HAS_SUFFIX(fname, ".BRIK") ||
547         STRING_HAS_SUFFIX(fname, ".BRIK.gz") )  RETURN(STORAGE_BY_BRICK);
548 
549 
550     if( 0 )                                     RETURN(STORAGE_BY_VOLUMES);
551 
552     if( 0 )   /* default is NIFTI */            RETURN(STORAGE_BY_ANALYZE);
553 
554     if( STRING_HAS_SUFFIX(fname, ".mri") )      RETURN(STORAGE_BY_CTFMRI);
555 
556     if( STRING_HAS_SUFFIX(fname, ".svl") )      RETURN(STORAGE_BY_CTFSAM);
557 
558     if( STRING_HAS_SUFFIX(fname, ".1D") ||
559         STRING_HAS_SUFFIX(fname, ".1D.dset"))       RETURN(STORAGE_BY_1D);
560 
561     if( STRING_HAS_SUFFIX(fname, ".3D") )       RETURN(STORAGE_BY_3D);
562 
563     if( STRING_HAS_SUFFIX(fname, ".nii")    ||
564         STRING_HAS_SUFFIX(fname, ".nii.gz") ||
565         STRING_HAS_SUFFIX(fname, ".nia")    ||
566         STRING_HAS_SUFFIX(fname, ".hdr")    ||
567         STRING_HAS_SUFFIX(fname, ".img") )      RETURN(STORAGE_BY_NIFTI);
568 
569     if( STRING_HAS_SUFFIX_CASE(fname,".mpg") ||
570         STRING_HAS_SUFFIX_CASE(fname,".mpeg")  )RETURN(STORAGE_BY_MPEG);
571 
572     /* 26 May 2006 [rickr] */
573     if( STRING_HAS_SUFFIX(fname, ".niml") )     RETURN(STORAGE_BY_NIML);
574 
575     if( STRING_HAS_SUFFIX(fname,".niml.dset") ) RETURN(STORAGE_BY_NI_SURF_DSET);
576     if( STRING_HAS_SUFFIX(fname,".tract.dset") ) RETURN(STORAGE_BY_NI_TRACT);
577 
578     if( STRING_HAS_SUFFIX(fname,".gii") ||
579         STRING_HAS_SUFFIX(fname,".gii.dset") )  RETURN(STORAGE_BY_GIFTI);
580 
581     RETURN(STORAGE_UNDEFINED);
582 }
583 
584 /* ------------------------------------------------------------- */
585 /* return whether the given storage mode suggests a surface type
586  *
587  * Note that 3D, 1D and NIML do not imply either way, life is hard.
588  * For now, return as true for them.
589  *
590  * returns 0 or 1 as boolean                 04 Apr 2012 [rickr] */
is_surface_storage_mode(int smode)591 int is_surface_storage_mode( int smode )
592 
593 {
594 ENTRY("is_surface_storage_mode");
595 
596     if ( smode == STORAGE_BY_1D           ||
597          smode == STORAGE_BY_3D           ||
598          smode == STORAGE_BY_NIML         ||
599          smode == STORAGE_BY_NI_SURF_DSET ||
600          smode == STORAGE_BY_GIFTI
601        ) RETURN(1);
602 
603     RETURN(0);
604 }
605 
606 
storage_mode_from_prefix(char * fname)607 int storage_mode_from_prefix( char * fname )
608 {
609    int sm=STORAGE_UNDEFINED;
610 
611 ENTRY("storage_mode_from_prefix");
612 
613    if( !fname || !*fname )                     RETURN(STORAGE_UNDEFINED);
614    sm = storage_mode_from_filename(fname);
615    if( sm != STORAGE_UNDEFINED ) RETURN(sm);
616 
617    if (fname[strlen(fname)-1] == '.') {
618       if( STRING_HAS_SUFFIX(fname, "+orig.") ||
619           STRING_HAS_SUFFIX(fname, "+acpc.") ||
620           STRING_HAS_SUFFIX(fname, "+tlrc.") ) sm = STORAGE_BY_BRICK;
621    } else {
622       if( STRING_HAS_SUFFIX(fname, "+orig") ||
623           STRING_HAS_SUFFIX(fname, "+acpc") ||
624           STRING_HAS_SUFFIX(fname, "+tlrc") ) sm = STORAGE_BY_BRICK;
625    }
626 
627    RETURN(sm);
628 }
629 
630 /* There is also: storage_mode_str() */
storage_mode_name(int mode)631 char *storage_mode_name(int mode) {
632    switch (mode) {
633       case STORAGE_UNDEFINED:
634          return("UNDEFINED");
635       case STORAGE_BY_BRICK:
636          return("BRIK");
637       case STORAGE_BY_VOLUMES:
638          return("VOLUMES");
639       case STORAGE_BY_ANALYZE:
640          return("ANALYZE");
641       case STORAGE_BY_CTFMRI:
642          return("CTFMRI");
643       case STORAGE_BY_CTFSAM:
644          return("CTFSAM");
645       case STORAGE_BY_1D:
646          return("1D");
647       case STORAGE_BY_3D:
648          return("3D");
649       case STORAGE_BY_NIFTI:
650          return("NIFTI");
651       case STORAGE_BY_MPEG:
652          return("MPEG");
653       case STORAGE_BY_NIML:
654          return("NIML");
655       case STORAGE_BY_NI_SURF_DSET:
656          return("NI_SURF_DSET");
657       case STORAGE_BY_NI_TRACT:
658          return("NI_TRACT");
659       case STORAGE_BY_GIFTI:
660          return("GIFTI");
661    }
662    return("UNDEFINED");
663 }
664 
665 /* ---------------------------------------------------- */
666 /* given a filename, return a pointer to the extension
667  * (from file_extension_list)
668  *                                  28 Jun 2006 [rickr] */
669 
find_filename_extension(char * fname)670 char * find_filename_extension( char * fname )
671 {
672     char ** eptr;
673     int c, flen, num_ext;
674 
675 ENTRY("find_filename_extension");
676 
677     if( !fname || !*fname ) RETURN(NULL);
678 
679     num_ext = sizeof(file_extension_list)/sizeof(char *);
680     flen = strlen(fname);
681 
682     for( c = 0, eptr = file_extension_list; c < num_ext; c++, eptr++ )
683         if( STRING_HAS_SUFFIX(fname, *eptr) )
684             RETURN(fname + (flen - strlen(*eptr)));
685 
686     RETURN(NULL);   /* not found */
687 }
688 
689 
690 /* ------------------------------------------------------------- */
691 /* given a filename, return 1 if it has a know extension that is
692  * not an AFNI extension                     20 Apr 2006 [rickr] */
693 
has_known_non_afni_extension(char * fname)694 int has_known_non_afni_extension( char * fname )
695 {
696     int mode;
697 
698 ENTRY("has_known_non_afni_extension");
699 
700     mode = storage_mode_from_filename(fname);
701 
702     /* UNDEFINED, BRICK and VOLUMES are the unknown or AFNI cases */
703     if( mode <= STORAGE_UNDEFINED   ||
704         mode == STORAGE_BY_BRICK    ||
705         mode == STORAGE_BY_VOLUMES  ||
706         mode  > LAST_STORAGE_MODE ) RETURN(0);
707 
708     RETURN(1); /* otherwise, we recognize it as non-AFNI */
709 }
710 
711 /* --------------------------------------------------------------- */
712 /* return 1 if smode is for a writable format   5 Mar 2012 [rickr] */
713 
is_writable_storage_mode(int smode)714 int is_writable_storage_mode( int smode )
715 {
716 ENTRY("has_writable_extension");
717 
718    switch (smode) {
719       case STORAGE_UNDEFINED:           RETURN(0);
720       case STORAGE_BY_ANALYZE:          RETURN(0);  /* returns NIFTI */
721       case STORAGE_BY_CTFMRI:           RETURN(0);
722       case STORAGE_BY_CTFSAM:           RETURN(0);
723       case STORAGE_BY_MPEG:             RETURN(0);
724 
725       case STORAGE_BY_BRICK:            RETURN(1);
726       case STORAGE_BY_VOLUMES:          RETURN(1);
727       case STORAGE_BY_1D:               RETURN(1);
728       case STORAGE_BY_3D:               RETURN(1);
729       case STORAGE_BY_NIFTI:            RETURN(1);
730       case STORAGE_BY_NIML:             RETURN(1);
731       case STORAGE_BY_NI_SURF_DSET:     RETURN(1);
732       case STORAGE_BY_NI_TRACT:         RETURN(1);
733       case STORAGE_BY_GIFTI:            RETURN(1);
734    }
735 
736    RETURN(0); /* not writable */
737 }
738 
739 /* ---------------------------------------------------- */
740 /* given a filename, return a string excluding known
741    afni extensions (from file_extension_list)
742    DO NOT FREE output.
743                                    06 Feb 2012 [ZSS] */
744 
without_afni_filename_extension(char * fname)745 char * without_afni_filename_extension( char * fname )
746 {
747     char ** eptr;
748     static char onames[5][THD_MAX_NAME+1];
749     static int icall=0;
750     int c, flen, num_ext;
751 
752     ENTRY("without_afni_filename_extension");
753 
754     if( !fname || !*fname ) RETURN(NULL);
755     ++icall;
756     if (icall > 4) icall = 0;
757     onames[icall][0]='\0';
758 
759     if (strlen(fname) >= THD_MAX_NAME) {
760       WARNING_message("Filename too long for without_afni_filename_extension()"
761                       "Returing fname");
762       RETURN(fname);
763     }
764     num_ext = sizeof(file_extension_list)/sizeof(char *);
765     flen = strlen(fname);
766 
767     for( c = 0, eptr = file_extension_list; c < num_ext; c++, eptr++ ) {
768         if( STRING_HAS_SUFFIX(fname, *eptr) ) {
769             flen = flen - strlen(*eptr);
770             strncpy(onames[icall], fname, flen);
771             onames[icall][flen]='\0';
772             RETURN(onames[icall]);
773         }
774     }
775     RETURN(fname);   /* not found */
776 }
777 
without_afni_filename_view_and_extension(char * fname)778 char * without_afni_filename_view_and_extension( char * fname )
779 {
780     char *noext;
781     static char onames[5][THD_MAX_NAME+1];
782     static int icall=0;
783     int flen;
784 
785 ENTRY("without_afni_filename_view_and_extension");
786 
787     if( !fname || !*fname ) RETURN(NULL);
788     ++icall;
789     if (icall > 4) icall = 0;
790     onames[icall][0]='\0';
791 
792     if ((noext = without_afni_filename_extension(fname))) {
793       flen = strlen(noext);
794       if (fname[strlen(noext)-1] == '.') {
795          if( STRING_HAS_SUFFIX(noext, "+orig.") ||
796              STRING_HAS_SUFFIX(noext, "+acpc.") ||
797              STRING_HAS_SUFFIX(noext, "+tlrc.") ) {
798             flen = flen - 6;
799             strncpy(onames[icall], noext, flen);
800             onames[icall][flen]='\0';
801          }
802       } else if( STRING_HAS_SUFFIX(noext, "+orig") ||
803                  STRING_HAS_SUFFIX(noext, "+acpc") ||
804                  STRING_HAS_SUFFIX(noext, "+tlrc") ) {
805          flen = flen - 5;
806          strncpy(onames[icall], noext, flen);
807          onames[icall][flen]='\0';
808       } else {
809          strncpy(onames[icall], noext, flen);
810          onames[icall][flen]='\0';
811       }
812 
813       RETURN(onames[icall]);
814     }
815 
816     RETURN(fname);   /* not found */
817 }
818 
819 /*--------------------------------------------------------------*/
820 /* Add prefix and/or suffix to filename fname taking care
821    to leave the path undisturbed and known extensions preserved */
822 
modify_afni_prefix(char * fname,char * pref,char * suf)823 char * modify_afni_prefix( char * fname , char *pref, char *suf)
824 {
825     char ** eptr;
826     static char onames[9][THD_MAX_NAME+1];
827     static int icall=0;
828     int c, isl, icp, flen, num_ext;
829 
830 ENTRY("modify_afni_prefix");
831 
832     if( !fname || !*fname ) RETURN(NULL);
833     ++icall;
834     if (icall > 8) icall = 0;
835     onames[icall][0]='\0';
836 
837 
838     if (!suf && !pref) {
839       /* nothing to do */
840       RETURN(fname);
841     }
842 
843     if (pref && strlen(pref)) {
844       flen = strlen(fname);
845       if (flen+strlen(pref) >= THD_MAX_NAME) {
846          WARNING_message("Filename too long for modify_afni_prefix()"
847                          "Returing fname");
848          RETURN(fname);
849       }
850 
851       /* find last '/' */
852       isl=flen-1;
853       while(isl>=0) {
854          if (fname[isl] == '/') break;
855          --isl;
856       }
857       for (icp=0; icp<=isl; ++icp) onames[icall][icp]=fname[icp];
858       onames[icall][icp]='\0';
859       strcat(onames[icall], pref);
860       strcat(onames[icall],fname+isl+1);
861 
862       fname = onames[icall];
863       ++icall; if (icall > 8) icall = 0;
864       onames[icall][0]='\0';
865     }
866 
867     if (suf && strlen(suf)) {
868       flen = strlen(fname);
869       if (flen+strlen(suf) >= THD_MAX_NAME) {
870          WARNING_message("Filename too long for modify_afni_prefix()"
871                          "Returing fname");
872          RETURN(fname);
873       }
874 
875       /* remove the extension */
876       num_ext = sizeof(file_extension_list)/sizeof(char *);
877       for( c = 0, eptr = file_extension_list; c < num_ext; c++, eptr++ ) {
878         if( STRING_HAS_SUFFIX(fname, *eptr) ) {
879             flen = flen - strlen(*eptr);
880             strncpy(onames[icall], fname, flen); onames[icall][flen]='\0';
881             strcat(onames[icall], suf);
882             strcat(onames[icall], *eptr);
883             break;
884         }
885       }
886       if (onames[icall][0] == '\0') {
887          /* no extensions, just append */
888          strcat(onames[icall],fname);
889          strcat(onames[icall], suf);
890       }
891 
892       RETURN(onames[icall]);
893    }
894 
895    /* should not get here, but be nice anyway */
896    RETURN(fname);   /* not found */
897 
898 }
899