/* ******** nrrdAlloc_va() ** ** Handy wrapper around nrrdAlloc_nva, which takes, as its vararg list, ** all the axes sizes. */ int nrrdAlloc_va(Nrrd *nrrd, int type, unsigned int dim, ...) { char me[]="nrrdAlloc_va", err[BIFF_STRLEN]; size_t size[NRRD_DIM_MAX]; unsigned int ai; va_list ap; if (!nrrd) { sprintf(err, "%s: got NULL pointer", me); biffAdd(NRRD, err); return 1; } va_start(ap, dim); for (ai=0; ai<dim; ai++) { size[ai] = va_arg(ap, size_t); } va_end(ap); if (nrrdAlloc_nva(nrrd, type, dim, size)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); return 1; } return 0; }
/* ******** nrrdMaybeAlloc_nva ** ** calls nrrdAlloc_nva if the requested space is different than ** what is currently held ** ** also subscribes to the "don't mess with peripheral information" philosophy */ int nrrdMaybeAlloc_nva(Nrrd *nrrd, int type, unsigned int dim, const size_t *size) { char me[]="nrrdMaybeAlloc_nva", err[BIFF_STRLEN]; size_t sizeWant, sizeHave, numWant, elementSizeWant; int need; unsigned int ai; if (!nrrd) { sprintf(err, "%s: got NULL pointer", me); biffAdd(NRRD, err); return 1; } if (airEnumValCheck(nrrdType, type)) { sprintf(err, "%s: type (%d) is invalid", me, type); biffAdd(NRRD, err); return 1; } if (nrrdTypeBlock == type) { if (nrrdTypeBlock == nrrd->type) { sprintf(err, "%s: can't change from one block nrrd to another", me); biffAdd(NRRD, err); return 1; } if (!(0 < nrrd->blockSize)) { sprintf(err, "%s: given nrrd->blockSize " _AIR_SIZE_T_CNV " invalid", me, nrrd->blockSize); biffAdd(NRRD, err); return 1; } elementSizeWant = nrrd->blockSize; } else { elementSizeWant = nrrdTypeSize[type]; } if (_nrrdSizeCheck(size, dim, AIR_TRUE)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); return 1; } if (!(nrrd->data)) { need = 1; } else { numWant = 1; for (ai=0; ai<dim; ai++) { numWant *= size[ai]; } if (!nrrdElementSize(nrrd)) { sprintf(err, "%s: nrrd reports zero element size!", me); biffAdd(NRRD, err); return 1; } sizeHave = nrrdElementNumber(nrrd) * nrrdElementSize(nrrd); /* fprintf(stderr, "##%s: sizeHave = %d * %d = %d\n", me, (int)(nrrdElementNumber(nrrd)), (int)(nrrdElementSize(nrrd)), (int)sizeHave); */ sizeWant = numWant * elementSizeWant; /* fprintf(stderr, "##%s: sizeWant = %d * %d = %d\n", me, (int)(numWant), (int)(elementSizeWant), (int)sizeWant); */ need = sizeHave != sizeWant; /* fprintf(stderr, "##%s: need = %d\n", me, need); */ } if (need) { if (nrrdAlloc_nva(nrrd, type, dim, size)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); return 1; } } else { if (nrrdWrap_nva(nrrd, nrrd->data, type, dim, size)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); return 1; } /* but we do have to initialize memory! */ memset(nrrd->data, 0, nrrdElementNumber(nrrd)*nrrdElementSize(nrrd)); } return 0; }
/* *************************************************************** */ Nrrd *reg_io_nifti2nrrd(nifti_image *niiImage) { // Create a nrrd image Nrrd *nrrdImage = nrrdNew(); // Set the nrrd image size size_t size[NRRD_DIM_MAX]; for(int i=1;i<=niiImage->ndim;++i) size[i-1]=niiImage->dim[i]; // Allocate the nrrd data array based on the nii image data type switch(niiImage->datatype){ case NIFTI_TYPE_UINT8: nrrdAlloc_nva(nrrdImage,nrrdTypeUChar,niiImage->ndim,size); break; case NIFTI_TYPE_INT8: nrrdAlloc_nva(nrrdImage,nrrdTypeChar,niiImage->ndim,size); break; case NIFTI_TYPE_UINT16: nrrdAlloc_nva(nrrdImage,nrrdTypeUShort,niiImage->ndim,size); break; case NIFTI_TYPE_INT16: nrrdAlloc_nva(nrrdImage,nrrdTypeShort,niiImage->ndim,size); break; case NIFTI_TYPE_UINT32: nrrdAlloc_nva(nrrdImage,nrrdTypeUInt,niiImage->ndim,size); break; case NIFTI_TYPE_INT32: nrrdAlloc_nva(nrrdImage,nrrdTypeInt,niiImage->ndim,size); break; case NIFTI_TYPE_FLOAT32: nrrdAlloc_nva(nrrdImage,nrrdTypeFloat,niiImage->ndim,size); break; case NIFTI_TYPE_FLOAT64: nrrdAlloc_nva(nrrdImage,nrrdTypeDouble,niiImage->ndim,size); break; default: fprintf(stderr, "[NiftyReg ERROR] reg_io_nifti2nrrd - The data type is not supported\n"); exit(1); } // Rescale the nii image intensity if required if(niiImage->scl_slope!=1 && niiImage->scl_slope!=0){ reg_tools_addSubMulDivValue(niiImage, niiImage,niiImage->scl_slope,2); // *(niiImage->scl_slope) niiImage->scl_slope=1; } if(niiImage->scl_inter!=0){ reg_tools_addSubMulDivValue(niiImage, niiImage,niiImage->scl_inter,0); // +(niiImage->scl_inter) niiImage->scl_inter=0; } // Set the space if suitable with the nrrd file format if(niiImage->qform_code>0 || niiImage->sform_code>0){ // Set the space dim variable nrrdImage->spaceDim=niiImage->ndim<3?niiImage->ndim:3; // Create a matrix to store the relevant information mat44 currentAffineMatrix; // Use the sform information if it is defined if(niiImage->sform_code>0) currentAffineMatrix=niiImage->sto_xyz; // Use the qform orientation otherwise else currentAffineMatrix=niiImage->qto_xyz; if(niiImage->ndim>2){ /** @todo need to investigate what ITK is doing with the SPACE as all images seems to be LPS */ // // The space orientation is extracted // int i_orient, j_orient, k_orient; // nifti_mat44_to_orientation(currentAffineMatrix,&i_orient,&j_orient,&k_orient); // if(i_orient==NIFTI_L2R && j_orient==NIFTI_P2A && k_orient==NIFTI_I2S){ // if(niiImage->nt>1) // nrrdImage->space=nrrdSpaceRightAnteriorSuperiorTime; // else nrrdImage->space=nrrdSpaceRightAnteriorSuperior; // } // else if(i_orient==NIFTI_R2L && j_orient==NIFTI_P2A && k_orient==NIFTI_I2S){ // if(niiImage->nt>1) // nrrdImage->space=nrrdSpaceLeftAnteriorSuperiorTime; // else nrrdImage->space=nrrdSpaceLeftAnteriorSuperior; // } // else if(i_orient==NIFTI_R2L && j_orient==NIFTI_A2P && k_orient==NIFTI_I2S){ // if(niiImage->nt>1) // nrrdImage->space=nrrdSpaceLeftPosteriorSuperiorTime; // else nrrdImage->space=nrrdSpaceLeftPosteriorSuperior; // } // else{ // nrrdImage->space=nrrdSpaceUnknown; // fprintf(stderr, "[NiftyReg WARNING] reg_io_nifti2nrrd - The nifti qform information can be stored in the space variable.\n"); // fprintf(stderr, "[NiftyReg WARNING] reg_io_nifti2nrrd - The space direction will be used.\n"); // } nrrdImage->space=nrrdSpaceUnknown; } // The matrix is flipped to go from nifti to nrrd // and follow the ITK style for(unsigned int i=0;i<2;++i) for(unsigned int j=0;j<4;++j) currentAffineMatrix.m[i][j]*=-1.0f; // the space direction is initialised to identity nrrdImage->axis[0].spaceDirection[0]=1; nrrdImage->axis[0].spaceDirection[1]=0; nrrdImage->axis[0].spaceDirection[2]=0; nrrdImage->axis[1].spaceDirection[0]=0; nrrdImage->axis[1].spaceDirection[1]=1; nrrdImage->axis[1].spaceDirection[2]=0; nrrdImage->axis[2].spaceDirection[0]=0; nrrdImage->axis[2].spaceDirection[1]=0; nrrdImage->axis[2].spaceDirection[2]=1; for(int i=0;i<(niiImage->ndim<3?niiImage->ndim:3);++i) for(int j=0;j<(niiImage->ndim<3?niiImage->ndim:3);++j) nrrdImage->axis[i].spaceDirection[j]=currentAffineMatrix.m[i][j]; // Set the origin of the image nrrdImage->spaceOrigin[0]=currentAffineMatrix.m[0][3]; nrrdImage->spaceOrigin[1]=currentAffineMatrix.m[1][3]; if(niiImage->ndim>2) nrrdImage->spaceOrigin[2]=currentAffineMatrix.m[2][3]; } else{ for(int i=0;i<niiImage->ndim;i++){ // Set the spacing values if qform and sform are not defined nrrdImage->axis[i].spacing=niiImage->pixdim[i+1]; // As well as the origin to zero nrrdImage->spaceOrigin[i]=0; } } // Set the units if they are defined for(int i=0; i<NRRD_SPACE_DIM_MAX; i++){ airFree(nrrdImage->spaceUnits[i]); nrrdImage->spaceUnits[i] = NULL; } switch(niiImage->xyz_units){ case NIFTI_UNITS_METER: for(int i=0;i<(niiImage->ndim<3?niiImage->ndim:3);++i){ nrrdImage->spaceUnits[i]=(char *)malloc(200); sprintf(nrrdImage->spaceUnits[i],"m"); nrrdImage->axis[i].kind=nrrdKindDomain; } break; case NIFTI_UNITS_MM: for(int i=0;i<(niiImage->ndim<3?niiImage->ndim:3);++i){ nrrdImage->spaceUnits[i]=(char *)malloc(200); sprintf(nrrdImage->spaceUnits[i],"mm"); nrrdImage->axis[i].kind=nrrdKindDomain; } break; case NIFTI_UNITS_MICRON: for(int i=0;i<(niiImage->ndim<3?niiImage->ndim:3);++i){ nrrdImage->spaceUnits[i]=(char *)malloc(200); sprintf(nrrdImage->spaceUnits[i],"um"); nrrdImage->axis[i].kind=nrrdKindDomain; } break; } // Set the time unit if it is defined if(niiImage->ndim>3){ switch(niiImage->time_units){ case NIFTI_UNITS_SEC: nrrdImage->spaceUnits[4]=(char *)"sec"; nrrdImage->axis[4].kind=nrrdKindTime; break; case NIFTI_UNITS_MSEC: nrrdImage->spaceUnits[4]=(char *)"msec"; nrrdImage->axis[4].kind=nrrdKindTime; break; } } // Check if the image is a vector field if(niiImage->intent_code==NIFTI_INTENT_VECTOR){ // The intensity array has to be reoriented switch(niiImage->datatype){ case NIFTI_TYPE_FLOAT32: reg_convertVectorField_nifti_to_nrrd<float>(niiImage,nrrdImage); break; case NIFTI_TYPE_FLOAT64: reg_convertVectorField_nifti_to_nrrd<double>(niiImage,nrrdImage); break; default: fprintf(stderr, "[NiftyReg ERROR] - reg_convertVectorField_nifti_to_nrrd - unsupported datatype\n"); exit(1); } // The orientation flag are re-organised for(int i=niiImage->nu;i>0;--i){ for(int j=0;j<niiImage->nu;++j){ nrrdImage->axis[i].spaceDirection[j]=nrrdImage->axis[i-1].spaceDirection[j]; } nrrdImage->axis[i].size=nrrdImage->axis[i-1].size; nrrdImage->axis[i].spacing=nrrdImage->axis[i-1].spacing; nrrdImage->axis[i].kind=nrrdKindDomain; nrrdImage->spaceUnits[i]=nrrdImage->spaceUnits[i-1]; } nrrdImage->axis[0].size=niiImage->nu; nrrdImage->axis[0].spaceDirection[0]=std::numeric_limits<double>::quiet_NaN(); nrrdImage->axis[0].spaceDirection[1]=std::numeric_limits<double>::quiet_NaN(); nrrdImage->axis[0].spaceDirection[2]=std::numeric_limits<double>::quiet_NaN(); nrrdImage->axis[0].kind=nrrdKindVector; nrrdImage->spaceUnits[0]=NULL; nrrdImage->dim=niiImage->nu+1; // Check if the image is a stationary field from NiftyReg if(strcmp(niiImage->intent_name,"NREG_VEL_STEP")==0){ // The number of step is store in the nrrdImage->axis[0].label pointer char temp[64]; sprintf(temp,"NREG_VEL_STEP %f",niiImage->intent_p1); std::string str=temp; if(nrrdImage->axis[0].label!=NULL) free(nrrdImage->axis[0].label); nrrdImage->axis[0].label=(char *)malloc(str.length()*sizeof(char)); strcpy(nrrdImage->axis[0].label,str.c_str()); } else if(strcmp(niiImage->intent_name,"NREG_CPP_FILE")==0){ std::string str="NREG_CPP_FILE"; if(nrrdImage->axis[0].label!=NULL) free(nrrdImage->axis[0].label); nrrdImage->axis[0].label=(char *)malloc(str.length()*sizeof(char)); strcpy(nrrdImage->axis[0].label, str.c_str()); } } else{ // Copy the data from the nifti image to the nrrd image memcpy(nrrdImage->data, niiImage->data, niiImage->nvox*niiImage->nbyper); } return nrrdImage; }