~ubuntu-branches/ubuntu/lucid/fslview/lucid

« back to all changes in this revision

Viewing changes to fsl/fslio/fslio.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2009-02-06 12:13:24 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090206121324-pib80tw725kqxe45
Tags: 3.0.2+4.1.2-2
* Compile internal libraries as shared libs and install them under
  /usr/lib/fsl/lib, so FSL itself can use them as well.
* Expose FSL's internal libs via RPATH to the included binaries.
  That should be appropriate, since they are built from the same package
  and are not intended to be used by other packages than FSL (hence, no -dev
  package).
* Added patch to prevent fslview from crashing with images that have dim4=0.
  Thanks to Wim Otte.
* Build package with -Wl,--no-undefined.
* Added 'XS-DM-Upload-Allowed: yes' to debian/control.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    fslio.c  (Input and output routines for images in FSL)
 
3
 
 
4
    Mark Jenkinson
 
5
    FMRIB Image Analysis Group
 
6
*/
 
7
 
 
8
 
 
9
    
 
10
/*
 
11
 
 
12
    The fslio.c file was originally part of FSL - FMRIB's Software Library
 
13
    http://www.fmrib.ox.ac.uk/fsl
 
14
    fslio.c has now been placed in the public domain.
 
15
   
 
16
    Developed at FMRIB (Oxford Centre for Functional Magnetic Resonance
 
17
    Imaging of the Brain), Department of Clinical Neurology, Oxford
 
18
    University, Oxford, UK
 
19
    
 
20
*/
 
21
 
 
22
/** \file fslio.c 
 
23
    \brief Main collection of FSL i/o routines, written by Mark Jenkinson, FMRIB
 
24
 
 
25
    - updates by Rick Reynolds, SSCC, NIMH
 
26
 */
 
27
 
 
28
#include "fslio.h"
 
29
#include "assert.h"
 
30
 
 
31
static int FslIgnoreMFQ=0;
 
32
static int FslOverrideOutputType=-1;
 
33
 
 
34
#define FSLIOERR(x) { fprintf(stderr,"Error:: %s\n",(x)); fflush(stderr); exit(EXIT_FAILURE); }
 
35
 
 
36
 
 
37
/************************************************************
 
38
 * FslFileTypeString
 
39
 ************************************************************/
 
40
/*! \fn char* FslFileTypeString(int filetype)
 
41
    \brief  Return a string describing the format of the dataset
 
42
    \param filetype  FSL data format code.  Legal values are as defined
 
43
        by FSL_TYPE.
 
44
    \return  A string with the data format name, e.g. "ANALYZE-7.5"
 
45
    \sa FSL_TYPE
 
46
*/
 
47
char* FslFileTypeString(int filetype)
 
48
{
 
49
  if (filetype==FSL_TYPE_ANALYZE)          return "ANALYZE-7.5";
 
50
  if (filetype==FSL_TYPE_NIFTI)            return "NIFTI-1+";
 
51
  if (filetype==FSL_TYPE_NIFTI_PAIR)       return "NIFTI-1";
 
52
  if (filetype==FSL_TYPE_ANALYZE_GZ)       return "ANALYZE-7.5";
 
53
  if (filetype==FSL_TYPE_NIFTI_GZ)         return "NIFTI-1+";
 
54
  if (filetype==FSL_TYPE_NIFTI_PAIR_GZ)    return "NIFTI-1";
 
55
  return "UNKNOWN";
 
56
}
 
57
 
 
58
 
 
59
int FslIsValidFileType(int filetype)
 
60
{
 
61
  if ( (filetype!=FSL_TYPE_ANALYZE)    && (filetype!=FSL_TYPE_ANALYZE_GZ) && 
 
62
       (filetype!=FSL_TYPE_NIFTI)      && (filetype!=FSL_TYPE_NIFTI_GZ) && 
 
63
       (filetype!=FSL_TYPE_NIFTI_PAIR) && (filetype!=FSL_TYPE_NIFTI_PAIR_GZ) &&
 
64
       (filetype!=FSL_TYPE_MINC)       && (filetype!=FSL_TYPE_MINC_GZ) ) {
 
65
    fprintf(stderr,"Error: unrecognised file type: %d\n",filetype);
 
66
    return 0;
 
67
  }
 
68
  return 1;
 
69
}
 
70
 
 
71
 
 
72
int FslBaseFileType(int filetype)
 
73
{
 
74
  /* returns -1 to indicate error - unrecognised filetype */
 
75
  if ( (filetype==FSL_TYPE_ANALYZE_GZ)    || (filetype==FSL_TYPE_ANALYZE) )
 
76
    return FSL_TYPE_ANALYZE;
 
77
  if ( (filetype==FSL_TYPE_NIFTI_GZ)      || (filetype==FSL_TYPE_NIFTI) )
 
78
    return FSL_TYPE_NIFTI;
 
79
  if ( (filetype==FSL_TYPE_NIFTI_PAIR_GZ) || (filetype==FSL_TYPE_NIFTI_PAIR) )
 
80
    return FSL_TYPE_NIFTI_PAIR;
 
81
  if ( (filetype==FSL_TYPE_MINC_GZ)       || (filetype==FSL_TYPE_MINC) )  
 
82
    return FSL_TYPE_MINC;
 
83
  fprintf(stderr,"Error: unrecognised file type (%d)\n",filetype);
 
84
  return -1;
 
85
}
 
86
 
 
87
 
 
88
int FslGetFileType2(const FSLIO *fslio, int quiet)
 
89
{
 
90
  FSLIO *mutablefslio;
 
91
  if (fslio==NULL)  FSLIOERR("FslGetFileType: Null pointer passed for FSLIO");
 
92
  if ( (fslio->file_mode==FSL_TYPE_MINC) || (fslio->file_mode==FSL_TYPE_MINC_GZ) ) {
 
93
    return fslio->file_mode;
 
94
  }
 
95
  if ( !FslIsValidFileType(fslio->file_mode) )    return -1;
 
96
 
 
97
  if (fslio->niftiptr!=NULL) {   /* check that it is nifti_type and filetype are consistent */
 
98
    if (fslio->niftiptr->nifti_type != FslBaseFileType(fslio->file_mode)) {
 
99
      if (!quiet) {
 
100
        fprintf(stderr,"Warning: nifti structure and fsl structure disagree on file type\n");
 
101
        fprintf(stderr,"nifti = %d and fslio = %d\n",fslio->niftiptr->nifti_type,fslio->file_mode);
 
102
      }
 
103
      mutablefslio = (FSLIO *) fslio;  /* dodgy and will generate warnings */
 
104
      mutablefslio->niftiptr->nifti_type = FslBaseFileType(fslio->file_mode);
 
105
      return fslio->file_mode;
 
106
    }
 
107
 }
 
108
  return fslio->file_mode;
 
109
}
 
110
 
 
111
int FslGetFileType(const FSLIO *fslio)
 
112
 
113
  return FslGetFileType2(fslio,0);
 
114
}
 
115
 
 
116
 
 
117
 
 
118
void FslSetFileType(FSLIO *fslio, int filetype)
 
119
{
 
120
  if (fslio==NULL)  FSLIOERR("FslSetFileType: Null pointer passed for FSLIO");
 
121
  if ( (filetype==FSL_TYPE_MINC) || (filetype==FSL_TYPE_MINC_GZ) ) {
 
122
    fslio->file_mode = filetype;
 
123
    return;
 
124
  }
 
125
  if (! FslIsValidFileType(filetype)) { return; } 
 
126
  fslio->file_mode = filetype;  /* indicates general nifti - details in niftiptr */
 
127
  if (fslio->niftiptr!=NULL) { 
 
128
    fslio->niftiptr->nifti_type = FslBaseFileType(filetype); 
 
129
    nifti_set_iname_offset(fslio->niftiptr);
 
130
  }
 
131
}
 
132
 
 
133
 
 
134
 
 
135
int FslIsSingleFileType(int filetype)
 
136
{
 
137
  if ( (filetype==FSL_TYPE_NIFTI) || (filetype==FSL_TYPE_NIFTI_GZ) || 
 
138
       (filetype==FSL_TYPE_MINC)  || (filetype==FSL_TYPE_MINC_GZ) )
 
139
    return 1;
 
140
  return 0;
 
141
}
 
142
 
 
143
 
 
144
int FslIsCompressedFileType(int filetype)
 
145
{
 
146
  if ( filetype >=100 ) return 1;
 
147
  return 0;
 
148
}
 
149
 
 
150
 
 
151
int FslGetWriteMode(const FSLIO *fslio)
 
152
{
 
153
  if (fslio==NULL)  FSLIOERR("FslGetWriteMode: Null pointer passed for FSLIO");
 
154
  return fslio->write_mode;
 
155
 
156
 
 
157
 
 
158
void FslSetWriteMode(FSLIO *fslio, int mode)
 
159
{
 
160
  if (fslio==NULL)  FSLIOERR("FslSetWriteMode: Null pointer passed for FSLIO");
 
161
  fslio->write_mode = mode;
 
162
}
 
163
 
 
164
 
 
165
int FslGetEnvOutputType(void)
 
166
{
 
167
  /* return type is one of FSL_TYPE_* or -1 to indicate error */
 
168
  char *otype;
 
169
  if (FslOverrideOutputType>=0)  return FslOverrideOutputType;
 
170
  otype = getenv("FSLOUTPUTTYPE");
 
171
  if (otype == NULL) {
 
172
    fprintf(stderr,"ERROR:: Environment variable FSLOUTPUTTYPE is not set!\n");
 
173
    fprintf(stderr,"Please make sure that the appropriate configuration file is sourced by your shell (e.g. by putting it in .profile).\n");
 
174
    fprintf(stderr,"e.g. bash or sh users add the line \". ${FSLDIR}/etc/fslconf/fsl.sh\"\n");
 
175
    fprintf(stderr,"e.g. tcsh or csh users add the line \"source ${FSLDIR}/etc/fslconf/fsl.csh\"\n");
 
176
    exit(EXIT_FAILURE);
 
177
  }
 
178
  if (strcmp(otype,"NIFTI")==0) { return FSL_TYPE_NIFTI; }
 
179
  if (strcmp(otype,"NIFTI_GZ")==0) { return FSL_TYPE_NIFTI_GZ; }
 
180
  if (strcmp(otype,"NIFTI_PAIR")==0) { return FSL_TYPE_NIFTI_PAIR; }
 
181
  if (strcmp(otype,"NIFTI_PAIR_GZ")==0) { return FSL_TYPE_NIFTI_PAIR_GZ; }
 
182
  fprintf(stderr,"ERROR:: Unrecognised value (%s) of environment variable FSLOUTPUTTYPE\n",otype);
 
183
  fprintf(stderr,"Legal values are: NIFTI, NIFTI_PAIR, NIFTI_GZ, NIFTI_PAIR_GZ\n");
 
184
  exit(EXIT_FAILURE);
 
185
  return -1;
 
186
}
 
187
    
 
188
 
 
189
int FslFileType(const char* fname) 
 
190
{
 
191
  /* return type is FSL_TYPE_* or -1 to indicate undetermined */
 
192
  /* use name as first priority but if that is ambiguous then resolve using environment */
 
193
  int flen;
 
194
  int retval=-1;
 
195
  if (fname==NULL) return retval;
 
196
  flen = strlen(fname);
 
197
  /* group conditions to avoid possible illegal memory access */
 
198
  if (flen<5) return retval;  /* smallest name + extension is a.nii */
 
199
  if (strcmp(fname + flen - 4,".nii")==0)  retval=FSL_TYPE_NIFTI;
 
200
  if (strcmp(fname + flen - 4,".mnc")==0)  retval=FSL_TYPE_MINC;
 
201
  if (strcmp(fname + flen - 4,".hdr")==0)  retval=FSL_TYPE_NIFTI_PAIR;
 
202
  if (strcmp(fname + flen - 4,".img")==0)  retval=FSL_TYPE_NIFTI_PAIR;
 
203
  if ((retval==-1) && (flen<8)) return retval; /* small name + ext.gz is a.nii.gz */
 
204
  if (strcmp(fname + flen - 7,".mnc.gz")==0)  retval=FSL_TYPE_MINC;
 
205
  if (strcmp(fname + flen - 7,".nii.gz")==0)  retval=FSL_TYPE_NIFTI_GZ;
 
206
  if (strcmp(fname + flen - 7,".hdr.gz")==0)  retval=FSL_TYPE_NIFTI_PAIR_GZ;
 
207
  if (strcmp(fname + flen - 7,".img.gz")==0)  retval=FSL_TYPE_NIFTI_PAIR_GZ;
 
208
  if ( (retval==FSL_TYPE_NIFTI_PAIR) || (retval==FSL_TYPE_NIFTI_PAIR_GZ) ) {
 
209
    /* If it was hdr or img, check if Analyze was requested by environment */
 
210
    if ( (FslGetEnvOutputType() == FSL_TYPE_ANALYZE) && (retval == FSL_TYPE_NIFTI_PAIR) ) 
 
211
      retval=FSL_TYPE_ANALYZE;
 
212
    if ( (FslGetEnvOutputType() == FSL_TYPE_ANALYZE_GZ) && (retval == FSL_TYPE_NIFTI_PAIR_GZ) )
 
213
      retval=FSL_TYPE_ANALYZE_GZ;
 
214
  }
 
215
  return retval;
 
216
}
 
217
 
 
218
 
 
219
/************************************************************
 
220
 * FslGetReadFileType
 
221
 ************************************************************/
 
222
/*! \fn int FslGetReadFileType(const FSLIO *fslio)
 
223
    \brief  return the best estimate of the true file type 
 
224
 
 
225
  This function is used to return the best estimate of the true file type once
 
226
   a simple open has occurred - for now it is used after a nifti open call is made 
 
227
 
 
228
    \param  fslio data structure
 
229
    \return FSL_TYPE filetype code
 
230
    \sa FSL_TYPE
 
231
*/
 
232
int FslGetReadFileType(const FSLIO *fslio)
 
233
{
 
234
  int filetype=FSL_TYPE_ANALYZE;  /* unused default */
 
235
  if (fslio==NULL)  FSLIOERR("FslReadGetFileType: Null pointer passed for FSLIO");
 
236
  /* Don't use fslio->file_mode as it hasn't been set yet */
 
237
  if (fslio->niftiptr!=NULL) {   
 
238
    /* use the nifti_type and hdr or img name to determine the actual type */
 
239
    if (fslio->niftiptr->nifti_type == FSL_TYPE_ANALYZE) {
 
240
      if (FslIsCompressedFileType(FslFileType(fslio->niftiptr->iname))) {
 
241
        filetype = FSL_TYPE_ANALYZE_GZ;
 
242
      } else {
 
243
        filetype = FSL_TYPE_ANALYZE;
 
244
      }
 
245
    }
 
246
    if (fslio->niftiptr->nifti_type == FSL_TYPE_NIFTI_PAIR) {
 
247
      if (FslIsCompressedFileType(FslFileType(fslio->niftiptr->iname))) {
 
248
        filetype = FSL_TYPE_NIFTI_PAIR_GZ;
 
249
      } else {
 
250
        filetype = FSL_TYPE_NIFTI_PAIR;
 
251
      }
 
252
    }
 
253
    if (fslio->niftiptr->nifti_type == FSL_TYPE_NIFTI) {
 
254
      if (FslIsCompressedFileType(FslFileType(fslio->niftiptr->fname))) {
 
255
        filetype = FSL_TYPE_NIFTI_GZ;
 
256
      } else {
 
257
        filetype = FSL_TYPE_NIFTI;
 
258
      }
 
259
    }
 
260
    
 
261
  }
 
262
  if (fslio->mincptr!=NULL) { 
 
263
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
264
    filetype = FSL_TYPE_MINC;
 
265
  }
 
266
  return filetype;
 
267
}
 
268
 
 
269
int FslFileExists(const char *filename)
 
270
 
271
  /* return 1 if file(s) exists, otherwise return 0 */
 
272
  char *hdrname = nifti_findhdrname(filename);
 
273
  char *imgname = NULL;
 
274
  if (hdrname!=NULL){
 
275
      imgname = nifti_findimgname(filename,
 
276
                                  FslBaseFileType(FslFileType(hdrname)));
 
277
      free(hdrname);
 
278
      if (imgname != NULL) { free(imgname);  return 1; }
 
279
  }
 
280
  return 0;
 
281
}
 
282
 
 
283
char *FslMakeBaseName(const char *fname)
 
