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 + -
显示快捷键?