nifti1_io.c
来自「DTMK软件开发包,此为开源软件,是一款很好的医学图像开发资源.」· C语言 代码 · 共 1,582 行 · 第 1/5 页
C
1,582 行
/*! global nifti options structure */
static nifti_global_options g_opts = { 1, 0 };
/*! global nifti types structure list (per type, ordered oldest to newest) */
static nifti_type_ele nifti_type_list[] = {
/* type nbyper swapsize name */
{ 0, 0, 0, "DT_UNKNOWN" },
{ 0, 0, 0, "DT_NONE" },
{ 1, 0, 0, "DT_BINARY" }, /* not usable */
{ 2, 1, 0, "DT_UNSIGNED_CHAR" },
{ 2, 1, 0, "DT_UINT8" },
{ 2, 1, 0, "NIFTI_TYPE_UINT8" },
{ 4, 2, 2, "DT_SIGNED_SHORT" },
{ 4, 2, 2, "DT_INT16" },
{ 4, 2, 2, "NIFTI_TYPE_INT16" },
{ 8, 4, 4, "DT_SIGNED_INT" },
{ 8, 4, 4, "DT_INT32" },
{ 8, 4, 4, "NIFTI_TYPE_INT32" },
{ 16, 4, 4, "DT_FLOAT" },
{ 16, 4, 4, "DT_FLOAT32" },
{ 16, 4, 4, "NIFTI_TYPE_FLOAT32" },
{ 32, 8, 4, "DT_COMPLEX" },
{ 32, 8, 4, "DT_COMPLEX64" },
{ 32, 8, 4, "NIFTI_TYPE_COMPLEX64" },
{ 64, 8, 8, "DT_DOUBLE" },
{ 64, 8, 8, "DT_FLOAT64" },
{ 64, 8, 8, "NIFTI_TYPE_FLOAT64" },
{ 128, 3, 0, "DT_RGB" },
{ 128, 3, 0, "DT_RGB24" },
{ 128, 3, 0, "NIFTI_TYPE_RGB24" },
{ 255, 0, 0, "DT_ALL" },
{ 256, 1, 0, "DT_INT8" },
{ 256, 1, 0, "NIFTI_TYPE_INT8" },
{ 512, 2, 2, "DT_UINT16" },
{ 512, 2, 2, "NIFTI_TYPE_UINT16" },
{ 768, 4, 4, "DT_UINT32" },
{ 768, 4, 4, "NIFTI_TYPE_UINT32" },
{ 1024, 8, 8, "DT_INT64" },
{ 1024, 8, 8, "NIFTI_TYPE_INT64" },
{ 1280, 8, 8, "DT_UINT64" },
{ 1280, 8, 8, "NIFTI_TYPE_UINT64" },
{ 1536, 16, 16, "DT_FLOAT128" },
{ 1536, 16, 16, "NIFTI_TYPE_FLOAT128" },
{ 1792, 16, 8, "DT_COMPLEX128" },
{ 1792, 16, 8, "NIFTI_TYPE_COMPLEX128" },
{ 2048, 32, 16, "DT_COMPLEX256" },
{ 2048, 32, 16, "NIFTI_TYPE_COMPLEX256" },
{ 2304, 4, 0, "DT_RGBA32" },
{ 2304, 4, 0, "NIFTI_TYPE_RGBA32" },
};
/*---------------------------------------------------------------------------*/
/* prototypes for internal functions - not part of exported library */
/* extension routines */
static int nifti_read_extensions( nifti_image *nim, znzFile fp, int remain );
static int nifti_read_next_extension( nifti1_extension * nex, nifti_image *nim, int remain, znzFile fp );
static int nifti_check_extension(nifti_image *nim, int size,int code, int rem);
static void update_nifti_image_for_brick_list(nifti_image * nim , int nbricks);
static int nifti_add_exten_to_list(nifti1_extension * new_ext,
nifti1_extension ** list, int new_length);
static int nifti_fill_extension(nifti1_extension * ext, const char * data,
int len, int ecode);
/* NBL routines */
static int nifti_load_NBL_bricks(nifti_image * nim , int * slist, int * sindex, nifti_brick_list * NBL, znzFile fp );
static int nifti_alloc_NBL_mem( nifti_image * nim, int nbricks,
nifti_brick_list * nbl);
static int nifti_copynsort(int nbricks, const int *blist, int **slist,
int **sindex);
/* for nifti_read_collapsed_image: */
static int rci_read_data(nifti_image *nim, int *pivots, int *prods, int nprods,
const int dims[], char *data, znzFile fp, size_t base_offset);
static int rci_alloc_mem(void ** data, int prods[8], int nprods, int nbyper );
static int make_pivot_list(nifti_image * nim, const int dims[], int pivots[],
int prods[], int * nprods );
/* misc */
static int need_nhdr_swap (short dim0, int hdrsize);
static int print_hex_vals (const char * data, int nbytes, FILE * fp);
static int unescape_string (char *str); /* string utility functions */
static char *escapize_string (const char *str);
/* internal I/O routines */
static znzFile nifti_image_load_prep( nifti_image *nim );
static int has_ascii_header(znzFile fp);
/*---------------------------------------------------------------------------*/
/* for calling from some main program */
/*----------------------------------------------------------------------*/
/*! display the nifti library module history (via stdout)
*//*--------------------------------------------------------------------*/
void nifti_disp_lib_hist( void )
{
int c, len = sizeof(gni_history)/sizeof(char *);
for( c = 0; c < len; c++ )
fputs(gni_history[c], stdout);
}
/*----------------------------------------------------------------------*/
/*! display the nifti library version (via stdout)
*//*--------------------------------------------------------------------*/
void nifti_disp_lib_version( void )
{
printf("%s, compiled %s\n", gni_version, __DATE__);
}
/*----------------------------------------------------------------------*/
/*! nifti_image_read_bricks - read nifti data as array of bricks
*
* 13 Dec 2004 [rickr]
*
* \param hname - filename of dataset to read (must be valid)
* \param nbricks - number of sub-bricks to read
* (if blist is valid, nbricks must be > 0)
* \param blist - list of sub-bricks to read
* (can be NULL; if NULL, read complete dataset)
* \param NBL - pointer to empty nifti_brick_list struct
* (must be a valid pointer)
*
* \return
* <br> nim - same as nifti_image_read, but nim->data will be NULL
* <br> NBL - filled with data
*
* By default, this function will read the nifti dataset and break the data
* into a list of nt*nu*nv*nw sub-bricks, each having size nx*ny*nz elements.
* That is to say, instead of reading the entire dataset as a single array,
* break it up into sub-bricks, each of size nx*ny*nz elements.
*
* If 'blist' is valid, it is taken to be a list of sub-bricks, of length
* 'nbricks'. The data will still be separated into sub-bricks of size
* nx*ny*nz elements, but now 'nbricks' sub-bricks will be returned, of the
* caller's choosing via 'blist'.
*
* E.g. consider a dataset with 12 sub-bricks (numbered 0..11), and the
* following code:
*
* <pre>
* { nifti_brick_list NB_orig, NB_select;
* nifti_image * nim_orig, * nim_select;
* int blist[5] = { 7, 0, 5, 5, 9 };
*
* nim_orig = nifti_image_read_bricks("myfile.nii", 0, NULL, &NB_orig);
* nim_select = nifti_image_read_bricks("myfile.nii", 5, blist, &NB_select);
* }
* </pre>
*
* Here, nim_orig gets the entire dataset, where NB_orig.nbricks = 11. But
* nim_select has NB_select.nbricks = 5.
*
* Note that the first case is not quite the same as just calling the
* nifti_image_read function, as here the data is separated into sub-bricks.
*
* Note that valid blist elements are in [0..nt*nu*nv*nw-1],
* or written [ 0 .. (dim[4]*dim[5]*dim[6]*dim[7] - 1) ].
*
* Note that, as is the case with all of the reading functions, the
* data will be allocated, read in, and properly byte-swapped, if
* necessary.
*
* \sa nifti_image_load_bricks, nifti_free_NBL, valid_nifti_brick_list,
nifti_image_read
*//*----------------------------------------------------------------------*/
nifti_image *nifti_image_read_bricks(const char * hname, int nbricks,
const int * blist, nifti_brick_list * NBL)
{
nifti_image * nim;
if( !hname || !NBL ){
fprintf(stderr,"** nifti_image_read_bricks: bad params (%p,%p)\n",
hname, (void *)NBL);
return NULL;
}
if( blist && nbricks <= 0 ){
fprintf(stderr,"** nifti_image_read_bricks: bad nbricks, %d\n", nbricks);
return NULL;
}
nim = nifti_image_read(hname, 0); /* read header, but not data */
if( !nim ) return NULL; /* errors were already printed */
/* if we fail, free image and return */
if( nifti_image_load_bricks(nim, nbricks, blist, NBL) <= 0 ){
nifti_image_free(nim);
return NULL;
}
if( blist ) update_nifti_image_for_brick_list(nim, nbricks);
return nim;
}
/*----------------------------------------------------------------------
* update_nifti_image_for_brick_list - update nifti_image
*
* When loading a specific brick list, the distinction between
* nt, nu, nv and nw is lost. So put everything in t, and set
* dim[0] = 4.
*----------------------------------------------------------------------*/
static void update_nifti_image_for_brick_list( nifti_image * nim , int nbricks )
{
int ndim;
if( g_opts.debug > 2 ){
fprintf(stderr,"+d updating image dimensions for %d bricks in list\n",
nbricks);
fprintf(stderr," ndim = %d\n",nim->ndim);
fprintf(stderr," nx,ny,nz,nt,nu,nv,nw: (%d,%d,%d,%d,%d,%d,%d)\n",
nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw);
}
nim->nt = nbricks;
nim->nu = nim->nv = nim->nw = 1;
nim->dim[4] = nbricks;
nim->dim[5] = nim->dim[6] = nim->dim[7] = 1;
/* compute nvox */
/* do not rely on dimensions above dim[0] 16 Nov 2005 [rickr] */
for( nim->nvox = 1, ndim = 1; ndim <= nim->dim[0]; ndim++ )
nim->nvox *= nim->dim[ndim];
/* update the dimensions to 4 or lower */
for( ndim = 4; (ndim > 1) && (nim->dim[ndim] <= 1); ndim-- )
;
if( g_opts.debug > 2 ){
fprintf(stderr,"+d ndim = %d -> %d\n",nim->ndim, ndim);
fprintf(stderr," --> (%d,%d,%d,%d,%d,%d,%d)\n",
nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw);
}
nim->dim[0] = nim->ndim = ndim;
}
/*----------------------------------------------------------------------*/
/*! nifti_update_dims_from_array - update nx, ny, ... from nim->dim[]
Fix all the dimension information, based on a new nim->dim[].
Note: we assume that dim[0] will not increase.
Check for updates to pixdim[], dx,..., nx,..., nvox, ndim, dim[0].
*//*--------------------------------------------------------------------*/
int nifti_update_dims_from_array( nifti_image * nim )
{
int c, ndim;
if( !nim ){
fprintf(stderr,"** update_dims: missing nim\n");
return 1;
}
if( g_opts.debug > 2 ){
fprintf(stderr,"+d updating image dimensions given nim->dim:");
for( c = 0; c < 8; c++ ) fprintf(stderr," %d", nim->dim[c]);
fputc('\n',stderr);
}
/* verify dim[0] first */
if(nim->dim[0] < 1 || nim->dim[0] > 7){
fprintf(stderr,"** invalid dim[0], dim[] = ");
for( c = 0; c < 8; c++ ) fprintf(stderr," %d", nim->dim[c]);
fputc('\n',stderr);
return 1;
}
/* set nx, ny ..., dx, dy, ..., one by one */
/* less than 1, set to 1, else copy */
if(nim->dim[1] < 1) nim->nx = nim->dim[1] = 1;
else nim->nx = nim->dim[1];
nim->dx = nim->pixdim[1];
/* if undefined, or less than 1, set to 1 */
if(nim->dim[0] < 2 || (nim->dim[0] >= 2 && nim->dim[2] < 1))
nim->ny = nim->dim[2] = 1;
else
nim->ny = nim->dim[2];
/* copy delta values, in any case */
nim->dy = nim->pixdim[2];
if(nim->dim[0] < 3 || (nim->dim[0] >= 3 && nim->dim[3] < 1))
nim->nz = nim->dim[3] = 1;
else /* just copy vals from arrays */
nim->nz = nim->dim[3];
nim->dz = nim->pixdim[3];
if(nim->dim[0] < 4 || (nim->dim[0] >= 4 && nim->dim[4] < 1))
nim->nt = nim->dim[4] = 1;
else /* just copy vals from arrays */
nim->nt = nim->dim[4];
nim->dt = nim->pixdim[4];
if(nim->dim[0] < 5 || (nim->dim[0] >= 5 && nim->dim[5] < 1))
nim->nu = nim->dim[5] = 1;
else /* just copy vals from arrays */
nim->nu = nim->dim[5];
nim->du = nim->pixdim[5];
if(nim->dim[0] < 6 || (nim->dim[0] >= 6 && nim->dim[6] < 1))
nim->nv = nim->dim[6] = 1;
else /* just copy vals from arrays */
nim->nv = nim->dim[6];
nim->dv = nim->pixdim[6];
if(nim->dim[0] < 7 || (nim->dim[0] >= 7 && nim->dim[7] < 1))
nim->nw = nim->dim[7] = 1;
else /* just copy vals from arrays */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?