284
{
 
285
  char *basename;
 
286
  int blen;
 
287
  basename = nifti_makebasename(fname);
 
288
  blen = strlen(basename);
 
289
#ifdef HAVE_ZLIB
 
290
  if ((blen>7) && (strcmp(basename + blen-7,".mnc.gz") == 0))
 
291
    { basename[blen-7]='\0'; return basename; }
 
292
#endif
 
293
  if ((blen>4) && (strcmp(basename + blen-4,".mnc") == 0))
 
294
    { basename[blen-4]='\0'; return basename; }
 
295
  return basename;
 
296
}
 
297
 
 
298
 
 
299
void FslGetHdrImgNames(const char* filename, const FSLIO* fslio, 
 
300
                       char** hdrname, char** imgname)
 
301
{
 
302
  char *basename;
 
303
  int filetype;
 
304
  basename = FslMakeBaseName(filename);
 
305
  *hdrname = (char *)calloc(sizeof(char),strlen(basename)+8);
 
306
  *imgname = (char *)calloc(sizeof(char),strlen(basename)+8);
 
307
  strcpy(*hdrname,basename);
 
308
  strcpy(*imgname,basename);
 
309
  filetype = FslGetFileType(fslio);
 
310
  if (filetype==FSL_TYPE_NIFTI_GZ) {
 
311
    strcat(*hdrname,".nii.gz");
 
312
    strcat(*imgname,".nii.gz");
 
313
    free(basename);
 
314
    return;
 
315
  }
 
316
  if (filetype==FSL_TYPE_NIFTI) {
 
317
    strcat(*hdrname,".nii");
 
318
    strcat(*imgname,".nii");
 
319
    free(basename);
 
320
    return;
 
321
  }
 
322
  if (filetype==FSL_TYPE_MINC_GZ) {
 
323
    strcat(*hdrname,".mnc.gz");
 
324
    strcat(*imgname,".mnc.gz");
 
325
    free(basename);
 
326
    return;
 
327
  }
 
328
  if (filetype==FSL_TYPE_MINC) {
 
329
    strcat(*hdrname,".mnc");
 
330
    strcat(*imgname,".mnc");
 
331
    free(basename);
 
332
    return;
 
333
  }
 
334
  if ( (filetype==FSL_TYPE_NIFTI_PAIR_GZ) || (filetype==FSL_TYPE_ANALYZE_GZ) ) {
 
335
    strcat(*hdrname,".hdr.gz");
 
336
    strcat(*imgname,".img.gz");
 
337
    free(basename);
 
338
    return;
 
339
  }
 
340
  if ( (filetype==FSL_TYPE_NIFTI_PAIR) || (filetype==FSL_TYPE_ANALYZE) ) {
 
341
    strcat(*hdrname,".hdr");
 
342
    strcat(*imgname,".img");
 
343
    free(basename);
 
344
    return;
 
345
  }
 
346
 
 
347
  fprintf(stderr,"Error: Unrecognised filetype (%d)\n",FslGetFileType(fslio));
 
348
  free(basename);
 
349
  
 
350
  /* Failure */
 
351
  *hdrname = NULL;
 
352
  *imgname = NULL;
 
353
}
 
354
 
 
355
 
 
356
 
 
357
/***************************************************************
 
358
 * FslInit()
 
359
 ***************************************************************/
 
360
/*! \fn FSLIO *FslInit()
 
361
    \brief allocate space for the FSLIO struct and set some sensible defaults 
 
362
    \return  A pointer to an initialized FSLIO data structure
 
363
 */
 
364
FSLIO *FslInit(void)
 
365
{
 
366
  FSLIO *fslio;
 
367
  fslio = (FSLIO *) calloc(1,sizeof(FSLIO));
 
368
  FslSetInit(fslio);
 
369
  return fslio;
 
370
}
 
371
 
 
372
void FslSetInit(FSLIO* fslio)
 
373
{
 
374
  /* set some sensible defaults */
 
375
  fslio->niftiptr = NULL;
 
376
  fslio->mincptr  = NULL;
 
377
  FslSetFileType(fslio,FslGetEnvOutputType());
 
378
  FslSetWriteMode(fslio,0);
 
379
  fslio->written_hdr = 0;
 
380
}
 
381
 
 
382
 
 
383
 
 
384
void FslInit4Write(FSLIO* fslio, const char* filename, int ft)
 
385
{
 
386
  /* ft determines filetype if ft>=0*/ 
 
387
  int imgtype;
 
388
 
 
389
  FslSetWriteMode(fslio,1);
 
390
 
 
391
  /* Determine file type from image name (first priority) or environment (default) */
 
392
 
 
393
  imgtype = FslGetEnvOutputType();
 
394
 
 
395
  if (ft >= 0) imgtype = ft;
 
396
 
 
397
  if (!FslIsValidFileType(imgtype)) {
 
398
    fprintf(stderr,"Error: Failed to determine file type for writing in FslOpen()\n");
 
399
    exit(EXIT_FAILURE);
 
400
  }
 
401
  
 
402
  if ( (FslBaseFileType(imgtype)!=FSL_TYPE_MINC) ) {
 
403
    FslInitHeader(fslio, NIFTI_TYPE_FLOAT32,
 
404
                  1, 1, 1, 3,  0.0, 0.0, 0.0, 0.0,  4, "mm");
 
405
    
 
406
    FslSetFileType(fslio,imgtype);  /* this is after InitHeader as niftiptr set there */
 
407
    
 
408
    /* determine the header and image filename */
 
409
    FslGetHdrImgNames(filename,fslio,&(fslio->niftiptr->fname),&(fslio->niftiptr->iname));
 
410
    if ( (fslio->niftiptr->fname == NULL) || (fslio->niftiptr->iname == NULL) ) { 
 
411
      fprintf(stderr,"Error: cannot find filenames for %s\n",filename); 
 
412
    }
 
413
 
 
414
  } else if (FslBaseFileType(imgtype)==FSL_TYPE_MINC) {
 
415
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
416
    return;
 
417
  } else {
 
418
    fprintf(stderr,"Error:: unrecognised image type requested\n");
 
419
    return;
 
420
  }
 
421
 
 
422
  return;
 
423
}
 
424
 
 
425
 
 
426
 
 
427
void FslInitHeader(FSLIO *fslio, short t, 
 
428
                   size_t x, size_t y, size_t z, size_t v,
 
429
                   float vx, float vy, float vz, float tr,
 
430
                   size_t dim,
 
431
                   const char* units)
 
432
{
 
433
  /* NB: This function does not set the file type or write mode*/
 
434
 
 
435
  if (fslio==NULL)  FSLIOERR("FslInitHeader: Null pointer passed for FSLIO");
 
436
  
 
437
  fslio->niftiptr = nifti_simple_init_nim();
 
438
  /* make nifti type consistent with fslio */
 
439
  fslio->niftiptr->nifti_type = FslBaseFileType(fslio->file_mode);
 
440
 
 
441
  fslio->mincptr = NULL;
 
442
 
 
443
  FslSetDataType(fslio,t);
 
444
  FslSetDim(fslio,x,y,z,v);
 
445
  FslSetVoxDim(fslio,vx,vy,vz,tr);
 
446
  FslSetTimeUnits(fslio,"s");
 
447
  FslSetDimensionality(fslio,dim);
 
448
}
 
449
 
 
450
 
 
451
void FslCloneHeader(FSLIO *dest, const FSLIO *src)
 
452
{
 
453
  /* only clone the information that is stored in the disk version of the header */
 
454
  /*  - therefore _not_ the filenames, output type, write mode, etc */ 
 
455
 
 
456
  char *fname=NULL, *iname=NULL;
 
457
  void *data=NULL;
 
458
  int filetype, writemode;
 
459
  int preserve_nifti_values = 0;
 
460
  if (dest==NULL)  FSLIOERR("FslCloneHeader: Null pointer passed for FSLIO");
 
461
  if (src==NULL)   FSLIOERR("FslCloneHeader: Null pointer passed for FSLIO");
 
462
 
 
463
  if (src->niftiptr!=NULL) {
 
464
    /* preserve the filenames, output type and write mode */
 
465
    if (dest->niftiptr != NULL) {
 
466
      fname = dest->niftiptr->fname;
 
467
      iname = dest->niftiptr->iname;
 
468
      data = dest->niftiptr->data;
 
469
      preserve_nifti_values = 1;
 
470
    }
 
471
    filetype = FslGetFileType2(dest,1);
 
472
    writemode = FslGetWriteMode(dest);
 
473
 
 
474
    /* copy _all_ info across */
 
475
    dest->niftiptr = nifti_copy_nim_info(src->niftiptr);
 
476
 
 
477
    /* restore old values */
 
478
    if (preserve_nifti_values) {
 
479
      dest->niftiptr->fname = fname;
 
480
      dest->niftiptr->iname = iname; 
 
481
      dest->niftiptr->data = data; 
 
482
    } else { 
 
483
        /* destroy the values that the nifti copy creates */
 
484
      free(dest->niftiptr->fname);
 
485
      free(dest->niftiptr->iname);
 
486
      nifti_free_extensions(dest->niftiptr);
 
487
      dest->niftiptr->fname = NULL;
 
488
      dest->niftiptr->iname = NULL; 
 
489
      dest->niftiptr->data = NULL;   /* should already be NULL */
 
490
    }
 
491
    FslSetFileType(dest,filetype);
 
492
    FslSetWriteMode(dest,writemode);
 
493
  }
 
494
 
 
495
  if (src->mincptr!=NULL) {
 
496
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
497
  }
 
498
 
 
499
}
 
500
 
 
501
 
 
502
int  fsl_fileexists(const char* fname)
 
503
{
 
504
   znzFile fp;
 
505
   fp = znzopen( fname , "rb" , 1 ) ;
 
506
   if( !znz_isnull(fp) )  { znzclose(fp);  return 1; }
 
507
   return 0;
 
508
}
 
509
 
 
510
 
 
511
int FslCheckForMultipleFileNames(const char* filename)
 
512
{
 
513
  char *basename, *tmpname;
 
514
  int singlecount=0, hdrcount=0, imgcount=0, ambiguous=0;
 
515
  basename =  nifti_makebasename(filename);
 
516
  tmpname = (char *)calloc(strlen(basename) + 10,sizeof(char));
 
517
 
 
518
  strcpy(tmpname,basename);
 
519
  strcat(tmpname,".nii"); 
 
520
  if (fsl_fileexists(tmpname)) { singlecount++; }
 
521
  strcpy(tmpname,basename);
 
522
  strcat(tmpname,".nii.gz"); 
 
523
  if (fsl_fileexists(tmpname)) { singlecount++; }
 
524
  strcpy(tmpname,basename);
 
525
  strcat(tmpname,".mnc"); 
 
526
  if (fsl_fileexists(tmpname)) { singlecount++; }
 
527
  strcpy(tmpname,basename);
 
528
  strcat(tmpname,".mnc.gz"); 
 
529
  if (fsl_fileexists(tmpname)) { singlecount++; }
 
530
 
 
531
  strcpy(tmpname,basename);
 
532
  strcat(tmpname,".img"); 
 
533
  if (fsl_fileexists(tmpname)) { imgcount++; }
 
534
  strcpy(tmpname,basename);
 
535
  strcat(tmpname,".img.gz"); 
 
536
  if (fsl_fileexists(tmpname)) { imgcount++; }
 
537
 
 
538
  strcpy(tmpname,basename);
 
539
  strcat(tmpname,".hdr"); 
 
540
  if (fsl_fileexists(tmpname)) { hdrcount++; }
 
541
  strcpy(tmpname,basename);
 
542
  strcat(tmpname,".hdr.gz"); 
 
543
  if (fsl_fileexists(tmpname)) { hdrcount++; }
 
544
 
 
545
  ambiguous = 1;
 
546
  if ( (hdrcount==1) && (imgcount==1) && (singlecount==0) )  { ambiguous=0; }
 
547
  if ( (hdrcount==0) && (imgcount==0) && (singlecount==1) )  { ambiguous=0; }
 
548
 
 
549
  /* treat no image found as not ambiguous - want opening errors instead */
 
550
  if ( (hdrcount==0) && (imgcount==0) && (singlecount==0) )  { ambiguous=0; }
 
551
 
 
552
  free(tmpname);
 
553
  free(basename);
 
554
  return ambiguous;
 
555
}
 
556
 
 
557
 
 
558
 
 
559
int check_for_multiple_filenames(const char* filename)
 
560
{
 
561
  char *basename, *tmpname;
 
562
  char *otype;
 
563
  if (FslCheckForMultipleFileNames(filename))
 
564
    {  /* take action */
 
565
      basename =  nifti_makebasename(filename);
 
566
      tmpname = (char *)calloc(strlen(basename) + 10,sizeof(char));
 
567
      fprintf(stderr,"\n\n\nWARNING!!!! Multiple image files detected:\n");
 
568
      /* list the offending files */
 
569
      strcpy(tmpname,basename);
 
570
      strcat(tmpname,".nii"); 
 
571
      if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
 
572
      strcpy(tmpname,basename);
 
573
      strcat(tmpname,".nii.gz"); 
 
574
      if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
 
575
      strcpy(tmpname,basename);
 
576
      strcat(tmpname,".mnc"); 
 
577
      if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
 
578
      strcpy(tmpname,basename);
 
579
      strcat(tmpname,".mnc.gz"); 
 
580
      if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
 
581
      strcpy(tmpname,basename);
 
582
      strcat(tmpname,".img"); 
 
583
      if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
 
584
      strcpy(tmpname,basename);
 
585
      strcat(tmpname,".img.gz"); 
 
586
      if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
 
587
      strcpy(tmpname,basename);
 
588
      strcat(tmpname,".hdr"); 
 
589
      if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
 
590
      strcpy(tmpname,basename);
 
591
      strcat(tmpname,".hdr.gz"); 
 
592
      if (fsl_fileexists(tmpname)) { fprintf(stderr,"%s ",tmpname); }
 
593
      fprintf(stderr,"\n\n");
 
594
 
 
595
      if (!FslIgnoreMFQ) {
 
596
        otype = getenv("FSLMULTIFILEQUIT");
 
597
        if (otype!=NULL) {
 
598
          fprintf(stderr,"STOPPING PROGRAM\n");
 
599
          exit(EXIT_FAILURE);
 
600
        }
 
601
      }
 
602
      return 1;
 
603
    }
 
604
  return 0;
 
605
}
 
606
 
 
607
 
 
608
/***************************************************************
 
609
 * FslOpen
 
610
 ***************************************************************/
 
611
/*! \fn FSLIO *FslOpen(const char *filename, const char *opts)
 
612
    \brief Opens a file for either reading or writing. 
 
613
 
 
614
        The format of the output dataset is determined automatically by 
 
615
        passing filetype -1 to FslXOpen.
 
616
    \sa FslXOpen
 
617
 */
 
618
FSLIO *FslOpen(const char *filename, const char *opts)
 
619
{
 
620
  /* Note: -1 for filetype indicates that FslXOpen should determine filetype for itself */
 
621
  return FslXOpen(filename,opts,-1);
 
622
}
 
623
 
 
624
 
 
625
/***************************************************************
 
626
 * FslXOpen
 
627
 ***************************************************************/
 
628
/*! \fn FSLIO *FslXOpen(const char *filename, const char *opts, int filetype)
 
629
    \brief Opens a file for either reading or writing
 
630
 
 
631
        Files to be read are automatically read whether 
 
632
        compressed or not.  Also, reading uses the file extension 
 
633
        and will fail if that file does not exist.
 
634
        For a more robust read, pass the basename in as then all types 
 
635
        will be tried.
 
636
    \param filename Name (or basename) of the file to open
 
637
    \param opts Flags for fopen() of dataset, eg "r", "wb", etc.
 
638
    \param filetype specifies the type of file to be written. Legal
 
639
        values are as defined by FSL_TYPE.  If filetype is less than 
 
640
        zero, then it is ignored and the type is determined by the 
 
641
        filename extension or, failing that, the environment default.
 
642
    \return pointer to FSLIO dataset datastructure
 
643
    \sa FSLIO
 
644
    \sa FSL_TYPE
 
645
 */
 
646
FSLIO *FslXOpen(const char *filename, const char *opts, int filetype)
 
