/** Copy one time frame (1..dimt) from 4D image to 3D short int volume. * Svol can be but need not to be allocated. * * @param img image structure * @param svol short volume structure * @param frame frame number [1..number of frames] * @return 0 if ok, 1 invalid image status, 2 invalid input */ int img2svol(IMG *img, SVOL *svol, int frame) { int ret; unsigned short int zi, yi, xi, fi; float fmin, fmax, g; if(VOL_TEST) printf("img2svol(img, %d, svol)\n", frame); /* Check input */ if(svol==NULL) return(1); svol->statmsg=_volStatusMessage[1]; if(img->status!=IMG_STATUS_OCCUPIED) return(1); if(frame<1 || img->dimt<frame) return(2); if(svol->status==IMG_STATUS_UNINITIALIZED) return(1); /* Allocate memory (if needed) for volume */ ret=svolAllocate(svol, img->dimz, img->dimy, img->dimx); if(ret) return(ret); /* Copy data */ fi=frame-1; svol->orientation=img->orientation; svol->sizex=img->sizex; svol->sizey=img->sizey; svol->sizez=img->sizez; ret=imgFrameMinMax(img, frame, &fmin, &fmax); if(ret) return(10+ret); if(fabs(fmin)>fabs(fmax)) g=fabs(fmin); else g=fabs(fmax); if(g!=0) g=32766./g; else g=1.0; for(zi=0; zi<svol->dimz; zi++) for(yi=0; yi<svol->dimy; yi++) for(xi=0; xi<svol->dimx; xi++) svol->v[zi][yi][xi]=(short int)temp_roundf(g*img->m[zi][yi][xi][fi]); svol->scale_factor=1.0/g; 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; }
/** * Copy header information in IMG struct into Analyze 7.5 header struct. * Min, max, and scale factor are set here and they apply to all frames. * * @return errstatus, which is STATUS_OK (0) when call was successful, * and >0 in case of an error. */ int imgSetAnalyzeHeader( /** pointer to IMG struct from which header information is read */ IMG *img, /** Analyze 7.5 database name */ const char *dbname, /** pointer to Analyze header struct to be filled */ ANALYZE_DSR *dsr, /** minimum pixel value in all frames that will be written */ float fmin, /** maximum pixel value in all frames that will be written */ float fmax ) { struct tm *st; char *cptr; float g; if(IMG_TEST) printf("\nimgSetAnalyzeHeader(*img, %s, *dsr, %g, %g)\n", dbname, fmin, fmax); /* Check the input */ if(img==NULL) return STATUS_FAULT; if(img->status!=IMG_STATUS_INITIALIZED && img->status!=IMG_STATUS_OCCUPIED) return STATUS_FAULT; imgSetStatus(img, STATUS_FAULT); if(dsr==NULL) return STATUS_FAULT; /* Byte order */ if(img->_fileFormat==IMG_ANA_L) dsr->little=1; else dsr->little=0; /* Header key */ memset(&dsr->hk, 0, sizeof(ANALYZE_HEADER_KEY)); memset(&dsr->dime, 0, sizeof(ANALYZE_HEADER_IMGDIM)); memset(&dsr->hist, 0, sizeof(ANALYZE_HEADER_HISTORY)); dsr->hk.sizeof_hdr=348; strcpy(dsr->hk.data_type, ""); cptr=strrchr(dbname, '/'); if(cptr==NULL) cptr=strrchr(dbname, '\\'); if(cptr!=NULL) cptr++; if(cptr==NULL) cptr=(char*)dbname; strncpy(dsr->hk.db_name, cptr, 17); dsr->hk.extents=16384; dsr->hk.regular='r'; /* Image dimension */ dsr->dime.dim[0]=4; dsr->dime.dim[1]=img->dimx; dsr->dime.dim[2]=img->dimy; dsr->dime.dim[3]=img->dimz; dsr->dime.dim[4]=img->dimt; dsr->dime.datatype=ANALYZE_DT_SIGNED_SHORT; dsr->dime.bitpix=16; dsr->dime.pixdim[0]=0.0; dsr->dime.pixdim[1]=img->sizex; dsr->dime.pixdim[2]=img->sizey; dsr->dime.pixdim[3]=img->sizez; dsr->dime.pixdim[4]=0.0; dsr->dime.funused1=0.0; /* Scale factor is set later */ /* dsr.dime.funused2=img->zoom; */ /* Reconstruction zoom */ dsr->dime.funused3=img->isotopeHalflife; /* Data history */ if(img->decayCorrection==IMG_DC_CORRECTED) strcpy(dsr->hist.descrip, "Decay corrected."); else if(img->decayCorrection==IMG_DC_NONCORRECTED) strcpy(dsr->hist.descrip, "No decay correction."); else strcpy(dsr->hist.descrip, ""); if(strlen(img->studyNr)>0 && strcmp(img->studyNr, ".")!=0) strncpy(dsr->hist.scannum, img->studyNr, 10); else strcpy(img->studyNr, ""); st=localtime(&img->scanStart); if(st!=NULL) { strftime(dsr->hist.exp_date, 10, "%Y%m%d", st); strftime(dsr->hist.exp_time, 10, "%H:%M:%S", st); } else { strcpy(dsr->hist.exp_date, "19000101"); strcpy(dsr->hist.exp_time, "00:00:00"); } /* Determine and set scale factor and cal_min & cal_max */ if(fmin<fmax) { dsr->dime.cal_min=fmin; dsr->dime.cal_max=fmax; } else { /* not given in function call, try to find those here */ if(img->status==IMG_STATUS_OCCUPIED && imgMinMax(img, &dsr->dime.cal_min, &dsr->dime.cal_max)==0) {} else return STATUS_FAULT; } if(fabs(dsr->dime.cal_min) > fabs(dsr->dime.cal_max)) g=fabs(dsr->dime.cal_min); else g = fabs(dsr->dime.cal_max); /* if(fabs(dsr->dime.cal_min)>fabs(dsr->dime.cal_max)) g=fabs(dsr->dime.cal_min); */ /* else g=fabs(dsr->dime.cal_max); */ if(g<1E-20) g=1.0; else g=32767./g; dsr->dime.funused1=1.0/g; /* Set header glmin & glmax */ dsr->dime.glmin=temp_roundf(fmin*g); dsr->dime.glmax=temp_roundf(fmax*g); /* printf("glmin=%d\n", dsr->dime.glmin); */ /* printf("glmax=%d\n", dsr->dime.glmax); */ imgSetStatus(img, STATUS_OK); return STATUS_OK; }
/*! * Write Analyze 7.5 image. * Analyze database name must be given with path. Path must exist. * Image and header files with .img and .hdr extensions are created. * Existing files are overwritten. * anaFlipping() determines whether image is flipped in z-direction; * image is always flipped in x,y-directions. * Byte order is determined based on _fileFormat field. * * @param dbname analyze database name with path, without extension * @param img pointer to IMG data * @return 0 if ok, 1 invalid input, 2 invalid image status (image not occupied), * 3 failed to resolve extreme values (min and max), * 12 failed to allocate temp memory, 14 failed to open file for writing, * 15 failed to write data, 21 failed to write header, and * sets IMG->statmsg in case of error */ int imgWriteAnalyze(const char *dbname, IMG *img) { FILE *fp; int ret, fi, pi, xi, yi, little; float g; ANALYZE_DSR dsr; char datfile[FILENAME_MAX], hdrfile[FILENAME_MAX], siffile[FILENAME_MAX]; const char *cptr; int pxlNr=0; struct tm *st; short int *sdata, *sptr, smin, smax; SIF sif; if(IMG_TEST) printf("imgWriteAnalyze(%s, *img)\n", dbname); /* Check the arguments */ imgSetStatus(img, STATUS_OK); if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) { imgSetStatus(img, STATUS_FAULT); return(2);} if(dbname==NULL || !dbname[0]) {imgSetStatus(img, STATUS_FAULT); return(1);} /* Make the image and header filenames */ strcpy(datfile, dbname); strcat(datfile, ".img"); strcpy(hdrfile, dbname); strcat(hdrfile, ".hdr"); strcpy(siffile, dbname); strcat(siffile, ".sif"); /* * Fill Analyze header */ if(img->_fileFormat==IMG_ANA_L) dsr.little=1; else dsr.little=0; /* Header key */ memset(&dsr.hk, 0, sizeof(ANALYZE_HEADER_KEY)); memset(&dsr.dime, 0, sizeof(ANALYZE_HEADER_IMGDIM)); memset(&dsr.hist, 0, sizeof(ANALYZE_HEADER_HISTORY)); dsr.hk.sizeof_hdr=348; strcpy(dsr.hk.data_type, ""); cptr=strrchr(dbname, '/'); if(cptr==NULL) cptr=strrchr(dbname, '\\'); if(cptr!=NULL) cptr++; if(cptr==NULL) cptr=dbname; strncpy(dsr.hk.db_name, cptr, 17); dsr.hk.extents=16384; dsr.hk.regular='r'; /* Image dimension */ dsr.dime.dim[0]=4; dsr.dime.dim[1]=img->dimx; dsr.dime.dim[2]=img->dimy; dsr.dime.dim[3]=img->dimz; dsr.dime.dim[4]=img->dimt; dsr.dime.datatype=ANALYZE_DT_SIGNED_SHORT; dsr.dime.bitpix=16; dsr.dime.pixdim[0]=0.0; dsr.dime.pixdim[1]=img->sizex; dsr.dime.pixdim[2]=img->sizey; dsr.dime.pixdim[3]=img->sizez; dsr.dime.pixdim[4]=0.0; dsr.dime.funused1=0.0; /* Scale factor is set later */ /* dsr.dime.funused2=img->zoom; */ /* Reconstruction zoom */ dsr.dime.funused3=img->isotopeHalflife; /* Data history */ if(img->decayCorrection==IMG_DC_CORRECTED) strcpy(dsr.hist.descrip, "Decay corrected."); else if(img->decayCorrection==IMG_DC_NONCORRECTED) strcpy(dsr.hist.descrip, "No decay correction."); else strcpy(dsr.hist.descrip, ""); if(strlen(img->studyNr)>0 && strcmp(img->studyNr, ".")!=0) strncpy(dsr.hist.scannum, img->studyNr, 10); else strcpy(dsr.hist.scannum, ""); st=localtime(&img->scanStart); if(st!=NULL) { strftime(dsr.hist.exp_date, 10, "%Y-%m-%d", st); strftime(dsr.hist.exp_time, 10, "%H:%M:%S", st); } else { strncpy(dsr.hist.exp_date, "1900-01-01", 10); strncpy(dsr.hist.exp_time, "00:00:00", 10); } /* * Scale data to short int range * Determine and set scale factor and cal_min & cal_max */ if(IMG_TEST) printf("scaling data to short ints\n"); ret=imgMinMax(img, &dsr.dime.cal_min, &dsr.dime.cal_max); if(ret) {imgSetStatus(img, STATUS_FAULT); return(3);} if(fabs(dsr.dime.cal_min)>fabs(dsr.dime.cal_max)) g=fabs(dsr.dime.cal_min); else g=fabs(dsr.dime.cal_max); if(g<1E-20) g=1.0; else g=32767./g; dsr.dime.funused1=1.0/g; if(IMG_TEST) printf("min=%g max=%g scale_factor=%g\n", dsr.dime.cal_min, dsr.dime.cal_max, dsr.dime.funused1); /* Allocate memory for short int array */ pxlNr=(img->dimx)*(img->dimy)*(img->dimz); sdata=malloc(pxlNr*sizeof(short int)); if(sdata==NULL) { imgSetStatus(img, STATUS_NOMEMORY); return 12; } /* Open image data file for write */ if((fp=fopen(datfile, "wb")) == NULL) { imgSetStatus(img, STATUS_CANTWRITEIMGFILE); free(sdata); return 14; } /* Copy and write image matrix data to short int array */ /* Data is written one frame at a time */ smin=smax=temp_roundf(g*img->m[0][0][0][0]); for(fi=0; fi<img->dimt; fi++) { sptr=sdata; if(anaFlipping()==0) { for(pi=0; pi<img->dimz; pi++) for(yi=img->dimy-1; yi>=0; yi--) for(xi=img->dimx-1; xi>=0; xi--) { *sptr=temp_roundf(g*img->m[pi][yi][xi][fi]); if(*sptr>smax) smax=*sptr; else if(*sptr<smin) smin=*sptr; sptr++; } } 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--) { *sptr=temp_roundf(g*img->m[pi][yi][xi][fi]); if(*sptr>smax) smax=*sptr; else if(*sptr<smin) smin=*sptr; sptr++; } } /* Change byte order if necessary */ little=little_endian(); if(little!=dsr.little) swabip(sdata, pxlNr*sizeof(short int)); /* Write image data */ if(fwrite(sdata, 2, pxlNr, fp) != pxlNr) { imgSetStatus(img, STATUS_CANTWRITEIMGFILE); free(sdata); fclose(fp); return 15; } } /* Done writing */ fclose(fp); free(sdata); if(IMG_TEST) printf("smin=%d smax=%d\n", smin, smax); /* Set header glmin & glmax */ dsr.dime.glmin=smin; dsr.dime.glmax=smax; /* Write Analyze header */ ret=anaWriteHeader(hdrfile, &dsr); if(ret) { imgSetStatus(img, STATUS_CANTWRITEHEADERFILE); return 21; } imgSetStatus(img, STATUS_OK); /* Otherwise ready, but check if SIF should/can be written */ sifInit(&sif); /* Try to read existing SIF */ ret=sifRead(siffile, &sif); if(ret==0) { // SIF could be read if(sif.frameNr==img->dimt) { /* If size matches, then update the contents, but keep counts, in case previous SIF comes with actual count info from scanner */ ret=img2sif(img, &sif, 1, 1, 0, IMG_TEST-2); } else { /* otherwise create SIF contents */ ret=img2sif(img, &sif, 1, 1, 2, IMG_TEST-2); } } else { /* otherwise create SIF contents */ ret=img2sif(img, &sif, 1, 1, 2, IMG_TEST-2); } if(ret!=0) { /* SIF data could not be made: do not give error, just do not write it */ if(IMG_TEST>0) printf("SIF contents could not be filled.\n"); return 0; } /* Write SIF */ ret=sifWrite(&sif, siffile); if(ret!=0) { /* SIF could not be written: do not give error, just do not write it */ if(IMG_TEST>0) fprintf(stderr, "Error: SIF could not be written (%d).\n", ret); } imgSetStatus(img, STATUS_OK); return 0; }
/** The matrix is filled with 0's (outside of ROI), 1's (on the ROI border), * and 2's (inside the ROI border). * If ROI extends outside image borders, those points are ignored. * Matrix coordinates are up-to-bottom and left-to-right. \return Function returns 0, if everything is OK. */ int roiOnOff( /** Definitions for one region-of-interest */ ROI *roi, /** Image matrix x dimension */ int dimx, /** Image matrix y dimension */ int dimy, /** Image reconstruction zoom */ float zoom, /** Allocated memory for output matrix[dimx][dimy] */ char **m ) { int i, j, n, *x, *y, pos_x, pos_y, *fx, *fy; float f; /* Check the parameters */ if(roi==NULL || dimx<2 || dimy<2 || zoom<1.0e-6 || m==NULL) { strcpy(roierrmsg, "invalid arguments for roiOnOff()"); return(1); } /* Make scaled ROI points */ strcpy(roierrmsg, "out of memory"); if((x=malloc(roi->point_nr*sizeof(int)))==NULL) return(2); if((y=malloc(roi->point_nr*sizeof(int)))==NULL) { free((char*)x); return(2);} f=roi->zoom; if(f<=0.0) f=1.0; pos_x=(int)temp_roundf(((float)roi->pos_x)/f); pos_y=(int)temp_roundf(((float)roi->pos_y)/f); f=roi->zoom*(roi->recon_zoom/zoom); if(f<=0.0) f=1.0; for(i=0; i<roi->point_nr; i++) { x[i]=pos_x+(int)temp_roundf((float)roi->x[i]/f); y[i]=pos_y+(int)temp_roundf((float)roi->y[i]/f); } /* Fill the gaps between points */ n=roiFillGaps(x, y, roi->point_nr, &fx, &fy); if(n<1) { strcpy(roierrmsg, "cannot fill the gaps in ROI border"); free((char*)x); free((char*)y); return(3); } /* Set matrix */ for(i=0; i<dimy; i++) for(j=0; j<dimx; j++) m[j][i]=(char)0; for(i=0; i<n; i++) if(fx[i]>=0 && fx[i]<dimx && fy[i]>=0 && fy[i]<dimy) m[fx[i]][fy[i]]=(char)1; /* Fill the inside of ROI */ for(i=0; i<dimy; i++) if(m[0][i]==0) m[0][i]=2; else break; for(i=dimy-1; i>=0; i--) if(m[0][i]==0) m[0][i]=2; else break; for(i=0; i<dimy; i++) if(m[dimx-1][i]==0) m[dimx-1][i]=2; else break; for(i=dimy-1; i>=0; i--) if(m[dimx-1][i]==0) m[dimx-1][i]=2; else break; for(i=0; i<dimx; i++) if(m[i][0]==0) m[i][0]=2; else break; for(i=dimx-1; i>=0; i--) if(m[i][0]==0) m[i][0]=2; else break; for(i=0; i<dimx; i++) if(m[i][dimy-1]==0) m[i][dimy-1]=2; else break; for(i=dimx-1; i>=0; i--) if(m[i][dimy-1]==0) m[i][dimy-1]=2; else break; for(i=0; i<dimy; i++) for(j=0; j<dimx; j++) { if(m[j][i]!=2) continue; if(i>0 && m[j][i-1]==0) {m[j][i-1]=2; j=-1; i-=2; continue;} if(j>0 && m[j-1][i]==0) {m[j-1][i]=2; j-=2; continue;} if(j+1<dimx) {if(m[j+1][i]!=1) m[j+1][i]=2;} if(i+1<dimy) {if(m[j][i+1]!=1) m[j][i+1]=2;} m[j][i]=3; } for(i=0; i<dimy; i++) for(j=0; j<dimx; j++) if(m[j][i]==0) m[j][i]=2; else if(m[j][i]>1) m[j][i]=0; //if(m[j][i]<2) m[j][i]=1; else m[j][i]=0; /* Free memory */ free((char*)x); free((char*)y); free((char*)fx); free((char*)fy); return(0); }
/** Fills the gaps between ROI points; join them with new points. * Allocates memory for new point data in fx and fy. \return Returns the number of new points or =< 0, if error. */ int roiFillGaps(int *x, int *y, int nr, int **ffx, int **ffy) { int i, j, x1, x2=0, y1, y2=0, dx, dy, nx, ny, *fx, *fy, n; float k; /* Check data */ if(nr<1) return(0); /* Allocate memory for new data */ if((fx=malloc(nr*sizeof(int)))==NULL) return -1; if((fy=malloc(nr*sizeof(int)))==NULL) {free((char*)fx); return -1;} /* Process from first to last (last->first is done already) */ for(i=1, n=j=0; i<nr; i++) { x1=x[i-1]; x2=x[i]; y1=y[i-1]; y2=y[i]; dx=x2-x1; dy=y2-y1; fx[j]=x1; fy[j++]=y1; if(abs(dx)<2 && abs(dy)<2) continue; if(abs(dx)>=abs(dy)) { k=(float)dy/(float)dx; if(x2>x1) for(nx=x1+1; nx<x2; nx++) { ny=y1+(int)temp_roundf(k*(nx-x1)); fx[j]=nx; fy[j++]=ny; n++; if((fx=(int*)realloc((char*)fx, (nr+n)*sizeof(int)))==NULL) { free((char*)fy); return -1;} if((fy=(int*)realloc((char*)fy, (nr+n)*sizeof(int)))==NULL) { free((char*)fx); return -1;} } else for(nx=x1-1; nx>x2; nx--) { ny=y1+(int)temp_roundf(k*(nx-x1)); fx[j]=nx; fy[j++]=ny; n++; if((fx=(int*)realloc((char*)fx, (nr+n)*sizeof(int)))==NULL) { free((char*)fy); return -1;} if((fy=(int*)realloc((char*)fy, (nr+n)*sizeof(int)))==NULL) { free((char*)fx); return -1;} } } else { k=(float)dx/(float)dy; if(y2>y1) for(ny=y1+1; ny<y2; ny++) { nx=x1+(int)temp_roundf(k*(ny-y1)); fx[j]=nx; fy[j++]=ny; n++; if((fx=(int*)realloc((char*)fx, (nr+n)*sizeof(int)))==NULL) { free((char*)fy); return -1;} if((fy=(int*)realloc((char*)fy, (nr+n)*sizeof(int)))==NULL) { free((char*)fx); return -1;} } else for(ny=y1-1; ny>y2; ny--) { nx=x1+(int)temp_roundf(k*(ny-y1)); fx[j]=nx; fy[j++]=ny; n++; if((fx=(int*)realloc((char*)fx, (nr+n)*sizeof(int)))==NULL) { free((char*)fy); return -1;} if((fy=(int*)realloc((char*)fy, (nr+n)*sizeof(int)))==NULL) { free((char*)fx); return -1;} } } } fx[j]=x2; fy[j++]=y2; n=j; *ffx=fx; *ffy=fy; return(n); }
/*! * Write ECAT 6.3 sinogram matrix header and data * * @param fp target file pointer * @param matnum matrix number [1..number of matrixes] * @param h Ecat 6.3 scan header * @param fdata matrix data * @return 0 if ok, 1 invalid input, 3 invalid matrix dimension, * 4 invalid block number, 5 failed to allocate memory for data, * 8 failed to resolve next block number, 10 cannot write sub header, * 13 failed to write data */ int ecat63WriteScanMatrix(FILE *fp, int matnum, ECAT63_scanheader *h, float *fdata) { int i, nxtblk, blkNr, data_size, pxlNr, ret; float *fptr, fmin, fmax, g, f; char *mdata, *mptr; short int *sptr; if(ECAT63_TEST) printf("ecat63WriteScanMatrix(fp, %d, h, data)\n", matnum); if(fp==NULL || matnum<1 || h==NULL || fdata==NULL) { sprintf(ecat63errmsg, "invalid function parameter.\n"); return(1); } /* nr of pixels */ pxlNr=h->dimension_1*h->dimension_2; if(pxlNr<1) { sprintf(ecat63errmsg, "invalid matrix dimension.\n"); return(3); } /* How much memory is needed for ALL pixels */ data_size=pxlNr*ecat63pxlbytes(h->data_type); /* block nr taken by all pixels */ blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) { sprintf(ecat63errmsg, "invalid block number.\n"); return(4); } /* Allocate memory for matrix data */ mdata=(char*)calloc(blkNr, MatBLKSIZE); if(mdata==NULL) { sprintf(ecat63errmsg, "out of memory.\n"); return(5); } /* Search for min and max for calculation of scale factor */ fptr=fdata; fmin=fmax=*fptr; for(i=0; i<pxlNr; i++, fptr++) { if(*fptr>fmax) fmax=*fptr; else if(*fptr<fmin) fmin=*fptr; } if(fabs(fmin)>fabs(fmax)) g=fabs(fmin); else g=fabs(fmax); if(g>0) f=32766./g; else f=1.0; /* Check if pixels values can be left as such with scale_factor = 1 */ fptr=fdata; if(f>=1.0 && ecat63_is_scaling_needed(g, fptr, pxlNr)==0) f=1.0; /* Scale matrix data to shorts */ h->scale_factor=1.0/f; sptr=(short int*)mdata; fptr=fdata; for(i=0; i<pxlNr; i++, sptr++, fptr++) *sptr=(short int)temp_roundf(f*(*fptr)); /* Set header short min & max */ h->scan_min=(short int)temp_roundf(f*fmin); h->scan_max=(short int)temp_roundf(f*fmax); /* Get block number for matrix header and data */ nxtblk=ecat63Matenter(fp, matnum, blkNr); if(nxtblk<1) { sprintf(ecat63errmsg, "cannot determine matrix block (%d).\n", -nxtblk); free(mdata); return(8); } if(ECAT63_TEST>2) printf(" block=%d fmin=%g fmax=%g\n", nxtblk, fmin, fmax); /* Write header */ ret=ecat63WriteScanheader(fp, nxtblk, h); if(ret) { sprintf(ecat63errmsg, "cannot write subheader (%d).\n", ret); free(mdata); return(10); } /* Write matrix data */ mptr=mdata; ret=ecat63WriteMatdata(fp, nxtblk+1, mptr, pxlNr, ecat63pxlbytes(h->data_type)); free(mdata); if(ret) { sprintf(ecat63errmsg, "cannot write matrix data (%d).\n", ret); return(13); } return(0); }