/*! * Fill IMG struct header information from Analyze 7.5 database files. * SIF file is read if available. Information concerning separate frames * or planes is not filled though. * * @param dbname name of Analyze database, may contain filename extension * @param img pointer to the initiated IMG data * @return errstatus, which is STATUS_OK (0) when call was successful, * and >0 in case of an error. */ int imgReadAnalyzeHeader(const char *dbname, IMG *img) { char hdrfile[FILENAME_MAX], siffile[FILENAME_MAX]; ANALYZE_DSR ana_header; SIF sif; double f; int ret; if(IMG_TEST) printf("\nimgReadAnalyzeHeader(%s, *img)\n", dbname); /* Check the input */ if(img==NULL) return STATUS_FAULT; if(img->status!=IMG_STATUS_INITIALIZED) return STATUS_FAULT; imgSetStatus(img, STATUS_FAULT); if(dbname==NULL) return STATUS_FAULT; /* Determine the names of hdr and sif files */ ret=anaDatabaseExists(dbname, hdrfile, NULL, siffile); if(ret==0) return STATUS_NOFILE; /* Read Analyze header file */ ret=anaReadHeader(hdrfile, &ana_header); if(ret!=0) { if(IMG_TEST>1) printf("anaReadHeader() return value := %d\n", ret); if(ret==1) return STATUS_FAULT; else if(ret==2) return STATUS_NOHEADERFILE; else return STATUS_UNSUPPORTED; return(STATUS_FAULT); } /* and set IMG contents */ ret=imgGetAnalyzeHeader(img, &ana_header); if(ret!=0) { imgSetStatus(img, ret); return(ret); } /* If SIF does not exist, then that's it */ if(!siffile[0]) { imgSetStatus(img, STATUS_OK); return STATUS_OK; } /* SIF is available, so read that too */ sifInit(&sif); ret=0; if(sifRead(siffile, &sif)!=0) return STATUS_OK; /* Copy scan time */ img->scanStart=sif.scantime; /* Study number, if not yet defined */ if(!img->studyNr[0] && strlen(sif.studynr)>1 ) strncpy(img->studyNr, sif.studynr, MAX_STUDYNR_LEN); /* Isotope half-life, if not yet defined */ f=hlFromIsotope(sif.isotope_name); if(img->isotopeHalflife<=0.0 && f>0.0) img->isotopeHalflife=60.0*f; sifEmpty(&sif); return STATUS_OK; }
/*! * Remove header and data files belonging to specified Analyze 7.5 database. * SIF is not deleted in any case. * @return 0 when call was successful, 1 if header file deletion failed, * 2 if data file deletion failed. * Call is considered successful, if database does not exist initially. */ int anaRemove(const char *dbname) { char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX]; if(ANALYZE_TEST) printf("anaRemove(%s)\n", dbname); if(anaDatabaseExists(dbname, hdrfile, datfile, siffile)==0) return 0; if(ANALYZE_TEST>2) printf(" removing %s and %s\n", hdrfile, datfile); if(remove(hdrfile)!=0) return 1; if(remove(datfile)!=0) return 2; return 0; }
/*! * Write one PET frame from IMG data struct into Analyze 7.5 database file. * This function can be called repeatedly to write all frames one at a time * to conserve memory. This function does not write SIF. * * @param dbname name of file where IMG contents will be written. * If file does not exist, it is created. * Make sure to delete existing file, unless you want to add data * @param frame_to_write PET frame number (1..frameNr) which will be written: * If set to 0, frame data will be written to an existing or new PET file as * a new frame, never overwriting existing data. * If >0, then frame data is written as specified frame number, overwriting * any data existing with the same frame number * @param img pointer to the IMG data struct * @param frame_index IMG frame index (0..dimt-1) which will be written * @param fmin minimum pixel value in all frames that will be written; * used only when writing the first frame * @param fmax maximum pixel value in all frames that will be written; * used only when writing the first frame * @return errstatus, which is STATUS_OK (0) when call was successful, * and >0 in case of an error. */ int imgWriteAnalyzeFrame( const char *dbname, int frame_to_write, IMG *img, int frame_index, float fmin, float fmax ) { IMG test_img; int ret=0, pxlNr, zi, xi, yi, little; FILE *fp; short int *sdata=NULL, *sptr; char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX]; ANALYZE_DSR dsr; float scale_factor=1.0; if(IMG_TEST) printf("\nimgWriteAnalyzeFrame(%s, %d, *img, %d, %g, %g)\n", dbname, frame_to_write, frame_index, fmin, fmax); /* * Check the input */ if(dbname==NULL) return STATUS_FAULT; if(img==NULL) return STATUS_FAULT; if(img->status!=IMG_STATUS_OCCUPIED) return STATUS_FAULT; if(frame_to_write<0) return STATUS_FAULT; if(frame_index<0 || frame_index>=img->dimt) return STATUS_FAULT; if(img->_fileFormat!=IMG_ANA_L && img->_fileFormat!=IMG_ANA) return STATUS_FAULT; /* * If database does not exist, then create it with new header, * and if it does exist, then read and check header information. * Create or edit header to contain correct frame nr. * Determine the global scaling factor. */ imgInit(&test_img); if(anaDatabaseExists(dbname, hdrfile, datfile, siffile)==0) { // not existing /* Create database filenames */ sprintf(hdrfile, "%s.hdr", dbname); sprintf(datfile, "%s.img", dbname); sprintf(siffile, "%s.sif", dbname); /* Set main header */ imgSetAnalyzeHeader(img, dbname, &dsr, fmin, fmax); if(frame_to_write==0) frame_to_write=1; dsr.dime.dim[4]=frame_to_write; scale_factor=dsr.dime.funused1; if(fabs(scale_factor)>1.0E-20) scale_factor=1.0/scale_factor; /* Write Analyze header */ ret=anaWriteHeader(hdrfile, &dsr); if(ret && IMG_TEST) printf("anaWriteHeader() := %d\n", ret); if(ret) return STATUS_CANTWRITEHEADERFILE; /* Remove datafile if necessary */ if(access(datfile, 0) != -1) remove(datfile); } else { /* database does exist */ /* Read header information for checking */ ret=imgReadAnalyzeHeader(dbname, &test_img); if(ret!=0) {imgEmpty(&test_img); return ret;} /* Check that file format is the same */ if(img->_fileFormat!=test_img._fileFormat || img->type!=test_img.type) { imgEmpty(&test_img); return STATUS_WRONGFILETYPE;} /* Check that matrix sizes are the same */ if(img->dimz!=test_img.dimz || img->dimx!=test_img.dimx || img->dimy!=test_img.dimy) { imgEmpty(&test_img); return STATUS_VARMATSIZE;} imgEmpty(&test_img); /* Read the header, set new frame number, and write it back */ /* Get also the scale factor */ if((ret=anaReadHeader(hdrfile, &dsr))!=0) return STATUS_NOMAINHEADER; scale_factor=1.0/dsr.dime.funused1; if(frame_to_write==0) frame_to_write=dsr.dime.dim[4]+1; if(dsr.dime.dim[4]<frame_to_write) { if(dsr.dime.dim[4]+1<frame_to_write) return STATUS_MISSINGMATRIX; dsr.dime.dim[4]=frame_to_write; } if((ret=anaWriteHeader(hdrfile, &dsr))!=0) return STATUS_NOWRITEPERM; } if(IMG_TEST>2) { printf("frame_to_write := %d\n", frame_to_write); printf("hdrfile := %s\n", hdrfile); printf("datfile := %s\n", datfile); printf("siffile := %s\n", siffile); } /* Allocate memory for matrix short int data (one plane) */ pxlNr=img->dimx*img->dimy; sdata=(short int*)malloc(pxlNr*sizeof(short int)); if(sdata==NULL) return STATUS_NOMEMORY; /* Open datafile, not removing possible old contents */ if(frame_to_write==1) fp=fopen(datfile, "wb"); else fp=fopen(datfile, "r+b"); if(fp==NULL) {free(sdata); return STATUS_CANTWRITEIMGFILE;} /* Move file pointer to the place of current frame */ if(fseek(fp, (frame_to_write-1)*pxlNr*img->dimz*sizeof(short int), SEEK_SET)!=0) { free(sdata); fclose(fp); return STATUS_MISSINGMATRIX;} little=little_endian(); /* Copy, scale and write data plane-by-plane */ if(anaFlipping()==0) { for(zi=0; zi<img->dimz; zi++) { sptr=sdata; /*printf("plane := %d\n scale_factor := %g\n", zi+1, scale_factor);*/ for(yi=img->dimy-1; yi>=0; yi--) for(xi=img->dimx-1; xi>=0; xi--) { *sptr=temp_roundf(scale_factor*img->m[zi][yi][xi][frame_index]); sptr++; } /* Change byte order if necessary */ sptr=sdata; if(little!=dsr.little) swabip(sptr, pxlNr*sizeof(short int)); /* Write image data */ sptr=sdata; if(fwrite(sptr, sizeof(short int), pxlNr, fp) != pxlNr) { free(sdata); fclose(fp); return STATUS_CANTWRITEIMGFILE; } } } else { for(zi=img->dimz-1; zi>=0; zi--) { sptr=sdata; for(yi=img->dimy-1; yi>=0; yi--) for(xi=img->dimx-1; xi>=0; xi--) { *sptr=temp_roundf(scale_factor*img->m[zi][yi][xi][frame_index]); sptr++; } /* Change byte order if necessary */ sptr=sdata; if(little!=dsr.little) swabip(sptr, pxlNr*sizeof(short int)); /* Write image data */ sptr=sdata; if(fwrite(sptr, sizeof(short int), pxlNr, fp) != pxlNr) { free(sdata); fclose(fp); return STATUS_CANTWRITEIMGFILE; } } } free(sdata); fclose(fp); return STATUS_OK; }
/*! * Read a specified frame from an Analyze 7.5 database into preallocated IMG * data structure. Analyze database consists of two or three files in the same * directory: fname.hdr, fname.img, and optionally fname.sif. * IMG header is assumed to be filled correctly before calling this function, * except for information concerning separate planes and this frame, * which is filled here. * If frame does not exist, then and only then STATUS_NOMATRIX is returned. * * @param fname name of Analyze database from which IMG contents will be read * @param frame_to_read frame which will be read [1..frameNr] * @param img pointer to the IMG data. Place for the frame must be preallocated * @param frame_index IMG frame index [0..dimt-1] where data will be placed * @return errstatus, which is STATUS_OK (0) when call was successful, * and >0 in case of an error. */ int imgReadAnalyzeFrame( const char *fname, int frame_to_read, IMG *img, int frame_index ) { FILE *fp; int ret, pi, xi, yi; float *fdata=NULL, *fptr; ANALYZE_DSR dsr; char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX]; SIF sif; if(IMG_TEST) printf("\nimgReadAnalyzeFrame(%s, %d, *img, %d)\n", fname, frame_to_read, frame_index); /* Check the input */ if(img==NULL) return STATUS_FAULT; if(img->status!=IMG_STATUS_OCCUPIED) return STATUS_FAULT; if(fname==NULL) return STATUS_FAULT; if(frame_index<0 || frame_index>img->dimt-1) return STATUS_FAULT; if(frame_to_read<1) return STATUS_FAULT; imgSetStatus(img, STATUS_FAULT); /* Determine the names of hdr, data and sif files */ ret=anaDatabaseExists(fname, hdrfile, datfile, siffile); if(ret==0) return STATUS_NOFILE; /* Read Analyze header file */ ret=anaReadHeader(hdrfile, &dsr); if(ret!=0) { if(ret==1) return STATUS_FAULT; else if(ret==2) return STATUS_NOHEADERFILE; else return STATUS_UNSUPPORTED; return(STATUS_FAULT); } /* Open image datafile */ if(IMG_TEST>2) fprintf(stdout, "reading image data %s\n", datfile); if((fp=fopen(datfile, "rb")) == NULL) return STATUS_NOIMGDATA; /* Allocate memory for one image frame */ fdata=malloc(img->dimx*img->dimy*img->dimz*sizeof(float)); if(fdata==NULL) {fclose(fp); return STATUS_NOMEMORY;} /* Read the required image frame */ fptr=fdata; ret=anaReadImagedata(fp, &dsr, frame_to_read, fptr); fclose(fp); if(ret==3) {free(fdata); return STATUS_NOMATRIX;} /* no more frames */ if(ret!=0) {free(fdata); return STATUS_UNSUPPORTED;} /* Copy pixel values to IMG */ fptr=fdata; if(anaFlipping()==0) { /* no flipping in z-direction */ for(pi=0; pi<img->dimz; pi++) for(yi=img->dimy-1; yi>=0; yi--) for(xi=img->dimx-1; xi>=0; xi--) img->m[pi][yi][xi][frame_index]=*fptr++; } else { for(pi=img->dimz-1; pi>=0; pi--) for(yi=img->dimy-1; yi>=0; yi--) for(xi=img->dimx-1; xi>=0; xi--) img->m[pi][yi][xi][frame_index]=*fptr++; } free(fdata); /* Set decay correction factor to zero */ img->decayCorrFactor[frame_index]=0.0; imgSetStatus(img, STATUS_OK); /* If the rest is failed, no problem */ /* * Try to read frame time information from SIF file */ sifInit(&sif); if(sifRead(siffile, &sif)!=0) return STATUS_OK; /* Frame information */ if(sif.frameNr>=frame_to_read) { img->start[frame_index]=sif.x1[frame_to_read-1]; img->end[frame_index]=sif.x2[frame_to_read-1]; img->mid[frame_index]=0.5*(img->start[frame_index]+img->end[frame_index]); img->prompts[frame_index]=sif.prompts[frame_to_read-1]; img->randoms[frame_index]=sif.randoms[frame_to_read-1]; } sifEmpty(&sif); return STATUS_OK; }