647
{
 
648
 
 
649
  FSLIO *fslio;
 
650
  char bopts[1024];
 
651
  size_t i, bi;
 
652
  int imgtype;
 
653
 
 
654
  fslio = FslInit();
 
655
 
 
656
  bi=0;
 
657
  for(i=0;i<strlen(opts);i++) {
 
658
    if (opts[i]=='w') { FslSetWriteMode(fslio,1); }
 
659
    if (opts[i]!='b' && opts[i]!='t') { bopts[bi++]=opts[i]; }
 
660
  }
 
661
  /* add in 'b' (at the end) for windows compatibility */
 
662
  bopts[bi++]='b';
 
663
  bopts[bi]='\0';
 
664
  
 
665
 
 
666
  if (FslGetWriteMode(fslio)==1) {
 
667
    
 
668
    /** ====================== Open file for writing ====================== **/
 
669
   
 
670
    FslInit4Write(fslio,filename,filetype);
 
671
    imgtype = FslGetFileType(fslio);
 
672
    fslio->written_hdr = 0;
 
673
 
 
674
    /* open the image file - not the header */
 
675
    fslio->fileptr = znzopen(fslio->niftiptr->iname,bopts,FslIsCompressedFileType(imgtype));
 
676
    if (znz_isnull(fslio->fileptr)) { 
 
677
      fprintf(stderr,"Error: failed to open file %s\n",fslio->niftiptr->iname); 
 
678
      return NULL;
 
679
    }
 
680
 
 
681
    if (!FslIsSingleFileType(imgtype)) {
 
682
      /* set up pointer at end of iname_offset for dual file formats (not singles) */
 
683
      FslSeekVolume(fslio,0);
 
684
    }
 
685
    return fslio;
 
686
 
 
687
  }
 
688
 
 
689
 
 
690
 
 
691
  /** ======================== Open file for reading ====================== **/
 
692
 
 
693
  check_for_multiple_filenames(filename);
 
694
 
 
695
  /* see if the extension indicates a minc file */
 
696
  imgtype = FslFileType(filename);
 
697
  if ((imgtype>=0) && (FslBaseFileType(imgtype)==FSL_TYPE_MINC)) {
 
698
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
699
    return NULL;
 
700
  }
 
701
 
 
702
  /* otherwise open nifti file: read header and open img file (may be same file) */
 
703
  fslio->fileptr = nifti_image_open(filename,bopts,&(fslio->niftiptr));
 
704
  if (znz_isnull(fslio->fileptr)) { 
 
705
    fprintf(stderr,"Error: failed to open file %s\n",filename); 
 
706
    return NULL;
 
707
  }
 
708
 
 
709
  /* set the file type given what has been read - it uses nifti_type and filenames */
 
710
  imgtype = FslGetReadFileType(fslio);
 
711
  FslSetFileType(fslio,imgtype);
 
712
  FslSetWriteMode(fslio,0);
 
713
 
 
714
  /* if it is a nifti file but has inconsistent left-right ordering in the sform and qform then complain/crash */
 
715
  if (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_NIFTI) {
 
716
    if (FslGetLeftRightOrder(fslio) == FSL_INCONSISTENT)
 
717
      {
 
718
        fprintf(stderr,"ERROR: inconsistent left-right order stored in sform and qform in file %s\n",filename); 
 
719
        fprintf(stderr,"       Using sform instead of qform values\n\n");
 
720
        /* return NULL; */
 
721
      }
 
722
  }
 
723
 
 
724
 
 
725
  if (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_ANALYZE) {
 
726
    /* For the ANALYZE case in FSL, must cheat and grab the originator field! */
 
727
    /* Note that the header file is always separate here and closed by now */
 
728
    struct dsr ahdr;
 
729
    short orig[5];
 
730
    FslReadRawHeader(&ahdr,fslio->niftiptr->fname);
 
731
    if (fslio->niftiptr->byteorder != nifti_short_order()) {
 
732
      AvwSwapHeader(&ahdr);
 
733
    }
 
734
    /* Read the origin and set the sform up (if origin is non-zero) */
 
735
    /* Note that signed pixdims are passed in to set the LR orientation */
 
736
    memcpy(orig,&(ahdr.hist.originator),10);
 
737
    FslSetAnalyzeSform(fslio, orig, fslio->niftiptr->pixdim[1],
 
738
                       fslio->niftiptr->pixdim[2], fslio->niftiptr->pixdim[3]);
 
739
  }
 
740
 
 
741
  /* from now on force all vox dims to be positive - LR info is in sform */
 
742
  if (fslio->niftiptr!=NULL) {
 
743
    fslio->niftiptr->dx = fabs(fslio->niftiptr->dx);
 
744
    fslio->niftiptr->dy = fabs(fslio->niftiptr->dy);
 
745
    fslio->niftiptr->dz = fabs(fslio->niftiptr->dz);
 
746
    fslio->niftiptr->pixdim[1] = fabs(fslio->niftiptr->pixdim[1]);
 
747
    fslio->niftiptr->pixdim[2] = fabs(fslio->niftiptr->pixdim[2]);
 
748
    fslio->niftiptr->pixdim[3] = fabs(fslio->niftiptr->pixdim[3]);
 
749
  }
 
750
  /* set up pointer at end of iname_offset , ready for reading */
 
751
  FslSeekVolume(fslio,0);  
 
752
 
 
753
  return fslio;
 
754
 
 
755
}
 
756
 
 
757
 
 
758
 
 
759
/***************************************************************
 
760
 * FslReadAllVolumes
 
761
 ***************************************************************/
 
762
/*! \fn void* FslReadAllVolumes(FSLIO* fslio, char* filename)
 
763
    \brief Read the header and all data into the FSLIO structure
 
764
 
 
765
        There is no need for FslOpen or FslClose calls when FslReadAllVolumes()
 
766
        is called.  
 
767
        <br>This routine allocates the buffer to hold the entire dataset. 
 
768
        <br>The data block returned will contain the data in whatever
 
769
        datatype it is stored as on disk (therefore it is a void *).
 
770
        <br>The data buffer will be byteswapped to native-endian.
 
771
        <br>The data buffer will not be scaled. 
 
772
        <br>The best call to make before this is FslInit() or a calloc() for 
 
773
        fslio.  (??? why calloc if this allocates the buffer ???)
 
774
 
 
775
    \param fslio pointer to an open dataset
 
776
    \param filename Name of the dataset to read.
 
777
    \return A pointer to the data block buffer (allocated by this function).
 
778
        <br> Return Null on error ??? is this true ???
 
779
        <ul>
 
780
        <li>Note this pointer is also in the FSLIO structure as 
 
781
        fslio->niftiptr->data.</li>
 
782
        <li>Note a void pointer is returned, as the datablock is of
 
783
        variable datatype.</li>
 
784
        </ul>
 
785
 
 
786
 */
 
787
void* FslReadAllVolumes(FSLIO* fslio, char* filename)
 
788
{
 
789
 
 
790
  int imgtype;
 
791
  if (fslio==NULL)  FSLIOERR("FslReadAllVolumes: Null pointer passed for FSLIO");
 
792
 
 
793
  /* see if the extension indicates a minc file */
 
794
  imgtype = FslFileType(filename);
 
795
  if ((imgtype>=0) && (FslBaseFileType(imgtype)==FSL_TYPE_MINC)) {
 
796
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
797
    return NULL;
 
798
  }
 
799
 
 
800
  /** otherwise it is a nifti file - so read it! **/
 
801
  fslio->mincptr = NULL;
 
802
  /* make sure an FslOpen hasn't locked the file */
 
803
  if (!znz_isnull(fslio->fileptr)) FslClose(fslio);  
 
804
  
 
805
  fslio->niftiptr = nifti_image_read(filename,1);
 
806
 
 
807
  /* check for failure, from David Akers */
 
808
  if (fslio->niftiptr == NULL) {
 
809
        FSLIOERR("FslReadAllVolumes: error reading NIfTI image");
 
810
        return(NULL);
 
811
  }
 
812
 
 
813
  FslSetFileType(fslio,fslio->niftiptr->nifti_type);
 
814
  FslSetWriteMode(fslio,0);
 
815
  return fslio->niftiptr->data;
 
816
}
 
817
 
 
818
 
 
819
 
 
820
/***************************************************************
 
821
 * FslReadVolumes
 
822
 ***************************************************************/
 
823
/*! \fn size_t FslReadVolumes(FSLIO *fslio, void *buffer, size_t nvols)
 
824
    \brief Read the first nvols Volumes from a 4D dataset
 
825
 
 
826
    \param fslio pointer to open dataset
 
827
    \param buffer buffer to read data into, allocated by ???
 
828
    \param nvols  number of volumes to read
 
829
    \return Number of volumes read.
 
830
 */
 
831
size_t FslReadVolumes(FSLIO *fslio, void *buffer, size_t nvols)
 
832
{
 
833
  int volbytes;
 
834
  size_t retval=0;
 
835
  if (fslio==NULL)  FSLIOERR("FslReadVolumes: Null pointer passed for FSLIO");
 
836
  if (znz_isnull(fslio->fileptr))  FSLIOERR("FslReadVolumes: Null file pointer");
 
837
  if (fslio->niftiptr!=NULL) {
 
838
    fslio->niftiptr->data = buffer;
 
839
    volbytes = FslGetVolSize(fslio)  * fslio->niftiptr->nbyper;
 
840
    retval = nifti_read_buffer(fslio->fileptr,fslio->niftiptr->data,nvols*volbytes,fslio->niftiptr);
 
841
    retval /= volbytes;
 
842
  }
 
843
 
 
844
  if (fslio->mincptr!=NULL) {
 
845
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
846
  }
 
847
  return retval;
 
848
}
 
849
 
 
850
 
 
851
 
 
852
/***************************************************************
 
853
 * FslWriteAllVolumes
 
854
 ***************************************************************/
 
855
/*! \fn void FslWriteAllVolumes(FSLIO *fslio, const void *buffer)
 
856
    \brief  Writes all data from buffer (using size info from fslio) to file.
 
857
        
 
858
        Dimension and datatype of buffer are as is specified in nifti_image structure
 
859
        fslio->niftiptr.
 
860
        Note: If file format is Analyze (not nifti) and in Neurological order then 
 
861
        SWAP DATA into Radiological order.
 
862
 
 
863
    \param fslio pointer to open dataset
 
864
    \param buffer pointer to data array. Size and datatype of this buffer  
 
865
 */
 
866
void FslWriteAllVolumes(FSLIO *fslio, const void *buffer)
 
867
{
 
868
  short x,y,z,t=1;
 
869
 
 
870
  if (fslio==NULL)  FSLIOERR("FslWriteAllVolumes: Null pointer passed for FSLIO");
 
871
 
 
872
  FslGetDim(fslio,&x,&y,&z,&t);
 
873
  FslWriteHeader(fslio);
 
874
  FslWriteVolumes(fslio,buffer,t);
 
875
  return;
 
876
}
 
877
 
 
878
 
 
879
 
 
880
/***************************************************************
 
881
 * FslWriteVolumes
 
882
 ***************************************************************/
 
883
/*! \fn size_t FslWriteVolumes(FSLIO *fslio, const void *buffer, size_t nvols)
 
884
    \brief Write the first nvols volumes in buffer to disk.  
 
885
 
 
886
        Dimension and datatype of buffer are as is specified in nifti_image structure
 
887
        fslio->niftiptr.
 
888
        Note: If file format is Analyze (not nifti) and in Neurological order then 
 
889
        SWAP DATA into Radiological order.
 
890
 
 
891
        
 
892
    \param fslio        pointer to open dataset
 
893
    \param buffer       pointer to data array. Size and datatype of this buffer  
 
894
    \param nvols        number of volumes to write
 
895
    \return ??? looks like return of retval is missing ???  0 on error.
 
896
 */
 
897
size_t FslWriteVolumes(FSLIO *fslio, const void *buffer, size_t nvols)
 
898
{
 
899
  /* The dimensions and datatype must be set before calling this function */
 
900
  int retval=0;
 
901
  if (fslio==NULL)  FSLIOERR("FslWriteVolumes: Null pointer passed for FSLIO");
 
902
  if ( (!fslio->written_hdr) && (FslIsSingleFileType(FslGetFileType(fslio))) &&
 
903
       (FslIsCompressedFileType(FslGetFileType(fslio))) )
 
904
    { FSLIOERR("FslWriteVolumes: header must be written before data for single compressed file types"); }
 
905
  
 
906
  if (fslio->niftiptr!=NULL) {
 
907
    long int nbytes, bpv;
 
908
    bpv = fslio->niftiptr->nbyper;  /* bytes per voxel */
 
909
    nbytes = nvols * FslGetVolSize(fslio) * bpv;
 
910
 
 
911
    if ( (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_ANALYZE)
 
912
         && (FslGetLeftRightOrder(fslio)==FSL_NEUROLOGICAL) ) {
 
913
      /* If it is Analyze and Neurological order then SWAP DATA into Radiological order */
 
914
      /* This is nasty - but what else can be done?!? */
 
915
      char *tmpbuf, *inbuf;
 
916
      long int x, b, n, nrows;
 
917
      short nx=1, ny, nz, nv;
 
918
      inbuf = (char *) buffer;
 
919
      tmpbuf = (char *)calloc(nbytes,1);
 
920
      FslGetDim(fslio,&nx,&ny,&nz,&nv);
 
921
      nrows = nbytes / (nx * bpv);
 
922
      for (n=0; n<nrows; n++) {
 
923
        for (x=0; x<nx; x++) {
 
924
          for (b=0; b<bpv; b++) {
 
925
            tmpbuf[b +  bpv * (n*nx + nx - 1 - x)] = inbuf[b + bpv * (n*nx + x)];
 
926
          }
 
927
        }
 
928
      }
 
929
      retval = nifti_write_buffer(fslio->fileptr, tmpbuf, nbytes);
 
930
      free(tmpbuf);
 
931
    } else {
 
932
      retval = nifti_write_buffer(fslio->fileptr, buffer, nbytes);
 
933
    }
 
934
  }
 
935
  if (fslio->mincptr!=NULL) {
 
936
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
937
  }
 
938
  return retval;  /* failure */
 
939
}
 
940
 
 
941
 
 
942
/***************************************************************
 
943
 * FslWriteHeader
 
944
 ***************************************************************/
 
945
/*! \fn void FslWriteHeader(FSLIO *fslio)
 
946
    \brief Writes nifti/anz header and opens img file ready for writing
 
947
        
 
948
    \param fslio        pointer to open dataset
 
949
 */
 
950
void FslWriteHeader(FSLIO *fslio)
 
951
{
 
952
  short sform_code, qform_code;
 
953
  mat44 smat, qmat;
 
954
  /* writes header and opens img file ready for writing */
 
955
  if (fslio==NULL)  FSLIOERR("FslWriteHeader: Null pointer passed for FSLIO");
 
956
 
 
957
  if (fslio->niftiptr!=NULL) {
 
958
    fslio->written_hdr = 1;
 
959
    if (znz_isnull(fslio->fileptr)) FSLIOERR("FslWriteHeader: no file opened!");
 
960
    /* modify niftiptr for FSL-specific purposes */
 
961
    strcpy(fslio->niftiptr->descrip,"FSL4.0");
 
962
    /* set qform to equal sform if currently unset (or vice versa) */
 
963
    qform_code = FslGetRigidXform(fslio,&qmat);
 
964
    sform_code = FslGetStdXform(fslio,&smat);
 
965
    if ( (sform_code != NIFTI_XFORM_UNKNOWN) && 
 
966
         (qform_code == NIFTI_XFORM_UNKNOWN) ) {
 
967
      FslSetRigidXform(fslio,sform_code,smat);
 
968
    }
 
969
    if ( (qform_code != NIFTI_XFORM_UNKNOWN) && 
 
970
         (sform_code == NIFTI_XFORM_UNKNOWN) ) {
 
971
      FslSetStdXform(fslio,qform_code,qmat);
 
972
    }
 
973
    if (FslIsSingleFileType(FslGetFileType(fslio))) {
 
974
      /* write header info but don't close the file */
 
975
      nifti_image_write_hdr_img2(fslio->niftiptr,2,"wb",fslio->fileptr,NULL);
 
976
      /* set up pointer at end of iname_offset for single files only */
 
977
      FslSeekVolume(fslio,0);
 
978
    } else {
 
979
      /* open a new hdr file, write it and close it */
 
980
      nifti_image_write_hdr_img(fslio->niftiptr,0,"wb");
 
981
    }
 
982
  }
 
983
 
 
984
  if (fslio->mincptr!=NULL) {
 
985
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
986
  }
 
987
  return;
 
988
}
 
989
 
 
990
 
 
991
/***************************************************************
 
992
 * FslReadSliceSeries
 
993
 ***************************************************************/
 
