/*------------------------------------------------------*/ 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() */
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; }