00001 #define _NIFTI1_IO_C_ 00002 00003 #include "nifti1_io.h" /*** typedefs, prototypes, macros, etc. ***/ 00004 00005 /*****===================================================================*****/ 00006 /***** Sample functions to deal with NIFTI-1 and ANALYZE files *****/ 00007 /*****...................................................................*****/ 00008 /***** This code is released to the public domain. *****/ 00009 /*****...................................................................*****/ 00010 /***** Author: Robert W Cox, SSCC/DIRP/NIMH/NIH/DHHS/USA/EARTH *****/ 00011 /***** Date: August 2003 *****/ 00012 /*****...................................................................*****/ 00013 /***** Neither the National Institutes of Health (NIH), nor any of its *****/ 00014 /***** employees imply any warranty of usefulness of this software for *****/ 00015 /***** any purpose, and do not assume any liability for damages, *****/ 00016 /***** incidental or otherwise, caused by any use of this document. *****/ 00017 /*****===================================================================*****/ 00018 00019 00020 /* global version and history strings, for printing */ 00021 static char gni_version[] = "nifti library version 0.5 (December 14, 2004)"; 00022 static char gni_history[] = 00023 "----------------------------------------------------------------------\n" 00024 "history (of nifti library changes):\n" 00025 "\n" 00026 "0.0 August, 2003 [rwcox]\n" 00027 " (Robert W Cox of the National Institutes of Health, SSCC/DIRP/NIMH)\n" 00028 " - initial version\n" 00029 "\n" 00030 "0.1 July/August, 2004 [Mark Jenkinson]\n" 00031 " (FMRIB Centre, University of Oxford, UK)\n" 00032 " - Mainly adding low-level IO and changing things to allow gzipped\n" 00033 " files to be read and written\n" 00034 " - Full backwards compatability should have been maintained\n" 00035 "\n" 00036 "0.2 16 Nov 2004 [rickr]\n" 00037 " (Rick Reynolds of the National Institutes of Health, SSCC/DIRP/NIMH)\n" 00038 " - included Mark's changes in the AFNI distribution (including znzlib/)\n" 00039 " (HAVE_ZLIB is commented out for the standard distribution)\n" 00040 " - modified nifti_validfilename() and nifti_makebasename()\n" 00041 " - added nifti_find_file_extension()\n" 00042 "\n" 00043 "0.3 3 Dec 2004 [rickr]\n" 00044 " - note: header extensions are not yet checked for\n" 00045 " - added formatted history as global string, for printing\n" 00046 " - added nifti_disp_lib_hist(), to display the nifti library history\n" 00047 " - added nifti_disp_lib_version(), to display the nifti library history\n" 00048 " - re-wrote nifti_findhdrname()\n" 00049 " o used nifti_find_file_extension()\n" 00050 " o changed order of file tests (default is .nii, depends on input)\n" 00051 " o free hdrname on failure\n" 00052 " - made similar changes to nifti_findimgname()\n" 00053 " - check for NULL return from nifti_findhdrname() calls\n" 00054 " - removed most of ERREX() macros\n" 00055 " - modified nifti_image_read()\n" 00056 " o added debug info and error checking (on gni_debug > 0, only)\n" 00057 " o fail if workingname is NULL\n" 00058 " o check for failure to open header file\n" 00059 " o free workingname on failure\n" 00060 " o check for failure of nifti_image_load()\n" 00061 " o check for failure of nifti_convert_nhdr2nim()\n" 00062 " - changed nifti_image_load() to int, and check nifti_read_buffer return\n" 00063 " - changed nifti_read_buffer() to fail on short read, and to count float\n" 00064 " fixes (to print on debug)\n" 00065 " - changed nifti_image_infodump to print to stderr\n" 00066 " - updated function header comments, or moved comments above header\n" 00067 " - removed const keyword\n" 00068 " - added LNI_FERR() macro for error reporting on input files\n" 00069 "\n" 00070 "0.4 10 Dec 2004 [rickr] - added header extensions\n" 00071 " - in nifti1_io.h:\n" 00072 " o added num_ext and ext_list to the definition of nifti_image\n" 00073 " o made many functions static (more to follow)\n" 00074 " o added LNI_MAX_NIA_EXT_LEN, for max nifti_type 3 extension length\n" 00075 " - added __DATE__ to version output in nifti_disp_lib_version()\n" 00076 " - added nifti_disp_matrix_orient() to print orientation information\n" 00077 " - added '.nia' as a valid file extension in nifti_find_file_extension()\n" 00078 " - added much more debug output\n" 00079 " - in nifti_image_read(), in the case of an ASCII header, check for\n" 00080 " extensions after the end of the header\n" 00081 " - added nifti_read_extensions() function\n" 00082 " - added nifti_read_next_extension() function\n" 00083 " - added nifti_add_exten_to_list() function\n" 00084 " - added nifti_valid_extension() function\n" 00085 " - added nifti_write_extensions() function\n" 00086 " - added nifti_extension_size() function\n" 00087 " - in nifti_set_iname_offest():\n" 00088 " o adjust offset by the extension size and the extender size\n" 00089 " o fixed the 'ceiling modulo 16' computation\n" 00090 " - in nifti_image_write_hdr_img2(): \n" 00091 " o added extension writing\n" 00092 " o check for NULL return from nifti_findimgname()\n" 00093 " - include number of extensions in nifti_image_to_ascii() output\n" 00094 " - in nifti_image_from_ascii():\n" 00095 " o return bytes_read as a parameter, computed from the final spos\n" 00096 " o extract num_ext from ASCII header\n" 00097 "\n" 00098 "0.5 14 Dec 2004 [rickr] - added sub-brick reading functions\n" 00099 " - added nifti_brick_list type to nifti1_io.h, along with new prototypes\n" 00100 " - added main nifti_image_read_bricks() function, with description\n" 00101 " - added nifti_image_load_bricks() - library function (requires nim)\n" 00102 " - added valid_nifti_brick_list() - library function\n" 00103 " - added free_NBL() - library function\n" 00104 " - added update_nifti_image_for_brick_list() for dimension update\n" 00105 " - added nifti_load_NBL_bricks(), nifti_alloc_NBL_mem(),\n" 00106 " nifti_copynsort() and force_positive() (static functions)\n" 00107 " - in nifti_image_read(), check for failed load only if read_data is set\n" 00108 " - broke most of nifti_image_load() into nifti_image_load_prep()\n" 00109 "----------------------------------------------------------------------\n"; 00110 00111 /* global debug level */ 00112 static int gni_debug = 0; 00113 00114 /*---------------------------------------------------------------------------*/ 00115 /* Return a pointer to a string holding the name of a NIFTI datatype. 00116 Don't free() or modify this string! It points to static storage. 00117 -----------------------------------------------------------------------------*/ 00118 00119 /* for calling from some main program */ 00120 void nifti_disp_lib_hist( void ) 00121 { 00122 fputs(gni_history, stdout); 00123 } 00124 00125 void nifti_disp_lib_version( void ) 00126 { 00127 printf("%s, compiled %s\n", gni_version, __DATE__); 00128 } 00129 00130 00131 /*---------------------------------------------------------------------- 00132 * nifti_image_read_bricks - read nifti data as array of bricks 00133 * 13 Dec 2004 [rickr] 00134 * inputs: 00135 * hname - filename of dataset to read 00136 * - must be valid 00137 * nbricks - number of sub-bricks to read 00138 * - if blist is valid, nbricks must be > 0 00139 * blist - list of sub-bricks to read (can be NULL) 00140 * - if NULL, read complete dataset 00141 * NBL - pointer to empty nifti_brick_list struct 00142 * - must be a valid pointer 00143 * 00144 * return: 00145 * nim - same as nifti_image_read, but data is always NULL 00146 * NBL - filled with data 00147 * 00148 * By default, this function will read the nifti dataset and break the data 00149 * into a list of nt*nu*nv*nw sub-bricks, each having size nx*ny*nz elements. 00150 * That is to say, instead of reading the entire dataset as a single array, 00151 * break it up into sub-bricks, each of size nx*ny*nz elements. 00152 * 00153 * If 'blist' is valid, it is taken to be a list of sub-bricks, of length 00154 * 'nbricks'. The data will still be separated into sub-bricks of size 00155 * nx*ny*nz elements, but now 'nbricks' sub-bricks will be returned, of the 00156 * caller's choosing via 'blist'. 00157 * 00158 * E.g. consider a dataset with 12 sub-bricks (numbered 0..11), and the 00159 * following code: 00160 * 00161 * { nifti_brick_list NB_orig, NB_select; 00162 * nifti_image * nim_orig, * nim_select; 00163 * int blist[5] = { 7, 0, 5, 5, 9 }; 00164 * 00165 * nim_orig = nifti_image_read_bricks("myfile.nii", 0, NULL, &NB_orig); 00166 * nim_select = nifti_image_read_bricks("myfile.nii", 5, blist, &NB_select); 00167 * } 00168 * 00169 * Here, nim_orig gets the entire dataset, where NB_orig.nbricks = 11. But 00170 * nim_select has NB_select.nbricks = 5. 00171 * 00172 * Note that the first case is not quite the same as just calling the 00173 * nifti_image_read function, as here the data is separated into sub-bricks. 00174 * 00175 * Note that valid values for blist are in [0..nt*nu*nv*nw-1], 00176 * or written [ 0 .. (dim[4]*dim[5]*dim[6]*dim[7] - 1) ]. 00177 *----------------------------------------------------------------------*/ 00178 nifti_image *nifti_image_read_bricks( char *hname , int nbricks, int * blist, 00179 nifti_brick_list * NBL ) 00180 { 00181 nifti_image * nim; 00182 00183 if( !hname || !NBL ){ 00184 fprintf(stderr,"** nifti_image_read_bricks: bad params (%p,%p)\n", 00185 hname, NBL); 00186 return NULL; 00187 } 00188 00189 if( blist && nbricks <= 0 ){ 00190 fprintf(stderr,"** nifti_image_read_bricks: bad nbricks, %d\n", nbricks); 00191 return NULL; 00192 } 00193 00194 nim = nifti_image_read(hname, 0); /* read header, but not data */ 00195 00196 if( !nim ) return NULL; /* errors were already printed */ 00197 00198 /* if we fail, free image and return */ 00199 if( nifti_image_load_bricks(nim, nbricks, blist, NBL) <= 0 ){ 00200 nifti_image_free(nim); 00201 return NULL; 00202 } 00203 00204 if( blist ) update_nifti_image_for_brick_list(nim, nbricks); 00205 00206 return nim; 00207 } 00208 00209 00210 /*---------------------------------------------------------------------- 00211 * update_nifti_image_for_brick_list - update nifti_image 00212 * 00213 * When loading a specific brick list, the distinction between 00214 * nt, nu, nv and nw is lost. So put everything in t, and set 00215 * dim[0] = 4. 00216 *----------------------------------------------------------------------*/ 00217 static void update_nifti_image_for_brick_list( nifti_image * nim , int nbricks ) 00218 { 00219 int ndim; 00220 00221 if( gni_debug > 2 ){ 00222 fprintf(stderr,"+d updating image dimensions for %d bricks in list\n", 00223 nbricks); 00224 fprintf(stderr," ndim = %d\n",nim->ndim); 00225 fprintf(stderr," nx,ny,nz,nt,nu,nv,nw: (%d,%d,%d,%d,%d,%d,%d)", 00226 nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw); 00227 } 00228 00229 nim->nt = nbricks; 00230 nim->nu = nim->nv = nim->nw = 1; 00231 00232 nim->dim[4] = nbricks; 00233 nim->dim[5] = nim->dim[6] = nim->dim[7] = 1; 00234 00235 /* update the dimensions to 4 or lower */ 00236 for( ndim = 4; (ndim > 1) && (nim->dim[ndim] <= 1); ndim-- ) 00237 ; 00238 nim->dim[0] = nim->ndim = ndim; 00239 00240 if( gni_debug > 2 ){ 00241 fprintf(stderr," --> (%d,%d,%d,%d,%d,%d,%d)\n", 00242 nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw); 00243 fprintf(stderr,"+d new ndim = %d\n",nim->ndim); 00244 } 00245 } 00246 00247 00248 /*---------------------------------------------------------------------- 00249 * Load the image data from disk into an already-prepared image struct. 00250 * 13 Dec 2004 [rickr] 00251 * 00252 * If blist is NULL, read the dataset normally. 00253 * 00254 * return the number of loaded bricks (NBL->nbricks) 00255 * 00256 * > 0 : success 00257 * 0 : failure 00258 * < 0 : error 00259 *----------------------------------------------------------------------*/ 00260 int nifti_image_load_bricks( nifti_image * nim , int nbricks, int * blist, 00261 nifti_brick_list * NBL ) 00262 { 00263 int * slist = NULL, * sindex = NULL, rv; 00264 znzFile fp; 00265 00266 /* we can have blist == NULL */ 00267 if( !nim || !NBL ){ 00268 fprintf(stderr,"** nifti_image_load_bricks, bad params (%p,%p)\n", 00269 nim, NBL); 00270 return -1; 00271 } 00272 00273 if( blist && ! valid_nifti_brick_list( nim, nbricks, blist, 1 ) ) 00274 return -1; 00275 00276 /* for efficiency, let's read the file in order */ 00277 if( blist && nifti_copynsort( nbricks, blist, &slist, &sindex ) != 0 ) 00278 return -1; 00279 00280 /* open the file and position the FILE pointer */ 00281 fp = nifti_image_load_prep( nim ); 00282 if( !fp ){ 00283 if( gni_debug > 0 ) 00284 fprintf(stderr,"** nifti_image_load_bricks, failed load_prep\n"); 00285 if( blist ){ free(slist); free(sindex); } 00286 return -1; 00287 } 00288 00289 /* this will flag to allocate defaults */ 00290 if( !blist ) nbricks = 0; 00291 if( nifti_alloc_NBL_mem( nim, nbricks, NBL ) != 0 ){ 00292 if( blist ){ free(slist); free(sindex); } 00293 znzclose(fp); 00294 return -1; 00295 } 00296 00297 rv = nifti_load_NBL_bricks(nim, slist, sindex, NBL, fp); 00298 00299 if( rv != 0 ){ 00300 free_NBL( NBL ); /* failure! */ 00301 NBL->nbricks = 0; /* repetative, but clear */ 00302 } 00303 00304 if( slist ){ free(slist); free(sindex); } 00305 00306 znzclose(fp); 00307 00308 return NBL->nbricks; 00309 } 00310 00311 00312 /*---------------------------------------------------------------------- 00313 * free_NBL - free all pointers and clear structure 00314 * 00315 * note: this does not presume to free the structure pointer 00316 *----------------------------------------------------------------------*/ 00317 void free_NBL( nifti_brick_list * NBL ) 00318 { 00319 int c; 00320 00321 if( NBL->bricks ){ 00322 for( c = 0; c < NBL->nbricks; c++ ) 00323 if( NBL->bricks[c] ) free(NBL->bricks[c]); 00324 free(NBL->bricks); 00325 NBL->bricks = NULL; 00326 } 00327 00328 NBL->nbricks = NBL->bsize = 0; 00329 } 00330 00331 00332 /*---------------------------------------------------------------------- 00333 * nifti_load_NBL_bricks - read the file data into the NBL struct 00334 * 00335 * return 0 on success, -1 on failure 00336 *----------------------------------------------------------------------*/ 00337 static int nifti_load_NBL_bricks( nifti_image * nim , int * slist, int * sindex, 00338 nifti_brick_list * NBL, znzFile fp ) 00339 { 00340 int c, rv; 00341 int oposn, fposn; /* orig and current file positions */ 00342 int prev, isrc, idest; /* previous and current sub-brick, and new index */ 00343 00344 oposn = znztell(fp); /* store current file position */ 00345 fposn = oposn; 00346 if( fposn < 0 ){ 00347 fprintf(stderr,"** load bricks: ztell failed??\n"); 00348 return -1; 00349 } 00350 00351 /* first, handle the default case, no passed blist */ 00352 if( !slist ){ 00353 for( c = 0; c < NBL->nbricks; c++ ) { 00354 rv = nifti_read_buffer(fp, NBL->bricks[c], NBL->bsize, nim); 00355 if( rv != NBL->bsize ){ 00356 fprintf(stderr,"** load bricks: cannot read brick %d from '%s'\n", 00357 c, nim->iname ? nim->iname : nim->fname); 00358 return -1; 00359 } 00360 } 00361 if( gni_debug > 1 ) 00362 fprintf(stderr,"+d read %d default bricks from file %s\n", 00363 NBL->nbricks, nim->iname ? nim->iname : nim->fname ); 00364 return 0; 00365 } 00366 00367 if( !sindex ){ 00368 fprintf(stderr,"** load_NBL_bricks: missing index list\n"); 00369 return -1; 00370 } 00371 00372 prev = -1; /* use prev for previous sub-brick */ 00373 for( c = 0; c < NBL->nbricks; c++ ){ 00374 isrc = slist[c]; /* this is original brick index (c is new one) */ 00375 idest = sindex[c]; /* this is the destination index for this data */ 00376 00377 /* if this sub-brick is not the previous, we must read from disk */ 00378 if( isrc != prev ){ 00379 00380 /* if we are not looking at the correct sub-brick, scan forward */ 00381 if( fposn != (oposn + isrc*NBL->bsize) ){ 00382 fposn = oposn + isrc*NBL->bsize; 00383 if( znzseek(fp, fposn, SEEK_SET) < 0 ){ 00384 fprintf(stderr,"** failed to locate brick %d in file '%s'\n", 00385 isrc, nim->iname ? nim->iname : nim->fname); 00386 return -1; 00387 } 00388 } 00389 00390 /* only 10,000 lines later and we're actually reading something! */ 00391 rv = nifti_read_buffer(fp, NBL->bricks[idest], NBL->bsize, nim); 00392 if( rv != NBL->bsize ){ 00393 fprintf(stderr,"** failed to read brick %d from file '%s'\n", 00394 isrc, nim->iname ? nim->iname : nim->fname); 00395 return -1; 00396 } 00397 fposn += NBL->bsize; 00398 } else { 00399 /* we have already read this sub-brick, just copy the previous one */ 00400 /* note that this works because they are sorted */ 00401 memcpy(NBL->bricks[idest], NBL->bricks[sindex[c-1]], NBL->bsize); 00402 } 00403 00404 prev = isrc; /* in any case, note the now previous sub-brick */ 00405 } 00406 00407 return 0; 00408 } 00409 00410 00411 /*---------------------------------------------------------------------- 00412 * nifti_alloc_NBL_mem - allocate memory for bricks 00413 * 00414 * return 0 on success, -1 on failure 00415 *----------------------------------------------------------------------*/ 00416 static int nifti_alloc_NBL_mem(nifti_image * nim, int nbricks, 00417 nifti_brick_list * nbl) 00418 { 00419 int c; 00420 00421 /* if nbricks is not specified, use the default */ 00422 if( nbricks > 0 ) nbl->nbricks = nbricks; 00423 else nbl->nbricks = nim->nt * nim->nu * nim->nv * nim->nw; 00424 00425 nbl->bsize = nim->nx * nim->ny * nim->nz; 00426 nbl->bricks = (void **)malloc(nbl->nbricks * sizeof(void *)); 00427 00428 if( ! nbl->bricks ){ 00429 fprintf(stderr,"** NANM: failed to alloc %d void ptrs\n",nbricks); 00430 return -1; 00431 } 00432 00433 for( c = 0; c < nbl->nbricks; c++ ){ 00434 nbl->bricks[c] = (void *)malloc(nbl->bsize * nim->nbyper); 00435 if( ! nbl->bricks[c] ){ 00436 fprintf(stderr,"** NANM: failed to alloc %d bytes for brick %d\n", 00437 nbl->bsize*nim->nbyper, c); 00438 /* so free and clear everything before returning */ 00439 while( c > 0 ){ 00440 c--; 00441 free(nbl->bricks[c]); 00442 } 00443 free(nbl->bricks); 00444 nbl->bricks = NULL; 00445 nbl->nbricks = nbl->bsize = 0; 00446 return -1; 00447 } 00448 } 00449 00450 if( gni_debug > 2 ) 00451 fprintf(stderr,"+d NANM: alloc'd %d bricks of %d bytes for NBL\n", 00452 nbl->nbricks, nbl->bsize*nim->nbyper); 00453 00454 return 0; 00455 } 00456 00457 00458 /*---------------------------------------------------------------------- 00459 * nifti_copynsort - copy int list, and sort with indices 00460 * 00461 * 1. duplicate the incoming list 00462 * 2. create an sindex list, and init with 0..nbricks-1 00463 * 3. do a slow insertion sort on the small slist, along with sindex list 00464 * 4. check results, just to be positive 00465 * 00466 * So slist is sorted, and sindex hold original positions. 00467 * 00468 * return 0 on success, -1 on failure 00469 *----------------------------------------------------------------------*/ 00470 static int nifti_copynsort(int nbricks, int * blist, int ** slist, 00471 int ** sindex) 00472 { 00473 int * stmp, * itmp; /* for ease of typing/reading */ 00474 int c1, c2, spos, tmp; 00475 00476 *slist = (int *)malloc(nbricks * sizeof(int)); 00477 *sindex = (int *)malloc(nbricks * sizeof(int)); 00478 00479 if( !*slist || !*sindex ){ 00480 fprintf(stderr,"** NCS: failed to alloc %d ints for sorting\n",nbricks); 00481 if(*slist) free(*slist); /* maybe one succeeded */ 00482 if(*sindex) free(*sindex); 00483 return -1; 00484 } 00485 00486 /* init the lists */ 00487 memcpy(*slist, blist, nbricks*sizeof(int)); 00488 for( c1 = 0; c1 < nbricks; c1++ ) (*sindex)[c1] = c1; 00489 00490 /* now actually sort slist */ 00491 stmp = *slist; 00492 itmp = *sindex; 00493 for( c1 = 0; c1 < nbricks-1; c1++ ) { 00494 /* find smallest value, init to current */ 00495 spos = c1; 00496 for( c2 = c1+1; c2 < nbricks; c2++ ) 00497 if( stmp[c2] < stmp[spos] ) spos = c2; 00498 if( spos != c1 ) /* swap: fine, don't maintain sub-order, see if I care */ 00499 { 00500 tmp = stmp[c1]; /* first swap the sorting values */ 00501 stmp[c1] = stmp[spos]; 00502 stmp[spos] = tmp; 00503 00504 tmp = itmp[c1]; /* then swap the index values */ 00505 itmp[c1] = itmp[spos]; 00506 itmp[spos] = tmp; 00507 } 00508 } 00509 00510 if( gni_debug > 2 ){ 00511 fprintf(stderr, "+d sorted indexing list:\n"); 00512 fprintf(stderr, " orig : "); 00513 for( c1 = 0; c1 < nbricks; c1++ ) fprintf(stderr," %d",blist[c1]); 00514 fprintf(stderr,"\n new : "); 00515 for( c1 = 0; c1 < nbricks; c1++ ) fprintf(stderr," %d",stmp[c1]); 00516 fprintf(stderr,"\n indices: "); 00517 for( c1 = 0; c1 < nbricks; c1++ ) fprintf(stderr," %d",itmp[c1]); 00518 fputc('\n', stderr); 00519 } 00520 00521 /* check the sort (why not? I've got time...) */ 00522 for( c1 = 0; c1 < nbricks-1; c1++ ){ 00523 if( (stmp[c1] > stmp[c1+1]) || (blist[itmp[c1]] != stmp[c1]) ){ 00524 fprintf(stderr,"** sorting screw-up, way to go, rick!\n"); 00525 free(stmp); free(itmp); *slist = NULL; *sindex = NULL; 00526 return -1; 00527 } 00528 } 00529 00530 if( gni_debug > 2 ) fprintf(stderr,"-d sorting is okay\n"); 00531 00532 return 0; 00533 } 00534 00535 00536 /*---------------------------------------------------------------------- 00537 * valid_nifti_brick_list - check sub-brick list for image 00538 * 00539 * return 1 if valid, 0 if not 00540 *----------------------------------------------------------------------*/ 00541 int valid_nifti_brick_list(nifti_image * nim , int nbricks, int * blist, 00542 int disp_error) 00543 { 00544 int c, nsubs; 00545 00546 if( !nim ){ 00547 if( disp_error || gni_debug > 0 ) 00548 fprintf(stderr,"** valid_nifti_brick_list: missing nifti image\n"); 00549 return 0; 00550 } 00551 00552 if( nbricks <= 0 || !blist ){ 00553 if( disp_error || gni_debug > 1 ) 00554 fprintf(stderr,"** valid_nifti_brick_list: no brick list to check\n"); 00555 return 0; 00556 } 00557 00558 /* nsubs sub-brick is nt*nu*nv*nw */ 00559 nsubs = nim->dim[4] * nim->dim[5] * nim->dim[6] * nim->dim[7]; 00560 00561 if( nsubs <= 0 ){ 00562 fprintf(stderr,"** VNBL warning: bad dim list (%d,%d,%d,%d)\n", 00563 nim->dim[4], nim->dim[5], nim->dim[6], nim->dim[7]); 00564 int_force_positive(nim->dim+4, 4); 00565 nsubs = nim->dim[4] * nim->dim[5] * nim->dim[6] * nim->dim[7]; 00566 } 00567 00568 for( c = 0; c < nbricks; c++ ) 00569 if( (blist[c] < 0) || (blist[c] >= nsubs) ){ 00570 if( disp_error || gni_debug > 1 ) 00571 fprintf(stderr, 00572 "-d ** bad sub-brick chooser %d (#%d), valid range is [0,%d]\n", 00573 blist[c], c, nsubs-1); 00574 return 0; 00575 } 00576 00577 return 1; /* all is well */ 00578 } 00579 00580 /* set any non-positive values to 1 */ 00581 static int int_force_positive( int * list, int nel ) 00582 { 00583 int c; 00584 if( *list || nel <= 0 ){ 00585 if( gni_debug > 0 ) 00586 fprintf(stderr,"** int_force_positive: bad params (%p,%d)\n",list,nel); 00587 return -1; 00588 } 00589 for( c = 0; c < nel; c++ ) 00590 if( list[c] <= 0 ) list[c] = 1; 00591 return 0; 00592 } 00593 /* end of new nifti_image_read_bricks() functionality */ 00594 00595 /*---------------------------------------------------------------------- 00596 * display the orientation from the quaternian fields 00597 * 00598 * return < 0 if results cannot be determined, 0 if okay 00599 *----------------------------------------------------------------------*/ 00600 int nifti_disp_matrix_orient( char * mesg, mat44 mat ) 00601 { 00602 int i, j, k; 00603 00604 if ( mesg ) fputs( mesg, stderr ); /* use stdout? */ 00605 00606 mat44_to_orientation( mat, &i,&j,&k ); 00607 if ( i <= 0 || j <= 0 || k <= 0 ) return -1; 00608 00609 /* so we have good codes */ 00610 fprintf(stderr, " i orientation = '%s'\n" 00611 " j orientation = '%s'\n" 00612 " k orientation = '%s'\n", 00613 nifti_orientation_string(i), 00614 nifti_orientation_string(j), 00615 nifti_orientation_string(k) ); 00616 return 0; 00617 } 00618 00619 00620 char *nifti_strdup(char *str) 00621 { 00622 char *dup= (char *)malloc( strlen(str)+1 ); 00623 if (dup) strcpy(dup,str); 00624 return dup; 00625 } 00626 #ifndef HAVE_STRDUP 00627 #endif 00628 00629 00630 char *nifti_datatype_string( int dt ) 00631 { 00632 switch( dt ){ 00633 case DT_UNKNOWN: return "UNKNOWN" ; 00634 case DT_BINARY: return "BINARY" ; 00635 case DT_INT8: return "INT8" ; 00636 case DT_UINT8: return "UINT8" ; 00637 case DT_INT16: return "INT16" ; 00638 case DT_UINT16: return "UINT16" ; 00639 case DT_INT32: return "INT32" ; 00640 case DT_UINT32: return "UINT32" ; 00641 case DT_INT64: return "INT64" ; 00642 case DT_UINT64: return "UINT64" ; 00643 case DT_FLOAT32: return "FLOAT32" ; 00644 case DT_FLOAT64: return "FLOAT64" ; 00645 case DT_FLOAT128: return "FLOAT128" ; 00646 case DT_COMPLEX64: return "COMPLEX64" ; 00647 case DT_COMPLEX128: return "COMPLEX128" ; 00648 case DT_COMPLEX256: return "COMPLEX256" ; 00649 case DT_RGB24: return "RGB24" ; 00650 } 00651 return "**ILLEGAL**" ; 00652 } 00653 00654 /*---------------------------------------------------------------------------*/ 00655 /* Determine if the datatype code dt is an integer type (1=YES, 0=NO). 00656 -----------------------------------------------------------------------------*/ 00657 00658 int nifti_is_inttype( int dt ) 00659 { 00660 switch( dt ){ 00661 case DT_UNKNOWN: return 0 ; 00662 case DT_BINARY: return 0 ; 00663 case DT_INT8: return 1 ; 00664 case DT_UINT8: return 1 ; 00665 case DT_INT16: return 1 ; 00666 case DT_UINT16: return 1 ; 00667 case DT_INT32: return 1 ; 00668 case DT_UINT32: return 1 ; 00669 case DT_INT64: return 1 ; 00670 case DT_UINT64: return 1 ; 00671 case DT_FLOAT32: return 0 ; 00672 case DT_FLOAT64: return 0 ; 00673 case DT_FLOAT128: return 0 ; 00674 case DT_COMPLEX64: return 0 ; 00675 case DT_COMPLEX128: return 0 ; 00676 case DT_COMPLEX256: return 0 ; 00677 case DT_RGB24: return 1 ; 00678 } 00679 return 0 ; 00680 } 00681 00682 /*---------------------------------------------------------------------------*/ 00683 /* Return a pointer to a string holding the name of a NIFTI units type. 00684 Don't free() or modify this string! It points to static storage. 00685 -----------------------------------------------------------------------------*/ 00686 00687 char *nifti_units_string( int uu ) 00688 { 00689 switch( uu ){ 00690 case NIFTI_UNITS_METER: return "m" ; 00691 case NIFTI_UNITS_MM: return "mm" ; 00692 case NIFTI_UNITS_MICRON: return "um" ; 00693 case NIFTI_UNITS_SEC: return "s" ; 00694 case NIFTI_UNITS_MSEC: return "ms" ; 00695 case NIFTI_UNITS_USEC: return "us" ; 00696 case NIFTI_UNITS_HZ: return "Hz" ; 00697 case NIFTI_UNITS_PPM: return "ppm" ; 00698 case NIFTI_UNITS_RADS: return "rad/s" ; 00699 } 00700 return "Unknown" ; 00701 } 00702 00703 /*---------------------------------------------------------------------------*/ 00704 /* Return a pointer to a string holding the name of a NIFTI transform type. 00705 Don't free() or modify this string! It points to static storage. 00706 -----------------------------------------------------------------------------*/ 00707 00708 char *nifti_xform_string( int xx ) 00709 { 00710 switch( xx ){ 00711 case NIFTI_XFORM_SCANNER_ANAT: return "Scanner Anat" ; 00712 case NIFTI_XFORM_ALIGNED_ANAT: return "Aligned Anat" ; 00713 case NIFTI_XFORM_TALAIRACH: return "Talairach" ; 00714 case NIFTI_XFORM_MNI_152: return "MNI_152" ; 00715 } 00716 return "Unknown" ; 00717 } 00718 00719 /*---------------------------------------------------------------------------*/ 00720 /* Return a pointer to a string holding the name of a NIFTI intent type. 00721 Don't free() or modify this string! It points to static storage. 00722 -----------------------------------------------------------------------------*/ 00723 00724 char *nifti_intent_string( int ii ) 00725 { 00726 switch( ii ){ 00727 case NIFTI_INTENT_CORREL: return "Correlation statistic" ; 00728 case NIFTI_INTENT_TTEST: return "T-statistic" ; 00729 case NIFTI_INTENT_FTEST: return "F-statistic" ; 00730 case NIFTI_INTENT_ZSCORE: return "Z-score" ; 00731 case NIFTI_INTENT_CHISQ: return "Chi-squared distribution" ; 00732 case NIFTI_INTENT_BETA: return "Beta distribution" ; 00733 case NIFTI_INTENT_BINOM: return "Binomial distribution" ; 00734 case NIFTI_INTENT_GAMMA: return "Gamma distribution" ; 00735 case NIFTI_INTENT_POISSON: return "Poisson distribution" ; 00736 case NIFTI_INTENT_NORMAL: return "Normal distribution" ; 00737 case NIFTI_INTENT_FTEST_NONC: return "F-statistic noncentral" ; 00738 case NIFTI_INTENT_CHISQ_NONC: return "Chi-squared noncentral" ; 00739 case NIFTI_INTENT_LOGISTIC: return "Logistic distribution" ; 00740 case NIFTI_INTENT_LAPLACE: return "Laplace distribution" ; 00741 case NIFTI_INTENT_UNIFORM: return "Uniform distribition" ; 00742 case NIFTI_INTENT_TTEST_NONC: return "T-statistic noncentral" ; 00743 case NIFTI_INTENT_WEIBULL: return "Weibull distribution" ; 00744 case NIFTI_INTENT_CHI: return "Chi distribution" ; 00745 case NIFTI_INTENT_INVGAUSS: return "Inverse Gaussian distribution" ; 00746 case NIFTI_INTENT_EXTVAL: return "Extreme Value distribution" ; 00747 case NIFTI_INTENT_PVAL: return "P-value" ; 00748 00749 case NIFTI_INTENT_LOGPVAL: return "Log P-value" ; 00750 case NIFTI_INTENT_LOG10PVAL: return "Log10 P-value" ; 00751 00752 case NIFTI_INTENT_ESTIMATE: return "Estimate" ; 00753 case NIFTI_INTENT_LABEL: return "Label index" ; 00754 case NIFTI_INTENT_NEURONAME: return "NeuroNames index" ; 00755 case NIFTI_INTENT_GENMATRIX: return "General matrix" ; 00756 case NIFTI_INTENT_SYMMATRIX: return "Symmetric matrix" ; 00757 case NIFTI_INTENT_DISPVECT: return "Displacement vector" ; 00758 case NIFTI_INTENT_VECTOR: return "Vector" ; 00759 case NIFTI_INTENT_POINTSET: return "Pointset" ; 00760 case NIFTI_INTENT_TRIANGLE: return "Triangle" ; 00761 case NIFTI_INTENT_QUATERNION: return "Quaternion" ; 00762 00763 case NIFTI_INTENT_DIMLESS: return "Dimensionless number" ; 00764 } 00765 return "Unknown" ; 00766 } 00767 00768 /*---------------------------------------------------------------------------*/ 00769 /* Return a pointer to a string holding the name of a NIFTI slice_code 00770 string. Don't free() or modify this string! It points to static storage. 00771 -----------------------------------------------------------------------------*/ 00772 00773 char *nifti_slice_string( int ss ) 00774 { 00775 switch( ss ){ 00776 case NIFTI_SLICE_SEQ_INC: return "sequential_increasing" ; 00777 case NIFTI_SLICE_SEQ_DEC: return "sequential_decreasing" ; 00778 case NIFTI_SLICE_ALT_INC: return "alternating_increasing" ; 00779 case NIFTI_SLICE_ALT_DEC: return "alternating_decreasing" ; 00780 } 00781 return "Unknown" ; 00782 } 00783 00784 /*---------------------------------------------------------------------------*/ 00785 /* Return a pointer to a string holding the name of a NIFTI orientation 00786 string. Don't free() or modify this string! It points to static storage. 00787 -----------------------------------------------------------------------------*/ 00788 00789 char *nifti_orientation_string( int ii ) 00790 { 00791 switch( ii ){ 00792 case NIFTI_L2R: return "Left-to-Right" ; 00793 case NIFTI_R2L: return "Right-to-Left" ; 00794 case NIFTI_P2A: return "Posterior-to-Anterior" ; 00795 case NIFTI_A2P: return "Anterior-to-Posterior" ; 00796 case NIFTI_I2S: return "Inferior-to-Superior" ; 00797 case NIFTI_S2I: return "Superior-to-Inferior" ; 00798 } 00799 return "Unknown" ; 00800 } 00801 00802 /*--------------------------------------------------------------------------*/ 00803 /* Given a datatype code, set number of bytes per voxel and the swapsize. 00804 The swapsize is set to 0 if this datatype doesn't ever need swapping. 00805 ----------------------------------------------------------------------------*/ 00806 00807 void nifti_datatype_sizes( int datatype , int *nbyper, int *swapsize ) 00808 { 00809 int nb=0, ss=0 ; 00810 switch( datatype ){ 00811 case DT_INT8: 00812 case DT_UINT8: nb = 1 ; ss = 0 ; break ; 00813 00814 case DT_INT16: 00815 case DT_UINT16: nb = 2 ; ss = 2 ; break ; 00816 00817 case DT_RGB24: nb = 3 ; ss = 0 ; break ; 00818 00819 case DT_INT32: 00820 case DT_UINT32: 00821 case DT_FLOAT32: nb = 4 ; ss = 4 ; break ; 00822 00823 case DT_COMPLEX64: nb = 8 ; ss = 4 ; break ; 00824 00825 case DT_FLOAT64: 00826 case DT_INT64: 00827 case DT_UINT64: nb = 8 ; ss = 8 ; break ; 00828 00829 case DT_FLOAT128: nb = 16 ; ss = 16 ; break ; 00830 00831 case DT_COMPLEX128: nb = 16 ; ss = 8 ; break ; 00832 00833 case DT_COMPLEX256: nb = 32 ; ss = 16 ; break ; 00834 } 00835 00836 ASSIF(nbyper,nb) ; ASSIF(swapsize,ss) ; return ; 00837 } 00838 00839 /*---------------------------------------------------------------------------*/ 00840 /* Given the quaternion parameters (etc.), compute a transformation matrix. 00841 See comments in nifti1.h for details. 00842 - qb,qc,qd = quaternion parameters 00843 - qx,qy,qz = offset parameters 00844 - dx,dy,dz = grid stepsizes (non-negative inputs are set to 1.0) 00845 - qfac = sign of dz step (< 0 is negative; >= 0 is positive) 00846 If qx=qy=qz=0, dx=dy=dz=1, then the output is a rotation matrix. 00847 For qfac >= 0, the rotation is proper. 00848 For qfac < 0, the rotation is improper. 00849 -----------------------------------------------------------------------------*/ 00850 00851 mat44 quatern_to_mat44( float qb, float qc, float qd, 00852 float qx, float qy, float qz, 00853 float dx, float dy, float dz, float qfac ) 00854 { 00855 mat44 R ; 00856 double a,b=qb,c=qc,d=qd , xd,yd,zd ; 00857 00858 /* last row is always [ 0 0 0 1 ] */ 00859 00860 R.m[3][0]=R.m[3][1]=R.m[3][2] = 0.0 ; R.m[3][3]= 1.0 ; 00861 00862 /* compute a parameter from b,c,d */ 00863 00864 a = 1.0l - (b*b + c*c + d*d) ; 00865 if( a < 1.e-7l ){ /* special case */ 00866 a = 1.0l / sqrt(b*b+c*c+d*d) ; 00867 b *= a ; c *= a ; d *= a ; /* normalize (b,c,d) vector */ 00868 a = 0.0l ; /* a = 0 ==> 180 degree rotation */ 00869 } else{ 00870 a = sqrt(a) ; /* angle = 2*arccos(a) */ 00871 } 00872 00873 /* load rotation matrix, including scaling factors for voxel sizes */ 00874 00875 xd = (dx > 0.0) ? dx : 1.0l ; /* make sure are positive */ 00876 yd = (dy > 0.0) ? dy : 1.0l ; 00877 zd = (dz > 0.0) ? dz : 1.0l ; 00878 00879 if( qfac < 0.0 ) zd = -zd ; /* left handedness? */ 00880 00881 R.m[0][0] = (a*a+b*b-c*c-d*d) * xd ; 00882 R.m[0][1] = 2.0l * (b*c-a*d ) * yd ; 00883 R.m[0][2] = 2.0l * (b*d+a*c ) * zd ; 00884 R.m[1][0] = 2.0l * (b*c+a*d ) * xd ; 00885 R.m[1][1] = (a*a+c*c-b*b-d*d) * yd ; 00886 R.m[1][2] = 2.0l * (c*d-a*b ) * zd ; 00887 R.m[2][0] = 2.0l * (b*d-a*c ) * xd ; 00888 R.m[2][1] = 2.0l * (c*d+a*b ) * yd ; 00889 R.m[2][2] = (a*a+d*d-c*c-b*b) * zd ; 00890 00891 /* load offsets */ 00892 00893 R.m[0][3] = qx ; R.m[1][3] = qy ; R.m[2][3] = qz ; 00894 00895 return R ; 00896 } 00897 00898 /*---------------------------------------------------------------------------*/ 00899 /* Given the 3x4 upper corner of the matrix R, compute the quaternion 00900 parameters that fit it. See comments in nifti1.h for details. 00901 - Any NULL pointer on input won't get assigned (e.g., if you don't want 00902 dx,dy,dz, just pass NULL in for those pointers). 00903 - If the 3 input matrix columns are NOT orthogonal, they will be 00904 orthogonalized prior to calculating the parameters, using 00905 the polar decomposition to find the orthogonal matrix closest 00906 to the column-normalized input matrix. 00907 - However, if the 3 input matrix columns are NOT orthogonal, then 00908 the matrix produced by quatern_to_mat44 WILL have orthogonal 00909 columns, so it won't be the same as the matrix input here. 00910 This "feature" is because the NIFTI 'qform' transform is 00911 deliberately not fully general -- it is intended to model a volume 00912 with perpendicular axes. 00913 - If the 3 input matrix columns are not even linearly independent, 00914 you'll just have to take your luck, won't you? 00915 -----------------------------------------------------------------------------*/ 00916 00917 void mat44_to_quatern( mat44 R , 00918 float *qb, float *qc, float *qd, 00919 float *qx, float *qy, float *qz, 00920 float *dx, float *dy, float *dz, float *qfac ) 00921 { 00922 double r11,r12,r13 , r21,r22,r23 , r31,r32,r33 ; 00923 double xd,yd,zd , a,b,c,d ; 00924 mat33 P,Q ; 00925 00926 /* offset outputs are read write out of input matrix */ 00927 00928 ASSIF(qx,R.m[0][3]) ; ASSIF(qy,R.m[1][3]) ; ASSIF(qz,R.m[2][3]) ; 00929 00930 /* load 3x3 matrix into local variables */ 00931 00932 r11 = R.m[0][0] ; r12 = R.m[0][1] ; r13 = R.m[0][2] ; 00933 r21 = R.m[1][0] ; r22 = R.m[1][1] ; r23 = R.m[1][2] ; 00934 r31 = R.m[2][0] ; r32 = R.m[2][1] ; r33 = R.m[2][2] ; 00935 00936 /* compute lengths of each column; these determine grid spacings */ 00937 00938 xd = sqrt( r11*r11 + r21*r21 + r31*r31 ) ; 00939 yd = sqrt( r12*r12 + r22*r22 + r32*r32 ) ; 00940 zd = sqrt( r13*r13 + r23*r23 + r33*r33 ) ; 00941 00942 /* if a column length is zero, patch the trouble */ 00943 00944 if( xd == 0.0l ){ r11 = 1.0l ; r21 = r31 = 0.0l ; xd = 1.0l ; } 00945 if( yd == 0.0l ){ r22 = 1.0l ; r12 = r32 = 0.0l ; yd = 1.0l ; } 00946 if( zd == 0.0l ){ r33 = 1.0l ; r13 = r23 = 0.0l ; zd = 1.0l ; } 00947 00948 /* assign the output lengths */ 00949 00950 ASSIF(dx,xd) ; ASSIF(dy,yd) ; ASSIF(dz,zd) ; 00951 00952 /* normalize the columns */ 00953 00954 r11 /= xd ; r21 /= xd ; r31 /= xd ; 00955 r12 /= yd ; r22 /= yd ; r32 /= yd ; 00956 r13 /= zd ; r23 /= zd ; r33 /= zd ; 00957 00958 /* At this point, the matrix has normal columns, but we have to allow 00959 for the fact that the hideous user may not have given us a matrix 00960 with orthogonal columns. 00961 00962 So, now find the orthogonal matrix closest to the current matrix. 00963 00964 One reason for using the polar decomposition to get this 00965 orthogonal matrix, rather than just directly orthogonalizing 00966 the columns, is so that inputting the inverse matrix to R 00967 will result in the inverse orthogonal matrix at this point. 00968 If we just orthogonalized the columns, this wouldn't necessarily hold. */ 00969 00970 Q.m[0][0] = r11 ; Q.m[0][1] = r12 ; Q.m[0][2] = r13 ; /* load Q */ 00971 Q.m[1][0] = r21 ; Q.m[1][1] = r22 ; Q.m[1][2] = r23 ; 00972 Q.m[2][0] = r31 ; Q.m[2][1] = r32 ; Q.m[2][2] = r33 ; 00973 00974 P = mat33_polar(Q) ; /* P is orthog matrix closest to Q */ 00975 00976 r11 = P.m[0][0] ; r12 = P.m[0][1] ; r13 = P.m[0][2] ; /* unload */ 00977 r21 = P.m[1][0] ; r22 = P.m[1][1] ; r23 = P.m[1][2] ; 00978 r31 = P.m[2][0] ; r32 = P.m[2][1] ; r33 = P.m[2][2] ; 00979 00980 /* [ r11 r12 r13 ] */ 00981 /* at this point, the matrix [ r21 r22 r23 ] is orthogonal */ 00982 /* [ r31 r32 r33 ] */ 00983 00984 /* compute the determinant to determine if it is proper */ 00985 00986 zd = r11*r22*r33-r11*r32*r23-r21*r12*r33 00987 +r21*r32*r13+r31*r12*r23-r31*r22*r13 ; /* should be -1 or 1 */ 00988 00989 if( zd > 0 ){ /* proper */ 00990 ASSIF(qfac,1.0) ; 00991 } else { /* improper ==> flip 3rd column */ 00992 ASSIF(qfac,-1.0) ; 00993 r13 = -r13 ; r23 = -r23 ; r33 = -r33 ; 00994 } 00995 00996 /* now, compute quaternion parameters */ 00997 00998 a = r11 + r22 + r33 + 1.0l ; 00999 01000 if( a > 0.5l ){ /* simplest case */ 01001 a = 0.5l * sqrt(a) ; 01002 b = 0.25l * (r32-r23) / a ; 01003 c = 0.25l * (r13-r31) / a ; 01004 d = 0.25l * (r21-r12) / a ; 01005 } else { /* trickier case */ 01006 xd = 1.0 + r11 - (r22+r33) ; /* 4*b*b */ 01007 yd = 1.0 + r22 - (r11+r33) ; /* 4*c*c */ 01008 zd = 1.0 + r33 - (r11+r22) ; /* 4*d*d */ 01009 if( xd > 1.0 ){ 01010 b = 0.5l * sqrt(xd) ; 01011 c = 0.25l* (r12+r21) / b ; 01012 d = 0.25l* (r13+r31) / b ; 01013 a = 0.25l* (r32-r23) / b ; 01014 } else if( yd > 1.0 ){ 01015 c = 0.5l * sqrt(yd) ; 01016 b = 0.25l* (r12+r21) / c ; 01017 d = 0.25l* (r23+r32) / c ; 01018 a = 0.25l* (r13-r31) / c ; 01019 } else { 01020 d = 0.5l * sqrt(zd) ; 01021 b = 0.25l* (r13+r31) / d ; 01022 c = 0.25l* (r23+r32) / d ; 01023 a = 0.25l* (r21-r12) / d ; 01024 } 01025 if( a < 0.0l ){ b=-b ; c=-c ; d=-d; a=-a; } 01026 } 01027 01028 ASSIF(qb,b) ; ASSIF(qc,c) ; ASSIF(qd,d) ; 01029 return ; 01030 } 01031 01032 /*---------------------------------------------------------------------------*/ 01033 /* Compute the inverse of a bordered 4x4 matrix. 01034 Some numerical code fragments were generated by Maple 8. 01035 If a singular matrix is input, the output matrix will be all zero. 01036 You can check for this by examining the [3][3] element, which will 01037 be 1.0 for the normal case and 0.0 for the bad case. 01038 -----------------------------------------------------------------------------*/ 01039 01040 mat44 mat44_inverse( mat44 R ) 01041 { 01042 double r11,r12,r13,r21,r22,r23,r31,r32,r33,v1,v2,v3 , deti ; 01043 mat44 Q ; 01044 /** INPUT MATRIX IS: **/ 01045 r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2]; /* [ r11 r12 r13 v1 ] */ 01046 r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2]; /* [ r21 r22 r23 v2 ] */ 01047 r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2]; /* [ r31 r32 r33 v3 ] */ 01048 v1 = R.m[0][3]; v2 = R.m[1][3]; v3 = R.m[2][3]; /* [ 0 0 0 1 ] */ 01049 01050 deti = r11*r22*r33-r11*r32*r23-r21*r12*r33 01051 +r21*r32*r13+r31*r12*r23-r31*r22*r13 ; 01052 01053 if( deti != 0.0l ) deti = 1.0l / deti ; 01054 01055 Q.m[0][0] = deti*( r22*r33-r32*r23) ; 01056 Q.m[0][1] = deti*(-r12*r33+r32*r13) ; 01057 Q.m[0][2] = deti*( r12*r23-r22*r13) ; 01058 Q.m[0][3] = deti*(-r12*r23*v3+r12*v2*r33+r22*r13*v3 01059 -r22*v1*r33-r32*r13*v2+r32*v1*r23) ; 01060 01061 Q.m[1][0] = deti*(-r21*r33+r31*r23) ; 01062 Q.m[1][1] = deti*( r11*r33-r31*r13) ; 01063 Q.m[1][2] = deti*(-r11*r23+r21*r13) ; 01064 Q.m[1][3] = deti*( r11*r23*v3-r11*v2*r33-r21*r13*v3 01065 +r21*v1*r33+r31*r13*v2-r31*v1*r23) ; 01066 01067 Q.m[2][0] = deti*( r21*r32-r31*r22) ; 01068 Q.m[2][1] = deti*(-r11*r32+r31*r12) ; 01069 Q.m[2][2] = deti*( r11*r22-r21*r12) ; 01070 Q.m[2][3] = deti*(-r11*r22*v3+r11*r32*v2+r21*r12*v3 01071 -r21*r32*v1-r31*r12*v2+r31*r22*v1) ; 01072 01073 Q.m[3][0] = Q.m[3][1] = Q.m[3][2] = 0.0l ; 01074 Q.m[3][3] = (deti == 0.0l) ? 0.0l : 1.0l ; /* failure flag if deti == 0 */ 01075 01076 return Q ; 01077 } 01078 01079 /*---------------------------------------------------------------------------*/ 01080 /* Input 9 floats and make an orthgonal mat44 out of them. 01081 Each row is normalized, then mat33_polar() is used to orthogonalize them. 01082 If row #3 (r31,r32,r33) is input as zero, then it will be taken to be 01083 the cross product of rows #1 and #2. 01084 01085 This function can be used to create a rotation matrix for transforming 01086 an oblique volume to anatomical coordinates. For this application: 01087 - row #1 (r11,r12,r13) is the direction vector along the image i-axis 01088 - row #2 (r21,r22,r23) is the direction vector along the image j-axis 01089 - row #3 (r31,r32,r33) is the direction vector along the slice direction 01090 (if available; otherwise enter it as 0's) 01091 The first 2 rows can be taken from the DICOM attribute (0020,0037) 01092 "Image Orientation (Patient)". 01093 01094 After forming the rotation matrix, the complete affine transformation from 01095 (i,j,k) grid indexes to (x,y,z) spatial coordinates can be computed by 01096 multiplying each column by the appropriate grid spacing: 01097 - column #1 (R.m[0][0],R.m[1][0],R.m[2][0]) by delta-x 01098 - column #2 (R.m[0][1],R.m[1][1],R.m[2][1]) by delta-y 01099 - column #3 (R.m[0][2],R.m[1][2],R.m[2][2]) by delta-z 01100 And by placing the center (x,y,z) coordinates of voxel (0,0,0) into 01101 the column #4 (R.m[0][3],R.m[1][3],R.m[2][3]). 01102 -----------------------------------------------------------------------------*/ 01103 01104 mat44 make_orthog_mat44( float r11, float r12, float r13 , 01105 float r21, float r22, float r23 , 01106 float r31, float r32, float r33 ) 01107 { 01108 mat44 R ; 01109 mat33 Q , P ; 01110 double val ; 01111 01112 R.m[3][0] = R.m[3][1] = R.m[3][2] = 0.0l ; R.m[3][3] = 1.0l ; 01113 01114 Q.m[0][0] = r11 ; Q.m[0][1] = r12 ; Q.m[0][2] = r13 ; /* load Q */ 01115 Q.m[1][0] = r21 ; Q.m[1][1] = r22 ; Q.m[1][2] = r23 ; 01116 Q.m[2][0] = r31 ; Q.m[2][1] = r32 ; Q.m[2][2] = r33 ; 01117 01118 /* normalize row 1 */ 01119 01120 val = Q.m[0][0]*Q.m[0][0] + Q.m[0][1]*Q.m[0][1] + Q.m[0][2]*Q.m[0][2] ; 01121 if( val > 0.0l ){ 01122 val = 1.0l / sqrt(val) ; 01123 Q.m[0][0] *= val ; Q.m[0][1] *= val ; Q.m[0][2] *= val ; 01124 } else { 01125 Q.m[0][0] = 1.0l ; Q.m[0][1] = 0.0l ; Q.m[0][2] = 0.0l ; 01126 } 01127 01128 /* normalize row 2 */ 01129 01130 val = Q.m[1][0]*Q.m[1][0] + Q.m[1][1]*Q.m[1][1] + Q.m[1][2]*Q.m[1][2] ; 01131 if( val > 0.0l ){ 01132 val = 1.0l / sqrt(val) ; 01133 Q.m[1][0] *= val ; Q.m[1][1] *= val ; Q.m[1][2] *= val ; 01134 } else { 01135 Q.m[1][0] = 0.0l ; Q.m[1][1] = 1.0l ; Q.m[1][2] = 0.0l ; 01136 } 01137 01138 /* normalize row 3 */ 01139 01140 val = Q.m[2][0]*Q.m[2][0] + Q.m[2][1]*Q.m[2][1] + Q.m[2][2]*Q.m[2][2] ; 01141 if( val > 0.0l ){ 01142 val = 1.0l / sqrt(val) ; 01143 Q.m[2][0] *= val ; Q.m[2][1] *= val ; Q.m[2][2] *= val ; 01144 } else { 01145 Q.m[2][0] = Q.m[0][1]*Q.m[1][2] - Q.m[0][2]*Q.m[1][1] ; /* cross */ 01146 Q.m[2][1] = Q.m[0][2]*Q.m[1][0] - Q.m[0][0]*Q.m[1][2] ; /* product */ 01147 Q.m[2][2] = Q.m[0][0]*Q.m[1][1] - Q.m[0][1]*Q.m[1][0] ; 01148 } 01149 01150 P = mat33_polar(Q) ; /* P is orthog matrix closest to Q */ 01151 01152 R.m[0][0] = P.m[0][0] ; R.m[0][1] = P.m[0][1] ; R.m[0][2] = P.m[0][2] ; 01153 R.m[1][0] = P.m[1][0] ; R.m[1][1] = P.m[1][1] ; R.m[1][2] = P.m[1][2] ; 01154 R.m[2][0] = P.m[2][0] ; R.m[2][1] = P.m[2][1] ; R.m[2][2] = P.m[2][2] ; 01155 01156 R.m[0][3] = R.m[1][3] = R.m[2][3] = 0.0 ; return R ; 01157 } 01158 01159 /*---------------------------------------------------------------------------*/ 01160 01161 mat33 mat33_inverse( mat33 R ) /* inverse of 3x3 matrix */ 01162 { 01163 double r11,r12,r13,r21,r22,r23,r31,r32,r33 , deti ; 01164 mat33 Q ; 01165 /** INPUT MATRIX: **/ 01166 r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2]; /* [ r11 r12 r13 ] */ 01167 r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2]; /* [ r21 r22 r23 ] */ 01168 r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2]; /* [ r31 r32 r33 ] */ 01169 01170 deti = r11*r22*r33-r11*r32*r23-r21*r12*r33 01171 +r21*r32*r13+r31*r12*r23-r31*r22*r13 ; 01172 01173 if( deti != 0.0l ) deti = 1.0l / deti ; 01174 01175 Q.m[0][0] = deti*( r22*r33-r32*r23) ; 01176 Q.m[0][1] = deti*(-r12*r33+r32*r13) ; 01177 Q.m[0][2] = deti*( r12*r23-r22*r13) ; 01178 01179 Q.m[1][0] = deti*(-r21*r33+r31*r23) ; 01180 Q.m[1][1] = deti*( r11*r33-r31*r13) ; 01181 Q.m[1][2] = deti*(-r11*r23+r21*r13) ; 01182 01183 Q.m[2][0] = deti*( r21*r32-r31*r22) ; 01184 Q.m[2][1] = deti*(-r11*r32+r31*r12) ; 01185 Q.m[2][2] = deti*( r11*r22-r21*r12) ; 01186 01187 return Q ; 01188 } 01189 01190 /*---------------------------------------------------------------------------*/ 01191 01192 float mat33_determ( mat33 R ) /* determinant of 3x3 matrix */ 01193 { 01194 double r11,r12,r13,r21,r22,r23,r31,r32,r33 ; 01195 /** INPUT MATRIX: **/ 01196 r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2]; /* [ r11 r12 r13 ] */ 01197 r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2]; /* [ r21 r22 r23 ] */ 01198 r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2]; /* [ r31 r32 r33 ] */ 01199 01200 return r11*r22*r33-r11*r32*r23-r21*r12*r33 01201 +r21*r32*r13+r31*r12*r23-r31*r22*r13 ; 01202 } 01203 01204 /*---------------------------------------------------------------------------*/ 01205 01206 float mat33_rownorm( mat33 A ) /* max row norm of 3x3 matrix */ 01207 { 01208 float r1,r2,r3 ; 01209 01210 r1 = fabs(A.m[0][0])+fabs(A.m[0][1])+fabs(A.m[0][2]) ; 01211 r2 = fabs(A.m[1][0])+fabs(A.m[1][1])+fabs(A.m[1][2]) ; 01212 r3 = fabs(A.m[2][0])+fabs(A.m[2][1])+fabs(A.m[2][2]) ; 01213 if( r1 < r2 ) r1 = r2 ; 01214 if( r1 < r3 ) r1 = r3 ; 01215 return r1 ; 01216 } 01217 01218 /*---------------------------------------------------------------------------*/ 01219 01220 float mat33_colnorm( mat33 A ) /* max column norm of 3x3 matrix */ 01221 { 01222 float r1,r2,r3 ; 01223 01224 r1 = fabs(A.m[0][0])+fabs(A.m[1][0])+fabs(A.m[2][0]) ; 01225 r2 = fabs(A.m[0][1])+fabs(A.m[1][1])+fabs(A.m[2][1]) ; 01226 r3 = fabs(A.m[0][2])+fabs(A.m[1][2])+fabs(A.m[2][2]) ; 01227 if( r1 < r2 ) r1 = r2 ; 01228 if( r1 < r3 ) r1 = r3 ; 01229 return r1 ; 01230 } 01231 01232 /*---------------------------------------------------------------------------*/ 01233 01234 mat33 mat33_mul( mat33 A , mat33 B ) /* multiply 2 3x3 matrices */ 01235 { 01236 mat33 C ; int i,j ; 01237 for( i=0 ; i < 3 ; i++ ) 01238 for( j=0 ; j < 3 ; j++ ) 01239 C.m[i][j] = A.m[i][0] * B.m[0][j] 01240 + A.m[i][1] * B.m[1][j] 01241 + A.m[i][2] * B.m[2][j] ; 01242 return C ; 01243 } 01244 01245 /*---------------------------------------------------------------------------*/ 01246 /* Polar decomposition of a 3x3 matrix: finds the closest orthogonal matrix 01247 to input A (in both the Frobenius and L2 norms). Algorithm is that from 01248 NJ Higham, SIAM J Sci Stat Comput, 7:1160-1174. 01249 -----------------------------------------------------------------------------*/ 01250 01251 mat33 mat33_polar( mat33 A ) 01252 { 01253 mat33 X , Y , Z ; 01254 float alp,bet,gam,gmi , dif=1.0 ; 01255 int k=0 ; 01256 01257 X = A ; 01258 01259 /* force matrix to be nonsingular */ 01260 01261 gam = mat33_determ(X) ; 01262 while( gam == 0.0 ){ /* perturb matrix */ 01263 gam = 0.00001 * ( 0.001 + mat33_rownorm(X) ) ; 01264 X.m[0][0] += gam ; X.m[1][1] += gam ; X.m[2][2] += gam ; 01265 gam = mat33_determ(X) ; 01266 } 01267 01268 while(1){ 01269 Y = mat33_inverse(X) ; 01270 if( dif > 0.3 ){ /* far from convergence */ 01271 alp = sqrt( mat33_rownorm(X) * mat33_colnorm(X) ) ; 01272 bet = sqrt( mat33_rownorm(Y) * mat33_colnorm(Y) ) ; 01273 gam = sqrt( bet / alp ) ; 01274 gmi = 1.0 / gam ; 01275 } else { 01276 gam = gmi = 1.0 ; /* close to convergence */ 01277 } 01278 Z.m[0][0] = 0.5 * ( gam*X.m[0][0] + gmi*Y.m[0][0] ) ; 01279 Z.m[0][1] = 0.5 * ( gam*X.m[0][1] + gmi*Y.m[1][0] ) ; 01280 Z.m[0][2] = 0.5 * ( gam*X.m[0][2] + gmi*Y.m[2][0] ) ; 01281 Z.m[1][0] = 0.5 * ( gam*X.m[1][0] + gmi*Y.m[0][1] ) ; 01282 Z.m[1][1] = 0.5 * ( gam*X.m[1][1] + gmi*Y.m[1][1] ) ; 01283 Z.m[1][2] = 0.5 * ( gam*X.m[1][2] + gmi*Y.m[2][1] ) ; 01284 Z.m[2][0] = 0.5 * ( gam*X.m[2][0] + gmi*Y.m[0][2] ) ; 01285 Z.m[2][1] = 0.5 * ( gam*X.m[2][1] + gmi*Y.m[1][2] ) ; 01286 Z.m[2][2] = 0.5 * ( gam*X.m[2][2] + gmi*Y.m[2][2] ) ; 01287 01288 dif = fabs(Z.m[0][0]-X.m[0][0])+fabs(Z.m[0][1]-X.m[0][1]) 01289 +fabs(Z.m[0][2]-X.m[0][2])+fabs(Z.m[1][0]-X.m[1][0]) 01290 +fabs(Z.m[1][1]-X.m[1][1])+fabs(Z.m[1][2]-X.m[1][2]) 01291 +fabs(Z.m[2][0]-X.m[2][0])+fabs(Z.m[2][1]-X.m[2][1]) 01292 +fabs(Z.m[2][2]-X.m[2][2]) ; 01293 01294 k = k+1 ; 01295 if( k > 100 || dif < 3.e-6 ) break ; /* convergence or exhaustion */ 01296 X = Z ; 01297 } 01298 01299 return Z ; 01300 } 01301 01302 /*---------------------------------------------------------------------------*/ 01303 /* Input: 4x4 matrix that transforms (i,j,k) indexes to (x,y,z) coordinates, 01304 where +x=Right, +y=Anterior, +z=Superior. 01305 (Only the upper-left 3x3 corner of R is used herein.) 01306 Output: 3 orientation codes that correspond to the closest "standard" 01307 anatomical orientation of the (i,j,k) axes. 01308 Method: Find which permutation of (x,y,z) has the smallest angle to the 01309 (i,j,k) axes directions, which are the columns of the R matrix. 01310 Errors: The codes returned will be zero. 01311 01312 For example, an axial volume might get return values of 01313 *icod = NIFTI_R2L (i axis is mostly Right to Left) 01314 *jcod = NIFTI_P2A (j axis is mostly Posterior to Anterior) 01315 *kcod = NIFTI_I2S (k axis is mostly Inferior to Superior) 01316 -----------------------------------------------------------------------------*/ 01317 01318 void mat44_to_orientation( mat44 R , int *icod, int *jcod, int *kcod ) 01319 { 01320 float xi,xj,xk , yi,yj,yk , zi,zj,zk , val,detQ,detP ; 01321 mat33 P , Q , M ; 01322 int i,j,k=0,p,q,r , ibest,jbest,kbest,pbest,qbest,rbest ; 01323 float vbest ; 01324 01325 if( icod == NULL || jcod == NULL || kcod == NULL ) return ; /* bad */ 01326 01327 *icod = *jcod = *kcod = 0 ; /* error returns, if sh*t happens */ 01328 01329 /* load column vectors for each (i,j,k) direction from matrix */ 01330 01331 /*-- i axis --*/ /*-- j axis --*/ /*-- k axis --*/ 01332 01333 xi = R.m[0][0] ; xj = R.m[0][1] ; xk = R.m[0][2] ; 01334 yi = R.m[1][0] ; yj = R.m[1][1] ; yk = R.m[1][2] ; 01335 zi = R.m[2][0] ; zj = R.m[2][1] ; zk = R.m[2][2] ; 01336 01337 /* normalize column vectors to get unit vectors along each ijk-axis */ 01338 01339 /* normalize i axis */ 01340 01341 val = sqrt( xi*xi + yi*yi + zi*zi ) ; 01342 if( val == 0.0 ) return ; /* stupid input */ 01343 xi /= val ; yi /= val ; zi /= val ; 01344 01345 /* normalize j axis */ 01346 01347 val = sqrt( xj*xj + yj*yj + zj*zj ) ; 01348 if( val == 0.0 ) return ; /* stupid input */ 01349 xj /= val ; yj /= val ; zj /= val ; 01350 01351 /* orthogonalize j axis to i axis, if needed */ 01352 01353 val = xi*xj + yi*yj + zi*zj ; /* dot product between i and j */ 01354 if( fabs(val) > 1.e-4 ){ 01355 xj -= val*xi ; yj -= val*yi ; zj -= val*zi ; 01356 val = sqrt( xj*xj + yj*yj + zj*zj ) ; /* must renormalize */ 01357 if( val == 0.0 ) return ; /* j was parallel to i? */ 01358 xj /= val ; yj /= val ; zj /= val ; 01359 } 01360 01361 /* normalize k axis; if it is zero, make it the cross product i x j */ 01362 01363 val = sqrt( xk*xk + yk*yk + zk*zk ) ; 01364 if( val == 0.0 ){ xk = yi*zj-zi*yj; yk = zi*xj-zj*xi ; zk=xi*yj-yi*xj ; } 01365 else { xk /= val ; yk /= val ; zk /= val ; } 01366 01367 /* orthogonalize k to i */ 01368 01369 val = xi*xk + yi*yk + zi*zk ; /* dot product between i and k */ 01370 if( fabs(val) > 1.e-4 ){ 01371 xk -= val*xi ; yk -= val*yi ; zk -= val*zi ; 01372 val = sqrt( xk*xk + yk*yk + zk*zk ) ; 01373 if( val == 0.0 ) return ; /* bad */ 01374 xk /= val ; yk /= val ; zk /= val ; 01375 } 01376 01377 /* orthogonalize k to j */ 01378 01379 val = xj*xk + yj*yk + zj*zk ; /* dot product between j and k */ 01380 if( fabs(val) > 1.e-4 ){ 01381 xk -= val*xj ; yk -= val*yj ; zk -= val*zj ; 01382 val = sqrt( xk*xk + yk*yk + zk*zk ) ; 01383 if( val == 0.0 ) return ; /* bad */ 01384 xk /= val ; yk /= val ; zk /= val ; 01385 } 01386 01387 Q.m[0][0] = xi ; Q.m[0][1] = xj ; Q.m[0][2] = xk ; 01388 Q.m[1][0] = yi ; Q.m[1][1] = yj ; Q.m[1][2] = yk ; 01389 Q.m[2][0] = zi ; Q.m[2][1] = zj ; Q.m[2][2] = zk ; 01390 01391 /* at this point, Q is the rotation matrix from the (i,j,k) to (x,y,z) axes */ 01392 01393 detQ = mat33_determ( Q ) ; 01394 if( detQ == 0.0 ) return ; /* shouldn't happen unless user is a DUFIS */ 01395 01396 /* Build and test all possible +1/-1 coordinate permutation matrices P; 01397 then find the P such that the rotation matrix M=PQ is closest to the 01398 identity, in the sense of M having the smallest total rotation angle. */ 01399 01400 /* Despite the formidable looking 6 nested loops, there are 01401 only 3*3*3*2*2*2 = 216 passes, which will run very quickly. */ 01402 01403 vbest = -666.0 ; ibest=pbest=qbest=rbest=1 ; jbest=2 ; kbest=3 ; 01404 for( i=1 ; i <= 3 ; i++ ){ /* i = column number to use for row #1 */ 01405 for( j=1 ; j <= 3 ; j++ ){ /* j = column number to use for row #2 */ 01406 if( i == j ) continue ; 01407 for( k=1 ; k <= 3 ; k++ ){ /* k = column number to use for row #3 */ 01408 if( i == k || j == k ) continue ; 01409 P.m[0][0] = P.m[0][1] = P.m[0][2] = 01410 P.m[1][0] = P.m[1][1] = P.m[1][2] = 01411 P.m[2][0] = P.m[2][1] = P.m[2][2] = 0.0 ; 01412 for( p=-1 ; p <= 1 ; p+=2 ){ /* p,q,r are -1 or +1 */ 01413 for( q=-1 ; q <= 1 ; q+=2 ){ /* and go into rows #1,2,3 */ 01414 for( r=-1 ; r <= 1 ; r+=2 ){ 01415 P.m[0][i-1] = p ; P.m[1][j-1] = q ; P.m[2][k-1] = r ; 01416 detP = mat33_determ(P) ; /* sign of permutation */ 01417 if( detP * detQ <= 0.0 ) continue ; /* doesn't match sign of Q */ 01418 M = mat33_mul(P,Q) ; 01419 01420 /* angle of M rotation = 2.0*acos(0.5*sqrt(1.0+trace(M))) */ 01421 /* we want largest trace(M) == smallest angle == M nearest to I */ 01422 01423 val = M.m[0][0] + M.m[1][1] + M.m[2][2] ; /* trace */ 01424 if( val > vbest ){ 01425 vbest = val ; 01426 ibest = i ; jbest = j ; kbest = k ; 01427 pbest = p ; qbest = q ; rbest = r ; 01428 } 01429 }}}}}} 01430 01431 /* At this point ibest is 1 or 2 or 3; pbest is -1 or +1; etc. 01432 01433 The matrix P that corresponds is the best permutation approximation 01434 to Q-inverse; that is, P (approximately) takes (x,y,z) coordinates 01435 to the (i,j,k) axes. 01436 01437 For example, the first row of P (which contains pbest in column ibest) 01438 determines the way the i axis points relative to the anatomical 01439 (x,y,z) axes. If ibest is 2, then the i axis is along the y axis, 01440 which is direction P2A (if pbest > 0) or A2P (if pbest < 0). 01441 01442 So, using ibest and pbest, we can assign the output code for 01443 the i axis. Mutatis mutandis for the j and k axes, of course. */ 01444 01445 switch( ibest*pbest ){ 01446 case 1: i = NIFTI_L2R ; break ; 01447 case -1: i = NIFTI_R2L ; break ; 01448 case 2: i = NIFTI_P2A ; break ; 01449 case -2: i = NIFTI_A2P ; break ; 01450 case 3: i = NIFTI_I2S ; break ; 01451 case -3: i = NIFTI_S2I ; break ; 01452 } 01453 01454 switch( jbest*qbest ){ 01455 case 1: j = NIFTI_L2R ; break ; 01456 case -1: j = NIFTI_R2L ; break ; 01457 case 2: j = NIFTI_P2A ; break ; 01458 case -2: j = NIFTI_A2P ; break ; 01459 case 3: j = NIFTI_I2S ; break ; 01460 case -3: j = NIFTI_S2I ; break ; 01461 } 01462 01463 switch( kbest*rbest ){ 01464 case 1: k = NIFTI_L2R ; break ; 01465 case -1: k = NIFTI_R2L ; break ; 01466 case 2: k = NIFTI_P2A ; break ; 01467 case -2: k = NIFTI_A2P ; break ; 01468 case 3: k = NIFTI_I2S ; break ; 01469 case -3: k = NIFTI_S2I ; break ; 01470 } 01471 01472 *icod = i ; *jcod = j ; *kcod = k ; return ; 01473 } 01474 01475 /*---------------------------------------------------------------------------*/ 01476 /* Routines to swap byte arrays in various ways: 01477 - 2 at a time: ab -> ba [short] 01478 - 4 at a time: abcd -> dcba [int, float] 01479 - 8 at a time: abcdDCBA -> ABCDdcba [long long, double] 01480 - 16 at a time: abcdefghHGFEDCBA -> ABCDEFGHhgfedcba [long double] 01481 -----------------------------------------------------------------------------*/ 01482 01483 typedef struct { unsigned char a,b ; } twobytes ; 01484 01485 void swap_2bytes( int n , void *ar ) /* 2 bytes at a time */ 01486 { 01487 register int ii ; 01488 register twobytes *tb = (twobytes *)ar ; 01489 register unsigned char tt ; 01490 01491 for( ii=0 ; ii < n ; ii++ ){ 01492 tt = tb[ii].a ; tb[ii].a = tb[ii].b ; tb[ii].b = tt ; 01493 } 01494 return ; 01495 } 01496 01497 /*---------------------------------------------------------------------------*/ 01498 01499 typedef struct { unsigned char a,b,c,d ; } fourbytes ; 01500 01501 void swap_4bytes( int n , void *ar ) /* 4 bytes at a time */ 01502 { 01503 register int ii ; 01504 register fourbytes *tb = (fourbytes *)ar ; 01505 register unsigned char tt ; 01506 01507 for( ii=0 ; ii < n ; ii++ ){ 01508 tt = tb[ii].a ; tb[ii].a = tb[ii].d ; tb[ii].d = tt ; 01509 tt = tb[ii].b ; tb[ii].b = tb[ii].c ; tb[ii].c = tt ; 01510 } 01511 return ; 01512 } 01513 01514 /*---------------------------------------------------------------------------*/ 01515 01516 typedef struct { unsigned char a,b,c,d , D,C,B,A ; } eightbytes ; 01517 01518 void swap_8bytes( int n , void *ar ) /* 8 bytes at a time */ 01519 { 01520 register int ii ; 01521 register eightbytes *tb = (eightbytes *)ar ; 01522 register unsigned char tt ; 01523 01524 for( ii=0 ; ii < n ; ii++ ){ 01525 tt = tb[ii].a ; tb[ii].a = tb[ii].A ; tb[ii].A = tt ; 01526 tt = tb[ii].b ; tb[ii].b = tb[ii].B ; tb[ii].B = tt ; 01527 tt = tb[ii].c ; tb[ii].c = tb[ii].C ; tb[ii].C = tt ; 01528 tt = tb[ii].d ; tb[ii].d = tb[ii].D ; tb[ii].D = tt ; 01529 } 01530 return ; 01531 } 01532 01533 /*---------------------------------------------------------------------------*/ 01534 01535 typedef struct { unsigned char a,b,c,d,e,f,g,h , 01536 H,G,F,E,D,C,B,A ; } sixteenbytes ; 01537 01538 void swap_16bytes( int n , void *ar ) /* 16 bytes at a time */ 01539 { 01540 register int ii ; 01541 register sixteenbytes *tb = (sixteenbytes *)ar ; 01542 register unsigned char tt ; 01543 01544 for( ii=0 ; ii < n ; ii++ ){ 01545 tt = tb[ii].a ; tb[ii].a = tb[ii].A ; tb[ii].A = tt ; 01546 tt = tb[ii].b ; tb[ii].b = tb[ii].B ; tb[ii].B = tt ; 01547 tt = tb[ii].c ; tb[ii].c = tb[ii].C ; tb[ii].C = tt ; 01548 tt = tb[ii].d ; tb[ii].d = tb[ii].D ; tb[ii].D = tt ; 01549 01550 tt = tb[ii].e ; tb[ii].e = tb[ii].E ; tb[ii].E = tt ; 01551 tt = tb[ii].f ; tb[ii].f = tb[ii].F ; tb[ii].F = tt ; 01552 tt = tb[ii].g ; tb[ii].g = tb[ii].G ; tb[ii].G = tt ; 01553 tt = tb[ii].h ; tb[ii].h = tb[ii].H ; tb[ii].H = tt ; 01554 } 01555 return ; 01556 } 01557 01558 /*---------------------------------------------------------------------------*/ 01559 01560 void swap_Nbytes( int n , int siz , void *ar ) /* subsuming case */ 01561 { 01562 switch( siz ){ 01563 case 2: swap_2bytes ( n , ar ) ; break ; 01564 case 4: swap_4bytes ( n , ar ) ; break ; 01565 case 8: swap_8bytes ( n , ar ) ; break ; 01566 case 16: swap_16bytes( n , ar ) ; break ; 01567 } 01568 return ; 01569 } 01570 01571 /*---------------------------------------------------------------*/ 01572 /* Byte swap NIFTI-1 file header in various places and ways. 01573 If is_nifti is nonzero, will also swap the NIFTI-specific 01574 components of the header; otherwise, only the components 01575 common to NIFTI and ANALYZE will be swapped. 01576 ---------------------------------------------------------------- */ 01577 01578 void swap_nifti_header( struct nifti_1_header *h , int is_nifti ) 01579 { 01580 01581 #if 0 /* ANALYZE fields not used by this software */ 01582 swap_4(h->sizeof_hdr) ; 01583 swap_4(h->extents) ; 01584 swap_2(h->session_error) ; 01585 swap_4(h->compressed) ; 01586 swap_4(h->glmax) ; swap_4(h->glmin) ; 01587 #endif 01588 01589 /* this stuff is always present, for ANALYZE and NIFTI */ 01590 01591 swap_2bytes( 8 , h->dim ) ; 01592 swap_4bytes( 8 , h->pixdim ) ; 01593 01594 swap_2(h->datatype) ; 01595 swap_2(h->bitpix) ; 01596 01597 swap_4(h->vox_offset); swap_4(h->cal_max); swap_4(h->cal_min); 01598 01599 /* this stuff is NIFTI specific */ 01600 01601 if( is_nifti ){ 01602 swap_2(h->qform_code); swap_2(h->sform_code); 01603 swap_4(h->quatern_b); swap_4(h->quatern_c); swap_4(h->quatern_d); 01604 swap_4(h->qoffset_x); swap_4(h->qoffset_y); swap_4(h->qoffset_z); 01605 swap_4(h->intent_p1); swap_4(h->intent_p2); swap_4(h->intent_p3); 01606 swap_4(h->scl_slope); swap_4(h->scl_inter); 01607 swap_4bytes(4,h->srow_x); 01608 swap_4bytes(4,h->srow_y); 01609 swap_4bytes(4,h->srow_z); 01610 swap_2(h->intent_code); swap_4(h->toffset); 01611 swap_2(h->slice_start); swap_2(h->slice_end); 01612 swap_4(h->slice_duration); 01613 } 01614 return ; 01615 } 01616 01617 /* rcr - start I/O routines here */ 01618 01619 #define USE_STAT 01620 #ifdef USE_STAT 01621 /*---------------------------------------------------------------------------*/ 01622 /* Return the file length (0 if file not found or has no contents). 01623 This is a Unix-specific function, since it uses stat(). 01624 -----------------------------------------------------------------------------*/ 01625 #include <sys/types.h> 01626 #include <sys/stat.h> 01627 01628 unsigned int get_filesize( char *pathname ) 01629 { 01630 struct stat buf ; int ii ; 01631 01632 if( pathname == NULL || *pathname == '\0' ) return 0 ; 01633 ii = stat( pathname , &buf ); if( ii != 0 ) return 0 ; 01634 return (unsigned int)buf.st_size ; 01635 } 01636 01637 #else /*---------- non-Unix version of the above, less efficient -----------*/ 01638 01639 unsigned int get_filesize( char *pathname ) 01640 { 01641 znzFile fp ; unsigned int len ; 01642 01643 if( pathname == NULL || *pathname == '\0' ) return 0 ; 01644 fp = znzopen(pathname,"rb",0); if( znz_isnull(fp) ) return 0 ; 01645 znzseek(fp,0L,SEEK_END) ; len = (unsigned int)znztell(fp) ; 01646 znzclose(fp) ; return len ; 01647 } 01648 01649 #endif /* USE_STAT */ 01650 01651 01652 size_t nifti_get_volsize(nifti_image *nim) 01653 { 01654 return (size_t)(nim->nbyper) * (size_t)(nim->nvox) ; /* total bytes */ 01655 } 01656 01657 01658 /*--------------------------------------------------------------------------*/ 01659 /* Support functions for filenames in read and write - allows for gzipped 01660 files 01661 */ 01662 01663 01664 int nifti_fileexists(char* fname) 01665 { 01666 znzFile fp; 01667 fp = znzopen( fname , "rb" , 1 ) ; 01668 if( !znz_isnull(fp) ) { znzclose(fp); return 1; } 01669 return 0; 01670 } 01671 01672 int nifti_validfilename(char* fname) 01673 { 01674 char * ext; 01675 int len; 01676 01677 /** check input file(s) for sanity **/ 01678 if( fname == NULL || *fname == '\0' ) return 0; 01679 01680 len = strlen(fname); 01681 01682 if( len < 1 ) { 01683 if ( gni_debug > 0 ) 01684 fprintf(stderr,"-- empty filename in nifti_validfilename()\n"); 01685 return 0; 01686 } 01687 01688 ext = nifti_find_file_extension((char *)fname); 01689 01690 if ( ext && ext == fname ) { /* then no filename prefix */ 01691 if ( gni_debug > 0 ) 01692 fprintf(stderr,"-- no prefix for filename '%s'\n", fname); 01693 return 0; 01694 } 01695 01696 return 1; 01697 } 01698 01699 char * nifti_find_file_extension( char * name ) 01700 { 01701 char * ext; 01702 int len; 01703 01704 if ( ! name ) return NULL; 01705 01706 len = strlen(name); 01707 if ( len < 4 ) return NULL; 01708 01709 ext = name + len - 4; 01710 01711 if ( (strcmp(ext, ".hdr") == 0) || (strcmp(ext, ".img") == 0) || 01712 (strcmp(ext, ".nia") == 0) || (strcmp(ext, ".nii") == 0) ) 01713 return ext; 01714 01715 #ifdef HAVE_ZLIB 01716 if ( len < 7 ) return NULL; 01717 01718 ext = name - 7; 01719 if ( (strcmp(ext, ".hdr.gz") == 0) || (strcmp(ext, ".img.gz") == 0) || 01720 (strcmp(ext, ".nia.gz") == 0) || (strcmp(ext, ".nii.gz") == 0) ) 01721 return ext; 01722 #endif 01723 01724 return NULL; 01725 } 01726 01727 static int nifti_is_gzfile(char* fname) 01728 { 01729 /* return true if the filename ends with .gz */ 01730 if (fname == NULL) { return 0; } 01731 #ifdef HAVE_ZLIB 01732 if (strcmp(fname + strlen(fname) - 3,".gz")==0) { return 1; } 01733 #endif 01734 return 0; 01735 } 01736 01737 01738 char * nifti_makebasename(char* fname) 01739 { 01740 /* 01741 NB: it allocates memory for basename which should be freed 01742 when no longer required 01743 */ 01744 char *basename, *ext; 01745 01746 basename=nifti_strdup(fname); 01747 01748 ext = nifti_find_file_extension(basename); 01749 if ( ext ) *ext = '\0'; /* clear out extension */ 01750 01751 return basename; /* in either case */ 01752 } 01753 01754 void nifti_set_debug_level( int level ) 01755 { 01756 gni_debug = level; 01757 } 01758 01759 01760 /*---------------------------------------------------------------------- 01761 * returns filename of header on success and NULL if no appropriate file 01762 * could be found 01763 * NB: it allocates memory for hdrname which should be freed 01764 * when no longer required 01765 ----------------------------------------------------------------------*/ 01766 static char * nifti_findhdrname(char* fname) 01767 { 01768 char *basename, *hdrname, *ext; 01769 char elist[2][5] = { ".hdr", ".nii" }; 01770 int efirst; 01771 01772 /** check input file(s) for sanity **/ 01773 if( !nifti_validfilename(fname) ) return NULL; 01774 01775 basename = nifti_makebasename(fname); 01776 if( !basename ) return NULL; /* only on string alloc failure */ 01777 01778 /* return filename if it has a valid extension and exists 01779 (except if it is an .img file (and maybe .gz)) */ 01780 ext = nifti_find_file_extension(fname); 01781 if ( ext && nifti_fileexists(fname) ) { 01782 if ( strncmp(ext,".img",4) != 0 ){ 01783 hdrname = nifti_strdup(fname); 01784 return hdrname; 01785 } 01786 } 01787 01788 /* So the requested name is a basename, contains .img, or does not exist. */ 01789 /* In any case, use basename. */ 01790 01791 /* if .img, look for .hdr, .hdr.gz, .nii, .nii.gz, in that order */ 01792 /* else, look for .nii, .nii.gz, .hdr, .hdr.gz, in that order */ 01793 01794 /* if we get more extension choices, this could be a loop */ 01795 01796 if ( ext && strncmp(ext,".img",4) != 0 ) efirst = 0; 01797 else efirst = 1; 01798 01799 hdrname = (char *)calloc(sizeof(char),strlen(basename)+8); 01800 01801 strcpy(hdrname,basename); 01802 strcat(hdrname,elist[efirst]); 01803 if (nifti_fileexists(hdrname)) { free(basename); return hdrname; } 01804 #ifdef HAVE_ZLIB 01805 strcat(hdrname,".gz"); 01806 if (nifti_fileexists(hdrname)) { free(basename); return hdrname; } 01807 #endif 01808 01809 /* okay, try the other possibility */ 01810 01811 efirst = 1 - efirst; 01812 01813 strcpy(hdrname,basename); 01814 strcat(hdrname,elist[efirst]); 01815 if (nifti_fileexists(hdrname)) { free(basename); return hdrname; } 01816 #ifdef HAVE_ZLIB 01817 strcat(hdrname,".gz"); 01818 if (nifti_fileexists(hdrname)) { free(basename); return hdrname; } 01819 #endif 01820 01821 /** if it gets to here then nothing has been found -> failure! **/ 01822 free(basename); 01823 free(hdrname); 01824 return NULL; 01825 } 01826 01827 01828 /*---------------------------------------------------------------------- 01829 * returns filename of data/img file on success and NULL if no appropriate 01830 * file could be found 01831 * NB: it allocates memory for imgname which should be freed 01832 * when no longer required 01833 ----------------------------------------------------------------------*/ 01834 static char * nifti_findimgname(char* fname , int nifti_type) 01835 { 01836 char *basename, *imgname, ext[2][5] = { ".nii", ".img" }; 01837 int first; /* first extension to use */ 01838 01839 /** check input file(s) for sanity **/ 01840 01841 if( !nifti_validfilename(fname) ) return NULL; 01842 01843 /** use nifti_type to decide whether to look for .img or .nii **/ 01844 /** if using compression libraries, .gz files are looked for first **/ 01845 basename = nifti_makebasename(fname); 01846 imgname = (char *)calloc(sizeof(char),strlen(basename)+8); 01847 01848 /* test one form, then another (don't assume input type from image type) */ 01849 /* if we get 3 or more extensions, can make a loop here... */ 01850 01851 if (nifti_type == 1) first = 0; /* type 1 should match .nii */ 01852 else first = 1; /* type 0 or 2 should match .img */ 01853 01854 strcpy(imgname,basename); 01855 strcat(imgname,ext[first]); 01856 if (nifti_fileexists(imgname)) { free(basename); return imgname; } 01857 #ifdef HAVE_ZLIB /* then also check for .gz */ 01858 strcat(imgname,".gz"); 01859 if (nifti_fileexists(imgname)) { free(basename); return imgname; } 01860 #endif 01861 01862 /* failed to find image file with expected extension, try the other */ 01863 01864 strcpy(imgname,basename); 01865 strcat(imgname,ext[1-first]); /* can do this with only 2 choices */ 01866 if (nifti_fileexists(imgname)) { free(basename); return imgname; } 01867 #ifdef HAVE_ZLIB /* then also check for .gz */ 01868 strcat(imgname,".gz"); 01869 if (nifti_fileexists(imgname)) { free(basename); return imgname; } 01870 #endif 01871 01872 /* otherwise - failure */ 01873 free(basename); 01874 free(imgname); 01875 return NULL; 01876 } 01877 01878 /*--------------------------------------------------------------------------*/ 01879 /* Determine if this is a NIFTI-formatted file. 01880 - returns 0 if file looks like ANALYZE 7.5 [checks sizeof_hdr field == 348] 01881 - returns 1 if file marked as NIFTI (header+data in 1 file) 01882 - returns 2 if file marked as NIFTI (header+data in 2 files) 01883 - returns -1 if it can't tell, file doesn't exist, etc. 01884 ----------------------------------------------------------------------------*/ 01885 01886 int is_nifti_file( char *hname ) 01887 { 01888 struct nifti_1_header nhdr ; 01889 znzFile fp ; 01890 int ii ; 01891 char *tmpname; 01892 01893 /* bad input name? */ 01894 01895 if( !nifti_validfilename(hname) ) return -1 ; 01896 01897 /* open file */ 01898 01899 tmpname = nifti_findhdrname(hname); 01900 if( tmpname == NULL ){ 01901 if( gni_debug > 0 ) 01902 fprintf(stderr,"** no header file found for '%s'\n",hname); 01903 return -1; 01904 } 01905 fp = znzopen( tmpname , "rb" , 1 ) ; 01906 free(tmpname); 01907 if (znz_isnull(fp)) return -1 ; /* bad open? */ 01908 01909 /* read header, close file */ 01910 01911 ii = znzread( &nhdr , 1 , sizeof(nhdr) , fp ) ; 01912 znzclose( fp ) ; 01913 if( ii < sizeof(nhdr) ) return -1 ; /* bad read? */ 01914 01915 /* check for NIFTI-ness */ 01916 01917 if( NIFTI_VERSION(nhdr) != 0 ){ 01918 return ( NIFTI_ONEFILE(nhdr) ) ? 1 : 2 ; 01919 } 01920 01921 /* check for ANALYZE-ness (sizeof_hdr field == 348) */ 01922 01923 ii = nhdr.sizeof_hdr ; 01924 if( ii == sizeof(nhdr) ) return 0 ; /* matches */ 01925 01926 /* try byte-swapping header */ 01927 01928 swap_4(ii) ; 01929 if( ii == sizeof(nhdr) ) return 0 ; /* matches */ 01930 01931 return -1 ; /* not good */ 01932 } 01933 01934 int print_hex_vals( char * data, int nbytes, FILE * fp ) 01935 { 01936 int c; 01937 01938 if ( !data || nbytes < 1 || !fp ) return -1; 01939 01940 fputs("0x", fp); 01941 for ( c = 0; c < nbytes; c++ ) 01942 fprintf(fp, " %x", data[c]); 01943 01944 return 0; 01945 } 01946 01947 int disp_nifti_1_header( char * info, nifti_1_header * hp ) 01948 { 01949 int c; 01950 01951 fputs( "-------------------------------------------------------\n", stderr ); 01952 if ( info ) fputs( info, stderr ); 01953 if ( !hp ){ fputs(" ** no nifti_1_header to display!\n",stderr); return 1; } 01954 01955 fprintf(stderr," nifti_1_header :\n" 01956 " sizeof_hdr = %d\n" 01957 " data_type[10] = ", hp->sizeof_hdr); 01958 print_hex_vals(hp->data_type, 10, stderr); 01959 fprintf(stderr, "\n" 01960 " db_name[18] = "); 01961 print_hex_vals(hp->db_name, 18, stderr); 01962 fprintf(stderr, "\n" 01963 " extents = %d\n" 01964 " session_error = %d\n" 01965 " regular = 0x%x\n" 01966 " dim_info = 0x%x\n", 01967 hp->extents, hp->session_error, hp->regular, hp->dim_info ); 01968 fprintf(stderr, " dim[8] ="); 01969 for ( c = 0; c < 8; c++ ) fprintf(stderr," %d", hp->dim[c]); 01970 fprintf(stderr, "\n" 01971 " intent_p1 = %f\n" 01972 " intent_p2 = %f\n" 01973 " intent_p3 = %f\n" 01974 " intent_code = %d\n" 01975 " datatype = %d\n" 01976 " bitpix = %d\n" 01977 " slice_start = %d\n" 01978 " pixdim[8] =", 01979 hp->intent_p1, hp->intent_p2, hp->intent_p3, hp->intent_code, 01980 hp->datatype, hp->bitpix, hp->slice_start); 01981 /* break pixdim over 2 lines */ 01982 for ( c = 0; c < 4; c++ ) fprintf(stderr," %f", hp->pixdim[c]); 01983 fprintf(stderr, "\n "); 01984 for ( c = 4; c < 8; c++ ) fprintf(stderr," %f", hp->pixdim[c]); 01985 fprintf(stderr, "\n" 01986 " vox_offset = %f\n" 01987 " scl_slope = %f\n" 01988 " scl_inter = %f\n" 01989 " slice_end = %d\n" 01990 " slice_code = %d\n" 01991 " xyzt_units = 0x%x\n" 01992 " cal_max = %f\n" 01993 " cal_min = %f\n" 01994 " slice_duration = %f\n" 01995 " toffset = %f\n" 01996 " glmax = %d\n" 01997 " glmin = %d\n", 01998 hp->vox_offset, hp->scl_slope, hp->scl_inter, hp->slice_end, 01999 hp->slice_code, hp->xyzt_units, hp->cal_max, hp->cal_min, 02000 hp->slice_duration, hp->toffset, hp->glmax, hp->glmin); 02001 fprintf(stderr, 02002 " descrip = '%s'\n" 02003 " aux_file = '%s'\n" 02004 " qform_code = %d\n" 02005 " sform_code = %d\n" 02006 " quatern_b = %f\n" 02007 " quatern_c = %f\n" 02008 " quatern_d = %f\n" 02009 " qoffset_x = %f\n" 02010 " qoffset_y = %f\n" 02011 " qoffset_z = %f\n" 02012 " srow_x[4] = %f, %f, %f, %f\n" 02013 " srow_y[4] = %f, %f, %f, %f\n" 02014 " srow_z[4] = %f, %f, %f, %f\n" 02015 " intent_name = %-16s\n" 02016 " magic = %-4s\n", 02017 hp->descrip, hp->aux_file, hp->qform_code, hp->sform_code, 02018 hp->quatern_b, hp->quatern_c, hp->quatern_d, 02019 hp->qoffset_x, hp->qoffset_y, hp->qoffset_z, 02020 hp->srow_x[0], hp->srow_x[1], hp->srow_x[2], hp->srow_x[3], 02021 hp->srow_y[0], hp->srow_y[1], hp->srow_y[2], hp->srow_y[3], 02022 hp->srow_z[0], hp->srow_z[1], hp->srow_z[2], hp->srow_z[3], 02023 hp->intent_name, hp->magic); 02024 fputs( "-------------------------------------------------------\n", stderr ); 02025 02026 return 0; 02027 } 02028 02029 02030 #undef ERREX 02031 #define ERREX(msg) \ 02032 do{ fprintf(stderr,"** ERROR: nifti_convert_nhdr2nim: %s\n", (msg) ) ; \ 02033 return NULL ; } while(0) 02034 02035 nifti_image* nifti_convert_nhdr2nim(struct nifti_1_header nhdr, char* fname) 02036 { 02037 int ii , doswap , ioff, ndim, nvox ; 02038 int is_nifti , is_onefile ; 02039 short ss ; 02040 char *iname=NULL; 02041 nifti_image *nim; 02042 02043 nim = (nifti_image *) calloc( 1 , sizeof(nifti_image) ) ; 02044 if( !nim ) ERREX("failed to allocate nifti image"); 02045 02046 nim->fname=NULL; 02047 nim->iname=NULL; 02048 02049 /** check if have to swap bytes **/ 02050 02051 doswap = 0 ; /* swap data flag */ 02052 ss = nhdr.dim[0] ; 02053 if( ss != 0 ){ /* check dim[0] for good value */ 02054 if( ss < 0 || ss > 7 ){ 02055 swap_2(ss) ; 02056 if( ss < 0 || ss > 7 ) ERREX("bad dim[0]") ; 02057 doswap = 1 ; 02058 } 02059 } else { /* dim[0] == 0 is illegal, but does occur */ 02060 ii = nhdr.sizeof_hdr ; /* so check sizeof_hdr field instead */ 02061 02062 if( ii != sizeof(nhdr) ){ 02063 swap_4(ii) ; 02064 if( ii != sizeof(nhdr) ) ERREX("bad sizeof_hdr") ; 02065 doswap = 1 ; 02066 } 02067 } 02068 02069 /** determine if this is a NIFTI-1 compliant header **/ 02070 02071 is_nifti = NIFTI_VERSION(nhdr) ; 02072 if( doswap ) { 02073 if ( gni_debug > 2 ) disp_nifti_1_header("-d ni1 pre-swap: ", &nhdr); 02074 swap_nifti_header( &nhdr , is_nifti ) ; 02075 } 02076 02077 if ( gni_debug > 1 ) disp_nifti_1_header("-d nhdr2nim : ", &nhdr); 02078 02079 if( nhdr.datatype == DT_BINARY || 02080 nhdr.datatype == DT_UNKNOWN ) ERREX("bad datatype") ; 02081 02082 if( nhdr.dim[1] <= 0 ) ERREX("bad dim[1]") ; 02083 02084 for( ii=2 ; ii <= 7 ; ii++ ) 02085 if( nhdr.dim[ii] <= 0 ) nhdr.dim[ii] = 1 ; /* fix bad dim[] values */ 02086 02087 /** get number of dimensions (ignoring dim[0] now) **/ 02088 02089 for( ii=7 ; ii >= 2 ; ii-- ) /* loop backwards until we */ 02090 if( nhdr.dim[ii] > 1 ) break ; /* find a dim bigger than 1 */ 02091 ndim = ii ; 02092 02093 /* set bad grid spacings to 1.0 */ 02094 02095 for( ii=1 ; ii <= 7 ; ii++ ){ 02096 if( nhdr.pixdim[ii] == 0.0 || 02097 !IS_GOOD_FLOAT(nhdr.pixdim[ii]) ) nhdr.pixdim[ii] = 1.0 ; 02098 } 02099 02100 is_onefile = is_nifti && NIFTI_ONEFILE(nhdr) ; 02101 02102 if( is_nifti ) nim->nifti_type = (is_onefile) ? 1 : 2 ; 02103 else nim->nifti_type = 0 ; 02104 02105 ii = short_order() ; 02106 if( doswap ) nim->byteorder = REVERSE_ORDER(ii) ; 02107 else nim->byteorder = ii ; 02108 02109 02110 /** dimensions of data array **/ 02111 02112 nim->ndim = nim->dim[0] = ndim ; 02113 nim->nx = nim->dim[1] = nhdr.dim[1]; nvox = nim->nx; 02114 nim->ny = nim->dim[2] = nhdr.dim[2]; nvox *= nim->ny; 02115 nim->nz = nim->dim[3] = nhdr.dim[3]; nvox *= nim->nz; 02116 nim->nt = nim->dim[4] = nhdr.dim[4]; nvox *= nim->nt; 02117 nim->nu = nim->dim[5] = nhdr.dim[5]; nvox *= nim->nu; 02118 nim->nv = nim->dim[6] = nhdr.dim[6]; nvox *= nim->nv; 02119 nim->nw = nim->dim[7] = nhdr.dim[7]; nvox *= nim->nw; nim->nvox = nvox; 02120 02121 /** type of data in voxels and how many bytes per voxel */ 02122 02123 nim->datatype = nhdr.datatype ; 02124 02125 nifti_datatype_sizes( nim->datatype , &(nim->nbyper) , &(nim->swapsize) ) ; 02126 if( nim->nbyper == 0 ){ free(nim); ERREX("bad datatype"); } 02127 02128 /** grid spacings **/ 02129 02130 nim->dx = nim->pixdim[1] = nhdr.pixdim[1] ; 02131 nim->dy = nim->pixdim[2] = nhdr.pixdim[2] ; 02132 nim->dz = nim->pixdim[3] = nhdr.pixdim[3] ; 02133 nim->dt = nim->pixdim[4] = nhdr.pixdim[4] ; 02134 nim->du = nim->pixdim[5] = nhdr.pixdim[5] ; 02135 nim->dv = nim->pixdim[6] = nhdr.pixdim[6] ; 02136 nim->dw = nim->pixdim[7] = nhdr.pixdim[7] ; 02137 02138 /** compute qto_xyz transformation from pixel indexes (i,j,k) to (x,y,z) **/ 02139 02140 if( !is_nifti || nhdr.qform_code <= 0 ){ /** default transformation **/ 02141 02142 nim->qto_xyz.m[0][0] = nim->dx ; /* grid spacings */ 02143 nim->qto_xyz.m[1][1] = nim->dy ; /* along diagonal */ 02144 nim->qto_xyz.m[2][2] = nim->dz ; 02145 02146 /* off diagonal is zero */ 02147 02148 nim->qto_xyz.m[0][1]=nim->qto_xyz.m[0][2]=nim->qto_xyz.m[0][3] = 0.0; 02149 nim->qto_xyz.m[1][0]=nim->qto_xyz.m[1][2]=nim->qto_xyz.m[1][3] = 0.0; 02150 nim->qto_xyz.m[2][0]=nim->qto_xyz.m[2][1]=nim->qto_xyz.m[2][3] = 0.0; 02151 02152 /* last row is always [ 0 0 0 1 ] */ 02153 02154 nim->qto_xyz.m[3][0]=nim->qto_xyz.m[3][1]=nim->qto_xyz.m[3][2] = 0.0; 02155 nim->qto_xyz.m[3][3]= 1.0 ; 02156 02157 nim->qform_code = NIFTI_XFORM_UNKNOWN ; 02158 02159 } else { /** NIFTI: quaternion-specified transformation **/ 02160 02161 nim->quatern_b = FIXED_FLOAT( nhdr.quatern_b ) ; 02162 nim->quatern_c = FIXED_FLOAT( nhdr.quatern_c ) ; 02163 nim->quatern_d = FIXED_FLOAT( nhdr.quatern_d ) ; 02164 02165 nim->qoffset_x = FIXED_FLOAT(nhdr.qoffset_x) ; 02166 nim->qoffset_y = FIXED_FLOAT(nhdr.qoffset_y) ; 02167 nim->qoffset_z = FIXED_FLOAT(nhdr.qoffset_z) ; 02168 02169 nim->qfac = (nhdr.pixdim[0] < 0.0) ? -1.0 : 1.0 ; /* left-handedness? */ 02170 02171 nim->qto_xyz = quatern_to_mat44( 02172 nim->quatern_b, nim->quatern_c, nim->quatern_d, 02173 nim->qoffset_x, nim->qoffset_y, nim->qoffset_z, 02174 nim->dx , nim->dy , nim->dz , 02175 nim->qfac ) ; 02176 02177 nim->qform_code = nhdr.qform_code ; 02178 02179 if( gni_debug > 1 ) 02180 nifti_disp_matrix_orient("-d qform orientations:\n", nim->qto_xyz); 02181 } 02182 02183 /** load inverse transformation (x,y,z) -> (i,j,k) **/ 02184 02185 nim->qto_ijk = mat44_inverse( nim->qto_xyz ) ; 02186 02187 /** load sto_xyz affine transformation, if present **/ 02188 02189 if( !is_nifti || nhdr.sform_code <= 0 ){ /** no sto transformation **/ 02190 02191 nim->sform_code = NIFTI_XFORM_UNKNOWN ; 02192 02193 } else { /** sto transformation from srow_*[] **/ 02194 02195 nim->sto_xyz.m[0][0] = nhdr.srow_x[0] ; 02196 nim->sto_xyz.m[0][1] = nhdr.srow_x[1] ; 02197 nim->sto_xyz.m[0][2] = nhdr.srow_x[2] ; 02198 nim->sto_xyz.m[0][3] = nhdr.srow_x[3] ; 02199 02200 nim->sto_xyz.m[1][0] = nhdr.srow_y[0] ; 02201 nim->sto_xyz.m[1][1] = nhdr.srow_y[1] ; 02202 nim->sto_xyz.m[1][2] = nhdr.srow_y[2] ; 02203 nim->sto_xyz.m[1][3] = nhdr.srow_y[3] ; 02204 02205 nim->sto_xyz.m[2][0] = nhdr.srow_z[0] ; 02206 nim->sto_xyz.m[2][1] = nhdr.srow_z[1] ; 02207 nim->sto_xyz.m[2][2] = nhdr.srow_z[2] ; 02208 nim->sto_xyz.m[2][3] = nhdr.srow_z[3] ; 02209 02210 /* last row is always [ 0 0 0 1 ] */ 02211 02212 nim->sto_xyz.m[3][0]=nim->sto_xyz.m[3][1]=nim->sto_xyz.m[3][2] = 0.0; 02213 nim->sto_xyz.m[3][3]= 1.0 ; 02214 02215 nim->sto_ijk = mat44_inverse( nim->sto_xyz ) ; 02216 02217 nim->sform_code = nhdr.sform_code ; 02218 02219 if( gni_debug > 1 ) 02220 nifti_disp_matrix_orient("-d qform orientations:\n", nim->sto_xyz); 02221 } 02222 02223 /* miscellaneous NIFTI stuff */ 02224 02225 if( is_nifti ){ 02226 nim->scl_slope = FIXED_FLOAT( nhdr.scl_slope ) ; 02227 nim->scl_inter = FIXED_FLOAT( nhdr.scl_inter ) ; 02228 02229 nim->intent_code = nhdr.intent_code ; 02230 02231 nim->intent_p1 = FIXED_FLOAT( nhdr.intent_p1 ) ; 02232 nim->intent_p2 = FIXED_FLOAT( nhdr.intent_p2 ) ; 02233 nim->intent_p3 = FIXED_FLOAT( nhdr.intent_p3 ) ; 02234 02235 nim->toffset = FIXED_FLOAT( nhdr.toffset ) ; 02236 02237 memcpy(nim->intent_name,nhdr.intent_name,15); nim->intent_name[15] = '\0'; 02238 02239 nim->xyz_units = XYZT_TO_SPACE(nhdr.xyzt_units) ; 02240 nim->time_units = XYZT_TO_TIME (nhdr.xyzt_units) ; 02241 02242 nim->freq_dim = DIM_INFO_TO_FREQ_DIM ( nhdr.dim_info ) ; 02243 nim->phase_dim = DIM_INFO_TO_PHASE_DIM( nhdr.dim_info ) ; 02244 nim->slice_dim = DIM_INFO_TO_SLICE_DIM( nhdr.dim_info ) ; 02245 02246 nim->slice_code = nhdr.slice_code ; 02247 nim->slice_start = nhdr.slice_start ; 02248 nim->slice_end = nhdr.slice_end ; 02249 nim->slice_duration = FIXED_FLOAT(nhdr.slice_duration) ; 02250 } 02251 02252 /* Miscellaneous ANALYZE stuff */ 02253 02254 nim->cal_min = FIXED_FLOAT(nhdr.cal_min) ; 02255 nim->cal_max = FIXED_FLOAT(nhdr.cal_max) ; 02256 02257 memcpy(nim->descrip ,nhdr.descrip ,79) ; nim->descrip [79] = '\0' ; 02258 memcpy(nim->aux_file,nhdr.aux_file,23) ; nim->aux_file[23] = '\0' ; 02259 02260 /** will read image data from file 'iname' starting at offset 'ioff' **/ 02261 02262 is_onefile = is_nifti && NIFTI_ONEFILE(nhdr) ; 02263 02264 if( is_onefile ){ 02265 ioff = (int)nhdr.vox_offset ; 02266 if( ioff < sizeof(nhdr) ) ioff = sizeof(nhdr) ; 02267 } else { 02268 ioff = (int)nhdr.vox_offset ; 02269 } 02270 nim->iname_offset = ioff ; 02271 02272 02273 /* deal with file names if set */ 02274 if (fname!=NULL) { 02275 nim->fname = nifti_strdup(fname); 02276 /* determine name of image, if not already set */ 02277 if (nim->iname==NULL) { 02278 if (is_onefile) { 02279 iname = nifti_strdup(nim->fname); 02280 } else { 02281 iname = nifti_findimgname(nim->fname,nim->nifti_type); 02282 if (iname==NULL) ERREX("bad filename"); 02283 } 02284 /* don't free iname, as now nim->iname is using this storage */ 02285 nim->iname = iname ; /* save image filename */ 02286 } 02287 } else { 02288 nim->fname = NULL; 02289 nim->iname = NULL; 02290 } 02291 02292 /* clear extension fields */ 02293 nim->num_ext = 0; 02294 nim->ext_list = NULL; 02295 02296 return nim; 02297 } 02298 02299 02300 /*--------------------------------------------------------------------------*/ 02301 /* Read in a NIFTI-1 or ANALYZE-7.5 file (pair) into a nifti_image struct. 02302 - Input is .hdr or .nii filename. 02303 - Return value is NULL if something fails badly. 02304 - If read_data parameter is nonzero, the image data will actually 02305 be read in; otherwise, it will have to be read later 02306 (e.g., using the nifti_image_load() function). 02307 - The image data will be stored in whatever data format the 02308 input data is; no scaling will be applied. 02309 - DT_BINARY data is not supported! 02310 - nifti_image_free() can be used to delete the returned struct, 02311 when you are done with it. 02312 ----------------------------------------------------------------------------*/ 02313 02314 #undef ERREX 02315 #define ERREX(msg) \ 02316 do{ fprintf(stderr,"** ERROR: nifti_image_open(%s): %s\n", \ 02317 (hname != NULL) ? hname : "(null)" , (msg) ) ; \ 02318 return fptr ; } while(0) 02319 02320 static znzFile nifti_image_open( char *hname , char *opts , nifti_image **nim) 02321 { 02322 znzFile fptr=NULL; 02323 znz_setnull(fptr); 02324 02325 /* open the hdr and reading it in, but do not load the data */ 02326 *nim = nifti_image_read(hname,0); 02327 02328 /* open the image file, ready for reading 02329 * - NB: compressed works for all reads */ 02330 if( ((*nim) == NULL) || ((*nim)->iname == NULL) || 02331 ((*nim)->nbyper <= 0) || ((*nim)->nvox <= 0) ) ERREX("bad header info") ; 02332 02333 /** open image data file **/ 02334 fptr = znzopen((*nim)->iname ,opts,1); 02335 if( znz_isnull(fptr) ) ERREX("Can't open data file") ; 02336 02337 return fptr; 02338 } 02339 02340 02341 /* use macro LNI_FILE_ERROR instead of ERREX() 02342 #undef ERREX 02343 #define ERREX(msg) \ 02344 do{ fprintf(stderr,"** ERROR: nifti_image_read(%s): %s\n", \ 02345 (hname != NULL) ? hname : "(null)" , (msg) ) ; \ 02346 return NULL ; } while(0) 02347 */ 02348 02349 nifti_image *nifti_image_read( char *hname , int read_data ) 02350 { 02351 struct nifti_1_header nhdr ; 02352 nifti_image *nim ; 02353 znzFile fp ; 02354 int ii , ilen; 02355 char fname[] = { "nifti_image_read" }; 02356 char buf[16] , *workingname=NULL; 02357 02358 /* determine file name to use for header */ 02359 workingname = nifti_findhdrname(hname); 02360 if( workingname == NULL ){ 02361 if( gni_debug > 0 ) 02362 LNI_FERR(fname,"failed to find header file for", hname); 02363 return NULL; /* check return */ 02364 } else if( gni_debug > 1 ) 02365 fprintf(stderr,"-d %s: found header filename '%s'\n",fname,workingname); 02366 02367 fp = znzopen(workingname,"rb",1); 02368 if( znz_isnull(fp) ){ 02369 if( gni_debug > 0 ) 02370 LNI_FERR(fname,"failed to open header file",workingname); 02371 free(workingname); 02372 return NULL; 02373 } 02374 02375 /** test if header file starts with ASCII string "<nifti_image"; 02376 if so, read the dataset that special way and return now 02377 (this is NOT part of the NIFTI-1 standard!) **/ 02378 02379 ii = znzread( buf , 1 , 12 , fp ) ; 02380 if( ii < 12 ){ 02381 znzclose( fp ) ; 02382 if( gni_debug > 0 ) 02383 LNI_FERR(fname,"short header read",workingname); 02384 free(workingname); 02385 return NULL; 02386 } 02387 02388 znzrewind(fp) ; 02389 buf[12] = '\0' ; 02390 if( strcmp(buf,"<nifti_image") == 0 ){ /* have an ASCII header! */ 02391 int slen, txt_size; 02392 char *sbuf ; 02393 if( nifti_is_gzfile(workingname) ){ 02394 LNI_FERR(fname, "compressed file with negative offset", workingname); 02395 free(workingname); 02396 return NULL; 02397 } 02398 slen = get_filesize( workingname ) ; 02399 02400 if( gni_debug > 1 ) 02401 fprintf(stderr,"-d %s: have ASCII image of size %d\n",fname,slen); 02402 02403 if( slen > 65530 ) slen = 65530 ; 02404 sbuf = (char *)calloc(sizeof(char),slen+1) ; 02405 znzread( sbuf , 1 , slen , fp ) ; 02406 nim = nifti_image_from_ascii( sbuf, &txt_size ) ; free( sbuf ) ; 02407 if( nim == NULL ){ 02408 LNI_FERR(fname,"failed nifti_image_from_ascii()",workingname); 02409 free(workingname); 02410 return NULL; 02411 } 02412 nim->nifti_type = 3 ; 02413 02414 /* read extensions (but reposition file pointer, first */ 02415 znzseek(fp, txt_size, SEEK_SET); 02416 (void) nifti_read_extensions(nim, fp); 02417 02418 znzclose( fp ) ; 02419 02420 nim->iname_offset = -1 ; /* now check from the end of the file */ 02421 02422 if( read_data ) ii = nifti_image_load( nim ) ; 02423 else nim->data = NULL ; 02424 02425 free(workingname); 02426 02427 /* check for nifti_image_load() failure, maybe bail out */ 02428 if( read_data && ii != 0 ){ 02429 if( gni_debug > 1 ) 02430 fprintf(stderr,"-d failed image_load, free nifti image struct\n"); 02431 free(nim); 02432 return NULL; 02433 } 02434 02435 return nim ; 02436 } 02437 02438 /**================ Normal case: read binary header ===================*/ 02439 02440 ii = znzread( &nhdr , 1 , sizeof(nhdr) , fp ) ; /* read the thing */ 02441 02442 /* rcr - test header struct for consistency here? */ 02443 02444 /* keep the file open for a while so we can check for extensions 02445 * after nifti_convert_nhdr2nim() */ 02446 02447 if( ii < sizeof(nhdr) ){ 02448 if( gni_debug > 0 ){ 02449 LNI_FERR(fname,"bad binary header read for file", workingname); 02450 fprintf(stderr," - read %d of %d bytes\n",ii, (int)sizeof(nhdr)); 02451 } 02452 free(workingname); 02453 return NULL; 02454 } 02455 02456 /*=== create output image struct and set it up ===*/ 02457 02458 /** convert all nhdr fields to nifti_image fields **/ 02459 nim = nifti_convert_nhdr2nim(nhdr,workingname); 02460 02461 if( nim == NULL ){ 02462 znzclose( fp ) ; /* close the file */ 02463 if( gni_debug > 0 ) 02464 LNI_FERR(fname,"failed to create nifti image from header",workingname); 02465 free(workingname); /* had to save this for debug message */ 02466 return NULL; 02467 } 02468 02469 if( gni_debug > 1 ){ 02470 fprintf(stderr,"+d nifti_image_read(), have nifti image:\n"); 02471 nifti_image_infodump(nim); 02472 } 02473 02474 /* check for extensions, let us just ignore any errors here */ 02475 (void) nifti_read_extensions(nim, fp); 02476 02477 znzclose( fp ) ; /* close the file */ 02478 free(workingname); 02479 /* check that the data file is OK */ 02480 if (!nifti_is_gzfile(nim->iname)) { 02481 /* can't use get_filesize on a compressed file :( */ 02482 ilen = get_filesize(nim->iname) ; 02483 if( ilen <= nim->iname_offset ){ 02484 fprintf(stderr,"ERROR %s: file size less than offset (%d < %d)\n", 02485 fname,ilen,nim->iname_offset); 02486 free(nim); 02487 return NULL; 02488 } 02489 } 02490 02491 /** read the data if desired, then bug out **/ 02492 if( read_data ) ii = nifti_image_load( nim ) ; 02493 else nim->data = NULL ; 02494 02495 return nim ; 02496 } 02497 02498 02499 /*---------------------------------------------------------------------- 02500 * Read the extensions into the nifti_image struct 08 Dec 2004 [rickr] 02501 * 02502 * This function is called just after the header struct is read in, and 02503 * it is assumed the file pointer has not moved. 02504 * 02505 * return the number of extensions read in, or < 0 on error 02506 *----------------------------------------------------------------------*/ 02507 static int nifti_read_extensions( nifti_image *nim, znzFile fp ) 02508 { 02509 nifti1_extender extdr; /* defines extension existance */ 02510 nifti1_extension extn; /* single extension to process */ 02511 nifti1_extension * Elist; /* list of processed extensions */ 02512 int posn, count; 02513 int remaining; /* until image data starts */ 02514 02515 if( !nim || znz_isnull(fp) ) { 02516 if( gni_debug > 0 ) 02517 fprintf(stderr,"** nifti_read_extensions: bad inputs (%p,%p)\n", 02518 nim, fp); 02519 return -1; 02520 } 02521 02522 posn = znztell(fp); 02523 02524 if( posn != sizeof(nifti_1_header) ){ 02525 int dlevel_test = 0; 02526 if( nim->nifti_type == 3 ) dlevel_test = 1; 02527 if( gni_debug > dlevel_test ) 02528 fprintf(stderr,"** WARNING: posn not header size (%d, %d)\n", 02529 posn, (int)sizeof(nifti_1_header)); 02530 } 02531 02532 if( gni_debug > 2 ) 02533 fprintf(stderr,"-d nre: posn = %d, offset = %d, type = %d\n", 02534 posn, nim->iname_offset, nim->nifti_type); 02535 02536 if( nim->iname_offset > 0 && 02537 (!nim->iname || (nim->fname && (strcmp(nim->fname,nim->iname) == 0))) ) 02538 { 02539 /* then same file and offset exists, so compute remaining space */ 02540 remaining = nim->iname_offset - posn - 4; /* 4 for extender bytes */ 02541 if( remaining <= 0 ){ 02542 if( gni_debug > 2 ) 02543 fprintf(stderr,"-d no space for extentions in file '%s'\n", 02544 nim->fname); 02545 return 0; /* no extensions to read */ 02546 } 02547 } 02548 else /* different files, so just read until we cannot */ 02549 remaining = 0; 02550 02551 count = znzread( extdr.extension, 1, 4, fp ); /* get extender */ 02552 02553 if( count < 4 ){ 02554 if( gni_debug > 1 ) 02555 fprintf(stderr,"-d no extender stored in header file '%s'\n", 02556 nim->fname); 02557 return 0; 02558 } 02559 02560 if( extdr.extension[0] != 1 ){ 02561 if( gni_debug > 1 ) 02562 fprintf(stderr,"-d extender[0] (%d) shows no extensions for '%s'\n", 02563 extdr.extension[0], nim->fname); 02564 return 0; 02565 } 02566 02567 /* so we expect extensions, but have no idea of how many there may be */ 02568 02569 count = 0; 02570 Elist = NULL; 02571 while ((remaining >= 0) && (nifti_read_next_extension(&extn, nim, fp) > 0)) 02572 { 02573 if( nifti_add_exten_to_list(&extn, &Elist, count+1) < 0 ){ 02574 if( gni_debug > 0 ) 02575 fprintf(stderr,"** failed after %d successful extionsion reads\n", 02576 count); 02577 return -1; 02578 } 02579 02580 /* we have a new extension */ 02581 if( gni_debug > 1 ) 02582 fprintf(stderr,"+d found extension #%d, code = 0x%x, size = %d\n", 02583 count, extn.ecode, extn.esize); 02584 if( remaining > 0 ) remaining -= extn.esize; 02585 count++; 02586 } 02587 02588 if( gni_debug > 2 ) fprintf(stderr,"+d found %d extensions\n", count); 02589 02590 nim->num_ext = count; 02591 nim->ext_list = Elist; 02592 02593 return count; 02594 } 02595 02596 02597 /*---------------------------------------------------------------------- 02598 * nifti_add_exten_to_list - add new extension to the list 02599 * 02600 * We will append via malloc, copy and free, because on an error, 02601 * the old data pointers must all be released. 02602 * 02603 * return: 02604 * 0 on success 02605 * -1 on error (and free the entire list) 02606 *----------------------------------------------------------------------*/ 02607 static int nifti_add_exten_to_list( nifti1_extension * new_ext, 02608 nifti1_extension ** list, int new_length ) 02609 02610 { 02611 nifti1_extension * tmplist; 02612 int count; 02613 02614 tmplist = *list; 02615 *list = (nifti1_extension *)malloc(new_length * sizeof(nifti1_extension)); 02616 02617 /* check for failure first */ 02618 if( ! *list ){ 02619 fprintf(stderr,"** failed to alloc %d extension structs (%d bytes)\n", 02620 new_length, new_length*(int)sizeof(nifti1_extension)); 02621 if( !tmplist ) return -1; /* no old list to lose */ 02622 02623 for ( count = 0; count < new_length-1; count++ ) 02624 if( tmplist[count].edata ) free(tmplist[count].edata); 02625 free(tmplist); 02626 return -1; 02627 } 02628 02629 /* we have memory, so copy the old and insert the new */ 02630 memcpy(*list, tmplist, (new_length-1)*sizeof(nifti1_extension)); 02631 02632 /* for some reason, I just don't like struct copy... */ 02633 (*list)[new_length-1].esize = new_ext->esize; 02634 (*list)[new_length-1].ecode = new_ext->ecode; 02635 (*list)[new_length-1].edata = new_ext->edata; 02636 02637 return 0; 02638 } 02639 02640 02641 /*---------------------------------------------------------------------- 02642 * nifti_read_next_extension - read a single extension from the file 02643 * 02644 * return (>= 0 is okay): 02645 * 02646 * success : esize 02647 * no extension : 0 02648 * error : -1 02649 *----------------------------------------------------------------------*/ 02650 static int nifti_read_next_extension( nifti1_extension * nex, 02651 nifti_image *nim, znzFile fp ) 02652 { 02653 int swap = nim->byteorder != short_order(); 02654 int count, size, code; 02655 02656 /* first clear nex */ 02657 nex->esize = nex->ecode = 0; 02658 nex->edata = NULL; 02659 02660 /* must start with 4-byte size and code */ 02661 count = znzread( &size, 4, 1, fp ); 02662 if( count == 1 ) count = znzread( &code, 4, 1, fp ); 02663 02664 if( count != 1 ){ 02665 if( gni_debug > 2 ) fprintf(stderr,"-d current extension read failed\n"); 02666 return 0; /* no extension, no error condition */ 02667 } 02668 02669 if( swap ){ 02670 if( gni_debug > 2 ) 02671 fprintf(stderr,"-d pre-swap exts: code = %d, size = %d\n", code, size); 02672 02673 swap_4bytes(1, &size); 02674 swap_4bytes(1, &code); 02675 } 02676 02677 if( gni_debug > 2 ) 02678 fprintf(stderr,"-d new extensions: code = %d, size = %d\n", code, size); 02679 02680 /* since size includes the space for size and code, it should be > 8 */ 02681 if( size < 8 ){ 02682 if( gni_debug > 0 ) 02683 fprintf(stderr,"-d extension size cannot be less than 8: %d\n",size); 02684 return -1; 02685 } else if( size == 8 ){ 02686 if( gni_debug > 1 ) 02687 fprintf(stderr,"-d extension size 8 shows empty extension\n"); 02688 return -1; 02689 } 02690 02691 if( !nifti_valid_extension(nim, size, code) ) return 0; 02692 02693 /* now get the actual data */ 02694 nex->esize = size; 02695 nex->ecode = code; 02696 02697 size -= 8; /* subtract space for size and code in extension */ 02698 nex->edata = (char *)malloc(size * sizeof(char)); 02699 if( !nex->edata ){ 02700 fprintf(stderr,"** failed to allocate %d bytes for extension\n",size); 02701 return -1; 02702 } 02703 02704 count = znzread(nex->edata, 1, size, fp); 02705 if( count < size ){ 02706 if( gni_debug > 0 ) 02707 fprintf(stderr,"-d read only %d (of %d) bytes for extension\n", 02708 count, size); 02709 free(nex->edata); 02710 nex->edata = NULL; 02711 return -1; 02712 } 02713 02714 /* success! */ 02715 if( gni_debug > 1 ) 02716 fprintf(stderr,"+d successfully read extension, code %d, size %d\n", 02717 nex->ecode, nex->esize); 02718 02719 return nex->esize; 02720 } 02721 02722 /*---------------------------------------------------------------------- 02723 * 02724 *----------------------------------------------------------------------*/ 02725 static int nifti_valid_extension( nifti_image *nim, int size, int code ) 02726 { 02727 /* first check for bad conditions */ 02728 if( !nim || size <= 0 || code < 0 ){ 02729 if( gni_debug > 2 ) 02730 fprintf(stderr,"** NVE, bad exten params %p,%d,%d\n", nim, size, code); 02731 return 0; 02732 } 02733 02734 if( nim->nifti_type == 3 && size > LNI_MAX_NIA_EXT_LEN ){ 02735 if( gni_debug > 2 ) 02736 fprintf(stderr,"** NVE, bad nifti_type 3 size %d\n", size); 02737 return 0; 02738 } 02739 02740 /* now known, good codes */ 02741 if( code == 0 || /* unknown, unregistered, not recommended */ 02742 code == 2 || /* DICOM */ 02743 code == 4 ) /* AFNI */ 02744 return 1; 02745 02746 if( gni_debug > 2 ) fprintf(stderr,"-d invalid extension code %d\n", code); 02747 02748 return 0; 02749 } 02750 02751 02752 /*---------------------------------------------------------------------- 02753 * nifti_image_load_prep - prepare to read data 02754 * 02755 * Check nifti_image fields, open the file and seek to the appropriate 02756 * offset for reading. 02757 * 02758 * return NULL on failure 02759 *----------------------------------------------------------------------*/ 02760 static znzFile nifti_image_load_prep( nifti_image *nim ) 02761 { 02762 /* set up data space, open data file and seek, then call nifti_read_buffer */ 02763 size_t ntot , ii , ioff; 02764 znzFile fp; 02765 char fname[] = { "nifti_image_load_prep" }; 02766 02767 if( nim == NULL || nim->iname == NULL || 02768 nim->nbyper <= 0 || nim->nvox <= 0 ) 02769 { 02770 if ( gni_debug > 0 ){ 02771 if( !nim ) fprintf(stderr,"** ERROR: N_image_load: no nifti image\n"); 02772 else fprintf(stderr,"** ERROR: N_image_load: bad params (%p,%d,%d)\n", 02773 nim->iname, nim->nbyper, nim->nvox); 02774 } 02775 return NULL; 02776 } 02777 02778 ntot = nifti_get_volsize(nim) ; /* total bytes to read */ 02779 02780 /** open image data file **/ 02781 02782 fp = znzopen(nim->iname , "rb",1); 02783 if( znz_isnull(fp) ){ 02784 if( gni_debug > 0 ) 02785 LNI_FERR(fname,"cannot open data file",nim->iname); 02786 return NULL; 02787 } 02788 02789 /* negative offset means to figure from end of file */ 02790 if( nim->iname_offset < 0 ){ 02791 if( nifti_is_gzfile(nim->iname) ){ 02792 if( gni_debug > 0 ) 02793 LNI_FERR(fname,"negative offset for compressed file",nim->iname); 02794 znzclose(fp); 02795 return NULL; 02796 } 02797 ii = get_filesize( nim->iname ) ; 02798 if( ii <= 0 ){ 02799 if( gni_debug > 0 ) 02800 LNI_FERR(fname,"empty data file",nim->iname); 02801 znzclose(fp); 02802 return NULL; 02803 } 02804 ioff = (ii > ntot) ? ii-ntot : 0 ; 02805 } else { /* non-negative offset */ 02806 ioff = nim->iname_offset ; /* means use it directly */ 02807 } 02808 znzseek( fp , ioff , SEEK_SET ) ; 02809 02810 return fp; 02811 } 02812 02813 02814 /*---------------------------------------------------------------------- 02815 * Load the image data from disk into an already-prepared image struct. 02816 * 02817 * change to return an int: 29 Nov 2004 [rickr] 02818 * 0 : success (image data space will be allocated if it wasn't already) 02819 * < 0 : error 02820 *----------------------------------------------------------------------*/ 02821 int nifti_image_load( nifti_image *nim ) 02822 { 02823 /* set up data space, open data file and seek, then call nifti_read_buffer */ 02824 size_t ntot , ii ; 02825 znzFile fp ; 02826 02827 fp = nifti_image_load_prep( nim ); 02828 02829 if( fp == NULL ){ 02830 if( gni_debug > 0 ) 02831 fprintf(stderr,"** nifti_image_load, failed load_prep\n"); 02832 return -1; 02833 } 02834 02835 ntot = nifti_get_volsize(nim); 02836 02837 /* if the data pointer is already set, use the given space */ 02838 02839 if( nim->data == NULL ) 02840 { 02841 nim->data = (void *)calloc(1,ntot) ; /* create image memory */ 02842 if( nim->data == NULL ){ 02843 if( gni_debug > 0 ) 02844 fprintf(stderr,"** failed to alloc %d bytes for image data\n", 02845 (int)ntot); 02846 znzclose(fp); 02847 return -1; 02848 } 02849 } 02850 02851 /* now that everything is set up - do the reading */ 02852 ii = nifti_read_buffer(fp,nim->data,ntot,nim); 02853 if( ii < ntot ){ 02854 znzclose(fp) ; 02855 free(nim->data) ; 02856 nim->data = NULL ; 02857 return -1 ; /* errors were printed in nifti_read_buffer() */ 02858 } 02859 02860 znzclose( fp ) ; 02861 02862 return 0 ; 02863 } 02864 02865 02866 /* 30 Nov 2004 [rickr] 02867 #undef ERREX 02868 #define ERREX(msg) \ 02869 do{ fprintf(stderr,"** ERROR: nifti_read_buffer: %s\n",(msg)) ; \ 02870 return 0; } while(0) 02871 */ 02872 02873 02874 /*---------------------------------------------------------------------- 02875 * reads ntot bytes of data from an open file and byte swaps if necessary 02876 * note that nifti_image is required for information on datatype, etc. 02877 *----------------------------------------------------------------------*/ 02878 static size_t nifti_read_buffer(znzFile fp, void* dataptr, size_t ntot, 02879 nifti_image *nim) 02880 { 02881 size_t ii; 02882 02883 if( dataptr == NULL ){ 02884 if( gni_debug > 0 ) 02885 fprintf(stderr,"** ERROR: nifti_read_buffer: NULL dataptr\n"); 02886 return -1; 02887 } 02888 02889 ii = znzread( dataptr , 1 , ntot , fp ) ; /* data input */ 02890 02891 /* if read was short, fail */ 02892 if( ii < ntot ){ 02893 if( gni_debug > 0 ) 02894 fprintf(stderr,"++ WARNING: nifti_read_buffer(%s):\n" 02895 " data bytes needed = %u\n" 02896 " data bytes input = %u\n" 02897 " number missing = %u (set to 0)\n", 02898 nim->iname , (unsigned int)ntot , 02899 (unsigned int)ii , (unsigned int)(ntot-ii) ) ; 02900 /* memset( (char *)(dataptr)+ii , 0 , ntot-ii ) ; now failure [rickr] */ 02901 return -1 ; 02902 } 02903 02904 /* byte swap array if needed */ 02905 02906 if( nim->swapsize > 1 && nim->byteorder != short_order() ) 02907 swap_Nbytes( ntot / nim->swapsize , nim->swapsize , dataptr ) ; 02908 02909 #ifdef isfinite 02910 { 02911 /* check input float arrays for goodness, and fix bad floats */ 02912 int fix_count = 0 ; 02913 02914 switch( nim->datatype ){ 02915 02916 case NIFTI_TYPE_FLOAT32: 02917 case NIFTI_TYPE_COMPLEX64:{ 02918 register float *far = (float *)dataptr ; register int jj,nj ; 02919 nj = ntot / sizeof(float) ; 02920 for( jj=0 ; jj < nj ; jj++ ) /* count fixes 30 Nov 2004 [rickr] */ 02921 if( !IS_GOOD_FLOAT(far[jj]) ){ 02922 far[jj] = 0 ; 02923 fix_count++ ; 02924 } 02925 } 02926 break ; 02927 02928 case NIFTI_TYPE_FLOAT64: 02929 case NIFTI_TYPE_COMPLEX128:{ 02930 register double *far = (double *)dataptr ; register int jj,nj ; 02931 nj = ntot / sizeof(double) ; 02932 for( jj=0 ; jj < nj ; jj++ ) /* count fixes 30 Nov 2004 [rickr] */ 02933 if( !IS_GOOD_FLOAT(far[jj]) ){ 02934 far[jj] = 0 ; 02935 fix_count++ ; 02936 } 02937 } 02938 break ; 02939 02940 } 02941 02942 if( gni_debug > 1 ) 02943 fprintf(stderr,"+d in image, %d bad floats were set to 0\n", fix_count); 02944 } 02945 #endif 02946 02947 return ii; 02948 } 02949 02950 /*--------------------------------------------------------------------------*/ 02951 /* Unload the data in a nifti_image struct, but keep the metadata. 02952 ----------------------------------------------------------------------------*/ 02953 02954 void nifti_image_unload( nifti_image *nim ) 02955 { 02956 if( nim != NULL && nim->data != NULL ){ 02957 free(nim->data) ; nim->data = NULL ; 02958 } 02959 return ; 02960 } 02961 02962 /*--------------------------------------------------------------------------*/ 02963 /* Free a nifti_image struct that was read by nifti_image_read(). 02964 ----------------------------------------------------------------------------*/ 02965 02966 void nifti_image_free( nifti_image *nim ) 02967 { 02968 if( nim == NULL ) return ; 02969 if( nim->fname != NULL ) free(nim->fname) ; 02970 if( nim->iname != NULL ) free(nim->iname) ; 02971 if( nim->data != NULL ) free(nim->data ) ; 02972 free(nim) ; return ; 02973 } 02974 02975 /*--------------------------------------------------------------------------*/ 02976 /* Print to stdout some info about a nifti_image struct. 02977 ----------------------------------------------------------------------------*/ 02978 02979 void nifti_image_infodump( nifti_image *nim ) 02980 { 02981 char *str = nifti_image_to_ascii( nim ) ; 02982 /* stdout -> stderr 2 Dec 2004 [rickr] */ 02983 if( str != NULL ){ fputs(str,stderr) ; free(str) ; } 02984 return ; 02985 } 02986 02987 /*--------------------------------------------------------------------------*/ 02988 /* Write a nifti_image to disk. The following fields of nim affect how 02989 the output appears: 02990 - nifti_type = 0 ==> ANALYZE-7.5 format file pair will be written 02991 - nifti_type = 1 ==> NIFTI-1 format single file will be written 02992 (data offset will be 348) 02993 - nifti_type = 2 ==> NIFTI_1 format file pair will be written 02994 - nifti_type = 3 ==> NIFTI_1 ASCII single file will be written 02995 - fname is the name of the output file (header or header+data) 02996 - if a file pair is being written, iname is the name of the data file 02997 - existing files WILL be overwritten with extreme prejudice 02998 - if qform_code > 0, the quatern_*, qoffset_*, and qfac fields determine 02999 the qform output, NOT the qto_xyz matrix; if you want to compute these 03000 fields from the qto_xyz matrix, you can use the utility function 03001 mat44_to_quatern() 03002 ----------------------------------------------------------------------------*/ 03003 03004 static size_t nifti_write_buffer(znzFile fp, void *buffer, size_t numbytes) 03005 { 03006 /** Write all the image data at once (no swapping here) **/ 03007 size_t ss; 03008 if (znz_isnull(fp)){ 03009 fprintf(stderr,"** ERROR: nifti_write_buffer: null file pointer\n"); 03010 return 0; 03011 } 03012 ss = znzwrite( (void *) buffer , 1 , numbytes , fp ) ; 03013 return ss; 03014 } 03015 03016 03017 /* just print... 03018 #undef ERREX 03019 #define ERREX(msg) \ 03020 do{ fprintf(stderr,"** ERROR: nifti_image_write: %s\n",(msg)) ; \ 03021 return ; } while(0) 03022 */ 03023 03024 static void nifti_write_all_data(znzFile fp, nifti_image *nim) 03025 { 03026 /** Write all the image data at once (no swapping here) **/ 03027 size_t ss; 03028 ss = nifti_write_buffer(fp,nim->data,nim->nbyper * nim->nvox); 03029 if (ss < (nim->nbyper * nim->nvox)){ 03030 fprintf(stderr, 03031 "** ERROR: nifti_image_write: wrote only %d of %d bytes to file\n", 03032 (int)ss, nim->nbyper * nim->nvox); 03033 return; 03034 } 03035 03036 nim->byteorder = short_order() ; /* mark as being in this CPU byte order */ 03037 return ; 03038 } 03039 03040 /* return number of extensions written, or -1 on error */ 03041 static int nifti_write_extensions(znzFile fp, nifti_image *nim) 03042 { 03043 nifti1_extension * list; 03044 char extdr[4] = { 0, 0, 0, 0 }; 03045 int c, size, ok = 1; 03046 03047 if( znz_isnull(fp) || !nim || nim->num_ext < 0 ){ 03048 if( gni_debug > 0 ) 03049 fprintf(stderr,"** nifti_write_extensions, bad params\n"); 03050 return -1; 03051 } 03052 03053 /* write out extender block */ 03054 if( nim->num_ext > 0 ) extdr[0] = 1; 03055 if( nifti_write_buffer(fp, extdr, 4) != 4 ){ 03056 fprintf(stderr,"** failed to write extender\n"); 03057 return -1; 03058 } 03059 03060 list = nim->ext_list; 03061 for ( c = 0; c < nim->num_ext; c++ ){ 03062 size = nifti_write_buffer(fp, &list->esize, sizeof(int)); 03063 ok = (size == (int)sizeof(int)); 03064 if( ok ) 03065 size = nifti_write_buffer(fp, &list->ecode, sizeof(int)); 03066 ok = (size == (int)sizeof(int)); 03067 if( ok ) 03068 size = nifti_write_buffer(fp, list->edata, list->esize); 03069 03070 if( !ok ){ 03071 fprintf(stderr,"** failed while writing extension #%d\n",c); 03072 return -1; 03073 } 03074 03075 list++; 03076 } 03077 03078 if( gni_debug > 1 ) 03079 fprintf(stderr,"+d wrote out %d extensions\n", nim->num_ext); 03080 03081 return nim->num_ext; 03082 } 03083 03084 03085 nifti_image* nifti_simple_init_nim() 03086 { 03087 nifti_image *nim; 03088 struct nifti_1_header nhdr; 03089 int nbyper, swapsize; 03090 03091 memset(&nhdr,0,sizeof(nhdr)) ; /* zero out header, to be safe */ 03092 03093 /** load the ANALYZE-7.5 generic parts of the header struct **/ 03094 03095 nhdr.sizeof_hdr = sizeof(nhdr) ; 03096 nhdr.regular = 'r' ; /* for some stupid reason */ 03097 03098 nhdr.dim[0] = 3 ; 03099 nhdr.dim[1] = 1 ; nhdr.dim[2] = 1 ; nhdr.dim[3] = 1 ; 03100 nhdr.dim[4] = 0 ; 03101 03102 nhdr.pixdim[0] = 0.0 ; 03103 nhdr.pixdim[1] = 1.0 ; nhdr.pixdim[2] = 1.0 ; 03104 nhdr.pixdim[3] = 1.0 ; 03105 03106 nhdr.datatype = NIFTI_TYPE_FLOAT32 ; 03107 nifti_datatype_sizes( nhdr.datatype , &nbyper, &swapsize ); 03108 nhdr.bitpix = 8 * nbyper ; 03109 03110 nim = nifti_convert_nhdr2nim(nhdr,NULL); 03111 nim->fname = NULL; 03112 nim->iname = NULL; 03113 return nim; 03114 } 03115 03116 03117 03118 03119 struct nifti_1_header nifti_convert_nim2nhdr(nifti_image* nim) 03120 { 03121 struct nifti_1_header nhdr; 03122 03123 memset(&nhdr,0,sizeof(nhdr)) ; /* zero out header, to be safe */ 03124 03125 03126 /** load the ANALYZE-7.5 generic parts of the header struct **/ 03127 03128 nhdr.sizeof_hdr = sizeof(nhdr) ; 03129 nhdr.regular = 'r' ; /* for some stupid reason */ 03130 03131 nhdr.dim[0] = nim->ndim ; 03132 nhdr.dim[1] = nim->nx ; nhdr.dim[2] = nim->ny ; nhdr.dim[3] = nim->nz ; 03133 nhdr.dim[4] = nim->nt ; nhdr.dim[5] = nim->nu ; nhdr.dim[6] = nim->nv ; 03134 nhdr.dim[7] = nim->nw ; 03135 03136 nhdr.pixdim[0] = 0.0 ; 03137 nhdr.pixdim[1] = nim->dx ; nhdr.pixdim[2] = nim->dy ; 03138 nhdr.pixdim[3] = nim->dz ; nhdr.pixdim[4] = nim->dt ; 03139 nhdr.pixdim[5] = nim->du ; nhdr.pixdim[6] = nim->dv ; 03140 nhdr.pixdim[7] = nim->dw ; 03141 03142 nhdr.datatype = nim->datatype ; 03143 nhdr.bitpix = 8 * nim->nbyper ; 03144 03145 if( nim->cal_max > nim->cal_min ){ 03146 nhdr.cal_max = nim->cal_max ; 03147 nhdr.cal_min = nim->cal_min ; 03148 } 03149 03150 if( nim->scl_slope != 0.0 ){ 03151 nhdr.scl_slope = nim->scl_slope ; 03152 nhdr.scl_inter = nim->scl_inter ; 03153 } 03154 03155 if( nim->descrip[0] != '\0' ){ 03156 memcpy(nhdr.descrip ,nim->descrip ,79) ; nhdr.descrip[79] = '\0' ; 03157 } 03158 if( nim->aux_file[0] != '\0' ){ 03159 memcpy(nhdr.aux_file ,nim->aux_file ,23) ; nhdr.aux_file[23] = '\0' ; 03160 } 03161 03162 /** Load NIFTI specific stuff into the header **/ 03163 03164 if( nim->nifti_type > 0 ){ 03165 03166 if( nim->nifti_type == 1 ) strcpy(nhdr.magic,"n+1") ; /* 1 file */ 03167 else strcpy(nhdr.magic,"ni1") ; /* 2 files */ 03168 03169 /* for nifti files, enforce positive pixdims! */ 03170 nhdr.pixdim[1] = fabs(nhdr.pixdim[1]) ; nhdr.pixdim[2] = fabs(nhdr.pixdim[2]) ; 03171 nhdr.pixdim[3] = fabs(nhdr.pixdim[3]) ; nhdr.pixdim[4] = fabs(nhdr.pixdim[4]) ; 03172 nhdr.pixdim[5] = fabs(nhdr.pixdim[5]) ; nhdr.pixdim[6] = fabs(nhdr.pixdim[6]) ; 03173 nhdr.pixdim[7] = fabs(nhdr.pixdim[7]) ; 03174 03175 nhdr.intent_code = nim->intent_code ; 03176 nhdr.intent_p1 = nim->intent_p1 ; 03177 nhdr.intent_p2 = nim->intent_p2 ; 03178 nhdr.intent_p3 = nim->intent_p3 ; 03179 if( nim->intent_name[0] != '\0' ){ 03180 memcpy(nhdr.intent_name,nim->intent_name,15) ; 03181 nhdr.intent_name[15] = '\0' ; 03182 } 03183 03184 nhdr.vox_offset = (float) nim->iname_offset ; 03185 nhdr.xyzt_units = SPACE_TIME_TO_XYZT( nim->xyz_units, nim->time_units ) ; 03186 nhdr.toffset = nim->toffset ; 03187 03188 if( nim->qform_code > 0 ){ 03189 nhdr.qform_code = nim->qform_code ; 03190 nhdr.quatern_b = nim->quatern_b ; 03191 nhdr.quatern_c = nim->quatern_c ; 03192 nhdr.quatern_d = nim->quatern_d ; 03193 nhdr.qoffset_x = nim->qoffset_x ; 03194 nhdr.qoffset_y = nim->qoffset_y ; 03195 nhdr.qoffset_z = nim->qoffset_z ; 03196 nhdr.pixdim[0] = (nim->qfac >= 0.0) ? 1.0 : -1.0 ; 03197 } 03198 03199 if( nim->sform_code > 0 ){ 03200 nhdr.sform_code = nim->sform_code ; 03201 nhdr.srow_x[0] = nim->sto_xyz.m[0][0] ; 03202 nhdr.srow_x[1] = nim->sto_xyz.m[0][1] ; 03203 nhdr.srow_x[2] = nim->sto_xyz.m[0][2] ; 03204 nhdr.srow_x[3] = nim->sto_xyz.m[0][3] ; 03205 nhdr.srow_y[0] = nim->sto_xyz.m[1][0] ; 03206 nhdr.srow_y[1] = nim->sto_xyz.m[1][1] ; 03207 nhdr.srow_y[2] = nim->sto_xyz.m[1][2] ; 03208 nhdr.srow_y[3] = nim->sto_xyz.m[1][3] ; 03209 nhdr.srow_z[0] = nim->sto_xyz.m[2][0] ; 03210 nhdr.srow_z[1] = nim->sto_xyz.m[2][1] ; 03211 nhdr.srow_z[2] = nim->sto_xyz.m[2][2] ; 03212 nhdr.srow_z[3] = nim->sto_xyz.m[2][3] ; 03213 } 03214 03215 nhdr.dim_info = FPS_INTO_DIM_INFO( nim->freq_dim , 03216 nim->phase_dim , nim->slice_dim ) ; 03217 nhdr.slice_code = nim->slice_code ; 03218 nhdr.slice_start = nim->slice_start ; 03219 nhdr.slice_end = nim->slice_end ; 03220 nhdr.slice_duration = nim->slice_duration ; 03221 } 03222 03223 return nhdr; 03224 } 03225 03226 03227 03228 int nifti_extension_size(nifti_image *nim) 03229 { 03230 int c, size = 0; 03231 03232 if( !nim || nim->num_ext <= 0 ) return 0; 03233 03234 if( gni_debug > 2 ) fprintf(stderr,"-d ext sizes:"); 03235 03236 for ( c = 0; c < nim->num_ext; c++ ){ 03237 size += nim->ext_list[c].esize; 03238 if( gni_debug > 2 ) fprintf(stderr," %d",nim->ext_list[c].esize); 03239 } 03240 03241 if( gni_debug > 2 ) fprintf(stderr," (total = %d)\n",size); 03242 03243 return size; 03244 } 03245 03246 void nifti_set_iname_offset(nifti_image *nim) 03247 { 03248 int offset = nifti_extension_size(nim); /* init based on extensions */ 03249 03250 03251 switch( nim->nifti_type ){ 03252 03253 default: /* writing into 2 files */ 03254 /* we only write files with 0 offset in the 2 file format */ 03255 nim->iname_offset = 0 ; 03256 break ; 03257 03258 case 1: /* NIFTI-1 single binary file */ 03259 if (nim->iname_offset < sizeof(struct nifti_1_header)) { 03260 offset += sizeof(struct nifti_1_header) + 4 ; 03261 /* be sure offset is aligned to a 16 byte word boundary */ 03262 if ( ( offset % 16 ) != 0 ) offset = ((offset + 0xf) & ~0xf); 03263 03264 if( nim->iname_offset != offset && gni_debug > 1 ){ 03265 fprintf(stderr,"+d changing offset from %d to %d\n", 03266 nim->iname_offset, offset); 03267 } 03268 nim->iname_offset = offset; 03269 } 03270 break ; 03271 03272 /* non-standard case: */ 03273 case 3:{ /* NIFTI-1 ASCII header + binary data (single file) */ 03274 nim->iname_offset = -1 ; /* compute offset from filesize */ 03275 } 03276 } 03277 } 03278 03279 03280 03281 #undef ERREX 03282 #define ERREX(msg) \ 03283 do{ fprintf(stderr,"** ERROR: nifti_image_write_hdr_img: %s\n",(msg)) ; \ 03284 return fp ; } while(0) 03285 03286 03287 /* ---------------------------------------------------------------------- 03288 * This writes the header (and optionally the image data) to file 03289 * If the image data file is left open it returns a valid znzFile handle 03290 * It also uses imgfile as the open image file is not null, and modifies 03291 * it inside. 03292 * 03293 * Values for write_data mode are based on two binary flags 03294 * ( 0/1 for no-write/write data, and 0/2 for close/leave-open files ) : 03295 * 0 = do not write data and close (do not open data file) 03296 * 1 = write data and close 03297 * 2 = do not write data and leave data file open 03298 * 3 = write data and leave data file open 03299 * ----------------------------------------------------------------------*/ 03300 03301 static znzFile nifti_image_write_hdr_img2( nifti_image *nim , int write_data , 03302 char* opts, znzFile *imgfile ) 03303 { 03304 struct nifti_1_header nhdr ; 03305 znzFile fp=NULL, hdrfile=NULL; 03306 size_t ss ; 03307 03308 if( nim == NULL ) ERREX("NULL input") ; 03309 if( !nifti_validfilename(nim->fname) ) ERREX("bad fname input") ; 03310 if( (nim->data == NULL) && ((write_data & 1)!=0) ) ERREX("no image data") ; 03311 03312 nifti_set_iname_offset(nim); 03313 03314 /* make iname from fname, if needed */ 03315 03316 switch( nim->nifti_type ){ 03317 03318 default: /* writing into 2 files */ 03319 if( nim->iname != NULL && strcmp(nim->iname,nim->fname) == 0 ){ 03320 free(nim->iname) ; nim->iname = NULL ; 03321 } 03322 if( nim->iname == NULL ){ 03323 /* choose a new name because either no name set, 03324 * or it wasn't different from hdr */ 03325 nim->iname = nifti_findimgname(nim->fname,nim->nifti_type); 03326 if( nim->iname == NULL ){ 03327 if( gni_debug > 0 ) 03328 fprintf(stderr,"** failed findimgname for '%s'\n", nim->fname); 03329 return NULL; 03330 } 03331 } 03332 break ; 03333 03334 case 1: /* NIFTI-1 single binary file */ 03335 break ; 03336 03337 /* non-standard case: */ 03338 case 3:{ /* NIFTI-1 ASCII header + binary data (single file) */ 03339 char *hstr ; 03340 nim->byteorder = short_order() ; /* am writing in current order */ 03341 hstr = nifti_image_to_ascii( nim ) ; /* get header in ASCII form */ 03342 if( hstr == NULL ) ERREX("bad ASCII header creation?") ; 03343 fp = znzopen( nim->fname , opts , nifti_is_gzfile(nim->fname) ) ; 03344 if( znz_isnull(fp) ){ free(hstr); ERREX("can't open output file"); } 03345 znzputs(hstr,fp) ; 03346 03347 nifti_write_extensions(fp,nim); 03348 03349 /* writes the binary data to fp */ 03350 if ( (write_data & 1)!=0) { nifti_write_all_data(fp,nim); } 03351 if ( (write_data & 2)==0) { znzclose(fp); } 03352 return fp; /* returned but may be closed */ 03353 } 03354 } 03355 03356 /***** Here -- write a binary header *****/ 03357 03358 nhdr = nifti_convert_nim2nhdr(nim); 03359 03360 if (imgfile==NULL) { 03361 03362 /** Open file, write header **/ 03363 03364 fp = znzopen( nim->fname , opts , nifti_is_gzfile(nim->fname) ) ; 03365 if( znz_isnull(fp) ) ERREX("can't open output file") ; 03366 03367 ss = znzwrite( &nhdr , 1 , sizeof(nhdr) , fp ) ; 03368 if( ss < sizeof(nhdr) ){ 03369 znzclose(fp) ; ERREX("bad write to output file") ; 03370 } 03371 nifti_write_extensions(fp,nim); 03372 03373 03374 /** if writing data or keeping data file open **/ 03375 if ((write_data & 3)!=0) { 03376 /** If writing dual files, close header and open image file **/ 03377 if( nim->nifti_type != 1 ){ 03378 znzclose(fp) ; 03379 fp = znzopen( nim->iname , opts , nifti_is_gzfile(nim->iname) ) ; 03380 if( znz_isnull(fp) ) ERREX("can't open image file") ; 03381 } 03382 /* skip to vox_offset, ready for writing */ 03383 znzseek(fp,nim->iname_offset,SEEK_SET); 03384 if ( (write_data & 1)!=0) nifti_write_all_data(fp,nim); 03385 } 03386 03387 /** close the file if requested **/ 03388 if ( (write_data & 2)==0) { znzclose(fp); } 03389 return fp; /* returned but may be closed */ 03390 03391 } 03392 03393 /** ----- otherwise use imgfile for the image -----**/ 03394 03395 /** write header **/ 03396 03397 if (nim->nifti_type==1) { 03398 if( znz_isnull(*imgfile) ) ERREX("bad image data file passed in") ; 03399 /* if header and data file are the same then seek to beginning and write */ 03400 znzseek(*imgfile,0,SEEK_SET); 03401 ss = znzwrite( &nhdr , 1 , sizeof(nhdr) , *imgfile ) ; 03402 if( ss < sizeof(nhdr) ){ ERREX("bad write to output file") ; } 03403 nifti_write_extensions(*imgfile,nim); 03404 } else { 03405 /* if a dual file type or no file opened, then start a new file */ 03406 hdrfile = znzopen( nim->fname , opts , nifti_is_gzfile(nim->fname) ) ; 03407 if( znz_isnull(hdrfile) ) ERREX("can't open output file") ; 03408 /* if the header file was separate then write and close it now */ 03409 ss = znzwrite( &nhdr , 1 , sizeof(nhdr) , hdrfile ) ; 03410 if( ss < sizeof(nhdr) ){ znzclose(fp); ERREX("bad write to output file"); } 03411 nifti_write_extensions(hdrfile,nim); 03412 znzclose(hdrfile); 03413 } 03414 03415 03416 /** if writing data or keeping data file open **/ 03417 if ((write_data & 3)!=0) { 03418 /* skip to vox_offset, ready for writing in image file */ 03419 znzseek(*imgfile,nim->iname_offset,SEEK_SET); 03420 if ( (write_data & 1)!=0) nifti_write_all_data(*imgfile,nim); 03421 } 03422 03423 /** close the file if requested **/ 03424 if ( (write_data & 2)==0) { znzclose(*imgfile); } 03425 return *imgfile; /* returned but may be closed */ 03426 } 03427 03428 03429 static znzFile nifti_image_write_hdr_img( nifti_image *nim , int write_data , 03430 char* opts) 03431 { 03432 return nifti_image_write_hdr_img2(nim,write_data,opts,NULL); 03433 } 03434 03435 03436 void nifti_image_write( nifti_image *nim ) 03437 { 03438 nifti_image_write_hdr_img(nim,1,"wb"); 03439 } 03440 03441 03442 03443 /* copy for nifti_image is via the nifti_1_header structure */ 03444 /* it does not copy data */ 03445 03446 nifti_image * nifti_copy_nim_info(nifti_image* src) 03447 { 03448 struct nifti_1_header nhdr; 03449 nifti_image *dest; 03450 dest = (nifti_image *)calloc(1,sizeof(nifti_image)); 03451 nhdr = nifti_convert_nim2nhdr(src); 03452 dest = nifti_convert_nhdr2nim(nhdr,src->fname); 03453 return dest; 03454 } 03455 03456 03457 /*------------------------------------------------------------------------*/ 03458 /* Un-escape a C string in place -- that is, convert XML escape sequences 03459 back into their characters. (This can be done in place since the 03460 replacement is always smaller than the input.) Escapes recognized are: 03461 - < -> < 03462 - > -> > 03463 - " -> " 03464 - ' -> ' 03465 - & -> & 03466 Also replace CR LF pair (Microsoft), or CR alone (Macintosh) with 03467 LF (Unix), per the XML standard. 03468 Return value is number of replacements made (if you care). 03469 --------------------------------------------------------------------------*/ 03470 03471 #undef CR 03472 #undef LF 03473 #define CR 0x0D 03474 #define LF 0x0A 03475 03476 int unescape_string( char *str ) 03477 { 03478 int ii,jj , nn,ll ; 03479 03480 if( str == NULL ) return 0 ; /* no string? */ 03481 ll = strlen(str) ; if( ll == 0 ) return 0 ; 03482 03483 /* scan for escapes: &something; */ 03484 03485 for( ii=jj=nn=0 ; ii<ll ; ii++,jj++ ){ /* scan at ii; results go in at jj */ 03486 03487 if( str[ii] == '&' ){ /* start of escape? */ 03488 03489 if( ii+3 < ll && /* < */ 03490 str[ii+1] == 'l' && 03491 str[ii+2] == 't' && 03492 str[ii+3] == ';' ){ str[jj] = '<' ; ii += 3 ; nn++ ; } 03493 03494 else if( ii+3 < ll && /* > */ 03495 str[ii+1] == 'g' && 03496 str[ii+2] == 't' && 03497 str[ii+3] == ';' ){ str[jj] = '>' ; ii += 3 ; nn++ ; } 03498 03499 else if( ii+5 < ll && /* " */ 03500 str[ii+1] == 'q' && 03501 str[ii+2] == 'u' && 03502 str[ii+3] == 'o' && 03503 str[ii+4] == 't' && 03504 str[ii+5] == ';' ){ str[jj] = '"' ; ii += 5 ; nn++ ; } 03505 03506 else if( ii+5 < ll && /* ' */ 03507 str[ii+1] == 'a' && 03508 str[ii+2] == 'p' && 03509 str[ii+3] == 'o' && 03510 str[ii+4] == 's' && 03511 str[ii+5] == ';' ){ str[jj] = '\'' ; ii += 5 ; nn++ ; } 03512 03513 else if( ii+4 < ll && /* & */ 03514 str[ii+1] == 'a' && 03515 str[ii+2] == 'm' && 03516 str[ii+3] == 'p' && 03517 str[ii+4] == ';' ){ str[jj] = '&' ; ii += 4 ; nn++ ; } 03518 03519 /* although the comments above don't mention it, 03520 we also look for XML style numeric escapes 03521 of the forms   (decimal) and ý (hex) */ 03522 03523 else if( ii+3 < ll && 03524 str[ii+1] == '#' && 03525 isdigit(str[ii+2]) ){ /* &#dec; */ 03526 03527 unsigned int val='?' ; int kk=ii+3 ; 03528 while( kk < ll && kk != ';' ) kk++ ; 03529 sscanf( str+ii+2 , "%u" , &val ) ; 03530 str[jj] = (char) val ; ii = kk ; nn++ ; 03531 } 03532 03533 else if( ii+4 < ll && 03534 str[ii+1] == '#' && 03535 str[ii+2] == 'x' && 03536 isxdigit(str[ii+3]) ){ /* &#hex; */ 03537 03538 unsigned int val='?' ; int kk=ii+4 ; 03539 while( kk < ll && kk != ';' ) kk++ ; 03540 sscanf( str+ii+3 , "%x" , &val ) ; 03541 str[jj] = (char) val ; ii = kk ; nn++ ; 03542 } 03543 03544 /* didn't start a recognized escape, so just copy as normal */ 03545 03546 else if( jj < ii ){ str[jj] = str[ii] ; } 03547 03548 } else if( str[ii] == CR ) { /* is a carriage return */ 03549 03550 if( str[ii+1] == LF ){ str[jj] = LF ; ii++ ; nn++ ; } /* CR LF */ 03551 else { str[jj] = LF ; ; nn++ ; } /* CR only */ 03552 03553 } else { /* is a normal character, just copy to output */ 03554 03555 if( jj < ii ){ str[jj] = str[ii] ; } 03556 } 03557 03558 /* at this point, ii=index of last character used up in scan 03559 jj=index of last character written to (jj <= ii) */ 03560 } 03561 03562 if( jj < ll ) str[jj] = '\0' ; /* end string properly */ 03563 03564 return nn ; 03565 } 03566 03567 /*------------------------------------------------------------------------*/ 03568 /* Quotize (and escapize) one string, returning a new string. 03569 Approximately speaking, this is the inverse of unescape_string(). 03570 The result should be free()-ed when you are done with it. 03571 --------------------------------------------------------------------------*/ 03572 03573 char *escapize_string( char *str ) 03574 { 03575 int ii,jj , lstr,lout ; 03576 char *out ; 03577 03578 if( str == NULL || (lstr=strlen(str)) == 0 ){ /* 0 length */ 03579 out = nifti_strdup("''") ; return out ; /* string?? */ 03580 } 03581 03582 lout = 4 ; /* initialize length of output */ 03583 for( ii=0 ; ii < lstr ; ii++ ){ /* count characters for output */ 03584 switch( str[ii] ){ 03585 case '&': lout += 5 ; break ; /* replace '&' with "&" */ 03586 03587 case '<': 03588 case '>': lout += 4 ; break ; /* replace '<' with "<" */ 03589 03590 case '"' : 03591 case '\'': lout += 6 ; break ; /* replace '"' with """ */ 03592 03593 case CR: 03594 case LF: lout += 6 ; break ; /* replace CR with "
" 03595 LF with "
" */ 03596 03597 default: lout++ ; break ; /* copy all other chars */ 03598 } 03599 } 03600 out = (char *)calloc(1,lout) ; /* allocate output string */ 03601 out[0] = '\'' ; /* opening quote mark */ 03602 for( ii=0,jj=1 ; ii < lstr ; ii++ ){ 03603 switch( str[ii] ){ 03604 default: out[jj++] = str[ii] ; break ; /* normal characters */ 03605 03606 case '&': memcpy(out+jj,"&",5) ; jj+=5 ; break ; 03607 03608 case '<': memcpy(out+jj,"<",4) ; jj+=4 ; break ; 03609 case '>': memcpy(out+jj,">",4) ; jj+=4 ; break ; 03610 03611 case '"' : memcpy(out+jj,""",6) ; jj+=6 ; break ; 03612 03613 case '\'': memcpy(out+jj,"'",6) ; jj+=6 ; break ; 03614 03615 case CR: memcpy(out+jj,"
",6) ; jj+=6 ; break ; 03616 case LF: memcpy(out+jj,"
",6) ; jj+=6 ; break ; 03617 } 03618 } 03619 out[jj++] = '\'' ; /* closing quote mark */ 03620 out[jj] = '\0' ; /* terminate the string */ 03621 return out ; 03622 } 03623 03624 /*---------------------------------------------------------------------------*/ 03625 /* Dump the information in a NIFTI image header to an XML-ish ASCII string 03626 that can later be converted back into a NIFTI header in 03627 nifti_image_from_ascii(). The resulting string can be free()-ed when 03628 you are done with it. 03629 -----------------------------------------------------------------------------*/ 03630 03631 char *nifti_image_to_ascii( nifti_image *nim ) 03632 { 03633 char *buf , *ebuf ; int nbuf ; 03634 03635 if( nim == NULL ) return NULL ; /* stupid caller */ 03636 03637 buf = (char *)calloc(1,65534); nbuf = 0; /* longer than needed, to be safe */ 03638 03639 sprintf( buf , "<nifti_image\n" ) ; /* XML-ish opener */ 03640 03641 sprintf( buf+strlen(buf) , " nifti_type = '%s'\n" , 03642 (nim->nifti_type == 1) ? "NIFTI-1+" 03643 :(nim->nifti_type == 2) ? "NIFTI-1" 03644 :(nim->nifti_type == 3) ? "NIFTI-1A" 03645 : "ANALYZE-7.5" ) ; 03646 03647 /** Strings that we don't control (filenames, etc.) that might 03648 contain "weird" characters (like quotes) are "escaped": 03649 - A few special characters are replaced by XML-style escapes, using 03650 the function escapize_string(). 03651 - On input, function unescape_string() reverses this process. 03652 - The result is that the NIFTI ASCII-format header is XML-compliant. **/ 03653 03654 ebuf = escapize_string(nim->fname) ; 03655 sprintf( buf+strlen(buf) , " header_filename = %s\n",ebuf); free(ebuf); 03656 03657 ebuf = escapize_string(nim->iname) ; 03658 sprintf( buf+strlen(buf) , " image_filename = %s\n", ebuf); free(ebuf); 03659 03660 sprintf( buf+strlen(buf) , " image_offset = '%d'\n" , nim->iname_offset ); 03661 03662 sprintf( buf+strlen(buf), " ndim = '%d'\n", nim->ndim); 03663 sprintf( buf+strlen(buf), " nx = '%d'\n", nim->nx ); 03664 if( nim->ndim > 1 ) sprintf( buf+strlen(buf), " ny = '%d'\n", nim->ny ); 03665 if( nim->ndim > 2 ) sprintf( buf+strlen(buf), " nz = '%d'\n", nim->nz ); 03666 if( nim->ndim > 3 ) sprintf( buf+strlen(buf), " nt = '%d'\n", nim->nt ); 03667 if( nim->ndim > 4 ) sprintf( buf+strlen(buf), " nu = '%d'\n", nim->nu ); 03668 if( nim->ndim > 5 ) sprintf( buf+strlen(buf), " nv = '%d'\n", nim->nv ); 03669 if( nim->ndim > 6 ) sprintf( buf+strlen(buf), " nw = '%d'\n", nim->nw ); 03670 sprintf( buf+strlen(buf), " dx = '%g'\n", nim->dx ); 03671 if( nim->ndim > 1 ) sprintf( buf+strlen(buf), " dy = '%g'\n", nim->dy ); 03672 if( nim->ndim > 2 ) sprintf( buf+strlen(buf), " dz = '%g'\n", nim->dz ); 03673 if( nim->ndim > 3 ) sprintf( buf+strlen(buf), " dt = '%g'\n", nim->dt ); 03674 if( nim->ndim > 4 ) sprintf( buf+strlen(buf), " du = '%g'\n", nim->du ); 03675 if( nim->ndim > 5 ) sprintf( buf+strlen(buf), " dv = '%g'\n", nim->dv ); 03676 if( nim->ndim > 6 ) sprintf( buf+strlen(buf), " dw = '%g'\n", nim->dw ); 03677 03678 sprintf( buf+strlen(buf) , " datatype = '%d'\n" , nim->datatype ) ; 03679 sprintf( buf+strlen(buf) , " datatype_name = '%s'\n" , 03680 nifti_datatype_string(nim->datatype) ) ; 03681 03682 sprintf( buf+strlen(buf) , " nvox = '%d'\n" , nim->nvox ) ; 03683 sprintf( buf+strlen(buf) , " nbyper = '%d'\n" , nim->nbyper ) ; 03684 03685 sprintf( buf+strlen(buf) , " byteorder = '%s'\n" , 03686 (nim->byteorder==MSB_FIRST) ? "MSB_FIRST" : "LSB_FIRST" ) ; 03687 03688 if( nim->cal_min < nim->cal_max ){ 03689 sprintf( buf+strlen(buf) , " cal_min = '%g'\n", nim->cal_min ) ; 03690 sprintf( buf+strlen(buf) , " cal_max = '%g'\n", nim->cal_max ) ; 03691 } 03692 03693 if( nim->scl_slope != 0.0 ){ 03694 sprintf( buf+strlen(buf) , " scl_slope = '%g'\n" , nim->scl_slope ) ; 03695 sprintf( buf+strlen(buf) , " scl_inter = '%g'\n" , nim->scl_inter ) ; 03696 } 03697 03698 if( nim->intent_code > 0 ){ 03699 sprintf( buf+strlen(buf) , " intent_code = '%d'\n", nim->intent_code ) ; 03700 sprintf( buf+strlen(buf) , " intent_code_name = '%s'\n" , 03701 nifti_intent_string(nim->intent_code) ) ; 03702 sprintf( buf+strlen(buf) , " intent_p1 = '%g'\n" , nim->intent_p1 ) ; 03703 sprintf( buf+strlen(buf) , " intent_p2 = '%g'\n" , nim->intent_p2 ) ; 03704 sprintf( buf+strlen(buf) , " intent_p3 = '%g'\n" , nim->intent_p3 ) ; 03705 03706 if( nim->intent_name[0] != '\0' ){ 03707 ebuf = escapize_string(nim->intent_name) ; 03708 sprintf( buf+strlen(buf) , " intent_name = %s\n",ebuf) ; 03709 free(ebuf) ; 03710 } 03711 } 03712 03713 if( nim->toffset != 0.0 ) 03714 sprintf( buf+strlen(buf) , " toffset = '%g'\n",nim->toffset ) ; 03715 03716 if( nim->xyz_units > 0 ) 03717 sprintf( buf+strlen(buf) , 03718 " xyz_units = '%d'\n" 03719 " xyz_units_name = '%s'\n" , 03720 nim->xyz_units , nifti_units_string(nim->xyz_units) ) ; 03721 03722 if( nim->time_units > 0 ) 03723 sprintf( buf+strlen(buf) , 03724 " time_units = '%d'\n" 03725 " time_units_name = '%s'\n" , 03726 nim->time_units , nifti_units_string(nim->time_units) ) ; 03727 03728 if( nim->freq_dim > 0 ) 03729 sprintf( buf+strlen(buf) , " freq_dim = '%d'\n",nim->freq_dim ) ; 03730 if( nim->phase_dim > 0 ) 03731 sprintf( buf+strlen(buf) , " phase_dim = '%d'\n",nim->phase_dim ) ; 03732 if( nim->slice_dim > 0 ) 03733 sprintf( buf+strlen(buf) , " slice_dim = '%d'\n",nim->slice_dim ) ; 03734 if( nim->slice_code > 0 ) 03735 sprintf( buf+strlen(buf) , 03736 " slice_code = '%d'\n" 03737 " slice_code_name = '%s'\n" , 03738 nim->slice_code , nifti_slice_string(nim->slice_code) ) ; 03739 if( nim->slice_start >= 0 && nim->slice_end > nim->slice_start ) 03740 sprintf( buf+strlen(buf) , 03741 " slice_start = '%d'\n" 03742 " slice_end = '%d'\n" , nim->slice_start , nim->slice_end ) ; 03743 if( nim->slice_duration != 0.0 ) 03744 sprintf( buf+strlen(buf) , " slice_duration = '%g'\n", 03745 nim->slice_duration ) ; 03746 03747 if( nim->descrip[0] != '\0' ){ 03748 ebuf = escapize_string(nim->descrip) ; 03749 sprintf( buf+strlen(buf) , " descrip = %s\n",ebuf) ; 03750 free(ebuf) ; 03751 } 03752 03753 if( nim->aux_file[0] != '\0' ){ 03754 ebuf = escapize_string(nim->aux_file) ; 03755 sprintf( buf+strlen(buf) , " aux_file = %s\n",ebuf) ; 03756 free(ebuf) ; 03757 } 03758 03759 if( nim->qform_code > 0 ){ 03760 int i,j,k ; 03761 03762 sprintf( buf+strlen(buf) , 03763 " qform_code = '%d'\n" 03764 " qform_code_name = '%s'\n" 03765 " qto_xyz_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" , 03766 nim->qform_code , nifti_xform_string(nim->qform_code) , 03767 nim->qto_xyz.m[0][0] , nim->qto_xyz.m[0][1] , 03768 nim->qto_xyz.m[0][2] , nim->qto_xyz.m[0][3] , 03769 nim->qto_xyz.m[1][0] , nim->qto_xyz.m[1][1] , 03770 nim->qto_xyz.m[1][2] , nim->qto_xyz.m[1][3] , 03771 nim->qto_xyz.m[2][0] , nim->qto_xyz.m[2][1] , 03772 nim->qto_xyz.m[2][2] , nim->qto_xyz.m[2][3] , 03773 nim->qto_xyz.m[3][0] , nim->qto_xyz.m[3][1] , 03774 nim->qto_xyz.m[3][2] , nim->qto_xyz.m[3][3] ) ; 03775 03776 sprintf( buf+strlen(buf) , 03777 " qto_ijk_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" , 03778 nim->qto_ijk.m[0][0] , nim->qto_ijk.m[0][1] , 03779 nim->qto_ijk.m[0][2] , nim->qto_ijk.m[0][3] , 03780 nim->qto_ijk.m[1][0] , nim->qto_ijk.m[1][1] , 03781 nim->qto_ijk.m[1][2] , nim->qto_ijk.m[1][3] , 03782 nim->qto_ijk.m[2][0] , nim->qto_ijk.m[2][1] , 03783 nim->qto_ijk.m[2][2] , nim->qto_ijk.m[2][3] , 03784 nim->qto_ijk.m[3][0] , nim->qto_ijk.m[3][1] , 03785 nim->qto_ijk.m[3][2] , nim->qto_ijk.m[3][3] ) ; 03786 03787 sprintf( buf+strlen(buf) , 03788 " quatern_b = '%g'\n" 03789 " quatern_c = '%g'\n" 03790 " quatern_d = '%g'\n" 03791 " qoffset_x = '%g'\n" 03792 " qoffset_y = '%g'\n" 03793 " qoffset_z = '%g'\n" 03794 " qfac = '%g'\n" , 03795 nim->quatern_b , nim->quatern_c , nim->quatern_d , 03796 nim->qoffset_x , nim->qoffset_y , nim->qoffset_z , nim->qfac ) ; 03797 03798 mat44_to_orientation( nim->qto_xyz , &i,&j,&k ) ; 03799 if( i > 0 && j > 0 && k > 0 ) 03800 sprintf( buf+strlen(buf) , 03801 " qform_i_orientation = '%s'\n" 03802 " qform_j_orientation = '%s'\n" 03803 " qform_k_orientation = '%s'\n" , 03804 nifti_orientation_string(i) , 03805 nifti_orientation_string(j) , 03806 nifti_orientation_string(k) ) ; 03807 } 03808 03809 if( nim->sform_code > 0 ){ 03810 int i,j,k ; 03811 03812 sprintf( buf+strlen(buf) , 03813 " sform_code = '%d'\n" 03814 " sform_code_name = '%s'\n" 03815 " sto_xyz_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" , 03816 nim->sform_code , nifti_xform_string(nim->sform_code) , 03817 nim->sto_xyz.m[0][0] , nim->sto_xyz.m[0][1] , 03818 nim->sto_xyz.m[0][2] , nim->sto_xyz.m[0][3] , 03819 nim->sto_xyz.m[1][0] , nim->sto_xyz.m[1][1] , 03820 nim->sto_xyz.m[1][2] , nim->sto_xyz.m[1][3] , 03821 nim->sto_xyz.m[2][0] , nim->sto_xyz.m[2][1] , 03822 nim->sto_xyz.m[2][2] , nim->sto_xyz.m[2][3] , 03823 nim->sto_xyz.m[3][0] , nim->sto_xyz.m[3][1] , 03824 nim->sto_xyz.m[3][2] , nim->sto_xyz.m[3][3] ) ; 03825 03826 sprintf( buf+strlen(buf) , 03827 " sto_ijk matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" , 03828 nim->sto_ijk.m[0][0] , nim->sto_ijk.m[0][1] , 03829 nim->sto_ijk.m[0][2] , nim->sto_ijk.m[0][3] , 03830 nim->sto_ijk.m[1][0] , nim->sto_ijk.m[1][1] , 03831 nim->sto_ijk.m[1][2] , nim->sto_ijk.m[1][3] , 03832 nim->sto_ijk.m[2][0] , nim->sto_ijk.m[2][1] , 03833 nim->sto_ijk.m[2][2] , nim->sto_ijk.m[2][3] , 03834 nim->sto_ijk.m[3][0] , nim->sto_ijk.m[3][1] , 03835 nim->sto_ijk.m[3][2] , nim->sto_ijk.m[3][3] ) ; 03836 03837 mat44_to_orientation( nim->sto_xyz , &i,&j,&k ) ; 03838 if( i > 0 && j > 0 && k > 0 ) 03839 sprintf( buf+strlen(buf) , 03840 " sform_i_orientation = '%s'\n" 03841 " sform_j_orientation = '%s'\n" 03842 " sform_k_orientation = '%s'\n" , 03843 nifti_orientation_string(i) , 03844 nifti_orientation_string(j) , 03845 nifti_orientation_string(k) ) ; 03846 } 03847 03848 sprintf( buf+strlen(buf) , " num_ext = '%d'\n", nim->num_ext ) ; 03849 03850 sprintf( buf+strlen(buf) , "/>\n" ) ; /* XML-ish closer */ 03851 03852 nbuf = strlen(buf) ; 03853 buf = (char *)realloc((void *)buf, nbuf+1); /* cut back to proper length */ 03854 return buf ; 03855 } 03856 03857 /*---------------------------------------------------------------------------*/ 03858 03859 int short_order(void) /* determine this CPU's byte order */ 03860 { 03861 union { unsigned char bb[2] ; 03862 short ss ; } fred ; 03863 03864 fred.bb[0] = 1 ; fred.bb[1] = 0 ; 03865 03866 return (fred.ss == 1) ? LSB_FIRST : MSB_FIRST ; 03867 } 03868 03869 /*---------------------------------------------------------------------------*/ 03870 03871 #undef QQNUM 03872 #undef QNUM 03873 #undef QSTR 03874 03875 /* macro to check lhs string against "n1"; if it matches, 03876 interpret rhs string as a number, and put it into nim->"n2" */ 03877 03878 #define QQNUM(n1,n2) if( strcmp(lhs,#n1)==0 ) nim->n2=strtod(rhs,NULL) 03879 03880 /* same, but where "n1" == "n2" */ 03881 03882 #define QNUM(nam) QQNUM(nam,nam) 03883 03884 /* macro to check lhs string against "nam"; if it matches, 03885 put rhs string into nim->"nam" string, with max length = "ml" */ 03886 03887 #define QSTR(nam,ml) if( strcmp(lhs,#nam) == 0 ) \ 03888 strncpy(nim->nam,rhs,ml), nim->intent_name[ml]='\0' 03889 03890 /*---------------------------------------------------------------------------*/ 03891 /* Take an XML-ish ASCII string and create a NIFTI image header to match. 03892 NULL is returned if enough information isn't present in the input string. 03893 - The image data can later be loaded with nifti_image_load(). 03894 - The struct returned here can be liberated with nifti_image_free(). 03895 - Not a lot of error checking is done here to make sure that the 03896 input values are reasonable! 03897 -----------------------------------------------------------------------------*/ 03898 03899 nifti_image *nifti_image_from_ascii( char *str, int * bytes_read ) 03900 { 03901 char lhs[1024] , rhs[1024] ; 03902 int ii , spos, nn , slen ; 03903 nifti_image *nim ; /* will be output */ 03904 03905 if( str == NULL || *str == '\0' ) return NULL ; /* bad input!? */ 03906 03907 /* scan for opening string */ 03908 03909 spos = 0 ; slen = strlen(str) ; 03910 ii = sscanf( str+spos , "%1023s%n" , lhs , &nn ) ; spos += nn ; 03911 if( ii == 0 || strcmp(lhs,"<nifti_image") != 0 ) return NULL ; 03912 03913 /* create empty image struct */ 03914 03915 nim = (nifti_image *) calloc( 1 , sizeof(nifti_image) ) ; 03916 03917 nim->nx = nim->ny = nim->nz = nim->nt 03918 = nim->nu = nim->nv = nim->nw = 1 ; 03919 nim->dx = nim->dy = nim->dz = nim->dt 03920 = nim->du = nim->dv = nim->dw = nim->qfac = 1.0 ; 03921 03922 nim->byteorder = short_order() ; 03923 03924 /* starting at str[spos], scan for "equations" of the form 03925 lhs = 'rhs' 03926 and assign rhs values into the struct component named by lhs */ 03927 03928 while(1){ 03929 03930 while( isspace(str[spos]) ) spos++ ; /* skip whitespace */ 03931 if( str[spos] == '\0' ) break ; /* end of string? */ 03932 03933 /* get lhs string */ 03934 03935 ii = sscanf( str+spos , "%1023s%n" , lhs , &nn ) ; spos += nn ; 03936 if( ii == 0 || strcmp(lhs,"/>") == 0 ) break ; /* end of input? */ 03937 03938 /* skip whitespace and the '=' marker */ 03939 03940 while( isspace(str[spos]) || str[spos] == '=' ) spos++ ; 03941 if( str[spos] == '\0' ) break ; /* end of string? */ 03942 03943 /* if next character is a quote ', copy everything up to next ' 03944 otherwise, copy everything up to next nonblank */ 03945 03946 if( str[spos] == '\'' ){ 03947 ii = spos+1 ; 03948 while( str[ii] != '\0' && str[ii] != '\'' ) ii++ ; 03949 nn = ii-spos-1 ; if( nn > 1023 ) nn = 1023 ; 03950 memcpy(rhs,str+spos+1,nn) ; rhs[nn] = '\0' ; 03951 spos = (str[ii] == '\'') ? ii+1 : ii ; 03952 } else { 03953 ii = sscanf( str+spos , "%1023s%n" , rhs , &nn ) ; spos += nn ; 03954 if( ii == 0 ) break ; /* nothing found? */ 03955 } 03956 unescape_string(rhs) ; /* remove any XML escape sequences */ 03957 03958 /* Now can do the assignment, based on lhs string. 03959 Start with special cases that don't fit the QNUM/QSTR macros. */ 03960 03961 if( strcmp(lhs,"nifti_type") == 0 ){ 03962 if( strcmp(rhs,"ANALYZE-7.5") == 0 ) nim->nifti_type = 0 ; 03963 else if( strcmp(rhs,"NIFTI-1+") == 0 ) nim->nifti_type = 1 ; 03964 else if( strcmp(rhs,"NIFTI-1") == 0 ) nim->nifti_type = 2 ; 03965 else if( strcmp(rhs,"NIFTI-1A") == 0 ) nim->nifti_type = 3 ; 03966 } 03967 else if( strcmp(lhs,"header_filename") == 0 ){ 03968 nim->fname = nifti_strdup(rhs) ; 03969 } 03970 else if( strcmp(lhs,"image_filename") == 0 ){ 03971 nim->iname = nifti_strdup(rhs) ; 03972 } 03973 else if( strcmp(lhs,"sto_xyz_matrix") == 0 ){ 03974 sscanf( rhs , "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f" , 03975 &(nim->sto_xyz.m[0][0]) , &(nim->sto_xyz.m[0][1]) , 03976 &(nim->sto_xyz.m[0][2]) , &(nim->sto_xyz.m[0][3]) , 03977 &(nim->sto_xyz.m[1][0]) , &(nim->sto_xyz.m[1][1]) , 03978 &(nim->sto_xyz.m[1][2]) , &(nim->sto_xyz.m[1][3]) , 03979 &(nim->sto_xyz.m[2][0]) , &(nim->sto_xyz.m[2][1]) , 03980 &(nim->sto_xyz.m[2][2]) , &(nim->sto_xyz.m[2][3]) , 03981 &(nim->sto_xyz.m[3][0]) , &(nim->sto_xyz.m[3][1]) , 03982 &(nim->sto_xyz.m[3][2]) , &(nim->sto_xyz.m[3][3]) ) ; 03983 } 03984 else if( strcmp(lhs,"byteorder") == 0 ){ 03985 if( strcmp(rhs,"MSB_FIRST") == 0 ) nim->byteorder = MSB_FIRST ; 03986 if( strcmp(rhs,"LSB_FIRST") == 0 ) nim->byteorder = LSB_FIRST ; 03987 } 03988 else QQNUM(image_offset,iname_offset) ; 03989 else QNUM(datatype) ; 03990 else QNUM(ndim) ; 03991 else QNUM(nx) ; 03992 else QNUM(ny) ; 03993 else QNUM(nz) ; 03994 else QNUM(nt) ; 03995 else QNUM(nu) ; 03996 else QNUM(nv) ; 03997 else QNUM(nw) ; 03998 else QNUM(dx) ; 03999 else QNUM(dy) ; 04000 else QNUM(dz) ; 04001 else QNUM(dt) ; 04002 else QNUM(du) ; 04003 else QNUM(dv) ; 04004 else QNUM(dw) ; 04005 else QNUM(cal_min) ; 04006 else QNUM(cal_max) ; 04007 else QNUM(scl_slope) ; 04008 else QNUM(scl_inter) ; 04009 else QNUM(intent_code) ; 04010 else QNUM(intent_p1) ; 04011 else QNUM(intent_p2) ; 04012 else QNUM(intent_p3) ; 04013 else QSTR(intent_name,15) ; 04014 else QNUM(toffset) ; 04015 else QNUM(xyz_units) ; 04016 else QNUM(time_units) ; 04017 else QSTR(descrip,79) ; 04018 else QSTR(aux_file,23) ; 04019 else QNUM(qform_code) ; 04020 else QNUM(quatern_b) ; 04021 else QNUM(quatern_c) ; 04022 else QNUM(quatern_d) ; 04023 else QNUM(qoffset_x) ; 04024 else QNUM(qoffset_y) ; 04025 else QNUM(qoffset_z) ; 04026 else QNUM(qfac) ; 04027 else QNUM(sform_code) ; 04028 else QNUM(freq_dim) ; 04029 else QNUM(phase_dim) ; 04030 else QNUM(slice_dim) ; 04031 else QNUM(slice_code) ; 04032 else QNUM(slice_start) ; 04033 else QNUM(slice_end) ; 04034 else QNUM(slice_duration) ; 04035 else QNUM(num_ext) ; 04036 04037 } /* end of while loop */ 04038 04039 if( bytes_read ) *bytes_read = spos+1; /* "process" last '\n' */ 04040 04041 /** do miscellaneous checking and cleanup **/ 04042 04043 if( nim->ndim <= 0 ){ nifti_image_free(nim); return NULL; } /** bad! **/ 04044 04045 nifti_datatype_sizes( nim->datatype, &(nim->nbyper), &(nim->swapsize) ); 04046 if( nim->nbyper == 0 ){ nifti_image_free(nim); return NULL; } /** bad! **/ 04047 04048 nim->dim[0] = nim->ndim ; 04049 nim->dim[1] = nim->nx ; nim->pixdim[1] = nim->dx ; 04050 nim->dim[2] = nim->ny ; nim->pixdim[2] = nim->dy ; 04051 nim->dim[3] = nim->nz ; nim->pixdim[3] = nim->dz ; 04052 nim->dim[4] = nim->nt ; nim->pixdim[4] = nim->dt ; 04053 nim->dim[5] = nim->nu ; nim->pixdim[5] = nim->du ; 04054 nim->dim[6] = nim->nv ; nim->pixdim[6] = nim->dv ; 04055 nim->dim[7] = nim->nw ; nim->pixdim[7] = nim->dw ; 04056 04057 nim->nvox = nim->nx * nim->ny * nim->nz 04058 * nim->nt * nim->nu * nim->nv * nim->nw ; 04059 04060 if( nim->qform_code > 0 ) 04061 nim->qto_xyz = quatern_to_mat44( 04062 nim->quatern_b, nim->quatern_c, nim->quatern_d, 04063 nim->qoffset_x, nim->qoffset_y, nim->qoffset_z, 04064 nim->dx , nim->dy , nim->dz , 04065 nim->qfac ) ; 04066 else 04067 nim->qto_xyz = quatern_to_mat44( 04068 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 04069 nim->dx , nim->dy , nim->dz , 0.0 ) ; 04070 04071 04072 nim->qto_ijk = mat44_inverse( nim->qto_xyz ) ; 04073 04074 if( nim->sform_code > 0 ) 04075 nim->sto_ijk = mat44_inverse( nim->sto_xyz ) ; 04076 04077 return nim ; 04078 }