994
/*! \fn size_t FslReadSliceSeries(FSLIO *fslio, void *buffer, short slice, size_t nvols)
 
995
    \brief Read one slice from each of the first nvols volumes in the dataset, ie get an xyt buffer.
 
996
 
 
997
        Dimension and datatype of buffer are as is specified in nifti_image structure
 
998
        fslio->niftiptr.
 
999
        Note: filepointer in file data array is restored to its initial position.
 
1000
        
 
1001
    \param fslio        pointer to open dataset
 
1002
    \param buffer       buffer large enough to hold 1 slice from each volume
 
1003
    \param slice        slice number (0 based) to read  [0 z-1]
 
1004
    \param nvols        number of volumes to read a slice from 
 
1005
    \return             Number of volumes from which a slice was successfully read. 0 on error.
 
1006
 */
 
1007
size_t FslReadSliceSeries(FSLIO *fslio, void *buffer, short slice, size_t nvols)
 
1008
{
 
1009
  size_t slbytes,volbytes;
 
1010
  size_t n, orig_offset;
 
1011
  short x,y,z,v,type;
 
1012
 
 
1013
  if (fslio==NULL)  FSLIOERR("FslReadSliceSeries: Null pointer passed for FSLIO");
 
1014
  if (fslio->niftiptr!=NULL) {
 
1015
    
 
1016
    FslGetDim(fslio,&x,&y,&z,&v);
 
1017
    
 
1018
    if ((slice<0) || (slice>=z)) FSLIOERR("FslReadSliceSeries: slice outside valid range");
 
1019
    
 
1020
    slbytes = x * y * (FslGetDataType(fslio, &type) / 8);
 
1021
    volbytes = slbytes * z;
 
1022
    
 
1023
    orig_offset = znztell(fslio->fileptr);
 
1024
    znzseek(fslio->fileptr, slbytes*slice, SEEK_CUR);
 
1025
    
 
1026
    for (n=0; n<nvols; n++) {
 
1027
      if (n>0) znzseek(fslio->fileptr, volbytes - slbytes, SEEK_CUR);
 
1028
      if (znzread((char *)buffer+n*slbytes, 1, slbytes, fslio->fileptr) != slbytes)
 
1029
        FSLIOERR("FslReadSliceSeries: failed to read values");
 
1030
     if (fslio->niftiptr->byteorder != nifti_short_order())
 
1031
        nifti_swap_Nbytes(slbytes / fslio->niftiptr->swapsize,
 
1032
                          fslio->niftiptr->swapsize, (char *)buffer+n*slbytes);
 
1033
     }
 
1034
    
 
1035
    
 
1036
    /* restore file pointer to original position */
 
1037
    znzseek(fslio->fileptr,orig_offset,SEEK_SET);
 
1038
    return n;
 
1039
  }
 
1040
  if (fslio->mincptr!=NULL) {
 
1041
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1042
  }
 
1043
  return 0;
 
1044
}
 
1045
 
 
1046
 
 
1047
/***************************************************************
 
1048
 * FslReadRowSeries
 
1049
 ***************************************************************/
 
1050
/*! \fn size_t FslReadRowSeries(FSLIO *fslio, void *buffer, short row, short slice, size_t nvols)
 
1051
    \brief Read one row from one slice for first nvols volumes in dataset; ie get an xt buffer.
 
1052
 
 
1053
        Dimension and datatype of buffer are as is specified in nifti_image structure
 
1054
        fslio->niftiptr.
 
1055
        Note: filepointer in file data array is restored to its initial position.
 
1056
        
 
1057
    \param fslio        pointer to open dataset
 
1058
    \param buffer       buffer to hold one row from each volume.
 
1059
    \param row          row number (0 based) to read [0 y-1]
 
1060
    \param slice        slice number (0 based) to read
 
1061
    \param nvols        number of volumes to read a row from 
 
1062
    \return Number of volumes from which a row was successfully read. 0 on error.
 
1063
 */
 
1064
size_t FslReadRowSeries(FSLIO *fslio, void *buffer, short row, short slice, size_t nvols)
 
1065
{
 
1066
  size_t rowbytes,slbytes,volbytes;
 
1067
  size_t n, orig_offset;
 
1068
  short x,y,z,v,type;
 
1069
  
 
1070
  if (fslio==NULL)  FSLIOERR("FslReadRowSeries: Null pointer passed for FSLIO");
 
1071
  if (fslio->niftiptr!=NULL) {
 
1072
    
 
1073
    FslGetDim(fslio,&x,&y,&z,&v);
 
1074
    
 
1075
    if ((slice<0) || (slice>=z)) FSLIOERR("FslReadRowSeries: slice outside valid range");
 
1076
    if ((row<0) || (row>=y)) FSLIOERR("FslReadRowSeries: row outside valid range");
 
1077
    
 
1078
    rowbytes = x * (FslGetDataType(fslio, &type)) / 8;
 
1079
    slbytes = rowbytes * y;
 
1080
    volbytes = slbytes * z;
 
1081
    
 
1082
    orig_offset = znztell(fslio->fileptr);
 
1083
    znzseek(fslio->fileptr, rowbytes*row + slbytes*slice, SEEK_CUR);
 
1084
    
 
1085
    for (n=0; n<nvols; n++){
 
1086
      if (n>0) znzseek(fslio->fileptr, volbytes - rowbytes, SEEK_CUR);
 
1087
      if (znzread((char *)buffer+n*rowbytes, 1, rowbytes, fslio->fileptr) != rowbytes)
 
1088
        FSLIOERR("FslReadRowSeries: failed to read values");
 
1089
      if (fslio->niftiptr->byteorder != nifti_short_order())
 
1090
        nifti_swap_Nbytes(rowbytes / fslio->niftiptr->swapsize,
 
1091
                          fslio->niftiptr->swapsize, (char *)buffer+n*rowbytes);
 
1092
    }
 
1093
    
 
1094
    /* restore file pointer to original position */
 
1095
    znzseek(fslio->fileptr,orig_offset,SEEK_SET);
 
1096
    return n;
 
1097
  }
 
1098
  if (fslio->mincptr!=NULL) {
 
1099
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1100
  }
 
1101
  return 0;
 
1102
}
 
1103
 
 
1104
 
 
1105
/***************************************************************
 
1106
 * FslReadTimeSeries
 
1107
 ***************************************************************/
 
1108
/*! \fn size_t FslReadTimeSeries(FSLIO *fslio, void *buffer, short xVox, short yVox, short zVox, size_t nvols)
 
1109
    \brief Read one voxel (xyz location) from first nvols volumes in dataset; ie get a t  dim buffer.
 
1110
 
 
1111
        Dimension and datatype of buffer are as is specified in nifti_image structure
 
1112
        fslio->niftiptr.
 
1113
        Note: filepointer in file data array is restored to its initial position.
 
1114
        
 
1115
    \param fslio        pointer to open dataset
 
1116
    \param buffer       buffer to hold one timeseries vector
 
1117
    \param xVox         x voxel [0 x-1]
 
1118
    \param yVox         y voxel [0 y-1]
 
1119
    \param zVox         z voxel [0 z-1]
 
1120
    \param nvols        number of volumes to read a voxel from
 
1121
    \return Number of volumes from which a voxel was successfully read. 0 on error.
 
1122
 */
 
1123
size_t FslReadTimeSeries(FSLIO *fslio, void *buffer, short xVox, short yVox, short zVox, 
 
1124
                         size_t nvols)
 
1125
{
 
1126
  size_t volbytes, offset, orig_offset;
 
1127
  size_t n;
 
1128
  short xdim,ydim,zdim,v,wordsize;
 
1129
 
 
1130
  if (fslio==NULL)  FSLIOERR("FslReadTimeSeries: Null pointer passed for FSLIO");
 
1131
  if (fslio->niftiptr!=NULL) {
 
1132
 
 
1133
    FslGetDim(fslio,&xdim,&ydim,&zdim,&v);
 
1134
    
 
1135
    if ((xVox<0) || (xVox >=xdim)) FSLIOERR("FslReadTimeSeries: voxel outside valid range");
 
1136
    if ((yVox<0) || (yVox >=ydim)) FSLIOERR("FslReadTimeSeries: voxel outside valid range");
 
1137
    if ((zVox<0) || (zVox >=zdim)) FSLIOERR("FslReadTimeSeries: voxel outside valid range");
 
1138
    
 
1139
    wordsize = fslio->niftiptr->nbyper;
 
1140
    volbytes = xdim * ydim * zdim * wordsize;
 
1141
    
 
1142
    orig_offset = znztell(fslio->fileptr);
 
1143
    offset = ((ydim * zVox + yVox) * xdim + xVox) * wordsize;
 
1144
    znzseek(fslio->fileptr,offset,SEEK_CUR);
 
1145
    
 
1146
    for (n=0; n<nvols; n++) {
 
1147
      if (n>0) znzseek(fslio->fileptr, volbytes - wordsize, SEEK_CUR);
 
1148
      if (znzread((char *)buffer+(n*wordsize), 1, wordsize,fslio->fileptr) != wordsize)
 
1149
        FSLIOERR("FslReadTimeSeries: failed to read values"); 
 
1150
      if (fslio->niftiptr->byteorder != nifti_short_order())
 
1151
        nifti_swap_Nbytes(1,fslio->niftiptr->swapsize,
 
1152
                          (char *)buffer+(n*wordsize));
 
1153
    }
 
1154
    
 
1155
    /* restore file pointer to original position */
 
1156
    znzseek(fslio->fileptr,orig_offset,SEEK_SET);
 
1157
    return n;
 
1158
 
 
1159
  }
 
1160
  if (fslio->mincptr!=NULL) {
 
1161
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1162
  }
 
1163
  return 0;
 
1164
}
 
1165
 
 
1166
 
 
1167
size_t FslReadCplxVolumes(FSLIO *fslio, void *buffer, size_t nvols, char mode)
 
1168
{
 
1169
  if (fslio==NULL)  FSLIOERR("FslReadCplxVolumes: Null pointer passed for FSLIO");
 
1170
  fprintf(stderr,"Warning:: FslReadCplxVolumes is not yet supported\n");
 
1171
  return 0;
 
1172
}
 
1173
 
 
1174
size_t FslWriteCplxVolumes(FSLIO *fslio, void *buffer, size_t nvols, char mode)
 
1175
{
 
1176
  if (fslio==NULL)  FSLIOERR("FslWriteCplxVolumes: Null pointer passed for FSLIO");
 
1177
  fprintf(stderr,"Warning:: FslWriteCplxVolumes is not yet supported\n");
 
1178
  return 0;
 
1179
}
 
1180
 
 
1181
long FslSeekVolume(FSLIO *fslio, size_t vols)
 
1182
{
 
1183
  long offset;
 
1184
  if (fslio==NULL)  FSLIOERR("FslSeekVolume: Null pointer passed for FSLIO");
 
1185
  if (fslio->niftiptr!=NULL) {
 
1186
    offset = fslio->niftiptr->iname_offset + 
 
1187
      vols * FslGetVolSize(fslio) * fslio->niftiptr->nbyper;
 
1188
    if (znz_isnull(fslio->fileptr)) FSLIOERR("FslSeekVolume: Null file pointer");
 
1189
    return znzseek(fslio->fileptr,offset,SEEK_SET);
 
1190
  }
 
1191
  if (fslio->mincptr!=NULL) {
 
1192
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1193
  }
 
1194
  return 0;
 
1195
}
 
1196
 
 
1197
size_t FslGetVolSize(FSLIO *fslio)
 
1198
{
 
1199
  /* returns number of voxels per 3D volume */
 
1200
  if (fslio==NULL)  FSLIOERR("FslGetVolSize: Null pointer passed for FSLIO");
 
1201
  if (fslio->niftiptr!=NULL) {
 
1202
    return (fslio->niftiptr->nx * fslio->niftiptr->ny * fslio->niftiptr->nz);
 
1203
  }
 
1204
  if (fslio->mincptr!=NULL) {
 
1205
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1206
  }
 
1207
  return 0;
 
1208
}
 
1209
 
 
1210
 
 
1211
void FslSetDim(FSLIO *fslio, short x, short y, short z, short v)
 
1212
{
 
1213
  int ndim;
 
1214
  if (fslio==NULL)  FSLIOERR("FslSetDim: Null pointer passed for FSLIO");
 
1215
  if (fslio->niftiptr!=NULL) {
 
1216
 
 
1217
    ndim=4;
 
1218
    if (v<=1) {ndim--; if (z<=1) {ndim--; if (y<=1) {ndim--; if (x<=1) {ndim--;}}}}
 
1219
 
 
1220
    fslio->niftiptr->ndim = ndim;
 
1221
 
 
1222
    if (x>=1) fslio->niftiptr->nx = x; else fslio->niftiptr->nx=1;
 
1223
    if (y>=1) fslio->niftiptr->ny = y; else fslio->niftiptr->ny=1;
 
1224
    if (z>=1) fslio->niftiptr->nz = z; else fslio->niftiptr->nz=1;
 
1225
    if (v>=1) fslio->niftiptr->nt = v; else fslio->niftiptr->nt=1;
 
1226
    fslio->niftiptr->nu = 1;
 
1227
    fslio->niftiptr->nv = 1;
 
1228
    fslio->niftiptr->nw = 1;
 
1229
 
 
1230
    /* deal with stupid redundancies */
 
1231
    fslio->niftiptr->dim[0] = fslio->niftiptr->ndim ;
 
1232
    fslio->niftiptr->dim[1] = fslio->niftiptr->nx;
 
1233
    fslio->niftiptr->dim[2] = fslio->niftiptr->ny;
 
1234
    fslio->niftiptr->dim[3] = fslio->niftiptr->nz;
 
1235
    fslio->niftiptr->dim[4] = fslio->niftiptr->nt;
 
1236
    fslio->niftiptr->dim[5] = fslio->niftiptr->nu;
 
1237
    fslio->niftiptr->dim[6] = fslio->niftiptr->nv;
 
1238
    fslio->niftiptr->dim[7] = fslio->niftiptr->nw;
 
1239
 
 
1240
    fslio->niftiptr->nvox =  fslio->niftiptr->nx * fslio->niftiptr->ny * fslio->niftiptr->nz
 
1241
      * fslio->niftiptr->nt * fslio->niftiptr->nu * fslio->niftiptr->nv * fslio->niftiptr->nw ;
 
1242
 
 
1243
  }
 
1244
  if (fslio->mincptr!=NULL) {
 
1245
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1246
  }
 
1247
}
 
1248
 
 
1249
 
 
1250
void FslGetDim(FSLIO *fslio, short *x, short *y, short *z, short *v)
 
1251
{
 
1252
  if (fslio==NULL)  FSLIOERR("FslGetDim: Null pointer passed for FSLIO");
 
1253
  if (fslio->niftiptr!=NULL) {
 
1254
    *x = fslio->niftiptr->nx;
 
1255
    *y = fslio->niftiptr->ny;
 
1256
    *z = fslio->niftiptr->nz;
 
1257
    *v = fslio->niftiptr->nt;
 
1258
  }
 
1259
  if (fslio->mincptr!=NULL) {
 
1260
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1261
  }
 
1262
}
 
1263
 
 
1264
 
 
1265
void FslSetDimensionality(FSLIO *fslio, size_t dim)
 
1266
{
 
1267
  if (fslio==NULL)  FSLIOERR("FslSetDimensionality: Null pointer passed for FSLIO");
 
1268
  if (fslio->niftiptr!=NULL) {
 
1269
    fslio->niftiptr->ndim = dim;
 
1270
    fslio->niftiptr->dim[0] = dim;
 
1271
  }
 
1272
  if (fslio->mincptr!=NULL) {
 
1273
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1274
  }
 
1275
}
 
1276
 
 
1277
 
 
1278
void FslGetDimensionality(FSLIO *fslio, size_t *dim)
 
1279
{
 
1280
  if (fslio==NULL)  FSLIOERR("FslGetDimensionality: Null pointer passed for FSLIO");
 
1281
  if (fslio->niftiptr!=NULL) {
 
1282
    *dim = fslio->niftiptr->ndim;
 
1283
  }
 
1284
  if (fslio->mincptr!=NULL) {
 
1285
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1286
  }
 
1287
}
 
1288
 
 
1289
 
 
1290
void FslSetVoxDim(FSLIO *fslio, float x, float y, float z, float tr)
 
