Beispiel #1
0
/** 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);
}
Beispiel #2
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;
}
Beispiel #3
0
/**
 * 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;
}
Beispiel #4
0
/*!
 * 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;
}
Beispiel #5
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);
}
Beispiel #6
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);
}
Beispiel #7
0
/*!
 * 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);
}