예제 #1
0
/*------------------------------------------------------*/
MRI *afniRead(const char *fname, int read_volume)
{

  FILE *fp;
  char header_fname[STRLEN];
  char *c;
  MRI *mri, *header;
  int big_endian_flag;
  long brik_file_length;
  long nvoxels;
  int bytes_per_voxel;
  int i, j, k;
  int swap_flag;
  AF af;
  float scaling = 1.;
  void *pmem = 0;
  float *pf;
  short *ps;
  unsigned char *pc;

  float det;
  float xfov, yfov, zfov;
  float fMin = 0.;
  float fMax = 0.;
  float flMin = 0.;
  float flMax = 0.;
  int initialized = 0;
  int frame;
  int bytes;

  strcpy(header_fname, fname);
  c = strrchr(header_fname, '.');

  if (c == NULL)
  {
    errno = 0;
    ErrorReturn(NULL, (ERROR_BADPARM, "afniRead(): bad file name %s", fname));
  }

  if (strcmp(c, ".BRIK") != 0)
  {
    errno = 0;
    ErrorReturn(NULL, (ERROR_BADPARM, "afniRead(): bad file name %s", fname));
  }

  sprintf(c, ".HEAD");

  if ((fp = fopen(header_fname, "r")) == NULL)
  {
    errno = 0;
    ErrorReturn(NULL, (ERROR_BADFILE, "afniRead(): error opening file %s", header_fname));
  }

  // initialize AFNI structure
  AFinit(&af);

  // read header file
  if (!readAFNIHeader(fp, &af))
    return (NULL);

  printAFNIHeader(&af);

  // well, we don't have time
  if (af.numtypes != 1) // should be the same as af.dataset_rank[1] = subbricks
  {
    errno = 0;
    // ErrorReturn(NULL, (ERROR_UNSUPPORTED, "afniRead(): nframes = %d (only 1 frame supported)", af.numtypes));
    printf("INFO: number of frames dataset_rank[1] = %d : numtypes = %d \n",
           af.dataset_rank[1], af.numtypes);
  }
  // byteorder_string : required field
  if (strcmp(af.byteorder_string, "MSB_FIRST") == 0)
    big_endian_flag = 1;
  else if (strcmp(af.byteorder_string, "LSB_FIRST") == 0)
    big_endian_flag = 0;
  else
  {
    errno = 0;
    ErrorReturn(NULL, (ERROR_BADPARM, "read_afni_header(): unrecognized byte order string %s",
                       af.byteorder_string));
  }
  // brick_types : required field
  if (af.brick_types[0] == 2 // int
      || af.brick_types[0] > 3 )// 4 = double, 5 = complex, 6 = rgb
  {
    errno = 0;
    ErrorReturn(NULL,
                (ERROR_BADPARM,
                 "afniRead(): unsupported data type %d, Must be 0 (byte), 1(short), or 3(float)",
                 af.brick_types[0]));
  }
  //////////////////////////////////////////////////////////////////////////////////
  // now we allocate space for MRI
  // dataset_dimensions : required field
  header = MRIallocHeader(af.dataset_dimensions[0],
                          af.dataset_dimensions[1],
                          af.dataset_dimensions[2],
                          MRI_UCHAR,
                          af.dataset_rank[1]
                          );
  // set number of frames
  header->nframes = af.dataset_rank[1];

  // direction cosines (use orient_specific)
  // orient_specific : required field
  header->x_r = afni_orientations[af.orient_specific[0]][0];
  header->x_a = afni_orientations[af.orient_specific[0]][1];
  header->x_s = afni_orientations[af.orient_specific[0]][2];
  header->y_r = afni_orientations[af.orient_specific[1]][0];
  header->y_a = afni_orientations[af.orient_specific[1]][1];
  header->y_s = afni_orientations[af.orient_specific[1]][2];
  header->z_r = afni_orientations[af.orient_specific[2]][0];
  header->z_a = afni_orientations[af.orient_specific[2]][1];
  header->z_s = afni_orientations[af.orient_specific[2]][2];

  /* --- quick determinant check --- */
  det = + header->x_r * (header->y_a * header->z_s - header->z_a * header->y_s)
        - header->x_a * (header->y_r * header->z_s - header->z_r * header->y_s)
        + header->x_s * (header->y_r * header->z_a - header->z_r * header->y_a);

  if (det == 0)
  {
    MRIfree(&header);
    errno = 0;
    ErrorReturn(NULL,
                (ERROR_BADPARM,
                 "read_afni_header(): error in orientations %d, %d, %d (direction cosine matrix has determinant zero)",
                 af.orient_specific[0], af.orient_specific[1], af.orient_specific[2]));
  }
  // sizes use delta
  // delta : required field
  header->xsize = af.delta[0];
  header->ysize = af.delta[1];
  header->zsize = af.delta[2];

  // uses origin
  // origin : required field
  header->c_r = header->x_r * (header->xsize * (header->width-1.0)/2.0 + af.origin[0]) +
                header->y_r * (header->ysize * (header->height-1.0)/2.0 + af.origin[1]) +
                header->z_r * (header->zsize * (header->depth-1.0)/2.0 + af.origin[2]);

  header->c_a = header->x_a * (header->xsize * (header->width-1.0)/2.0 + af.origin[0]) +
                header->y_a * (header->ysize * (header->height-1.0)/2.0 + af.origin[1]) +
                header->z_a * (header->zsize * (header->depth-1.0)/2.0 + af.origin[2]);

  header->c_s = header->x_s * (header->xsize * (header->width-1.0)/2.0 + af.origin[0]) +
                header->y_s * (header->ysize * (header->height-1.0)/2.0 + af.origin[1]) +
                header->z_s * (header->zsize * (header->depth-1.0)/2.0 + af.origin[2]);

  header->ras_good_flag = 1;

  if (header->xsize < 0)
    header->xsize = -header->xsize;

  if (header->ysize < 0)
    header->ysize = -header->ysize;

  if (header->zsize < 0)
    header->zsize = -header->zsize;

  header->imnr0 = 1;
  header->imnr1 = header->depth;

  header->ps = header->xsize;
  header->thick = header->zsize;

  header->xend = (header->width  / 2.0) * header->xsize;
  header->xstart = -header->xend;
  header->yend = (header->height / 2.0) * header->ysize;
  header->ystart = -header->yend;
  header->zend = (header->depth  / 2.0) * header->zsize;
  header->zstart = -header->zend;

  xfov = header->xend - header->xstart;
  yfov = header->yend - header->ystart;
  zfov = header->zend - header->zstart;

  header->fov = ( xfov > yfov ? (xfov > zfov ? xfov : zfov ) : (yfov > zfov ? yfov : zfov ) );

#if (BYTE_ORDER==LITTLE_ENDIAN)
  //#ifdef Linux
  swap_flag = big_endian_flag;
#else
  swap_flag = !big_endian_flag;
#endif

  if ((fp = fopen(fname, "r")) == NULL)
  {
    MRIfree(&header);
    errno = 0;
    ErrorReturn(NULL, (ERROR_BADFILE, "afniRead(): error opening file %s", header_fname));
  }

  fseek(fp, 0, SEEK_END);
  brik_file_length = ftell(fp);
  fseek(fp, 0, SEEK_SET);

  // number of voxels consecutive

  nvoxels = header->width * header->height * header->depth * header->nframes;

  if (brik_file_length % nvoxels)
  {
    fclose(fp);
    MRIfree(&header);
    errno = 0;
    ErrorReturn(NULL, (ERROR_BADFILE, "afniRead(): BRIK file length (%d) is not divisible by the number of voxels (%d)", brik_file_length, nvoxels));
  }
  // bytes_per_voxel = brik_file_length / nvoxels; // this assumes one frame
  bytes_per_voxel = af.brick_types[0] + 1; // 0(byte)-> 1, 1(short) -> 2, 3(float)->4

  bytes = header->width*header->height*header->depth*bytes_per_voxel;

  // this check is for nframes = 1 case which is the one we are supporting
  if (bytes_per_voxel != brik_file_length/nvoxels)
  {
    fclose(fp);
    MRIfree(&header);
    errno = 0;
    ErrorReturn(NULL,
                (ERROR_UNSUPPORTED,
                 "afniRead(): type info stored in header does not agree with the file size: %d != %d/%d",
                 bytes_per_voxel, brik_file_length/nvoxels));
  }

  // if brick_float_facs != 0 then we scale values to be float
  if (af.numfacs != 0 && af.brick_float_facs[0] != 0.)
  {
    header->type = MRI_FLOAT;
    scaling = af.brick_float_facs[0];
  }
  else
  {
    if (bytes_per_voxel == 1)
      header->type = MRI_UCHAR;
    else if (bytes_per_voxel == 2)
      header->type = MRI_SHORT;
    else if (bytes_per_voxel == 4)
      header->type = MRI_FLOAT;
    else
    {
      fclose(fp);
      MRIfree(&header);
      errno = 0;
      ErrorReturn(NULL, (ERROR_UNSUPPORTED, "afniRead(): don't know what to do with %d bytes per voxel", bytes_per_voxel));
    }
  }

  ///////////////////////////////////////////////////////////////////////
  if (read_volume)
  {
    // mri = MRIalloc(header->width, header->height, header->depth, header->type);
    mri = MRIallocSequence(header->width, header->height, header->depth,
                           header->type, header->nframes) ;
    MRIcopyHeader(header, mri);

    for (frame = 0; frame < header->nframes; ++frame)
    {
      initialized = 0;
      for (k = 0;k < mri->depth;k++)
      {
        for (j = 0;j < mri->height;j++)
        {
          if (af.brick_float_facs[frame])
            scaling = af.brick_float_facs[frame];
          else
            scaling = 1.;
          {
            pmem = (void *) malloc(bytes_per_voxel*mri->width);
            if (pmem)
            {
              if (fread(pmem, bytes_per_voxel, mri->width, fp) != mri->width)
              {
                fclose(fp);
                MRIfree(&header);
                errno = 0;
                ErrorReturn(NULL, (ERROR_BADFILE, "afniRead(): error reading from file %s", fname));
              }
              // swap bytes
              if (swap_flag)
              {
                if (bytes_per_voxel == 2) // short
                {
                  swab(pmem, pmem, mri->width * 2);
                }
                else if (bytes_per_voxel == 4) // float
                {
                  pf = (float *) pmem;
                  for (i = 0;i < mri->width;i++, pf++)
                    *pf = swapFloat(*pf);
                }
              }
              // now scaling
              if (bytes_per_voxel == 1) // byte
              {
                pc = (unsigned char *) pmem;
                for (i=0; i < mri->width; i++)
                {
                  if (scaling == 1.)
                    MRIseq_vox(mri, i, j, k, frame) = *pc;
                  else
                    MRIFseq_vox(mri, i, j, k, frame) = ((float) (*pc))*scaling;
                  ++pc;
                }
                findMinMaxByte((unsigned char *) pmem, mri->width, &flMin, &flMax);
              }
              if (bytes_per_voxel == 2) // short
              {
                ps = (short *) pmem;
                for (i=0; i < mri->width; i++)
                {
                  // if (*ps != 0)
                  //   printf("%d ", *ps);
                  if (scaling == 1.)
                    MRISseq_vox(mri, i, j, k, frame) = *ps;
                  else
                    MRIFseq_vox(mri, i, j, k, frame) = ((float) (*ps))*scaling;
                  ++ps;
                }
                findMinMaxShort((short *) pmem, mri->width, &flMin, &flMax);
              }
              else if (bytes_per_voxel == 4) // float
              {
                pf = (float *) pmem;
                for (i=0; i < mri->width; i++)
                {

                  MRIFseq_vox(mri, i, j, k, frame) = (*pf)*scaling;
                  ++pf;
                }
                findMinMaxFloat((float *) pmem, mri->width, &flMin, &flMax);
              }
              free(pmem);
              //
              if (initialized == 0)
              {
                fMin = flMin;
                fMax = flMax;
                initialized = 1;
              }
              else
              {
                if (flMin < fMin)
                  fMin = flMin;
                if (flMax > fMax)
                  fMax = flMax;
                // printf("\n fmin =%f, fmax = %f, local min = %f, max = %f\n", fMin, fMax, flMin, flMax);
              }
            }
            else
            {
              fclose(fp);
              MRIfree(&header);
              errno = 0;
              ErrorReturn(NULL,
                          (ERROR_BADFILE, "afniRead(): could not allocate memory for reading %s", fname));
            }
          }
        } // height
      } // depth
      // valid only for nframs == 1
      {
        printf("BRICK_STATS min = %f <--> actual min = %f\n",
               af.brick_stats[0+2*frame], fMin*scaling);
        printf("BRICK_STATS max = %f <--> actual max = %f\n",
               af.brick_stats[1+2*frame], fMax*scaling);
      }
    } // nframes
  }
  else // not reading volume
    mri = MRIcopy(header, NULL);

  strcpy(mri->fname, fname);

  fclose(fp);

  MRIfree(&header);
  AFclean(&af);

  return(mri);

} /* end afniRead() */
예제 #2
0
int loadRaw2Stack(char * filename, unsigned char ** img, long ** sz, int datatype) //this is the function of 4-byte raw format.
{
  /* This function reads 2-4D image stack from raw data generated by the program "saveStack2Raw.m". */
  /* The input parameters img, sz, and datatype should be empty, especially the pointers "img" and "sz". */

  int berror = 0;

  FILE * fid = fopen(filename, "rb");
  if (!fid)
    {
      printf("Fail to open file for reading.\n");
      berror = 1;
      return berror;
    }

  fseek (fid, 0, SEEK_END);
  long fileSize = ftell(fid);
  rewind(fid);

  /* Read header */

  char formatkey[] = "raw_image_stack_by_hpeng";
  long lenkey = strlen(formatkey);

  if (fileSize<lenkey+2+4*4+1) // datatype has 2 bytes, and sz has 4*4 bytes and endian flag has 1 byte. 
    {
      printf("The size of your input file is too small and is not correct, -- it is too small to contain the legal header.\n");
      printf("The fseek-ftell produces a file size = %ld.", fileSize);
      berror = 1;
      return berror;
    }

  char * keyread = (char*)Guarded_Malloc((lenkey+1)*sizeof(char), Program_Name());
  if (!keyread)
    {
      printf("Fail to allocate memory.\n");
      berror = 1;
      return berror;
    }
  long nread = fread(keyread, 1, lenkey, fid);
  if (nread!=lenkey)
    {
      printf("File unrecognized or corrupted file.\n");
      berror = 1;
      return berror;
    }
  keyread[lenkey] = '\0';

  long i;
  if (strcmp(formatkey, keyread)) /* is non-zero then the two strings are different */
    {
      printf("Unrecognized file format.\n");
      if (keyread) {free(keyread); keyread=0;}
      berror = 1;
      return berror;
    }

  char endianCodeData;
  fread(&endianCodeData, 1, 1, fid);
  if (endianCodeData!='B' && endianCodeData!='L')
    {
      printf("This program only supports big- or little- endian but not other format. Check your data endian.\n");
      berror = 1;
      if (keyread) {free(keyread); keyread=0;}
      return berror;
    }

  char endianCodeMachine;
  endianCodeMachine = checkMachineEndian();
  if (endianCodeMachine!='B' && endianCodeMachine!='L')
    {
      printf("This program only supports big- or little- endian but not other format. Check your data endian.\n");
      berror = 1;
      if (keyread) {free(keyread); keyread=0;}
      return berror;
    }

  int b_swap = (endianCodeMachine==endianCodeData)?0:1;
  printf("machine endian=[%c] data endian=[%c] b_swap=%d\n", endianCodeMachine, endianCodeData, b_swap);


  short int dcode = 0;
  fread(&dcode, 2, 1, fid); /* because I have already checked the file size to be bigger than the header, no need to check the number of actual bytes read. */
  if (b_swap)
    swap2bytes((void *)&dcode);

  switch (dcode)
    {
    case 1:
      datatype = 1; /* temporarily I use the same number, which indicates the number of bytes for each data point (pixel). This can be extended in the future. */
      break;

    case 2:
      datatype = 2;
      break;

    case 4:
      datatype = 4;
      break;

    default:
      printf("Unrecognized data type code [%d]. The file type is incorrect or this code is not supported in this version.\n", dcode);
      if (keyread) {free(keyread); keyread=0;}
      berror = 1;
      return berror;
    }

  long unitSize = datatype; // temporarily I use the same number, which indicates the number of bytes for each data point (pixel). This can be extended in the future. 

  printf("loadRaw2Stack unitSize=%d\n", unitSize);

  unsigned int mysz[4];
  mysz[0]=mysz[1]=mysz[2]=mysz[3]=0;
  int tmpn=fread(mysz, 4, 4, fid); // because I have already checked the file size to be bigger than the header, no need to check the number of actual bytes read. 
  if (tmpn!=4)
    {
      printf("This program only reads [%d] units.\n", tmpn);
      berror=1;
      return berror;
    }
  if (b_swap)
    {
      for (i=0;i<4;i++)
	{
	  //swap2bytes((void *)(mysz+i));
	  printf("mysz raw read unit[%ld]: [%d] ", i, mysz[i]);
	  swap4bytes((void *)(mysz+i));
	  printf("swap unit: [%d][%0x] \n", mysz[i], mysz[i]);
	}
    }

  if (*sz) {free(*sz); *sz=0;}
  *sz=(long*)Guarded_Malloc(4*sizeof(long), Program_Name());
  if (!(*sz))
    {
      printf("Fail to allocate memory.\n");
      if (keyread) {free(keyread); keyread=0;}
      berror = 1;
      return berror;
    }

  long totalUnit = 1;
  for (i=0;i<4;i++)
    {
      (*sz)[i] = (long)mysz[i];
      totalUnit *= (*sz)[i];
    }

  //mexPrintf("The input file has a size [%ld bytes], different from what specified in the header [%ld bytes]. Exit.\n", fileSize, totalUnit*unitSize+4*4+2+1+lenkey);
  //mexPrintf("The read sizes are: %ld %ld %ld %ld\n", sz[0], sz[1], sz[2], sz[3]);

  if ((totalUnit*unitSize+4*4+2+1+lenkey) != fileSize)
    {
      printf("The input file has a size [%ld bytes], different from what specified in the header [%ld bytes]. Exit.\n", fileSize, totalUnit*unitSize+4*4+2+1+lenkey);
      printf("The read sizes are: %ld %ld %ld %ld\n", (*sz)[0], (*sz)[1], (*sz)[2], (*sz)[3]);
      printf("The read sizes are: %d %d %d %d\n", mysz[0], mysz[1], mysz[2], mysz[3]);
      if (keyread) {free(keyread); keyread=0;}
      if (*sz) {free(*sz); *sz=0;}
      berror = 1;
      return berror;
    }

  if (*img) {free(*img); *img=0;}
  long totalBytes = unitSize*totalUnit;
  *img = (unsigned char *)Guarded_Malloc(totalBytes*sizeof(unsigned char), Program_Name());
  if (*img==0 || *img==NULL)
    {
      fprintf(stderr, "Fail to allocate memory in loadRaw2Stack().\n");
      if (keyread) {free(keyread); keyread=0;}
      if (*sz) {free(*sz); *sz=0;}
      berror = 1;
      return berror;
    }

  long remainingBytes = totalBytes;
  long nBytes2G = 1024L*1024L*1024L*2L;
  long cntBuf = 0;
  while (remainingBytes>0)
    {
      long curReadBytes = (remainingBytes<nBytes2G) ? remainingBytes : nBytes2G;
      long curReadUnits = curReadBytes/unitSize;
      nread = fread(*img+cntBuf*nBytes2G, unitSize, curReadUnits, fid);
      if (nread!=curReadUnits)
	{
	  printf("Something wrong in file reading. The program reads [%ld data points] but the file says there should be [%ld data points].\n", nread, totalUnit);
	  if (keyread) {free(keyread); keyread=0;}
	  if (*sz) {free(*sz); *sz=0;}
	  if (*img) {free(*img); *img=0;}
	  berror = 1;
	  return berror;
	}
      
      remainingBytes -= nBytes2G;
      cntBuf++;
    }

  // swap the data bytes if necessary 

  if (b_swap==1)
    {
      if (unitSize==2)
	{
	  for (i=0;i<totalUnit; i++)
	    {
	      swap2bytes((void *)(*img+i*unitSize));
	    }
	}
      else if (unitSize==4)
	{
	  for (i=0;i<totalUnit; i++)
	    {
	      swap4bytes((void *)(*img+i*unitSize));
	    }
	}
    }


  // clean and return 

  if (keyread) {free(keyread); keyread = 0;}
  fclose(fid); //bug fix on 060412

  double min=0.0, max=0.0;
  if (datatype==1) {
    findMinMax8bit(&min, &max, *img, totalUnit);
  } else if (datatype==2) {
    findMinMax16bit(&min, &max, *img, totalUnit);
  } else if (datatype==4) {
    findMinMaxFloat(&min, &max, *img, totalUnit);
  }
  printf("loadRaw2Stack() Min=%f Max=%f\n", min, max);

  return berror;
}