1291
{
 
1292
  if (fslio==NULL)  FSLIOERR("FslSetVoxDim: Null pointer passed for FSLIO");
 
1293
  if (fslio->niftiptr!=NULL) {
 
1294
    fslio->niftiptr->dx = fabs(x);
 
1295
    fslio->niftiptr->dy = fabs(y);
 
1296
    fslio->niftiptr->dz = fabs(z);
 
1297
    fslio->niftiptr->dt = fabs(tr);
 
1298
    fslio->niftiptr->pixdim[1] = fabs(x);
 
1299
    fslio->niftiptr->pixdim[2] = fabs(y);
 
1300
    fslio->niftiptr->pixdim[3] = fabs(z);
 
1301
    fslio->niftiptr->pixdim[4] = fabs(tr);
 
1302
    /* set the units to mm and seconds */
 
1303
    fslio->niftiptr->xyz_units  = NIFTI_UNITS_MM;
 
1304
    fslio->niftiptr->time_units = NIFTI_UNITS_SEC;
 
1305
 }
 
1306
  if (fslio->mincptr!=NULL) {
 
1307
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1308
  }
 
1309
}
 
1310
 
 
1311
 
 
1312
void FslGetVoxDim(FSLIO *fslio, float *x, float *y, float *z, float *tr)
 
1313
{
 
1314
  if (fslio==NULL)  FSLIOERR("FslGetVoxDim: Null pointer passed for FSLIO");
 
1315
  if (fslio->niftiptr!=NULL) {
 
1316
    *x = fabs(fslio->niftiptr->dx);
 
1317
    *y = fabs(fslio->niftiptr->dy);
 
1318
    *z = fabs(fslio->niftiptr->dz);
 
1319
    *tr = fabs(fslio->niftiptr->dt);
 
1320
    /* now check the units and convert to mm and sec */
 
1321
    if (fslio->niftiptr->xyz_units == NIFTI_UNITS_METER) 
 
1322
    { *x *= 1000.0;   *y *= 1000.0;   *z *= 1000.0; }
 
1323
    if (fslio->niftiptr->xyz_units == NIFTI_UNITS_MICRON) 
 
1324
    { *x /= 1000.0;   *y /= 1000.0;   *z /= 1000.0; }
 
1325
    if (fslio->niftiptr->xyz_units == NIFTI_UNITS_MSEC) 
 
1326
    { *tr /= 1000.0; }
 
1327
    if (fslio->niftiptr->xyz_units == NIFTI_UNITS_USEC) 
 
1328
    { *tr /= 1000000.0; }
 
1329
    /* if it is Hz or other frequency then leave it */
 
1330
  }
 
1331
  if (fslio->mincptr!=NULL) {
 
1332
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1333
  }
 
1334
}
 
1335
 
 
1336
 
 
1337
void FslGetCalMinMax(FSLIO *fslio, float *min, float *max)
 
1338
{
 
1339
  if (fslio==NULL)  FSLIOERR("FslGetCalMinMax: Null pointer passed for FSLIO");
 
1340
  if (fslio->niftiptr!=NULL) {
 
1341
    *min = fslio->niftiptr->cal_min;
 
1342
    *max = fslio->niftiptr->cal_max;
 
1343
  }
 
1344
  if (fslio->mincptr!=NULL) {
 
1345
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1346
  }
 
1347
}
 
1348
 
 
1349
 
 
1350
void FslSetCalMinMax(FSLIO *fslio, float  min, float  max)
 
1351
{
 
1352
  if (fslio==NULL)  FSLIOERR("FslSetCalMinMax: Null pointer passed for FSLIO");
 
1353
  if (fslio->niftiptr!=NULL) {
 
1354
    fslio->niftiptr->cal_min = min;
 
1355
    fslio->niftiptr->cal_max = max;
 
1356
  }
 
1357
  if (fslio->mincptr!=NULL) {
 
1358
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1359
  }
 
1360
}
 
1361
 
 
1362
 
 
1363
void FslGetAuxFile(FSLIO *fslio,char *aux_file)
 
1364
{
 
1365
  if (fslio==NULL)  FSLIOERR("FslGetAuxFile: Null pointer passed for FSLIO");
 
1366
  if (fslio->niftiptr!=NULL) {
 
1367
    strncpy(aux_file,fslio->niftiptr->aux_file, 24);
 
1368
    aux_file[23] = '\0';
 
1369
  }
 
1370
  if (fslio->mincptr!=NULL) {
 
1371
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1372
  }
 
1373
}
 
1374
 
 
1375
 
 
1376
void FslSetAuxFile(FSLIO *fslio,const char *aux_file)
 
1377
{
 
1378
  if (fslio==NULL)  FSLIOERR("FslSetAuxFile: Null pointer passed for FSLIO");
 
1379
  if (fslio->niftiptr!=NULL) {
 
1380
    strncpy(fslio->niftiptr->aux_file, aux_file, 24);
 
1381
  }
 
1382
  if (fslio->mincptr!=NULL) {
 
1383
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1384
  }
 
1385
}
 
1386
 
 
1387
 
 
1388
void FslSetVoxUnits(FSLIO *fslio, const char *units)
 
1389
{
 
1390
  int unitcode=0;
 
1391
  if (fslio==NULL)  FSLIOERR("FslSetVoxUnits: Null pointer passed for FSLIO");
 
1392
  if (fslio->niftiptr!=NULL) {
 
1393
    if (strcmp(units,nifti_units_string(NIFTI_UNITS_METER))==0) {
 
1394
      unitcode = NIFTI_UNITS_METER;
 
1395
    } else if (strcmp(units,nifti_units_string(NIFTI_UNITS_MM))==0) {
 
1396
      unitcode = NIFTI_UNITS_MM;
 
1397
    } else if (strcmp(units,nifti_units_string(NIFTI_UNITS_MICRON))==0) {
 
1398
      unitcode = NIFTI_UNITS_MICRON;
 
1399
    }
 
1400
    fslio->niftiptr->xyz_units  = unitcode;
 
1401
  }
 
1402
  if (fslio->mincptr!=NULL) {
 
1403
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1404
  }
 
1405
}
 
1406
 
 
1407
 
 
1408
void FslGetVoxUnits(FSLIO *fslio, char *units)
 
1409
{
 
1410
  if (fslio==NULL)  FSLIOERR("FslGetVoxUnits: Null pointer passed for FSLIO");
 
1411
  if (fslio->niftiptr!=NULL) {
 
1412
    strcpy(units,nifti_units_string(fslio->niftiptr->xyz_units));
 
1413
  }
 
1414
  if (fslio->mincptr!=NULL) {
 
1415
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1416
  }
 
1417
}
 
1418
 
 
1419
void FslSetTimeUnits(FSLIO *fslio, const char *units)
 
1420
{
 
1421
  int unitcode=0;
 
1422
  if (fslio==NULL)  FSLIOERR("FslSetTimeUnits: Null pointer passed for FSLIO");
 
1423
  if (fslio->niftiptr!=NULL) {
 
1424
    if (strcmp(units,nifti_units_string(NIFTI_UNITS_HZ))==0) {
 
1425
      unitcode = NIFTI_UNITS_HZ;
 
1426
    } else if (strcmp(units,nifti_units_string(NIFTI_UNITS_PPM))==0) {
 
1427
      unitcode = NIFTI_UNITS_PPM;
 
1428
    } else if (strcmp(units,nifti_units_string(NIFTI_UNITS_RADS))==0) {
 
1429
      unitcode = NIFTI_UNITS_RADS;
 
1430
    } else if (strcmp(units,nifti_units_string(NIFTI_UNITS_SEC))==0) {
 
1431
      unitcode = NIFTI_UNITS_SEC;
 
1432
    } else if (strcmp(units,nifti_units_string(NIFTI_UNITS_MSEC))==0) {
 
1433
        fprintf(stderr,"Warning::Setting time units to msec is not fully recommended in fslio\n");
 
1434
        unitcode = NIFTI_UNITS_MSEC;
 
1435
    } else if (strcmp(units,nifti_units_string(NIFTI_UNITS_USEC))==0) {
 
1436
        fprintf(stderr,"Warning::Setting time units to msec is not fully recommended in fslio\n");
 
1437
        unitcode = NIFTI_UNITS_USEC;
 
1438
    }
 
1439
    fslio->niftiptr->time_units = unitcode;
 
1440
  }
 
1441
  if (fslio->mincptr!=NULL) {
 
1442
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1443
  }
 
1444
}
 
1445
 
 
1446
 
 
1447
void FslGetTimeUnits(FSLIO *fslio, char *units)
 
1448
{
 
1449
  if (fslio==NULL)  FSLIOERR("FslGetTimeUnits: Null pointer passed for FSLIO");
 
1450
  if (fslio->niftiptr!=NULL) {
 
1451
    strcpy(units,nifti_units_string(fslio->niftiptr->time_units));
 
1452
  }
 
1453
  if (fslio->mincptr!=NULL) {
 
1454
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1455
  }
 
1456
}
 
1457
 
 
1458
 
 
1459
void FslSetDataType(FSLIO *fslio, short t)
 
1460
{
 
1461
  int nbytepix=0, ss=0;
 
1462
  if (fslio==NULL)  FSLIOERR("FslSetDataType: Null pointer passed for FSLIO");
 
1463
  if (fslio->niftiptr!=NULL) {
 
1464
    fslio->niftiptr->datatype = t;
 
1465
    nifti_datatype_sizes(t,&nbytepix,&ss);
 
1466
    fslio->niftiptr->nbyper = nbytepix;
 
1467
  }
 
1468
  if (fslio->mincptr!=NULL) {
 
1469
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1470
  }
 
1471
}
 
1472
 
 
1473
size_t FslGetDataType(FSLIO *fslio, short *t)
 
1474
{
 
1475
    /* returns bits per pixel */
 
1476
  int nbytepix=32, ss=0;
 
1477
  if (fslio==NULL)  FSLIOERR("FslGetDataType: Null pointer passed for FSLIO");
 
1478
  if (fslio->niftiptr!=NULL) {
 
1479
    *t = fslio->niftiptr->datatype;
 
1480
    nifti_datatype_sizes(*t,&nbytepix,&ss);
 
1481
  }
 
1482
  if (fslio->mincptr!=NULL) {
 
1483
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1484
  }
 
1485
  return (size_t) 8 * nbytepix;
 
1486
}
 
1487
 
 
1488
 
 
1489
void FslGetMMCoord(mat44 stdmat, float voxx, float voxy, float voxz, 
 
1490
                   float *mmx, float *mmy, float *mmz) 
 
1491
{
 
1492
    *mmx = stdmat.m[0][0] * voxx + stdmat.m[0][1] * voxy + stdmat.m[0][2] * voxz 
 
1493
        + stdmat.m[0][3];
 
1494
    *mmy = stdmat.m[1][0] * voxx + stdmat.m[1][1] * voxy + stdmat.m[1][2] * voxz 
 
1495
        + stdmat.m[1][3];
 
1496
    *mmz = stdmat.m[2][0] * voxx + stdmat.m[2][1] * voxy + stdmat.m[2][2] * voxz 
 
1497
        + stdmat.m[2][3];
 
1498
}
 
1499
 
 
1500
 
 
1501
void FslGetVoxCoord(mat44 stdmat, float mmx, float mmy, float mmz, 
 
1502
                   float *voxx, float *voxy, float *voxz) 
 
1503
{
 
1504
  mat44 mm2vox;
 
1505
 
 
1506
  mm2vox = nifti_mat44_inverse(stdmat);
 
1507
    *voxx = mm2vox.m[0][0] * mmx + mm2vox.m[0][1] * mmy + mm2vox.m[0][2] * mmz 
 
1508
        + mm2vox.m[0][3];
 
1509
    *voxy = mm2vox.m[1][0] * mmx + mm2vox.m[1][1] * mmy + mm2vox.m[1][2] * mmz 
 
1510
        + mm2vox.m[1][3];
 
1511
    *voxz = mm2vox.m[2][0] * mmx + mm2vox.m[2][1] * mmy + mm2vox.m[2][2] * mmz 
 
1512
        + mm2vox.m[2][3];
 
1513
}
 
1514
 
 
1515
 
 
1516
void FslSetStdXform(FSLIO *fslio, short sform_code, mat44 stdmat)
 
1517
{
 
1518
    /* NB: stdmat must point to a 4x4 array */
 
1519
  if (fslio==NULL)  FSLIOERR("FslSetStdXform: Null pointer passed for FSLIO");
 
1520
  if (fslio->niftiptr!=NULL) {
 
1521
      fslio->niftiptr->sform_code = sform_code;
 
1522
      fslio->niftiptr->sto_xyz.m[0][0] = stdmat.m[0][0];
 
1523
      fslio->niftiptr->sto_xyz.m[0][1] = stdmat.m[0][1];
 
1524
      fslio->niftiptr->sto_xyz.m[0][2] = stdmat.m[0][2];
 
1525
      fslio->niftiptr->sto_xyz.m[0][3] = stdmat.m[0][3];
 
1526
      fslio->niftiptr->sto_xyz.m[1][0] = stdmat.m[1][0];
 
1527
      fslio->niftiptr->sto_xyz.m[1][1] = stdmat.m[1][1];
 
1528
      fslio->niftiptr->sto_xyz.m[1][2] = stdmat.m[1][2];
 
1529
      fslio->niftiptr->sto_xyz.m[1][3] = stdmat.m[1][3];
 
1530
      fslio->niftiptr->sto_xyz.m[2][0] = stdmat.m[2][0];
 
1531
      fslio->niftiptr->sto_xyz.m[2][1] = stdmat.m[2][1];
 
1532
      fslio->niftiptr->sto_xyz.m[2][2] = stdmat.m[2][2];
 
1533
      fslio->niftiptr->sto_xyz.m[2][3] = stdmat.m[2][3];
 
1534
      fslio->niftiptr->sto_xyz.m[3][0] = 0;
 
1535
      fslio->niftiptr->sto_xyz.m[3][1] = 0;
 
1536
      fslio->niftiptr->sto_xyz.m[3][2] = 0;
 
1537
      fslio->niftiptr->sto_xyz.m[3][3] = 1;
 
1538
      fslio->niftiptr->sto_ijk = nifti_mat44_inverse(fslio->niftiptr->sto_xyz);
 
1539
  }
 
1540
  if (fslio->mincptr!=NULL) {
 
1541
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1542
  }
 
1543
}
 
1544
 
 
1545
 
 
1546
short FslGetStdXform(FSLIO *fslio, mat44 *stdmat)
 
1547
{
 
1548
    /* returns sform code  (NB: stdmat must point to a 4x4 array) */
 
1549
    float dx,dy,dz,tr;
 
1550
    if (fslio==NULL)  FSLIOERR("FslGetStdXform: Null pointer passed for FSLIO");
 
1551
    if (fslio->niftiptr!=NULL) {
 
1552
        stdmat->m[0][0] = fslio->niftiptr->sto_xyz.m[0][0];
 
1553
        stdmat->m[0][1] = fslio->niftiptr->sto_xyz.m[0][1];
 
1554
        stdmat->m[0][2] = fslio->niftiptr->sto_xyz.m[0][2];
 
1555
        stdmat->m[0][3] = fslio->niftiptr->sto_xyz.m[0][3];
 
1556
        stdmat->m[1][0] = fslio->niftiptr->sto_xyz.m[1][0];
 
1557
        stdmat->m[1][1] = fslio->niftiptr->sto_xyz.m[1][1];
 
1558
        stdmat->m[1][2] = fslio->niftiptr->sto_xyz.m[1][2];
 
1559
        stdmat->m[1][3] = fslio->niftiptr->sto_xyz.m[1][3];
 
1560
        stdmat->m[2][0] = fslio->niftiptr->sto_xyz.m[2][0];
 
1561
        stdmat->m[2][1] = fslio->niftiptr->sto_xyz.m[2][1];
 
1562
        stdmat->m[2][2] = fslio->niftiptr->sto_xyz.m[2][2];
 
1563
        stdmat->m[2][3] = fslio->niftiptr->sto_xyz.m[2][3];
 
1564
        stdmat->m[3][0] = 0.0;
 
1565
        stdmat->m[3][1] = 0.0;
 
1566
        stdmat->m[3][2] = 0.0;
 
1567
        stdmat->m[3][3] = 1.0;
 
1568
        
 
1569
        /* the code below gives a default but it really should never be used */
 
1570
        if (fslio->niftiptr->sform_code == NIFTI_XFORM_UNKNOWN) {
 
1571
            FslGetVoxDim(fslio,&dx,&dy,&dz,&tr);
 
1572
            stdmat->m[0][0] = -dx;  /* default Radiological convention */
 
1573
            stdmat->m[0][1] = 0;
 
1574
            stdmat->m[0][2] = 0;
 
1575
            stdmat->m[0][3] = 0;
 
1576
            stdmat->m[1][0] = 0;
 
1577
            stdmat->m[1][1] = dy;
 
1578
            stdmat->m[1][2] = 0;
 
1579
            stdmat->m[1][3] = 0;
 
1580
            stdmat->m[2][0] = 0;
 
1581
            stdmat->m[2][1] = 0;
 
1582
            stdmat->m[2][2] = dz;
 
1583
            stdmat->m[2][3] = 0;
 
1584
            stdmat->m[3][0] = 0.0;
 
1585
            stdmat->m[3][1] = 0.0;
 
1586
            stdmat->m[3][2] = 0.0;
 
1587
            stdmat->m[3][3] = 1.0;
 
1588
        }
 
1589
        return fslio->niftiptr->sform_code;
 
1590
    }
 
1591
    if (fslio->mincptr!=NULL) {
 
1592
        fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1593
    }
 
1594
    return NIFTI_XFORM_UNKNOWN;
 
1595
}
 
