void getNiftiImageOrientation(nifti_1_header hdr, char *orientation)
{
   orientation[0]='\0';

   if(hdr.qform_code == 0 && hdr.sform_code == 0) 
   {
      printf("\nWarning: Could not determine image orientation ...\n");
      printf("\nWarning: \"NIFTI\" header does not contain orientation information.\n");
      return;
   }

   if(hdr.qform_code > 0 )
   {
      mat44 R;

      R = nifti_quatern_to_mat44(hdr.quatern_b, hdr.quatern_c, hdr.quatern_d, hdr.qoffset_x, hdr.qoffset_y, 
      hdr.qoffset_z, hdr.pixdim[1], hdr.pixdim[2], hdr.pixdim[3], hdr.pixdim[0]);

      orientation[0] = directionCode(R.m[0][0],R.m[1][0],R.m[2][0]);
      orientation[1] = directionCode(R.m[0][1],R.m[1][1],R.m[2][1]);
      orientation[2] = directionCode(R.m[0][2],R.m[1][2],R.m[2][2]);
      orientation[3] = '\0';
   }
   else
   {
      orientation[0] = directionCode(hdr.srow_x[0],hdr.srow_y[0],hdr.srow_z[0]);
      orientation[1] = directionCode(hdr.srow_x[1],hdr.srow_y[1],hdr.srow_z[1]);
      orientation[2] = directionCode(hdr.srow_x[2],hdr.srow_y[2],hdr.srow_z[2]);
      orientation[3] = '\0';
   }

   return;
}
Exemple #2
0
unsigned char *  nii_setOrtho(unsigned char* img, struct nifti_1_header *h) {
    if ((h->dim[1] < 1) || (h->dim[2] < 1) || (h->dim[3] < 1)) return img;
    if ((h->sform_code == NIFTI_XFORM_UNKNOWN) && (h->qform_code != NIFTI_XFORM_UNKNOWN)) { //only q-form provided
        mat44 q = nifti_quatern_to_mat44(h->quatern_b, h->quatern_c, h->quatern_d,
                                         h->qoffset_x, h->qoffset_y, h->qoffset_z,
                                         h->pixdim[1], h->pixdim[2], h->pixdim[3],h->pixdim[0]);
        mat2sForm(h,q); //convert q-form to s-form
        h->sform_code = h->qform_code;
    }
    if (h->sform_code == NIFTI_XFORM_UNKNOWN) {
         #ifdef MY_DEBUG
         printf("No Q or S spatial transforms - assuming canonical orientation");
         #endif
         return img;
    }
    mat44 s = sFormMat(h);
    if (isMat44Canonical( s)) {
        #ifdef MY_DEBUG
        printf("Image in perfect alignment: no need to reorient");
        #endif
        return img;
    }
    vec3i  flipV;
    vec3 minMM = minCornerFlip(h, &flipV);
    mat33 orient = getBestOrient(s, flipV);
    vec3i orientVec = setOrientVec(orient);
    if ((orientVec.v[0]==1) && (orientVec.v[1]==2) && (orientVec.v[2]==3) ) {
        #ifdef MY_DEBUG
        printf("Image already near best orthogonal alignment: no need to reorient\n");
        #endif
        return img;
    }
    bool is24 = false;
    if (h->bitpix == 24 ) { //RGB stored as planar data. treat as 3 8-bit slices
        return img;
        is24 = true;
        h->bitpix = 8;
        h->dim[3] = h->dim[3] * 3;
    }
    img = reOrient(img, h,orientVec, orient, minMM);
    if (is24 ) {
        h->bitpix = 24;
        h->dim[3] = h->dim[3] / 3;
    }
    #ifdef MY_DEBUG
    printf("NewRotation= %d %d %d\n", orientVec.v[0],orientVec.v[1],orientVec.v[2]);
    printf("MinCorner= %.2f %.2f %.2f\n", minMM.v[0],minMM.v[1],minMM.v[2]);
    reportMat44o("input",s);
    s = sFormMat(h);
    reportMat44o("output",s);
    #endif
    return img;
}
Exemple #3
0
/* *************************************************************** */
nifti_image *reg_io_nrdd2nifti(Nrrd *nrrdImage)
{
    // Check if the file can be converted
    if(nrrdImage->dim>7){
        fprintf(stderr, "[NiftyReg ERROR] reg_io_nrdd2nifti - The Nifti format only support 7 dimensions\n");
        exit(1);
    }

    // Need first to extract the input image dimension
    int dim[8]={1,1,1,1,1,1,1,1};
    dim[0]=nrrdImage->dim;

    int vectorIncrement=0;
    if(nrrdImage->axis[0].kind==nrrdKindVector)
        vectorIncrement=1;

    for(int i=0;i<(dim[0]<7?dim[0]:7);++i)
        dim[i+1]=(int)nrrdImage->axis[i+vectorIncrement].size;

    if(vectorIncrement==1){
        dim[0]=5;
        dim[4]=1;
        dim[5]=nrrdImage->axis[0].size;
    }

    // The nifti_image pointer is created
    nifti_image *niiImage=NULL;

    // The nifti image is generated based on the nrrd image datatype
    switch(nrrdImage->type){
    case nrrdTypeUChar:
        niiImage=nifti_make_new_nim(dim,NIFTI_TYPE_UINT8,true);
        break;
    case nrrdTypeChar:
        niiImage=nifti_make_new_nim(dim,NIFTI_TYPE_INT8,true);
        break;
    case nrrdTypeUShort:
        niiImage=nifti_make_new_nim(dim,NIFTI_TYPE_UINT16,true);
        break;
    case nrrdTypeShort:
        niiImage=nifti_make_new_nim(dim,NIFTI_TYPE_INT16,true);
        break;
    case nrrdTypeUInt:
        niiImage=nifti_make_new_nim(dim,NIFTI_TYPE_UINT32,true);
        break;
    case nrrdTypeInt:
        niiImage=nifti_make_new_nim(dim,NIFTI_TYPE_INT32,true);
        break;
    case nrrdTypeFloat:
        niiImage=nifti_make_new_nim(dim,NIFTI_TYPE_FLOAT32,true);
        break;
    case nrrdTypeDouble:
        niiImage=nifti_make_new_nim(dim,NIFTI_TYPE_FLOAT64,true);
        break;
    default:
        fprintf(stderr, "[NiftyReg ERROR] reg_io_nrdd2nifti - The data type is not supported\n");
        exit(1);
    }

    // The data are copied over from the nrrd to the nifti structure
    memcpy(niiImage->data, nrrdImage->data, niiImage->nvox*niiImage->nbyper);

    // We set the spacing information for every axis
    double spaceDir[NRRD_SPACE_DIM_MAX], spacing;
    for(int i=0;i<7;++i){
        nrrdSpacingCalculate(nrrdImage,i+vectorIncrement,&spacing,spaceDir);
        if(spacing==spacing)
            niiImage->pixdim[i+1]=(float)spacing;
        else niiImage->pixdim[i+1]=1.0f;
    }
    niiImage->dx=niiImage->pixdim[1];
    niiImage->dy=niiImage->pixdim[2];
    niiImage->dz=niiImage->pixdim[3];
    niiImage->dt=niiImage->pixdim[4];
    niiImage->du=niiImage->pixdim[5];
    niiImage->dv=niiImage->pixdim[6];
    niiImage->dw=niiImage->pixdim[7];

    // Set the slope and intersection
    niiImage->scl_inter=0;
    niiImage->scl_slope=1;

    // Set the min and max intensities
    niiImage->cal_min=reg_tools_getMinValue(niiImage);
    niiImage->cal_max=reg_tools_getMaxValue(niiImage);

    // The space orientation is extracted and converted into a matrix
    mat44 qform_orientation_matrix;
    reg_mat44_eye(&qform_orientation_matrix);
    if(nrrdImage->space==nrrdSpaceRightAnteriorSuperior ||
       nrrdImage->space==nrrdSpaceRightAnteriorSuperiorTime ||
       nrrdImage->space==nrrdSpace3DRightHanded ||
       nrrdImage->space==nrrdSpace3DRightHandedTime ){
        qform_orientation_matrix.m[0][0]=1.f; // NIFTI_L2R
        qform_orientation_matrix.m[1][1]=1.f; // NIFTI_P2A
        qform_orientation_matrix.m[2][2]=1.f; // NIFTI_I2S
        niiImage->qform_code=1;
    }
    else if(nrrdImage->space==nrrdSpaceLeftAnteriorSuperior ||
            nrrdImage->space==nrrdSpaceLeftAnteriorSuperiorTime ||
            nrrdImage->space==nrrdSpace3DLeftHanded ||
            nrrdImage->space==nrrdSpace3DLeftHandedTime ){
        qform_orientation_matrix.m[0][0]=-1.f;  //NIFTI_R2L
        qform_orientation_matrix.m[1][1]=1.f; // NIFTI_P2A
        qform_orientation_matrix.m[2][2]=1.f; // NIFTI_I2S
        niiImage->qform_code=1;
    }
    else if(nrrdImage->space!=nrrdSpaceScannerXYZ &&
            nrrdImage->space!=nrrdSpaceScannerXYZTime ){
        niiImage->qform_code=0;
        fprintf(stderr, "[NiftyReg WARNING] reg_io_nrdd2nifti - nrrd space value unrecognised: the Nifti qform is set to identity\n");
    }
    if(niiImage->qform_code>0){
        // The origin is set
        // Note that x and y origin are negated to fit with ITK conversion
        if(niiImage->ndim>=1)
            qform_orientation_matrix.m[0][3]=niiImage->qoffset_x=-nrrdImage->spaceOrigin[0];
        if(niiImage->ndim>=2)
            qform_orientation_matrix.m[1][3]=niiImage->qoffset_y=-nrrdImage->spaceOrigin[1];
        if(niiImage->ndim>=3)
            qform_orientation_matrix.m[2][3]=niiImage->qoffset_z=nrrdImage->spaceOrigin[2];

        // Flipp the orientation to fit ITK's filters
        qform_orientation_matrix.m[0][0] *= -1.0f;
        qform_orientation_matrix.m[1][1] *= -1.0f;

        // Extract the quaternions and qfac values
        nifti_mat44_to_quatern(qform_orientation_matrix,
                               &niiImage->quatern_b,
                               &niiImage->quatern_c,
                               &niiImage->quatern_d,
                               &niiImage->qoffset_x,
                               &niiImage->qoffset_y,
                               &niiImage->qoffset_z,
                               &niiImage->dx,
                               &niiImage->dy,
                               &niiImage->dz,
                               &niiImage->qfac);

        // Set the qform matrices
        niiImage->qto_xyz=nifti_quatern_to_mat44(niiImage->quatern_b,
                                                 niiImage->quatern_c,
                                                 niiImage->quatern_d,
                                                 niiImage->qoffset_x,
                                                 niiImage->qoffset_y,
                                                 niiImage->qoffset_z,
                                                 niiImage->dx,
                                                 niiImage->dy,
                                                 niiImage->dz,
                                                 niiImage->qfac);
    }
    else{
        // diagonal matrix is assumed
        niiImage->qto_xyz=qform_orientation_matrix;
        niiImage->qto_xyz.m[0][0]=niiImage->dx;
        niiImage->qto_xyz.m[1][1]=niiImage->dy;
        if(niiImage->ndim>2)
            niiImage->qto_xyz.m[2][2]=niiImage->dz;
    }
    niiImage->qto_ijk=nifti_mat44_inverse(niiImage->qto_xyz);

    // The sform has to be set if required
    // Check if the spaceDirection array is set
    // The check is performed in the dim in case you are dealing with a vector
    if(nrrdImage->axis[1].spaceDirection[0]!=std::numeric_limits<double>::quiet_NaN()){
        niiImage->sform_code=1;
        reg_mat44_eye(&niiImage->sto_xyz);
        for(int i=0;i<(niiImage->ndim<3?niiImage->ndim:3);++i){
            for(int j=0;j<(niiImage->ndim<3?niiImage->ndim:3);++j){
                niiImage->sto_xyz.m[i][j]=(float)nrrdImage->axis[i+vectorIncrement].spaceDirection[j];
            }
            niiImage->sto_xyz.m[i][3]=(float)nrrdImage->spaceOrigin[i];
        }
        // The matrix is flipped to go from nrrd to nifti
        // and follow the ITK style
        for(unsigned int i=0;i<2;++i)
            for(unsigned int j=0;j<4;++j)
                niiImage->sto_xyz.m[i][j]*=-1.0f;
        niiImage->sto_ijk=nifti_mat44_inverse(niiImage->sto_xyz);
    }

    // Set the space unit if it is defined
    if(nrrdImage->spaceUnits[1]!=NULL){
        if(strcmp(nrrdImage->spaceUnits[1],"m")==0)
            niiImage->xyz_units=NIFTI_UNITS_METER;
        else if(strcmp(nrrdImage->spaceUnits[1],"mm")==0)
            niiImage->xyz_units=NIFTI_UNITS_MM;
        else if(strcmp(nrrdImage->spaceUnits[1],"um")==0)
            niiImage->xyz_units=NIFTI_UNITS_MICRON;
    }

    // Set the time unit if it is defined
    if(nrrdImage->axis[3].size>1){
        if(nrrdImage->spaceUnits[4]!=NULL){
            if(strcmp(nrrdImage->spaceUnits[4],"sec"))
                niiImage->time_units=NIFTI_UNITS_SEC;
            else if(strcmp(nrrdImage->spaceUnits[4],"msec"))
                niiImage->time_units=NIFTI_UNITS_MSEC;
        }
    }

    // Check if the nrrd image was a NiftyReg velocity field parametrisation
    if(vectorIncrement == 1){

        // The intensity array has to be reoriented
        switch(niiImage->datatype){
        case NIFTI_TYPE_FLOAT32:
            reg_convertVectorField_nrrd_to_nifti<float>(nrrdImage,niiImage);
            break;
        case NIFTI_TYPE_FLOAT64:
            reg_convertVectorField_nrrd_to_nifti<double>(nrrdImage,niiImage);
            break;
        default:
            fprintf(stderr, "[NiftyReg ERROR] - reg_convertVectorField_nrrd_to_nifti - unsupported datatype\n");
            exit(1);
        }
        // The orientation flag are re-organised
        niiImage->ndim=5;
        niiImage->dim[4]=niiImage->nt=1;
        niiImage->dim[5]=niiImage->nu=nrrdImage->axis[0].size;

        niiImage->intent_code=NIFTI_INTENT_VECTOR;

        // Check if the image is a stationary field from NiftyReg
        if(nrrdImage->axis[0].label!=NULL){
            std::string str=nrrdImage->axis[0].label;
            size_t it;
            if((it=str.find("NREG_VEL_STEP "))!=std::string::npos){
                str=str.substr(it+13);
                memset(niiImage->intent_name, 0, 16);
                strcpy(niiImage->intent_name,"NREG_VEL_STEP");
                niiImage->intent_p1=atof(str.c_str());
            }
            if(str.find("NREG_CPP_FILE")!=std::string::npos){
                memset(niiImage->intent_name, 0, 16);
                strcpy(niiImage->intent_name,"NREG_CPP_FILE");
            }
        }
    }

    // returns the new nii image
    return niiImage;
}
void getNiftiImageOrientation(const char *filename, char *orientation)
{
   FILE *fp;
   nifti_1_header hdr;
   int swapflg=0;

   orientation[0]='\0';

   // ensure that the specified image has either a .hdr or a .nii extension
   if( !checkNiftiFileExtension(filename) )
   {
      errorMessage("The image filename must have a `.hdr' or `.nii' extension.");
   }

   fp = fopen(filename,"r");

   if(fp==NULL)
   {
      file_open_error(filename);
   }

   if( fread(&hdr, sizeof(nifti_1_header), 1, fp) != 1 )
   {
      errorMessage("I have trouble reading the specified image file.");
   }

   fclose(fp);

   // looks like ANALYZE 7.5, cannot determine orientation
   if( hdr.magic[0]!='n' ||  (hdr.magic[1]!='+' && hdr.magic[1]!='i') ||  hdr.magic[2]!='1')
   {
      printf("\nWarning: Could not determine %s image orientation ...\n",filename);
      return;
   }

   // if dim[0] is outside range 1..7, then the header information
   // needs to be byte swapped appropriately
   if(hdr.dim[0]<1 || hdr.dim[0]>7) 
   {
      swapflg=1;
   }

   // Here I am only byte swapping the header fields relevant for determining the image orientation
   if(swapflg)
   {
      swapByteOrder( (char *)&(hdr.qform_code), sizeof(short));
      swapByteOrder( (char *)&(hdr.sform_code), sizeof(short));
      swapByteOrder( (char *)&(hdr.quatern_b), sizeof(float));
      swapByteOrder( (char *)&(hdr.quatern_c), sizeof(float));
      swapByteOrder( (char *)&(hdr.quatern_d), sizeof(float));
      swapByteOrder( (char *)&(hdr.qoffset_x), sizeof(float));
      swapByteOrder( (char *)&(hdr.qoffset_y), sizeof(float));
      swapByteOrder( (char *)&(hdr.qoffset_z), sizeof(float));
      for(int i=0; i<4; i++)
      {
         swapByteOrder( (char *)&(hdr.srow_x[i]), sizeof(float));
         swapByteOrder( (char *)&(hdr.srow_y[i]), sizeof(float));
         swapByteOrder( (char *)&(hdr.srow_z[i]), sizeof(float));
      }
   }

   if(hdr.qform_code == 0 && hdr.sform_code == 0) 
   {
      printf("\nWarning: Could not determine %s image orientation ...\n",filename);
      printf("\nWarning: The header of this \"NIFTI\" file does not contain orientation information.\n");
      return;
   }

   if(hdr.qform_code > 0 )
   {
      mat44 R;

      R = nifti_quatern_to_mat44(hdr.quatern_b, hdr.quatern_c, hdr.quatern_d, hdr.qoffset_x, hdr.qoffset_y, 
      hdr.qoffset_z, hdr.pixdim[1], hdr.pixdim[2], hdr.pixdim[3], hdr.pixdim[0]);

      orientation[0] = directionCode(R.m[0][0],R.m[1][0],R.m[2][0]);
      orientation[1] = directionCode(R.m[0][1],R.m[1][1],R.m[2][1]);
      orientation[2] = directionCode(R.m[0][2],R.m[1][2],R.m[2][2]);
      orientation[3] = '\0';
   }
   else
   {
      orientation[0] = directionCode(hdr.srow_x[0],hdr.srow_y[0],hdr.srow_z[0]);
      orientation[1] = directionCode(hdr.srow_x[1],hdr.srow_y[1],hdr.srow_z[1]);
      orientation[2] = directionCode(hdr.srow_x[2],hdr.srow_y[2],hdr.srow_z[2]);
      orientation[3] = '\0';
   }

   return;
}
Exemple #5
0
// returns the orientations vectors xvec, yvec, and zvec in NIFTI's RAS system
void readOrientationVectorsFromFile(const char *filename, float *xvec, float *yvec, float *zvec)
{
   FILE *fp;
   nifti_1_header hdr;
   int swapflg=0;

   // ensure that the specified image has either a .hdr or a .nii extension
   if( !checkNiftiFileExtension(filename) )
   {
      errorMessage("Error: The image filename must have a `.hdr' or `.nii' extension.");
   }

   fp = fopen(filename,"r");

   if(fp==NULL)
   {
      errorMessage("Error: I have trouble opening the specified image file.");
   }

   if( fread(&hdr, sizeof(nifti_1_header), 1, fp) != 1 )
   {
      errorMessage("Error: I have trouble reading the specified image file.");
   }

   fclose(fp);

   // looks like ANALYZE 7.5, cannot determine orientation
   if( hdr.magic[0]!='n' ||  (hdr.magic[1]!='+' && hdr.magic[1]!='i') ||  hdr.magic[2]!='1')
   {
      return;
   }

   // if dim[0] is outside range 1..7, then the header information
   // needs to be byte swapped appropriately
   if(hdr.dim[0]<1 || hdr.dim[0]>7) 
   {
      swapflg=1;
   }

   // Here I am only byte swapping the header fields relevant for determining the image orientation
   if(swapflg)
   {
      swapByteOrder( (char *)&(hdr.qform_code), sizeof(short));
      swapByteOrder( (char *)&(hdr.sform_code), sizeof(short));

      swapByteOrder( (char *)&(hdr.quatern_b), sizeof(float));
      swapByteOrder( (char *)&(hdr.quatern_c), sizeof(float));
      swapByteOrder( (char *)&(hdr.quatern_d), sizeof(float));
      swapByteOrder( (char *)&(hdr.qoffset_x), sizeof(float));
      swapByteOrder( (char *)&(hdr.qoffset_y), sizeof(float));
      swapByteOrder( (char *)&(hdr.qoffset_z), sizeof(float));

      for(int i=0; i<4; i++)
      {
         swapByteOrder( (char *)&(hdr.srow_x[i]), sizeof(float));
         swapByteOrder( (char *)&(hdr.srow_y[i]), sizeof(float));
         swapByteOrder( (char *)&(hdr.srow_z[i]), sizeof(float));
      }
   }

   if(hdr.qform_code == 0 && hdr.sform_code == 0) 
   {
      printf("\nThe header of this so called \"NIFTI\" file does not contain orientation information.\n");
      return;
   }

   if(hdr.qform_code > 0 )
   {
      mat44 R;

      R = nifti_quatern_to_mat44(hdr.quatern_b, hdr.quatern_c, hdr.quatern_d, hdr.qoffset_x, hdr.qoffset_y, 
      hdr.qoffset_z, hdr.pixdim[1], hdr.pixdim[2], hdr.pixdim[3], hdr.pixdim[0]);

      xvec[0] = R.m[0][0];
      xvec[1] = R.m[1][0];
      xvec[2] = R.m[2][0];

      yvec[0] = R.m[0][1];
      yvec[1] = R.m[1][1];
      yvec[2] = R.m[2][1];

      zvec[0] = R.m[0][2];
      zvec[1] = R.m[1][2];
      zvec[2] = R.m[2][2];
   }
   else
   {
      xvec[0] = hdr.srow_x[0];
      xvec[1] = hdr.srow_y[0];
      xvec[2] = hdr.srow_z[0];

      yvec[0] = hdr.srow_x[1];
      yvec[1] = hdr.srow_y[1];
      yvec[2] = hdr.srow_z[1];

      zvec[0] = hdr.srow_x[2];
      zvec[1] = hdr.srow_y[2];
      zvec[2] = hdr.srow_z[2];
   }

   normalizeVector(xvec, 3);
   normalizeVector(yvec, 3);
   normalizeVector(zvec, 3);

   return;
}