1596
 
 
1597
 
 
1598
void FslSetRigidXform(FSLIO *fslio, short qform_code, mat44 rigidmat)
 
1599
{
 
1600
    /* NB: rigidmat must point to an allocated mat44 */
 
1601
  float dx, dy, dz;
 
1602
  if (fslio==NULL)  FSLIOERR("FslSetRigidXform: Null pointer passed for FSLIO");
 
1603
  if (fslio->niftiptr!=NULL) {
 
1604
      fslio->niftiptr->qform_code = qform_code;
 
1605
      fslio->niftiptr->qto_xyz.m[0][0] = rigidmat.m[0][0];
 
1606
      fslio->niftiptr->qto_xyz.m[0][1] = rigidmat.m[0][1];
 
1607
      fslio->niftiptr->qto_xyz.m[0][2] = rigidmat.m[0][2];
 
1608
      fslio->niftiptr->qto_xyz.m[0][3] = rigidmat.m[0][3];
 
1609
      fslio->niftiptr->qto_xyz.m[1][0] = rigidmat.m[1][0];
 
1610
      fslio->niftiptr->qto_xyz.m[1][1] = rigidmat.m[1][1];
 
1611
      fslio->niftiptr->qto_xyz.m[1][2] = rigidmat.m[1][2];
 
1612
      fslio->niftiptr->qto_xyz.m[1][3] = rigidmat.m[1][3];
 
1613
      fslio->niftiptr->qto_xyz.m[2][0] = rigidmat.m[2][0];
 
1614
      fslio->niftiptr->qto_xyz.m[2][1] = rigidmat.m[2][1];
 
1615
      fslio->niftiptr->qto_xyz.m[2][2] = rigidmat.m[2][2];
 
1616
      fslio->niftiptr->qto_xyz.m[2][3] = rigidmat.m[2][3];
 
1617
      fslio->niftiptr->qto_xyz.m[3][0] = 0;
 
1618
      fslio->niftiptr->qto_xyz.m[3][1] = 0;
 
1619
      fslio->niftiptr->qto_xyz.m[3][2] = 0;
 
1620
      fslio->niftiptr->qto_xyz.m[3][3] = 1;
 
1621
      nifti_mat44_to_quatern(
 
1622
            fslio->niftiptr->qto_xyz,&(fslio->niftiptr->quatern_b),
 
1623
            &(fslio->niftiptr->quatern_c),&(fslio->niftiptr->quatern_d),
 
1624
            &(fslio->niftiptr->qoffset_x),&(fslio->niftiptr->qoffset_y),
 
1625
            &(fslio->niftiptr->qoffset_z),&dx,&dy,&dz,&(fslio->niftiptr->qfac));
 
1626
      fslio->niftiptr->qto_ijk = nifti_mat44_inverse(fslio->niftiptr->qto_xyz);
 
1627
 
 
1628
  }
 
1629
  if (fslio->mincptr!=NULL) {
 
1630
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1631
  }
 
1632
}
 
1633
 
 
1634
 
 
1635
short FslGetRigidXform(FSLIO *fslio, mat44 *rigidmat)
 
1636
{
 
1637
    /* returns qform code  (NB: rigidmat must point to an allocated mat44) */
 
1638
    float dx,dy,dz,tr;
 
1639
    if (fslio==NULL)  FSLIOERR("FslGetRigidXform: Null pointer passed for FSLIO");
 
1640
    if (fslio->niftiptr!=NULL) {
 
1641
        rigidmat->m[0][0] = fslio->niftiptr->qto_xyz.m[0][0];
 
1642
        rigidmat->m[0][1] = fslio->niftiptr->qto_xyz.m[0][1];
 
1643
        rigidmat->m[0][2] = fslio->niftiptr->qto_xyz.m[0][2];
 
1644
        rigidmat->m[0][3] = fslio->niftiptr->qto_xyz.m[0][3];
 
1645
        rigidmat->m[1][0] = fslio->niftiptr->qto_xyz.m[1][0];
 
1646
        rigidmat->m[1][1] = fslio->niftiptr->qto_xyz.m[1][1];
 
1647
        rigidmat->m[1][2] = fslio->niftiptr->qto_xyz.m[1][2];
 
1648
        rigidmat->m[1][3] = fslio->niftiptr->qto_xyz.m[1][3];
 
1649
        rigidmat->m[2][0] = fslio->niftiptr->qto_xyz.m[2][0];
 
1650
        rigidmat->m[2][1] = fslio->niftiptr->qto_xyz.m[2][1];
 
1651
        rigidmat->m[2][2] = fslio->niftiptr->qto_xyz.m[2][2];
 
1652
        rigidmat->m[2][3] = fslio->niftiptr->qto_xyz.m[2][3];
 
1653
        rigidmat->m[3][0] = 0.0;
 
1654
        rigidmat->m[3][1] = 0.0;
 
1655
        rigidmat->m[3][2] = 0.0;
 
1656
        rigidmat->m[3][3] = 1.0;
 
1657
        
 
1658
        /* the code gives a default but it should never really be used */
 
1659
        if (fslio->niftiptr->qform_code == NIFTI_XFORM_UNKNOWN) {
 
1660
          FslGetVoxDim(fslio,&dx,&dy,&dz,&tr);
 
1661
          rigidmat->m[0][0] = dx;
 
1662
          rigidmat->m[0][1] = 0;
 
1663
          rigidmat->m[0][2] = 0;
 
1664
          rigidmat->m[0][3] = 0;
 
1665
          rigidmat->m[1][0] = 0;
 
1666
          rigidmat->m[1][1] = dy;
 
1667
          rigidmat->m[1][2] = 0;
 
1668
          rigidmat->m[1][3] = 0;
 
1669
          rigidmat->m[2][0] = 0;
 
1670
          rigidmat->m[2][1] = 0;
 
1671
          rigidmat->m[2][2] = dz;
 
1672
          rigidmat->m[2][3] = 0;
 
1673
          rigidmat->m[3][0] = 0.0;
 
1674
          rigidmat->m[3][1] = 0.0;
 
1675
          rigidmat->m[3][2] = 0.0;
 
1676
          rigidmat->m[3][3] = 1.0;
 
1677
        }
 
1678
        return fslio->niftiptr->qform_code;
 
1679
    }
 
1680
    if (fslio->mincptr!=NULL) {
 
1681
        fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1682
    }
 
1683
    return NIFTI_XFORM_UNKNOWN;
 
1684
}
 
1685
 
 
1686
 
 
1687
void FslSetIntent(FSLIO *fslio, short intent_code, float p1, float p2, float p3)
 
1688
{
 
1689
  if (fslio==NULL)  FSLIOERR("FslSetIntent: Null pointer passed for FSLIO");
 
1690
  if (fslio->niftiptr!=NULL) {
 
1691
      fslio->niftiptr->intent_code = intent_code;
 
1692
      fslio->niftiptr->intent_p1 = p1;
 
1693
      fslio->niftiptr->intent_p2 = p2;
 
1694
      fslio->niftiptr->intent_p3 = p3;
 
1695
  }
 
1696
  if (fslio->mincptr!=NULL) {
 
1697
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1698
  }
 
1699
}
 
1700
 
 
1701
 
 
1702
short FslGetIntent(FSLIO *fslio, short *intent_code, float *p1, float *p2,
 
1703
                   float *p3)
 
1704
{
 
1705
  /* also returns intent code */
 
1706
  if (fslio==NULL)  FSLIOERR("FslGetIntent: Null pointer passed for FSLIO");
 
1707
  if (fslio->niftiptr!=NULL) {
 
1708
      *intent_code = fslio->niftiptr->intent_code;
 
1709
      *p1 = fslio->niftiptr->intent_p1;
 
1710
      *p2 = fslio->niftiptr->intent_p2;
 
1711
      *p3 = fslio->niftiptr->intent_p3;
 
1712
      return fslio->niftiptr->intent_code;
 
1713
  }
 
1714
  if (fslio->mincptr!=NULL) {
 
1715
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1716
  }
 
1717
  return NIFTI_INTENT_NONE;
 
1718
}
 
1719
 
 
1720
 
 
1721
 
 
1722
 
 
1723
void FslSetIntensityScaling(FSLIO *fslio, float slope, float intercept)
 
1724
{
 
1725
  if (fslio==NULL)  FSLIOERR("FslSetIntensityScaling: Null pointer passed for FSLIO");
 
1726
  if (fslio->niftiptr!=NULL) {
 
1727
      fslio->niftiptr->scl_slope = slope;
 
1728
      fslio->niftiptr->scl_inter = intercept;
 
1729
  }
 
1730
  if (fslio->mincptr!=NULL) {
 
1731
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1732
  }
 
1733
}
 
1734
 
 
1735
 
 
1736
int FslGetIntensityScaling(FSLIO *fslio, float *slope, float *intercept)
 
1737
{
 
1738
  /* returns 1 if scaling required or 0 otherwise */
 
1739
  if (fslio==NULL)  FSLIOERR("FslGetIntensityScaling: Null pointer passed for FSLIO");
 
1740
  if (fslio->niftiptr!=NULL) {
 
1741
    *slope = fslio->niftiptr->scl_slope;
 
1742
    *intercept = fslio->niftiptr->scl_inter;
 
1743
    if (fabs(*slope)<1e-30) {
 
1744
      *slope = 1.0;
 
1745
      *intercept = 0.0;
 
1746
      return 0;
 
1747
    }
 
1748
    if ( (fabs(*slope - 1.0)>1e-30) || (fabs(*intercept)>1e-30) ) {
 
1749
      return 1;
 
1750
    } else {
 
1751
      return 0;
 
1752
    }
 
1753
  }
 
1754
  if (fslio->mincptr!=NULL) {
 
1755
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1756
  }
 
1757
  return 0;
 
1758
 
 
1759
}
 
1760
 
 
1761
 
 
1762
mat33 mat44_to_mat33(mat44 x)
 
1763
{
 
1764
  mat33 y;
 
1765
  int i,j;
 
1766
  for (i=0; i<3; i++) {
 
1767
    for (j=0; j<3; j++) {
 
1768
      y.m[i][j] = x.m[i][j];
 
1769
    }
 
1770
  }
 
1771
  return y;
 
1772
}
 
1773
 
 
1774
 
 
1775
int FslGetLeftRightOrder2(int sform_code, mat44 sform44, 
 
1776
                          int qform_code, mat44 qform44)
 
1777
{
 
1778
  /* Determines if the image is stored in neurological or radiological convention */
 
1779
  int order=FSL_RADIOLOGICAL;
 
1780
  float dets=-1.0, detq=-1.0, det=-1.0;
 
1781
  mat33 sform33, qform33;
 
1782
  if (qform_code!=NIFTI_XFORM_UNKNOWN) { 
 
1783
    qform33 = mat44_to_mat33(qform44);
 
1784
    detq = nifti_mat33_determ(qform33);
 
1785
    det = detq;
 
1786
  }
 
1787
  if (sform_code!=NIFTI_XFORM_UNKNOWN) { 
 
1788
    sform33 = mat44_to_mat33(sform44);
 
1789
    dets = nifti_mat33_determ(sform33);
 
1790
    det = dets;
 
1791
  }
 
1792
  
 
1793
  if (det<0.0) order=FSL_RADIOLOGICAL;
 
1794
  else order=FSL_NEUROLOGICAL;
 
1795
  /* check for inconsistency if both are set */
 
1796
  if ( (sform_code!=NIFTI_XFORM_UNKNOWN) && 
 
1797
       (qform_code!=NIFTI_XFORM_UNKNOWN) ) { 
 
1798
    if (dets * detq < 0.0) order=FSL_INCONSISTENT;
 
1799
  }
 
1800
  return order;
 
1801
}
 
1802
 
 
1803
 
 
1804
int FslGetLeftRightOrder(FSLIO *fslio)
 
1805
{
 
1806
  int order=FSL_RADIOLOGICAL, sform_code, qform_code;
 
1807
  mat44 sform44, qform44;
 
1808
  if (fslio==NULL)  FSLIOERR("FslGetLeftRightOrder: Null pointer passed for FSLIO");
 
1809
  if (fslio->niftiptr!=NULL) {
 
1810
    sform_code = FslGetStdXform(fslio,&sform44);
 
1811
    qform_code = FslGetRigidXform(fslio,&qform44);
 
1812
    return FslGetLeftRightOrder2(sform_code,sform44,qform_code,qform44);
 
1813
  }
 
1814
  if (fslio->mincptr!=NULL) {
 
1815
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1816
  }
 
1817
  return order;
 
1818
}
 
1819
 
 
1820
 
 
1821
short FslGetVox2mmMatrix2(mat44 *vox2mm, int sform_code, mat44 sform44, 
 
1822
                          int qform_code, mat44 qform44, 
 
1823
                          float dx, float dy, float dz)
 
1824
{
 
1825
  short retcode=NIFTI_XFORM_UNKNOWN;
 
1826
  int ii,jj;
 
1827
  if (sform_code!=NIFTI_XFORM_UNKNOWN) { 
 
1828
    for (ii=0; ii<4; ii++) { 
 
1829
      for (jj=0; jj<4; jj++) {
 
1830
        vox2mm->m[ii][jj] = sform44.m[ii][jj];
 
1831
      } 
 
1832
    }
 
1833
    retcode=sform_code;
 
1834
  } else if (qform_code!=NIFTI_XFORM_UNKNOWN) { 
 
1835
    for (ii=0; ii<4; ii++) { 
 
1836
      for (jj=0; jj<4; jj++) {
 
1837
        vox2mm->m[ii][jj] = qform44.m[ii][jj];
 
1838
      } 
 
1839
    }
 
1840
    retcode=qform_code;
 
1841
  } else {
 
1842
    /* default case - for FSLView is positive voxel to mm scalings */
 
1843
    vox2mm->m[0][0] = dx;
 
1844
    vox2mm->m[0][1] = 0.0;
 
1845
    vox2mm->m[0][2] = 0.0;
 
1846
    vox2mm->m[0][3] = 0.0;
 
1847
    vox2mm->m[1][0] = 0.0;
 
1848
    vox2mm->m[1][1] = dy;
 
1849
    vox2mm->m[1][2] = 0.0;
 
1850
    vox2mm->m[1][3] = 0.0;
 
1851
    vox2mm->m[2][0] = 0.0;
 
1852
    vox2mm->m[2][1] = 0.0;
 
1853
    vox2mm->m[2][2] = dz;
 
1854
    vox2mm->m[2][3] = 0.0;
 
1855
    vox2mm->m[3][0] = 0.0;
 
1856
    vox2mm->m[3][1] = 0.0;
 
1857
    vox2mm->m[3][2] = 0.0;
 
1858
    vox2mm->m[3][3] = 1.0;
 
1859
    retcode=NIFTI_XFORM_UNKNOWN;
 
1860
  }
 
1861
  return retcode;
 
1862
}
 
1863
 
 
1864
 
 
1865
short FslGetVox2mmMatrix(FSLIO *fslio, mat44 *vox2mm)
 
1866
{
 
1867
  int sform_code, qform_code;
 
1868
  float dx, dy, dz, tr;
 
1869
  mat44 sform44, qform44;
 
1870
  if (fslio==NULL)  FSLIOERR("FslGetVox2mmMatrix: Null pointer passed for FSLIO");
 
1871
  if (fslio->niftiptr!=NULL) {
 
1872
    sform_code = FslGetStdXform(fslio,&sform44);
 
1873
    qform_code = FslGetRigidXform(fslio,&qform44);
 
1874
    FslGetVoxDim(fslio,&dx,&dy,&dz,&tr);
 
1875
    return FslGetVox2mmMatrix2(vox2mm,sform_code,sform44,
 
1876
                               qform_code,qform44,dx,dy,dz);
 
1877
  }
 
1878
  if (fslio->mincptr!=NULL) {
 
1879
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1880
  }
 
1881
  return NIFTI_XFORM_UNKNOWN;
 
1882
}
 
1883
 
 
1884
void FslSetAnalyzeSform(FSLIO *fslio, const short *orig,
 
1885
                        float dx, float dy, float dz)
 
1886
{
 
1887
  /* Creates an sform matrix for an Analyze file */
 
1888
  /* THIS ALWAYS CREATES A RADIOLOGICAL ORDERED SFORM */
 
1889
  /* NB: the origin passed in here is in Analyze convention - starting at 1, not 0 */
 
1890
  float x, y, z;
 
1891
  if (fslio==NULL)  FSLIOERR("FslSetAnalyzeSform: Null pointer passed for FSLIO");
 
1892
  if (fslio->niftiptr!=NULL) {
 
1893
    if (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_ANALYZE) {
 
1894
      /* default case */
 
1895
      fslio->niftiptr->sform_code = NIFTI_XFORM_UNKNOWN;
 
1896
    }
 
1897
    /* ignore all zero origins - really all serious coord stuff should
 
1898
       be done via the FslSetStdCoord call */
 
1899
    if ((orig[0]!=0) || (orig[1]!=0) || (orig[2]!=0))
 
1900
      {
 
1901
        short origx=0, origy=0, origz=0;
 
1902
        if ((orig[0]!=0) || (orig[1]!=0) || (orig[2]!=0)) {
 
1903
          /* convert to nifti conventions (start at 0 not 1) */
 
1904
          origx = orig[0] - 1;
 
1905
          origy = orig[1] - 1;
 
1906
          origz = orig[2] - 1;
 
1907
        }
 
1908
        if ( dx * dy * dz > 0 ) {
 
1909
          /* change neurological convention to radiological if necessary */
 
1910
          dx = -dx;
 
1911
        }
 
1912
        if ( (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_ANALYZE) 
 
1913
             || (fslio->niftiptr->sform_code == NIFTI_XFORM_UNKNOWN) ) {
 
1914
          /* make a default transform with the requested origin at xyz=000 */ 
 
1915
          fslio->niftiptr->sform_code = NIFTI_XFORM_ALIGNED_ANAT;
 
1916
          fslio->niftiptr->sto_xyz.m[0][0] = dx;
 
1917
          fslio->niftiptr->sto_xyz.m[0][1] = 0;
 
1918
          fslio->niftiptr->sto_xyz.m[0][2] = 0;
 
1919
          fslio->niftiptr->sto_xyz.m[0][3] = -(origx)*(dx);
 
1920
          fslio->niftiptr->sto_xyz.m[1][0] = 0;
 
1921
          fslio->niftiptr->sto_xyz.m[1][1] = dy;
 
1922
          fslio->niftiptr->sto_xyz.m[1][2] = 0;
 
1923
          fslio->niftiptr->sto_xyz.m[1][3] = -(origy)*(dy);
 
1924
          fslio->niftiptr->sto_xyz.m[2][0] = 0;
 
1925
          fslio->niftiptr->sto_xyz.m[2][1] = 0;
 
1926
          fslio->niftiptr->sto_xyz.m[2][2] = dz;
 
1927
          fslio->niftiptr->sto_xyz.m[2][3] = -(origz)*(dz);
 
1928
          fslio->niftiptr->sto_xyz.m[3][0] = 0;
 
1929
          fslio->niftiptr->sto_xyz.m[3][1] = 0;
 
1930
          fslio->niftiptr->sto_xyz.m[3][2] = 0;
 
1931
          fslio->niftiptr->sto_xyz.m[3][3] = 1;
 
1932
          fslio->niftiptr->sto_ijk =
 
1933
                 nifti_mat44_inverse(fslio->niftiptr->sto_xyz);
 
1934
        } else {
 
1935
          /* update the existing origin */
 
1936
          /* find out what the existing xyz of the requested origin is */
 
1937
          x = fslio->niftiptr->sto_xyz.m[0][0] * origx
 
1938
            + fslio->niftiptr->sto_xyz.m[0][1] * origy
 
1939
            + fslio->niftiptr->sto_xyz.m[0][2] * origz
 
1940
            + fslio->niftiptr->sto_xyz.m[0][3];
 
1941
          y = fslio->niftiptr->sto_xyz.m[1][0] * origx
 
1942
            + fslio->niftiptr->sto_xyz.m[1][1] * origy
 
1943
            + fslio->niftiptr->sto_xyz.m[1][2] * origz
 
1944
            + fslio->niftiptr->sto_xyz.m[1][3];
 
1945
          z = fslio->niftiptr->sto_xyz.m[2][0] * origx
 
1946
            + fslio->niftiptr->sto_xyz.m[2][1] * origy
 
1947
            + fslio->niftiptr->sto_xyz.m[2][2] * origz
 
1948
            + fslio->niftiptr->sto_xyz.m[2][3];
 
1949
          /* subtract off whatever is currently the xyz of the origin */
 
1950
          fslio->niftiptr->sto_xyz.m[0][3] -= x;
 
1951
          fslio->niftiptr->sto_xyz.m[1][3] -= y;
 
1952
          fslio->niftiptr->sto_xyz.m[2][3] -= z;
 
1953
          fslio->niftiptr->sto_ijk =
 
1954
                 nifti_mat44_inverse(fslio->niftiptr->sto_xyz);
 
1955
        }
 
1956
        
 
1957
      }
 
1958
    
 
1959
  }
 
1960
  if (fslio->mincptr!=NULL) {
 
1961
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1962
  }
 
1963
}
 
1964
 
 
1965
 
 
1966
void FslGetAnalyzeOrigin(FSLIO *fslio, short orig[5])
 
1967
{
 
1968
  /* NB: orig returned here is in Analyze convention - starting at 1, not 0 */
 
1969
  if (fslio==NULL)  FSLIOERR("FslGetAnalyzeOrigin: Null pointer passed for FSLIO");
 
1970
  if (fslio->niftiptr!=NULL) {
 
1971
    /* Use sform or qform to determine the origin - default is zero */
 
1972
      orig[0]=0; 
 
1973
      orig[1]=0; 
 
1974
      orig[2]=0; 
 
1975
      orig[3]=0; 
 
1976
      orig[4]=0;
 
1977
 
 
1978
      if (fslio->niftiptr->qform_code != NIFTI_XFORM_UNKNOWN) {
 
1979
        orig[0]=(short) fslio->niftiptr->qto_ijk.m[0][3] + 1;
 
1980
        orig[1]=(short) fslio->niftiptr->qto_ijk.m[1][3] + 1;
 
1981
        orig[2]=(short) fslio->niftiptr->qto_ijk.m[2][3] + 1;
 
1982
      } 
 
1983
 
 
1984
      if (fslio->niftiptr->sform_code != NIFTI_XFORM_UNKNOWN) {
 
1985
        orig[0]=(short) fslio->niftiptr->sto_ijk.m[0][3] + 1;
 
1986
        orig[1]=(short) fslio->niftiptr->sto_ijk.m[1][3] + 1;
 
1987
        orig[2]=(short) fslio->niftiptr->sto_ijk.m[2][3] + 1;
 
1988
      } 
 
1989
  }
 
1990
  if (fslio->mincptr!=NULL) {
 
1991
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
1992
  }
 
1993
}
 
1994
 
 
1995
 
 
1996
 
 
1997
/***************************************************************
 
1998
 * FslClose
 
1999
 ***************************************************************/
 
2000
/*! \fn int FslClose(FSLIO *fslio)
 
2001
    \brief  Write header and image data if this dataset was open for
 
2002
        writing.  Close the dataset header and data files.
 
2003
 
 
2004
        
 
2005
    \param fslio  pointer to FSLIO data structure
 
2006
    \return  -1 on error, 0 OK ???.
 
2007
 */
 
2008
int FslClose(FSLIO *fslio)
 
2009
{
 
2010
  int retval=0, filetype;
 
2011
  struct dsr *hdr;
 
2012
  znzFile hptr=NULL;
 
2013
 
 
2014
  if (fslio==NULL)   return 0;
 
2015
 
 
2016
  /* close the (data) file */
 
2017
  if (!znz_isnull(fslio->fileptr)) retval=znzclose(fslio->fileptr);
 
2018
 
 
2019
  /** ----- if writing the image, need to worry about the header bit ----- **/
 
2020
 
 
2021
  if ( (fslio->niftiptr!=NULL) && (FslGetWriteMode(fslio)==1) 
 
2022
       && (fslio->written_hdr==0) ) {
 
2023
 
 
2024
    /* ensure that the type is set correctly */
 
2025
    fslio->niftiptr->nifti_type = FslBaseFileType(FslGetFileType(fslio));
 
2026
 
 
2027
    /* must write the header now */
 
2028
    filetype = FslGetFileType(fslio);
 
2029
    strcpy(fslio->niftiptr->descrip,"FSL4.0");
 
2030
    if (!FslIsSingleFileType(filetype)) {
 
2031
      /* for file pairs - open new header file and write it */
 
2032
      nifti_image_write_hdr_img(fslio->niftiptr,0,"wb");
 
2033
    } else {
 
2034
      /* for single files it is more complicated */
 
2035
      if (!FslIsCompressedFileType(filetype)) {
 
2036
        /* noncompressed -> reopen this file in r+ mode and write the header part again */
 
2037
        nifti_image_write_hdr_img(fslio->niftiptr,0,"r+b");
 
2038
      } else {
 
2039
        /* compressed mode -> not possible! */
 
2040
        fprintf(stderr,"Error:: header must be written before writing any other data.\n");
 
2041
        return -1;
 
2042
      }
 
2043
    }
 
2044
  }
 
2045
    
 
2046
  /* --- nasty hack to write the origin in Analyze files --- */
 
2047
 
 
2048
  if ( (FslGetWriteMode(fslio)==1) && (fslio->niftiptr!=NULL) && 
 
2049
       (FslBaseFileType(FslGetFileType(fslio))==FSL_TYPE_ANALYZE) ) {
 
2050
 
 
2051
    /* read in the old header, change the origin and write it out again */
 
2052
    hdr = (struct dsr *) calloc(1,sizeof(struct dsr));
 
2053
    FslReadRawHeader(hdr,fslio->niftiptr->fname);
 
2054
    if (fslio->niftiptr->byteorder != nifti_short_order()) {AvwSwapHeader(hdr);}
 
2055
    
 
2056
    /* calculate origin from sform (if set) */
 
2057
    {
 
2058
      short blah[5];
 
2059
      FslGetAnalyzeOrigin(fslio,blah);
 
2060
      memcpy(hdr->hist.originator,blah,5*sizeof(short));
 
2061
    
 
2062
      /* Write out in radiological order if origin is non-zero */
 
2063
      /* set negative pixdim if needed to keep LR orientation consistent */
 
2064
      if ( (blah[0]!=0) || (blah[1]!=0) || (blah[2]!=0) ) {
 
2065
        if (hdr->dime.pixdim[1] * hdr->dime.pixdim[2] * hdr->dime.pixdim[3] > 0) {
 
2066
          hdr->dime.pixdim[1] = - hdr->dime.pixdim[1]; 
 
2067
        }
 
2068
      }
 
2069
    }
 
2070
 
 
2071
    /* swap back byte order and write out */
 
2072
    if (fslio->niftiptr->byteorder != nifti_short_order()) {AvwSwapHeader(hdr);}
 
2073
    hptr = znzopen(fslio->niftiptr->fname,"wb",FslIsCompressedFileType(FslGetFileType(fslio)));
 
2074
    if (znz_isnull(hptr)) {     
 
2075
      fprintf(stderr,"Error:: Could not write origin data to header file %s.\n",
 
2076
              fslio->niftiptr->fname);
 
2077
      return -1;
 
2078
    };
 
2079
    
 
2080
    znzwrite(hdr,1,sizeof(struct dsr),hptr);
 
2081
    znzclose(hptr);
 
2082
    free(hdr);
 
2083
  }
 
2084
 
 
2085
  if (fslio->mincptr!=NULL) {
 
2086
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
2087
    return -1;
 
2088
  }
 
2089
 
 
2090
  return retval;
 
2091
}
 
2092
  
 
2093
 
 
2094
void AvwSwapHeader(struct dsr *avw)
 
2095
{
 
2096
  char *ptr;
 
2097
 
 
2098
  ptr = (char *) &(avw->hk);
 
2099
  nifti_swap_4bytes(1,ptr);             /* sizeof_hdr */
 
2100
  ptr += 32;
 
2101
  nifti_swap_4bytes(1,ptr);             /* extents */
 
2102
  ptr += 4;
 
2103
  nifti_swap_2bytes(1,ptr);             /* session_error */
 
2104
  
 
2105
  ptr = (char *) &(avw->dime);
 
2106
  nifti_swap_2bytes(8,ptr);             /* dims */
 
2107
  ptr += 28;
 
2108
  nifti_swap_2bytes(4,ptr);             /* unused1, datatype, bitpix, dim_un0 */
 
2109
  ptr += 8;
 
2110
  nifti_swap_4bytes(18,ptr);            /* pixdim, vox_offset, ... */
 
2111
                                        /* cal_min, compressed, ... glmin */
 
2112
 
 
2113
  ptr = (char *) &(avw->hist);
 
2114
  ptr += 105;
 
2115
  nifti_swap_2bytes(5,ptr);             /* originator (used to store origin) */
 
2116
  ptr += 63;
 
2117
  nifti_swap_4bytes(8,ptr);             /* views, ... smin */
 
2118
}
 
2119
 
 
2120
 
 
2121
int FslReadRawHeader(void *buffer, const char* filename)
 
2122
{
 
2123
  znzFile fp;
 
2124
  int retval;
 
2125
  fp = znzopen(filename,"rb",1);
 
2126
  if (znz_isnull(fp)) {
 
2127
    fprintf(stderr,"Could not open header %s\n",filename);
 
2128
    return 0;
 
2129
  }
 
2130
  retval = znzread(buffer,1,348,fp);
 
2131
  znzclose(fp);
 
2132
  if (retval != 348) {
 
2133
    fprintf(stderr,"Could not read header %s\n",filename);
 
2134
    return retval;
 
2135
  }
 
2136
  return retval;
 
2137
}
 
2138
 
 
2139
void FslSetOverrideOutputType(int type)
 
2140
{
 
2141
  if ( (type==-1) || (FslIsValidFileType(type)) ) {
 
2142
    FslOverrideOutputType=type;
 
2143
  } else {
 
2144
    fprintf(stderr,"Invalid file type (%d) requested - ignoring this\n",type);
 
2145
  }
 
2146
}
 
2147
 
 
2148
int FslGetOverrideOutputType(void)
 
2149
{
 
2150
  return FslOverrideOutputType;
 
2151
}
 
2152
 
 
2153
void FslSetIgnoreMFQ(int flag)
 
2154
{
 
2155
  assert((flag==0) || (flag==1));
 
2156
  FslIgnoreMFQ=flag;
 
2157
}
 
2158
 
 
2159
 
 
2160
int FslGetIgnoreMFQ(void)
 
2161
{
 
2162
  return FslIgnoreMFQ;
 
2163
}
 
2164
 
 
2165
/***************************************************************
 
2166
 * FslReadHeader
 
2167
 ***************************************************************/
 
2168
/*! \fn FSLIO * FslReadHeader(char *fname)
 
2169
    \brief Reads nifti/anz header, no data is read
 
2170
        
 
2171
    \param fname        filename specification (could be .img,.hdr,.nii, or no ext
 
2172
    \return FSLIO data structure with the nifti_image structure fields filled 
 
2173
            as per fname header.
 
2174
            NULL on error 
 
2175
 */
 
2176
FSLIO * FslReadHeader(char *fname)
 
2177
{
 
2178
   char *hdrname, *imgname;
 
2179
   FSLIO *fslio;
 
2180
 
 
2181
 
 
2182
   fslio = FslInit();
 
2183
  
 
2184
  /** get header file name */
 
2185
  FslGetHdrImgNames(fname, fslio, &hdrname, &imgname);
 
2186
 
 
2187
  /** read header information */
 
2188
  fslio->niftiptr = nifti_image_read(hdrname, 0);
 
2189
 
 
2190
  if (fslio->niftiptr == NULL) {
 
2191
        FSLIOERR("FslReadHeader: error reading header information");
 
2192
        return(NULL);
 
2193
  }
 
2194
 
 
2195
  fslio->file_mode = FslGetReadFileType(fslio);
 
2196
 
 
2197
  return(fslio);
 
2198
}
 
2199
 
 
2200
 
 
2201
/***************************************************************
 
2202
 * FslGetVolumeAsScaledDouble
 
2203
 ***************************************************************/
 
2204
/*! \fn double *** FslGetVolumeAsScaledDouble(FSLIO *fslio, int vol)
 
2205
    \brief Return volume #vol (0-based) as a 3D array of scaled doubles. 
 
2206
 
 
2207
        Volume Array is indexed as [0..zdim-1][0..ydim-1][0..xdim-1].  
 
2208
        <br>The array will be byteswapped to native-endian.
 
2209
        <br>Array values are scaled as per fslio header slope and intercept fields.
 
2210
 
 
2211
    \param fslio pointer to open dataset
 
2212
    \param vol volume number to read (legal range [0..tdim-1])
 
2213
    \return Pointer to 3D double array, NULL on error
 
2214
 */
 
2215
double ***FslGetVolumeAsScaledDouble(FSLIO *fslio, int vol)
 
2216
{
 
2217
  double ***newbuf;
 
2218
  void *diskbuf;
 
2219
  int xx,yy,zz;
 
2220
  int ret;
 
2221
  float inter, slope;
 
2222
  int dims_to_get[8];
 
2223
  int i;
 
2224
 
 
2225
  if (fslio==NULL)  FSLIOERR("FslGetVolumeAsScaledDouble: Null pointer passed for FSLIO");
 
2226
 
 
2227
  if ((fslio->niftiptr->dim[0] < 3) || (fslio->niftiptr->dim[0] > 4))
 
2228
        FSLIOERR("FslGetVolumeAsScaledDouble: Incorrect dataset dimension, 3D-4D needed");
 
2229
 
 
2230
  /***** nifti dataset */
 
2231
  if (fslio->niftiptr!=NULL) {
 
2232
        xx = (fslio->niftiptr->nx == 0 ? 1 : (long)fslio->niftiptr->nx);
 
2233
        yy = (fslio->niftiptr->ny == 0 ? 1 : (long)fslio->niftiptr->ny);
 
2234
        zz = (fslio->niftiptr->nz == 0 ? 1 : (long)fslio->niftiptr->nz);
 
2235
 
 
2236
        if (fslio->niftiptr->scl_slope == 0) {
 
2237
                slope = 1.0;
 
2238
                inter = 0.0;
 
2239
        }
 
2240
        else {
 
2241
                slope = fslio->niftiptr->scl_slope;
 
2242
                inter = fslio->niftiptr->scl_inter;
 
2243
        }
 
2244
        
 
2245
 
 
2246
    /** allocate new 3D buffer */
 
2247
    newbuf = d3matrix(zz-1,yy-1,xx-1);
 
2248
 
 
2249
 
 
2250
    /** read in the data in disk format */
 
2251
    dims_to_get[0] = 0;
 
2252
    for (i=1; i<8; i++)
 
2253
        dims_to_get[i] = -1;
 
2254
    dims_to_get[4] = vol;
 
2255
 
 
2256
 
 
2257
    diskbuf = NULL;
 
2258
    ret = nifti_read_collapsed_image(fslio->niftiptr, dims_to_get, &diskbuf );
 
2259
    if (ret <= 0) {
 
2260
        fprintf(stderr,"ERROR:: read of disk buffer for volume %d from %s failed.\n",vol,fslio->niftiptr->iname);
 
2261
        return(NULL);
 
2262
    }
 
2263
 
 
2264
 
 
2265
    /** cvt disk buffer to scaled double buffer  */
 
2266
    ret = convertBufferToScaledDouble(newbuf[0][0], diskbuf, (long)(xx*yy*zz), slope, inter, fslio->niftiptr->datatype);
 
2267
 
 
2268
    free(diskbuf);
 
2269
 
 
2270
    if (ret == 0)
 
2271
        return(newbuf);
 
2272
    else
 
2273
        return(NULL);
 
2274
 
 
2275
  } /* nifti data */
 
2276
 
 
2277
 
 
2278
  if (fslio->mincptr!=NULL) {
 
2279
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
2280
  }
 
2281
 
 
2282
  return(NULL);
 
2283
}
 
2284
 
 
2285
 
 
2286
 
 
2287
 
 
2288
/***************************************************************
 
2289
 * FslGetBufferAsScaledDouble
 
2290
 ***************************************************************/
 
2291
/*! \fn double **** FslGetBufferAsScaledDouble(FSLIO *fslio)
 
2292
    \brief Return the fslio data buffer of a 1-4D dataset as a 4D array of 
 
2293
        scaled doubles. 
 
2294
 
 
2295
        Array is indexed as buf[0..tdim-1][0..zdim-1][0..ydim-1][0..xdim-1].  
 
2296
        <br>The array will be byteswapped to native-endian.
 
2297
        <br>Array values are scaled as per fslio header slope and intercept fields.
 
2298
 
 
2299
    \param fslio pointer to open dataset
 
2300
    \return Pointer to 4D double array, NULL on error
 
2301
 */
 
2302
double ****FslGetBufferAsScaledDouble(FSLIO *fslio)
 
2303
{
 
2304
  double ****newbuf;
 
2305
  int xx,yy,zz,tt;
 
2306
  int ret;
 
2307
  float inter, slope;
 
2308
 
 
2309
  if (fslio==NULL)  FSLIOERR("FslGetBufferAsScaledDouble: Null pointer passed for FSLIO");
 
2310
 
 
2311
  if ((fslio->niftiptr->dim[0] <= 0) || (fslio->niftiptr->dim[0] > 4))
 
2312
        FSLIOERR("FslGetBufferAsScaledDouble: Incorrect dataset dimension, 1-4D needed");
 
2313
 
 
2314
  /***** nifti dataset */
 
2315
  if (fslio->niftiptr!=NULL) {
 
2316
        xx = (fslio->niftiptr->nx == 0 ? 1 : (long)fslio->niftiptr->nx);
 
2317
        yy = (fslio->niftiptr->ny == 0 ? 1 : (long)fslio->niftiptr->ny);
 
2318
        zz = (fslio->niftiptr->nz == 0 ? 1 : (long)fslio->niftiptr->nz);
 
2319
        tt = (fslio->niftiptr->nt == 0 ? 1 : (long)fslio->niftiptr->nt);
 
2320
 
 
2321
        if (fslio->niftiptr->scl_slope == 0) {
 
2322
                slope = 1.0;
 
2323
                inter = 0.0;
 
2324
        }
 
2325
        else {
 
2326
                slope = fslio->niftiptr->scl_slope;
 
2327
                inter = fslio->niftiptr->scl_inter;
 
2328
        }
 
2329
        
 
2330
 
 
2331
    /** allocate new 4D buffer */
 
2332
    newbuf = d4matrix(tt-1,zz-1,yy-1,xx-1);
 
2333
 
 
2334
    /** cvt it */
 
2335
    ret = convertBufferToScaledDouble(newbuf[0][0][0], fslio->niftiptr->data, (long)(xx*yy*zz*tt), slope, inter, fslio->niftiptr->datatype);
 
2336
 
 
2337
    if (ret == 0)
 
2338
        return(newbuf);
 
2339
    else
 
2340
        return(NULL);
 
2341
 
 
2342
  } /* nifti data */
 
2343
 
 
2344
 
 
2345
  if (fslio->mincptr!=NULL) {
 
2346
    fprintf(stderr,"Warning:: Minc is not yet supported\n");
 
2347
  }
 
2348
 
 
2349
  return(NULL);
 
2350
}
 
2351
 
 
2352
/***************************************************************
 
2353
 * convertBufferToScaledDouble
 
2354
 ***************************************************************/
 
2355
/*! \fn int  convertBufferToScaledDouble(double *outbuf, void *inbuf, long len, float slope, float inter, int nifti_datatype )
 
2356
    \brief allocate a 4D buffer, use 1 contiguous buffer for the data 
 
2357
 
 
2358
        Array is indexed as buf[0..th-1][0..zh-1][0..yh-1][0..xh-1].  
 
2359
        <br>To access all elements as a vector, use buf[0][0][0][i] where
 
2360
        i can range from 0 to th*zh*yh*xh - 1.
 
2361
 
 
2362
    \param outbuf pointer to array of doubles of size len
 
2363
    \param inbuf void pointer to an array of len items of datatype nifti_datatype
 
2364
    \param len number of elements in outbuf and inbuf
 
2365
    \param slope slope term of scaling to be applied
 
2366
    \param inter intercept term of scaling to be applied:  out = (in*slope)+inter
 
2367
    \param nifti_datatype NIFTI datatype code for the datatype of the elements in inbuf
 
2368
    \return error code: 0=OK -1=error
 
2369
 */
 
2370
int  convertBufferToScaledDouble(double *outbuf, void *inbuf, long len, float slope, float inter, int nifti_datatype ) 
 
2371
{
 
2372
 
 
2373
        long i;
 
2374
 
 
2375
 
 
2376
    /** fill the buffer */
 
2377
    for (i=0; i<len; i++)
 
2378
        switch(nifti_datatype) {
 
2379
            case NIFTI_TYPE_UINT8:
 
2380
                outbuf[i] = (double) ( *((THIS_UINT8 *)(inbuf)+i) * slope + inter);
 
2381
                break;
 
2382
            case NIFTI_TYPE_INT8:
 
2383
                outbuf[i] = (double) ( *((THIS_INT8 *)(inbuf)+i) * slope + inter);
 
2384
                break;
 
2385
            case NIFTI_TYPE_UINT16:
 
2386
                outbuf[i] = (double) ( *((THIS_UINT16 *)(inbuf)+i) * slope + inter);
 
2387
                break;
 
2388
            case NIFTI_TYPE_INT16:
 
2389
                outbuf[i] = (double) ( *((THIS_INT16 *)(inbuf)+i) * slope + inter);
 
2390
                break;
 
2391
            case NIFTI_TYPE_UINT64:
 
2392
                outbuf[i] = (double) ( *((THIS_UINT64 *)(inbuf)+i) * slope + inter);
 
2393
                break;
 
2394
            case NIFTI_TYPE_INT64:
 
2395
                outbuf[i] = (double) ( *((THIS_INT64 *)(inbuf)+i) * slope + inter);
 
2396
                break;
 
2397
            case NIFTI_TYPE_UINT32:
 
2398
                outbuf[i] = (double) ( *((THIS_UINT32 *)(inbuf)+i) * slope + inter);
 
2399
                break;
 
2400
            case NIFTI_TYPE_INT32:
 
2401
                outbuf[i] = (double) ( *((THIS_INT32 *)(inbuf)+i) * slope + inter);
 
2402
                break;
 
2403
            case NIFTI_TYPE_FLOAT32:
 
2404
                outbuf[i] = (double) ( *((THIS_FLOAT32 *)(inbuf)+i) * slope + inter);
 
2405
                break;
 
2406
            case NIFTI_TYPE_FLOAT64:
 
2407
                outbuf[i] = (double) ( *((THIS_FLOAT64 *)(inbuf)+i) * slope + inter);
 
2408
                break;
 
2409
 
 
2410
            case NIFTI_TYPE_FLOAT128:
 
2411
            case NIFTI_TYPE_COMPLEX128:
 
2412
            case NIFTI_TYPE_COMPLEX256:
 
2413
            case NIFTI_TYPE_COMPLEX64:
 
2414
            default:
 
2415
                fprintf(stderr, "\nWarning, cannot support %s yet.\n",nifti_datatype_string(nifti_datatype));
 
2416
                return(-1);
 
2417
        }
 
2418
 
 
2419
return(0);
 
2420
}
 
2421
 
 
2422
/***************************************************************
 
2423
 * d3matrix
 
2424
 ***************************************************************/
 
2425
/*! \fn double ****d3matrix(int zh,  int yh, int xh)
 
2426
    \brief allocate a 3D buffer, use 1 contiguous buffer for the data 
 
2427
 
 
2428
        Array is indexed as buf[0..zh][0..yh][0..xh].  
 
2429
        <br>To access all elements as a vector, use buf[0][0][i] where
 
2430
        i can range from 0 to zh*yh*xh - 1.
 
2431
        Adaptation of Numerical Recipes in C nrutil.c allocation routines. 
 
2432
 
 
2433
    \param zh slowest changing dimension
 
2434
    \param yh 2nd fastest changing dimension
 
2435
    \param xh fastest changing dimension
 
2436
    \return Pointer to 3D double array
 
2437
 */
 
2438
double ***d3matrix(int zh,  int yh, int xh)
 
2439
{
 
2440
 
 
2441
        int j;
 
2442
        int nslice = zh+1;
 
2443
        int nrow = yh+1;
 
2444
        int ncol = xh+1;
 
2445
        double ***t;
 
2446
 
 
2447
 
 
2448
        /** allocate pointers to slices */
 
2449
        t=(double ***) malloc((size_t)((nslice)*sizeof(double**)));
 
2450
        if (!t) FSLIOERR("d3matrix: allocation failure");
 
2451
 
 
2452
        /** allocate pointers for ydim */
 
2453
        t[0]=(double **) malloc((size_t)((nslice*nrow)*sizeof(double*)));
 
2454
        if (!t[0]) FSLIOERR("d3matrix: allocation failure");
 
2455
 
 
2456
 
 
2457
        /** allocate the data blob */
 
2458
        t[0][0]=(double *) malloc((size_t)((nslice*nrow*ncol)*sizeof(double)));
 
2459
        if (!t[0][0]) FSLIOERR("d3matrix: allocation failure");
 
2460
 
 
2461
 
 
2462
        /** point everything to the data blob */
 
2463
        for(j=1;j<nrow*nslice;j++) t[0][j]=t[0][j-1]+ncol;
 
2464
        for(j=1;j<nslice;j++) t[j]=t[j-1]+nrow;
 
2465
 
 
2466
        return t;
 
2467
}
 
2468
 
 
2469
 
 
2470
/***************************************************************
 
2471
 * d4matrix
 
2472
 ***************************************************************/
 
2473
/*! \fn double ****d4matrix(int th, int zh,  int yh, int xh)
 
2474
    \brief allocate a 4D buffer, use 1 contiguous buffer for the data 
 
2475
 
 
2476
        Array is indexed as buf[0..th][0..zh][0..yh][0..xh].  
 
2477
        <br>To access all elements as a vector, use buf[0][0][0][i] where
 
2478
        i can range from 0 to th*zh*yh*xh - 1.
 
2479
        Adaptation of Numerical Recipes in C nrutil.c allocation routines. 
 
2480
 
 
2481
    \param th slowest changing dimension
 
2482
    \param zh 2nd slowest changing dimension
 
2483
    \param yh 2nd fastest changing dimension
 
2484
    \param xh fastest changing dimension
 
2485
    \return Pointer to 4D double array
 
2486
 */
 
2487
double ****d4matrix(int th, int zh,  int yh, int xh)
 
2488
{
 
2489
 
 
2490
        int j;
 
2491
        int nvol = th+1;
 
2492
        int nslice = zh+1;
 
2493
        int nrow = yh+1;
 
2494
        int ncol = xh+1;
 
2495
        double ****t;
 
2496
 
 
2497
 
 
2498
        /** allocate pointers to vols */
 
2499
        t=(double ****) malloc((size_t)((nvol)*sizeof(double***)));
 
2500
        if (!t) FSLIOERR("d4matrix: allocation failure");
 
2501
 
 
2502
        /** allocate pointers to slices */
 
2503
        t[0]=(double ***) malloc((size_t)((nvol*nslice)*sizeof(double**)));
 
2504
        if (!t[0]) FSLIOERR("d4matrix: allocation failure");
 
2505
 
 
2506
        /** allocate pointers for ydim */
 
2507
        t[0][0]=(double **) malloc((size_t)((nvol*nslice*nrow)*sizeof(double*)));
 
2508
        if (!t[0][0]) FSLIOERR("d4matrix: allocation failure");
 
2509
 
 
2510
 
 
2511
        /** allocate the data blob */
 
2512
        t[0][0][0]=(double *) malloc((size_t)((nvol*nslice*nrow*ncol)*sizeof(double)));
 
2513
        if (!t[0][0][0]) FSLIOERR("d4matrix: allocation failure");
 
2514
 
 
2515
 
 
2516
        /** point everything to the data blob */
 
2517
        for(j=1;j<nrow*nslice*nvol;j++) t[0][0][j]=t[0][0][j-1]+ncol;
 
2518
        for(j=1;j<nslice*nvol;j++) t[0][j]=t[0][j-1]+nrow;
 
2519
        for(j=1;j<nvol;j++) t[j]=t[j-1]+nslice;
 
2520
 
 
2521
        return t;
 
2522
}