コード例 #1
0
ファイル: cksum.c プロジェクト: CIBC-Internal/teem
int
unrrdu_cksumDoit(const char *me, char *inS, int endian,
                 int printendian, FILE *fout) {
  Nrrd *nrrd;
  airArray *mop;
  unsigned int crc;
  char stmp[AIR_STRLEN_SMALL], ends[AIR_STRLEN_SMALL];
  size_t nn;

  mop = airMopNew();
  airMopAdd(mop, nrrd=nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  if (nrrdLoad(nrrd, inS, NULL)) {
    biffMovef(me, NRRD, "%s: trouble loading \"%s\"", me, inS);
    airMopError(mop); return 1;
  }
  crc = nrrdCRC32(nrrd, endian);
  nn = nrrdElementNumber(nrrd)*nrrdElementSize(nrrd);
  sprintf(ends, "(%s)", airEnumStr(airEndian, endian));
  fprintf(fout, "%u%s %s%s%s\n", crc,
          printendian ? ends : "",
          airSprintSize_t(stmp, nn),
          strcmp("-", inS) ? " " : "",
          strcmp("-", inS) ? inS : "");

  airMopOkay(mop);
  return 0;
}
コード例 #2
0
ファイル: txf.c プロジェクト: CIBC-Internal/teem
int
_miteNtxfAlphaAdjust(miteRender *mrr, miteUser *muu) {
  static const char me[]="_miteNtxfAlphaAdjust";
  int ni, ei, ri, nnum, rnum;
  Nrrd *ntxf;
  mite_t *data, alpha, frac;

  if (_miteNtxfCopy(mrr, muu)) {
    biffAddf(MITE, "%s: trouble copying/converting transfer functions", me);
    return 1;
  }
  frac = muu->rayStep/muu->refStep;
  for (ni=0; ni<mrr->ntxfNum; ni++) {
    ntxf = mrr->ntxf[ni];
    if (!strchr(ntxf->axis[0].label, miteRangeChar[miteRangeAlpha])) {
      continue;
    }
    /* else this txf sets opacity */
    data = (mite_t *)ntxf->data;
    rnum = ntxf->axis[0].size;
    nnum = nrrdElementNumber(ntxf)/rnum;
    for (ei=0; ei<nnum; ei++) {
      for (ri=0; ri<rnum; ri++) {
        if (ntxf->axis[0].label[ri] == miteRangeChar[miteRangeAlpha]) {
          alpha = data[ri + rnum*ei];
          data[ri + rnum*ei] = 1 - pow(AIR_MAX(0, 1-alpha), frac);
        }
      }
    }
  }
  return 0;
}
コード例 #3
0
ファイル: clip.c プロジェクト: CIBC-Internal/teem
int
_baneClipAnswer_Percentile(int *countP, Nrrd *hvol, double *clipParm) {
  static const char me[]="_baneClipAnswer_Percentile";
  Nrrd *ncopy;
  int *hits, clip;
  size_t num, sum, out, outsofar, hi;

  if (nrrdCopy(ncopy=nrrdNew(), hvol)) {
    biffMovef(BANE, NRRD, "%s: couldn't create copy of histovol", me);
    return 1;
  }
  hits = (int *)ncopy->data;
  num = nrrdElementNumber(ncopy);
  qsort(hits, num, sizeof(int), nrrdValCompare[nrrdTypeInt]);
  sum = 0;
  for (hi=0; hi<num; hi++) {
    sum += hits[hi];
  }
  out = (size_t)(sum*clipParm[0]/100);
  outsofar = 0;
  hi = num-1;
  do {
    outsofar += hits[hi--];
  } while (outsofar < out);
  clip = hits[hi];
  nrrdNuke(ncopy);

  *countP = clip;
  return 0;
}
コード例 #4
0
ファイル: sampleIO.c プロジェクト: ewong718/freesurfer
void
demoIO(char *filename)
{
  char me[]="demoIO", newname[]="foo.nrrd", *err, *key, *val;
  int kvn, kvi;
  Nrrd *nin;

  /* create a nrrd; at this point this is just an empty container */
  nin = nrrdNew();

  /* read in the nrrd from file */
  if (nrrdLoad(nin, filename, NULL))
  {
    err = biffGetDone(NRRD);
    fprintf(stderr, "%s: trouble reading \"%s\":\n%s", me, filename, err);
    free(err);
    return;
  }

  /* say something about the array */
  printf("%s: \"%s\" is a %d-dimensional nrrd of type %d (%s)\n",
         me, filename, nin->dim, nin->type,
         airEnumStr(nrrdType, nin->type));
  printf("%s: the array contains %d elements, each %d bytes in size\n",
         me, (int)nrrdElementNumber(nin), (int)nrrdElementSize(nin));

  /* print out the key/value pairs present */
  kvn = nrrdKeyValueSize(nin);
  if (kvn)
  {
    for (kvi=0; kvi<kvn; kvi++)
    {
      nrrdKeyValueIndex(nin, &key, &val, kvi);
      printf("%s: key:value %d = %s:%s\n", me, kvi, key, val);
      free(key);
      free(val);
      key = val = NULL;
    }
  }

  /* modify key/value pairs, and write out the nrrd to a different file */
  nrrdKeyValueClear(nin);
  nrrdKeyValueAdd(nin, "new key", "precious value");
  if (nrrdSave(newname, nin, NULL))
  {
    err = biffGetDone(NRRD);
    fprintf(stderr, "%s: trouble writing \"%s\":\n%s", me, newname, err);
    free(err);
    return;
  }

  /* blow away both the Nrrd struct *and* the memory at nin->data
     (nrrdNix() frees the struct but not the data,
     nrrdEmpty() frees the data but not the struct) */
  nrrdNuke(nin);

  return;
}
コード例 #5
0
ファイル: methodsNrrd.c プロジェクト: ewong718/freesurfer
/*
******** nrrdAlloc_nva()
**
** allocates data array and sets information.  If this is a block type
** nrrd, it is necessary to set nrrd->blockSize PRIOR to calling
** this function.
**
** This function will always allocate more memory (via calloc), but
** it will free() nrrd->data if it is non-NULL when passed in.
**
** This function takes the same "don't mess with peripheral information"
** attitude as nrrdWrap().
**
** Note to Gordon: don't get clever and change ANY axis-specific
** information here.  It may be very convenient to set that before
** nrrdAlloc or nrrdMaybeAlloc
**
** Note: This function DOES use biff
*/
int
nrrdAlloc_nva(Nrrd *nrrd, int type, unsigned int dim, const size_t *size)
{
  char me[]="nrrdAlloc_nva", err[BIFF_STRLEN];
  size_t num;
  int esize;

  if (!(nrrd && size))
  {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err);
    return 1;
  }
  if (airEnumValCheck(nrrdType, type))
  {
    sprintf(err, "%s: type (%d) is invalid", me, type);
    biffAdd(NRRD, err);
    return 1;
  }
  if (nrrdTypeBlock == type)
  {
    if (!(0 < nrrd->blockSize))
    {
      sprintf(err, "%s: given nrrd->blockSize " _AIR_SIZE_T_CNV " invalid",
              me, nrrd->blockSize);
      biffAdd(NRRD, err);
      return 1;
    }
  }
  if (!AIR_IN_CL(1, dim, NRRD_DIM_MAX))
  {
    sprintf(err, "%s: dim (%d) not in valid range [1,%d]",
            me, dim, NRRD_DIM_MAX);
    biffAdd(NRRD, err);
    return 1;
  }

  nrrd->data = airFree(nrrd->data);
  if (nrrdWrap_nva(nrrd, NULL, type, dim, size))
  {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err);
    return 1 ;
  }
  num = nrrdElementNumber(nrrd);
  esize = nrrdElementSize(nrrd);
  nrrd->data = calloc(num, esize);
  if (!(nrrd->data))
  {
    sprintf(err, "%s: calloc(" _AIR_SIZE_T_CNV ",%d) failed",
            me, num, esize);
    biffAdd(NRRD, err);
    return 1 ;
  }

  return 0;
}
コード例 #6
0
ファイル: simple.c プロジェクト: 151706061/ITK
/*
******** nrrdDescribe
**
** writes verbose description of nrrd to given file
*/
void
nrrdDescribe(FILE *file, const Nrrd *nrrd) {
  unsigned int ai;
  char stmp[AIR_STRLEN_SMALL];

  if (file && nrrd) {
    fprintf(file, "Nrrd at 0x%p:\n", AIR_CVOIDP(nrrd));
    fprintf(file, "Data at 0x%p is %s elements of type %s.\n", nrrd->data,
            airSprintSize_t(stmp, nrrdElementNumber(nrrd)),
            airEnumStr(nrrdType, nrrd->type));
    if (nrrdTypeBlock == nrrd->type) {
      fprintf(file, "The blocks have size %s\n",
              airSprintSize_t(stmp, nrrd->blockSize));
    }
    if (airStrlen(nrrd->content)) {
      fprintf(file, "Content = \"%s\"\n", nrrd->content);
    }
    fprintf(file, "%d-dimensional array, with axes:\n", nrrd->dim);
    for (ai=0; ai<nrrd->dim; ai++) {
      if (airStrlen(nrrd->axis[ai].label)) {
        fprintf(file, "%d: (\"%s\") ", ai, nrrd->axis[ai].label);
      } else {
        fprintf(file, "%d: ", ai);
      }
      fprintf(file, "%s-centered, size=%s, ",
              airEnumStr(nrrdCenter, nrrd->axis[ai].center),
              airSprintSize_t(stmp, nrrd->axis[ai].size));
      airSinglePrintf(file, NULL, "spacing=%lg, \n", nrrd->axis[ai].spacing);
      airSinglePrintf(file, NULL, "thickness=%lg, \n",
                      nrrd->axis[ai].thickness);
      airSinglePrintf(file, NULL, "    axis(Min,Max) = (%lg,",
                       nrrd->axis[ai].min);
      airSinglePrintf(file, NULL, "%lg)\n", nrrd->axis[ai].max);
      if (airStrlen(nrrd->axis[ai].units)) {
        fprintf(file, "units=%s, \n", nrrd->axis[ai].units);
      }
    }
    /*
    airSinglePrintf(file, NULL, "The min, max values are %lg",
                     nrrd->min);
    airSinglePrintf(file, NULL, ", %lg\n", nrrd->max);
    */
    airSinglePrintf(file, NULL, "The old min, old max values are %lg",
                     nrrd->oldMin);
    airSinglePrintf(file, NULL, ", %lg\n", nrrd->oldMax);
    /* fprintf(file, "hasNonExist = %d\n", nrrd->hasNonExist); */
    if (nrrd->cmtArr->len) {
      fprintf(file, "Comments:\n");
      for (ai=0; ai<nrrd->cmtArr->len; ai++) {
        fprintf(file, "%s\n", nrrd->cmt[ai]);
      }
    }
    fprintf(file, "\n");
  }
}
コード例 #7
0
ファイル: triple.c プロジェクト: BRAINSia/teem
int
tenTripleConvert(Nrrd *nout, int dstType,
                 const Nrrd *nin, int srcType) {
  static const char me[]="tenTripleConvert";
  size_t II, NN;
  double (*ins)(void *, size_t, double), (*lup)(const void *, size_t);

  if (!( nout && nin )) {
    biffAddf(TEN, "%s: got NULL pointer", me);
    return 1;
  }
  if ( airEnumValCheck(tenTripleType, dstType) ||
       airEnumValCheck(tenTripleType, srcType) ) {
    biffAddf(TEN, "%s: got invalid %s dst (%d) or src (%d)", me,
             tenTripleType->name, dstType, srcType);
    return 1;
  }
  if (3 != nin->axis[0].size) {
    char stmp[AIR_STRLEN_SMALL];
    biffAddf(TEN, "%s: need axis[0].size 3, not %s", me,
             airSprintSize_t(stmp, nin->axis[0].size));
    return 1;
  }
  if (nrrdTypeBlock == nin->type) {
    biffAddf(TEN, "%s: input has non-scalar %s type",
             me, airEnumStr(nrrdType, nrrdTypeBlock));
    return 1;
  }

  if (nrrdCopy(nout, nin)) {
    biffMovef(TEN, NRRD, "%s: couldn't initialize output", me);
    return 1;
  }
  lup = nrrdDLookup[nin->type];
  ins = nrrdDInsert[nout->type];
  NN = nrrdElementNumber(nin)/3;
  for (II=0; II<NN; II++) {
    double src[3], dst[3];
    src[0] = lup(nin->data, 0 + 3*II);
    src[1] = lup(nin->data, 1 + 3*II);
    src[2] = lup(nin->data, 2 + 3*II);
    tenTripleConvertSingle_d(dst, dstType, src, srcType);
    ins(nout->data, 0 + 3*II, dst[0]);
    ins(nout->data, 1 + 3*II, dst[1]);
    ins(nout->data, 2 + 3*II, dst[2]);
  }

  return 0;
}
コード例 #8
0
ファイル: clip.c プロジェクト: CIBC-Internal/teem
int
_baneClipAnswer_PeakRatio(int *countP, Nrrd *hvol, double *clipParm) {
  int *hits, maxhits;
  size_t idx, num;

  hits = (int *)hvol->data;
  maxhits = 0;
  num = nrrdElementNumber(hvol);
  for (idx=0; idx<num; idx++) {
    maxhits = AIR_MAX(maxhits, hits[idx]);
  }

  *countP = (int)(maxhits*clipParm[0]);
  return 0;
}
コード例 #9
0
ファイル: arith.c プロジェクト: BRAINSia/teem
unsigned int
nrrdCRC32(const Nrrd *nin, int endian) {
  size_t nn;

  /* NULL nrrd or data */
  if (!nin
      || !(nin->data)
      || !(nn = nrrdElementSize(nin)*nrrdElementNumber(nin))
      || airEnumValCheck(airEndian, endian)) {
    return 0;
  }

  return airCRC32(AIR_CAST(const unsigned char *, nin->data),
                  nn, nrrdElementSize(nin),
                  endian == airMyEndian() ? AIR_FALSE : AIR_TRUE);
}
コード例 #10
0
ファイル: methodsNrrd.c プロジェクト: SCIInstitute/Cleaver
int
_nrrdCopy(Nrrd *nout, const Nrrd *nin, int bitflag) {
  char me[]="_nrrdCopy", err[BIFF_STRLEN];
  size_t size[NRRD_DIM_MAX];

  if (!(nin && nout)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nout == nin) {
    /* its not the case that we have nothing to do- the semantics of
       copying cannot be achieved if the input and output nrrd are
       the same; this is an error */
    sprintf(err, "%s: nout==nin disallowed", me);
    biffAdd(NRRD, err); return 1;
  }
  if (!nrrdElementSize(nin)) {
    sprintf(err, "%s: input nrrd reports zero element size!", me);
    biffAdd(NRRD, err); return 1;
  }
  nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, size);
  if (nin->data) {
    if (nrrdMaybeAlloc_nva(nout, nin->type, nin->dim, size)) {
      sprintf(err, "%s: couldn't allocate data", me);
      biffAdd(NRRD, err); return 1;
    }
    memcpy(nout->data, nin->data,
           nrrdElementNumber(nin)*nrrdElementSize(nin));
  } else {
    /* someone is trying to copy structs without data, fine fine fine */
    if (nrrdWrap_nva(nout, NULL, nin->type, nin->dim, size)) {
      sprintf(err, "%s: couldn't allocate data", me);
      biffAdd(NRRD, err); return 1;
    }
  }
  nrrdAxisInfoCopy(nout, nin, NULL, NRRD_AXIS_INFO_SIZE_BIT);
  /* if nin->data non-NULL (second branch above), this will 
     harmlessly unset and set type and dim */
  nrrdBasicInfoInit(nout, NRRD_BASIC_INFO_DATA_BIT | bitflag);
  if (nrrdBasicInfoCopy(nout, nin, NRRD_BASIC_INFO_DATA_BIT | bitflag)) {
    sprintf(err, "%s: trouble copying basic info", me);
    biffAdd(NRRD, err); return 1;
  }

  return 0;
}
コード例 #11
0
ファイル: arith.c プロジェクト: BRAINSia/teem
int
nrrdArithUnaryOp(Nrrd *nout, int op, const Nrrd *nin) {
  static const char me[]="nrrdArithUnaryOp";
  size_t N, I;
  int size[NRRD_DIM_MAX];
  double (*insert)(void *v, size_t I, double d),
    (*lookup)(const void *v, size_t I), (*uop)(double), val;

  if (!(nout && nin)) {
    biffAddf(NRRD, "%s: got NULL pointer", me);
    return 1;
  }
  if (nrrdTypeBlock == nin->type) {
    biffAddf(NRRD, "%s: can't operate on type %s", me,
             airEnumStr(nrrdType, nrrdTypeBlock));
    return 1;
  }
  if (airEnumValCheck(nrrdUnaryOp, op)) {
    biffAddf(NRRD, "%s: unary op %d invalid", me, op);
    return 1;
  }
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      biffAddf(NRRD, "%s:", me);
      return 1;
    }
  }
  nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, size);
  uop = _nrrdUnaryOp[op];

  N = nrrdElementNumber(nin);
  lookup = nrrdDLookup[nin->type];
  insert = nrrdDInsert[nin->type];
  for (I=0; I<N; I++) {
    val = lookup(nin->data, I);
    insert(nout->data, I, uop(val));
  }
  if (nrrdContentSet_va(nout, airEnumStr(nrrdUnaryOp, op), nin, "")) {
    biffAddf(NRRD, "%s:", me);
    return 1;
  }
  nrrdBasicInfoInit(nout,
                    NRRD_BASIC_INFO_ALL ^ (NRRD_BASIC_INFO_OLDMIN_BIT
                                           | NRRD_BASIC_INFO_OLDMAX_BIT));
  return 0;
}
コード例 #12
0
ファイル: arith.c プロジェクト: BRAINSia/teem
int
nrrdArithAffine(Nrrd *nout, double minIn,
                const Nrrd *nin, double maxIn,
                double minOut, double maxOut, int clamp) {
  static const char me[]="nrrdArithAffine";
  size_t I, N;
  double (*ins)(void *v, size_t I, double d),
    (*lup)(const void *v, size_t I), mmin, mmax;

  if ( !nout || nrrdCheck(nin) ) {
    biffAddf(NRRD, "%s: got NULL pointer or invalid input", me);
    return 1;
  }
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      biffAddf(NRRD, "%s: couldn't initialize output", me);
      return 1;
    }
  }
  N = nrrdElementNumber(nin);
  ins = nrrdDInsert[nout->type];
  lup = nrrdDLookup[nin->type];
  mmin = AIR_MIN(minOut, maxOut);
  mmax = AIR_MAX(minOut, maxOut);
  for (I=0; I<N; I++) {
    double val;
    val = lup(nin->data, I);
    val = AIR_AFFINE(minIn, val, maxIn, minOut, maxOut);
    if (clamp) {
      val = AIR_CLAMP(mmin, val, mmax);
    }
    ins(nout->data, I, val);
  }
  /* HEY: it would be much better if the ordering here was the same as in
     AIR_AFFINE, but that's not easy with the way the content functions are
     now set up */
  if (nrrdContentSet_va(nout, "affine", nin,
                        "%g,%g,%g,%g", minIn, maxIn,
                        minOut, maxOut)) {
    biffAddf(NRRD, "%s:", me);
  }
  return 0;
}
コード例 #13
0
ファイル: clip.c プロジェクト: CIBC-Internal/teem
int
_baneClipAnswer_TopN(int *countP, Nrrd *hvol, double *clipParm) {
  static const char me[]="_baneClipAnwer_TopN";
  Nrrd *copy;
  int *hits, tmp;
  size_t num;

  if (nrrdCopy(copy=nrrdNew(), hvol)) {
    biffMovef(BANE, NRRD, "%s: couldn't create copy of histovol", me);
    return 1;
  }
  hits = (int *)copy->data;
  num = nrrdElementNumber(copy);
  qsort(hits, num, sizeof(int), nrrdValCompare[nrrdTypeInt]);
  tmp = AIR_CLAMP(0, (int)clipParm[0], (int)num-1);
  *countP = hits[num-tmp-1];
  nrrdNuke(copy);

  return 0;
}
コード例 #14
0
ファイル: splineEval.c プロジェクト: rblake/seg3d2
int
limnSplineNrrdEvaluate(Nrrd *nout, limnSpline *spline, Nrrd *nin) {
  char me[]="limnSplineNrrdEvaluate", err[BIFF_STRLEN];
  double tt, *out, (*lup)(const void *, size_t);
  int odim, infoSize;
  size_t I, M, size[NRRD_DIM_MAX+1];

  if (!(nout && spline && nin)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(LIMN, err); return 1;
  }
  if (limnSplineInfoScalar == spline->info) {
    nrrdAxisInfoGet_va(nin, nrrdAxisInfoSize, size);
    infoSize = 1;
    odim = nin->dim;
  } else {
    nrrdAxisInfoGet_va(nin, nrrdAxisInfoSize, size+1);
    infoSize = size[0] = limnSplineInfoSize[spline->info];
    odim = 1 + nin->dim;
  }
  if (nrrdMaybeAlloc_nva(nout, nrrdTypeDouble, odim, size)) {
    sprintf(err, "%s: output allocation failed", me);
    biffMove(LIMN, err, NRRD); return 1;
  }
  lup = nrrdDLookup[nin->type];
  out = (double*)(nout->data);
  M = nrrdElementNumber(nin);
  for (I=0; I<M; I++) {
    tt = lup(nin->data, I);
    limnSplineEvaluate(out, spline, tt);
    out += infoSize;
  }

  /* HEY: peripheral info copying? */

  return 0;
}
コード例 #15
0
ファイル: formatVTK.c プロジェクト: CIBC-Internal/teem
/* this strongly assumes that nrrdFitsInFormat() was true */
int
_nrrdFormatVTK_write(FILE *file, const Nrrd *_nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdFormatVTK_write";
  int i, sx, sy, sz, sax;
  double xs, ys, zs, xm, ym, zm;
  char type[AIR_STRLEN_MED], name[AIR_STRLEN_SMALL];
  Nrrd *nrrd;
  airArray *mop;

  /* HEY: should this copy be done more conservatively */
  mop = airMopNew();
  airMopAdd(mop, nrrd=nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  if (nrrdCopy(nrrd, _nrrd)) {
    biffAddf(NRRD, "%s: couldn't make private copy", me);
    airMopError(mop); return 1;
  }
  if (!( 3 == nrrd->dim ||
         (4 == nrrd->dim && (3 == nrrd->axis[0].size ||
                             9 == nrrd->axis[0].size)) )) {
    biffAddf(NRRD, "%s: doesn't seem to be scalar, vector, or matrix", me);
    airMopError(mop); return 1;
  }
  sax = nrrd->dim - 3;
  xs = nrrd->axis[sax+0].spacing;
  ys = nrrd->axis[sax+1].spacing;
  zs = nrrd->axis[sax+2].spacing;
  if (!( AIR_EXISTS(xs) && AIR_EXISTS(ys) && AIR_EXISTS(zs) )) {
    xs = ys = zs = 1.0;
  }
  xm = nrrd->axis[sax+0].min;
  ym = nrrd->axis[sax+1].min;
  zm = nrrd->axis[sax+2].min;
  if (!( AIR_EXISTS(xm) && AIR_EXISTS(ym) && AIR_EXISTS(zm) )) {
    xm = ym = zm = 0.0;
  }
  sx = AIR_CAST(int, nrrd->axis[sax+0].size);
  sy = AIR_CAST(int, nrrd->axis[sax+1].size);
  sz = AIR_CAST(int, nrrd->axis[sax+2].size);

  switch(nrrd->type) {
  case nrrdTypeUChar:
    strcpy(type, "unsigned_char");
    break;
  case nrrdTypeChar:
    strcpy(type, "char");
    break;
  case nrrdTypeUShort:
    strcpy(type, "unsigned_short");
    break;
  case nrrdTypeShort:
    strcpy(type, "short");
    break;
  case nrrdTypeUInt:
    strcpy(type, "unsigned_int");
    break;
  case nrrdTypeInt:
    strcpy(type, "int");
    break;
  case nrrdTypeFloat:
    strcpy(type, "float");
    break;
  case nrrdTypeDouble:
    strcpy(type, "double");
    break;
  default:
    biffAddf(NRRD, "%s: can't put %s-type nrrd into VTK", me,
             airEnumStr(nrrdType, nrrd->type));
    airMopError(mop); return 1;
  }
  fprintf(file, "%s\n", MAGIC3);
  /* there is a file-format-imposed limit on the length of the "content" */
  if (nrrd->content) {
    /* when the "250" below was previously "255", vtk didn't deal */
    for (i=0; i<=250 && nrrd->content[i]; i++) {
      fputc(nrrd->content[i], file);
    }
    fputc('\n', file);
  } else {
    fprintf(file, NRRD_UNKNOWN "\n");
  }
  if (nrrdEncodingRaw == nio->encoding) {
    fprintf(file, "BINARY\n");
  } else {
    fprintf(file, "ASCII\n");
  }
  fprintf(file, "DATASET STRUCTURED_POINTS\n");
  fprintf(file, "DIMENSIONS %d %d %d\n", sx, sy, sz);
  fprintf(file, "ORIGIN %g %g %g\n", xm, ym, zm);
  fprintf(file, "SPACING %g %g %g\n", xs, ys, zs);
  fprintf(file, "POINT_DATA %d\n", sx*sy*sz);
  airSrandMT(AIR_CAST(unsigned int, airTime()));
  sprintf(name, "nrrd%05d", airRandInt(100000));
  if (3 == nrrd->dim) {
    fprintf(file, "SCALARS %s %s\n", name, type);
    fprintf(file, "LOOKUP_TABLE default\n");
  } else {
    /* 4 == nrrd->dim */
    if (3 == nrrd->axis[0].size) {
      fprintf(file, "VECTORS %s %s\n", name, type);
    } else {
      fprintf(file, "TENSORS %s %s\n", name, type);
    }
  }
  if (1 < nrrdElementSize(nrrd)
      && nio->encoding->endianMatters
      && airMyEndian() != airEndianBig) {
    /* encoding exposes endianness, and we're not big, as req.d by VTK */
    nrrdSwapEndian(nrrd);
  }
  if (nio->encoding->write(file, nrrd->data, nrrdElementNumber(nrrd),
                           nrrd, nio)) {
    biffAddf(NRRD, "%s:", me);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  return 0;
}
コード例 #16
0
ファイル: iso.cpp プロジェクト: kindlmann/hale
int
main(int argc, const char **argv) {
  const char *me;
  char *err;
  hestOpt *hopt=NULL;
  hestParm *hparm;
  airArray *mop;

  /* variables learned via hest */
  Nrrd *nin;
  float camfr[3], camat[3], camup[3], camnc, camfc, camFOV;
  int camortho, hitandquit;
  unsigned int camsize[2];
  double isovalue, sliso, isomin, isomax;

  /* boilerplate hest code */
  me = argv[0];
  mop = airMopNew();
  hparm = hestParmNew();
  hparm->respFileEnable = AIR_TRUE;
  airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways);
  /* setting up the command-line options */
  hparm->respFileEnable = AIR_TRUE;
  hestOptAdd(&hopt, "i", "volume", airTypeOther, 1, 1, &nin, NULL,
             "input volume to isosurface", NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&hopt, "v", "isovalue", airTypeDouble, 1, 1, &isovalue, "nan",
             "isovalue at which to run Marching Cubes");
  hestOptAdd(&hopt, "fr", "x y z", airTypeFloat, 3, 3, camfr, "3 4 5",
             "look-from point");
  hestOptAdd(&hopt, "at", "x y z", airTypeFloat, 3, 3, camat, "0 0 0",
             "look-at point");
  hestOptAdd(&hopt, "up", "x y z", airTypeFloat, 3, 3, camup, "0 0 1",
             "up direction");
  hestOptAdd(&hopt, "nc", "dist", airTypeFloat, 1, 1, &(camnc), "-2",
             "at-relative near clipping distance");
  hestOptAdd(&hopt, "fc", "dist", airTypeFloat, 1, 1, &(camfc), "2",
             "at-relative far clipping distance");
  hestOptAdd(&hopt, "fov", "angle", airTypeFloat, 1, 1, &(camFOV), "20",
             "vertical field-of-view, in degrees. Full vertical "
             "extent of image plane subtends this angle.");
  hestOptAdd(&hopt, "sz", "s0 s1", airTypeUInt, 2, 2, &(camsize), "640 480",
             "# samples (horz vert) of image plane. ");
  hestOptAdd(&hopt, "ortho", NULL, airTypeInt, 0, 0, &(camortho), NULL,
             "use orthographic instead of (the default) "
             "perspective projection ");
  hestOptAdd(&hopt, "haq", NULL, airTypeBool, 0, 0, &(hitandquit), NULL,
             "save a screenshot rather than display the viewer");

  hestParseOrDie(hopt, argc-1, argv+1, hparm,
                 me, "demo program", AIR_TRUE, AIR_TRUE, AIR_TRUE);
  airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways);
  airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways);

  /* learn value range, and set initial isovalue if needed */
  NrrdRange *range = nrrdRangeNewSet(nin, AIR_FALSE);
  airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
  isomin = range->min;
  isomax = range->max;
  if (!AIR_EXISTS(isovalue)) {
    isovalue = (isomin + isomax)/2;
  }

  /* first, make sure we can isosurface ok */
  limnPolyData *lpld = limnPolyDataNew();
  seekContext *sctx = seekContextNew();
  airMopAdd(mop, sctx, (airMopper)seekContextNix, airMopAlways);
  sctx->pldArrIncr = nrrdElementNumber(nin);
  seekVerboseSet(sctx, 0);
  seekNormalsFindSet(sctx, AIR_TRUE);
  if (seekDataSet(sctx, nin, NULL, 0)
      || seekTypeSet(sctx, seekTypeIsocontour)
      || seekIsovalueSet(sctx, isovalue)
      || seekUpdate(sctx)
      || seekExtract(sctx, lpld)) {
    airMopAdd(mop, err=biffGetDone(SEEK), airFree, airMopAlways);
    fprintf(stderr, "trouble with isosurfacing:\n%s", err);
    airMopError(mop);
    return 1;
  }
  if (!lpld->xyzwNum) {
    fprintf(stderr, "%s: warning: No isocontour generated at isovalue %g\n",
            me, isovalue);
  }

  /* then create empty scene */
  Hale::init();
  Hale::Scene scene;
  /* then create viewer (in order to create the OpenGL context) */
  Hale::Viewer viewer(camsize[0], camsize[1], "Iso", &scene);
  viewer.lightDir(glm::vec3(-1.0f, 1.0f, 3.0f));
  viewer.camera.init(glm::vec3(camfr[0], camfr[1], camfr[2]),
                     glm::vec3(camat[0], camat[1], camat[2]),
                     glm::vec3(camup[0], camup[1], camup[2]),
                     camFOV, (float)camsize[0]/camsize[1],
                     camnc, camfc, camortho);
  viewer.refreshCB((Hale::ViewerRefresher)render);
  viewer.refreshData(&viewer);
  sliso = isovalue;
  viewer.slider(&sliso, isomin, isomax);
  viewer.current();


  /* then create geometry, and add it to scene */
  Hale::Polydata hply(lpld, true,  // hply now owns lpld
                      Hale::ProgramLib(Hale::preprogramAmbDiff2SideSolid));
  scene.add(&hply);


  scene.drawInit();
  render(&viewer);
  if (hitandquit) {
    seekIsovalueSet(sctx, isovalue);
    seekUpdate(sctx);
    seekExtract(sctx, lpld);
    hply.rebuffer();

    render(&viewer);
    glfwWaitEvents();
    render(&viewer);
    viewer.snap();
    Hale::done();
    airMopOkay(mop);
    return 0;
  }
  while(!Hale::finishing){
    glfwWaitEvents();
    if (viewer.sliding() && sliso != isovalue) {
      isovalue = sliso;
      printf("%s: isosurfacing at %g\n", me, isovalue);
      seekIsovalueSet(sctx, isovalue);
      seekUpdate(sctx);
      seekExtract(sctx, lpld);
      hply.rebuffer();
    }
    render(&viewer);
  }

  /* clean exit; all okay */
  Hale::done();
  airMopOkay(mop);
  return 0;
}
コード例 #17
0
ファイル: write.c プロジェクト: guo2004131/freesurfer
/*
** _nrrdSprintFieldInfo
**
** this prints "<prefix><field>: <info>" into *strP (after allocating it for
** big enough, usually with a stupidly big margin of error), in a form
** suitable to be written to NRRD or other image headers.  This will always
** print something (for valid inputs), even stupid <info>s like
** "(unknown endian)".  It is up to the caller to decide which fields
** are worth writing, via _nrrdFieldInteresting().
**
** NOTE: some of these fields make sense in non-NRRD files (e.g. all
** the per-axis information), but many only make sense in NRRD files.
** This is just one example of NRRD-format-specific stuff that is not
** in formatNRRD.c
*/
void
_nrrdSprintFieldInfo(char **strP, char *prefix,
                     const Nrrd *nrrd, NrrdIoState *nio, int field)
{
    char me[]="_nrrdSprintFieldInfo", buff[AIR_STRLEN_MED], *fnb;
    double colvec[NRRD_SPACE_DIM_MAX];
    const char *fs;
    unsigned int ii, dd,
             uintStrlen = 11,
             size_tStrlen = 33,
             doubleStrlen = 513;
    int fslen, fdlen, endi, maxl;

    if (!( strP && prefix
            && nrrd
            && AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX)
            && AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) ))
    {
        return;
    }
    if (!_nrrdFieldInteresting(nrrd, nio, field))
    {
        *strP = airStrdup("");
    }

    fs = airEnumStr(nrrdField, field);
    fslen = strlen(prefix) + strlen(fs) + strlen(": ") + 1;
    switch (field)
    {
    case nrrdField_comment:
    case nrrdField_keyvalue:
        fprintf(stderr, "%s: CONFUSION: why are you calling me on \"%s\"?\n", me,
                airEnumStr(nrrdField, nrrdField_comment));
        *strP = airStrdup("");
        break;
    case nrrdField_content:
        airOneLinify(nrrd->content);
        *strP = (char *)calloc(fslen + strlen(nrrd->content), sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, nrrd->content);
        break;
    case nrrdField_number:
        *strP = (char *)calloc(fslen + size_tStrlen, sizeof(char));
        sprintf(*strP, "%s%s: " _AIR_SIZE_T_CNV, prefix, fs,
                nrrdElementNumber(nrrd));
        break;
    case nrrdField_type:
        *strP = (char *)calloc(fslen + strlen(airEnumStr(nrrdType, nrrd->type)),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdType, nrrd->type));
        break;
    case nrrdField_block_size:
        *strP = (char *)calloc(fslen + size_tStrlen, sizeof(char));
        sprintf(*strP, "%s%s: " _AIR_SIZE_T_CNV, prefix, fs, nrrd->blockSize);
        break;
    case nrrdField_dimension:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->dim);
        break;
    case nrrdField_space:
        *strP = (char *)calloc(fslen + strlen(airEnumStr(nrrdSpace, nrrd->space)),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdSpace, nrrd->space));
        break;
    case nrrdField_space_dimension:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->spaceDim);
        break;
    /* ---- begin per-axis fields ---- */
    case nrrdField_sizes:
        *strP = (char *)calloc(fslen + nrrd->dim*(size_tStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            sprintf(buff, " " _AIR_SIZE_T_CNV, nrrd->axis[ii].size);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_spacings:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].spacing);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_thicknesses:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].thickness);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_axis_mins:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].min);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_axis_maxs:
        *strP = (char *)calloc(fslen + nrrd->dim*(doubleStrlen + 1), sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            airSinglePrintf(NULL, buff, " %g", nrrd->axis[ii].max);
            strcat(*strP, buff);
        }
        break;
    case nrrdField_space_directions:
        *strP = (char *)calloc(fslen +
                               nrrd->dim*nrrd->spaceDim*(doubleStrlen
                                       + strlen("(,) ")),
                               sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim,
                                   nrrd->axis[ii].spaceDirection);
            if (ii < nrrd->dim-1)
            {
                strcat(*strP, " ");
            }
        }
        break;
    case nrrdField_centers:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += 1 + airStrlen(nrrd->axis[ii].center
                                   ? airEnumStr(nrrdCenter, nrrd->axis[ii].center)
                                   : NRRD_UNKNOWN);
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            sprintf(buff, " %s",
                    (nrrd->axis[ii].center
                     ? airEnumStr(nrrdCenter, nrrd->axis[ii].center)
                     : NRRD_UNKNOWN));
            strcat(*strP, buff);
        }
        break;
    case nrrdField_kinds:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += 1 + airStrlen(nrrd->axis[ii].kind
                                   ? airEnumStr(nrrdKind, nrrd->axis[ii].kind)
                                   : NRRD_UNKNOWN);
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            sprintf(buff, " %s",
                    (nrrd->axis[ii].kind
                     ? airEnumStr(nrrdKind, nrrd->axis[ii].kind)
                     : NRRD_UNKNOWN));
            strcat(*strP, buff);
        }
        break;
    case nrrdField_labels:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += airStrlen(nrrd->axis[ii].label) + 4;
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            strcat(*strP, " \"");
            if (airStrlen(nrrd->axis[ii].label))
            {
                strcat(*strP, nrrd->axis[ii].label);
            }
            strcat(*strP, "\"");
        }
        break;
    case nrrdField_units:
        fdlen = 0;
        for (ii=0; ii<nrrd->dim; ii++)
        {
            fdlen += airStrlen(nrrd->axis[ii].units) + 4;
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->dim; ii++)
        {
            strcat(*strP, " \"");
            if (airStrlen(nrrd->axis[ii].units))
            {
                strcat(*strP, nrrd->axis[ii].units);
            }
            strcat(*strP, "\"");
        }
        break;
    /* ---- end per-axis fields ---- */
    case nrrdField_min:
    case nrrdField_max:
        /* we're basically a no-op, now that these fields became meaningless */
        *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char));
        sprintf(*strP, "%s%s: 0.0", prefix, fs);
        strcat(*strP, buff);
        break;
    case nrrdField_old_min:
        *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        airSinglePrintf(NULL, buff, "%g", nrrd->oldMin);
        strcat(*strP, buff);
        break;
    case nrrdField_old_max:
        *strP = (char *)calloc(fslen + doubleStrlen, sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        airSinglePrintf(NULL, buff, "%g", nrrd->oldMax);
        strcat(*strP, buff);
        break;
    case nrrdField_endian:
        if (airEndianUnknown != nio->endian)
        {
            /* we know a specific endianness because either it was recorded as
               part of "unu make -h", or it was set (and data was possibly
               altered) as part of "unu save" */
            endi = nio->endian;
        }
        else
        {
            /* we record our current architecture's endian because we're
               going to writing out data */
            endi = AIR_ENDIAN;
        }
        *strP = (char *)calloc(fslen + strlen(airEnumStr(airEndian, endi)),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(airEndian, endi));
        break;
    case nrrdField_encoding:
        *strP = (char *)calloc(fslen + strlen(nio->encoding->name),
                               sizeof(char));
        sprintf(*strP, "%s%s: %s", prefix, fs, nio->encoding->name);
        break;
    case nrrdField_line_skip:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nio->lineSkip);
        break;
    case nrrdField_byte_skip:
        *strP = (char *)calloc(fslen + uintStrlen, sizeof(char));
        sprintf(*strP, "%s%s: %d", prefix, fs, nio->byteSkip);
        break;
    case nrrdField_sample_units:
        airOneLinify(nrrd->sampleUnits);
        *strP = (char *)calloc(fslen + strlen(nrrd->sampleUnits), sizeof(char));
        sprintf(*strP, "%s%s: \"%s\"", prefix, fs, nrrd->sampleUnits);
        break;
    case nrrdField_space_units:
        fdlen = 0;
        for (ii=0; ii<nrrd->spaceDim; ii++)
        {
            fdlen += airStrlen(nrrd->spaceUnits[ii]) + 4;
        }
        *strP = (char *)calloc(fslen + fdlen, sizeof(char));
        sprintf(*strP, "%s%s:", prefix, fs);
        for (ii=0; ii<nrrd->spaceDim; ii++)
        {
            strcat(*strP, " \"");
            if (airStrlen(nrrd->spaceUnits[ii]))
            {
                strcat(*strP, nrrd->spaceUnits[ii]);
            }
            strcat(*strP, "\"");
        }
        break;
    case nrrdField_space_origin:
        *strP = (char *)calloc(fslen + nrrd->spaceDim*(doubleStrlen
                               + strlen("(,) ")),
                               sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, nrrd->spaceOrigin);
        break;
    case nrrdField_measurement_frame:
        *strP = (char *)calloc(fslen + (nrrd->spaceDim*
                                        nrrd->spaceDim*(doubleStrlen
                                                + strlen("(,) "))),
                               sizeof(char));
        sprintf(*strP, "%s%s: ", prefix, fs);
        for (dd=0; dd<nrrd->spaceDim; dd++)
        {
            for (ii=0; ii<nrrd->spaceDim; ii++)
            {
                colvec[ii] = nrrd->measurementFrame[dd][ii];
            }
            _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, colvec);
            if (dd < nrrd->spaceDim-1)
            {
                strcat(*strP, " ");
            }
        }
        break;
    case nrrdField_data_file:
        /* NOTE: this comes last (nrrdField_data_file is the highest-valued
           member of the nrrdField* enum) because the "LIST" form of the
           data file specification requires that the following lines be
           the filenames */
        /* error checking elsewhere: assumes there is data file info */
        if (nio->dataFNFormat)
        {
            *strP = (char *)calloc(fslen + strlen(nio->dataFNFormat) + 4*uintStrlen,
                                   sizeof(char));
            if (nio->dataFileDim == nrrd->dim-1)
            {
                sprintf(*strP, "%s%s: %s %d %d %d", prefix, fs, nio->dataFNFormat,
                        nio->dataFNMin, nio->dataFNMax, nio->dataFNStep);
            }
            else
            {
                sprintf(*strP, "%s%s: %s %d %d %d %d", prefix, fs, nio->dataFNFormat,
                        nio->dataFNMin, nio->dataFNMax, nio->dataFNStep,
                        nio->dataFileDim);
            }
        }
        else if (nio->dataFNArr->len > 1)
        {
            maxl = 0;
            for (ii=0; ii<nio->dataFNArr->len; ii++)
            {
                maxl = AIR_MAX(maxl, (int)strlen(nio->dataFN[ii]));
            }
            *strP = (char *)calloc(fslen + strlen(NRRD_LIST_FLAG)
                                   + uintStrlen + nio->dataFNArr->len * (maxl + 1),
                                   sizeof(char));
            fnb = (char *)calloc(fslen + strlen(NRRD_LIST_FLAG)
                                 + uintStrlen + maxl + 1,
                                 sizeof(char));
            if (nio->dataFileDim == nrrd->dim-1)
            {
                sprintf(*strP, "%s%s: LIST\n", prefix, fs);
            }
            else
            {
                sprintf(*strP, "%s%s: LIST %d\n", prefix, fs, nio->dataFileDim);
            }
            for (ii=0; ii<nio->dataFNArr->len; ii++)
            {
                sprintf(fnb, "%s%s", nio->dataFN[ii],
                        ii<nio->dataFNArr->len-1 ? "\n" : "");
                strcat(*strP, fnb);
            }
            free(fnb);
        }
        else
        {
            /* there is some ambiguity between a "LIST" of length one,
               and a single explicit data filename, but that's harmless */
            *strP = (char *)calloc(fslen + strlen("./")
                                   + strlen(nio->dataFN[0]) + 1,
                                   sizeof(char));
            sprintf(*strP, "%s%s: %s%s", prefix, fs,
                    /* this is a favor to older readers that can deal with
                       this NRRD file because its being saved in a NRRD0003
                       (or below) version, so we don't want to confuse them
                       by not having the old explicit header-relative flag */
                    (_nrrdFormatNRRD_whichVersion(nrrd, nio) < 4 ? "./" : ""),
                    nio->dataFN[0]);
        }
        break;
    default:
        fprintf(stderr, "%s: CONFUSION: field %d unrecognized\n", me, field);
        break;
    }

    return;
}
コード例 #18
0
ファイル: resampleNrrd.c プロジェクト: rblake/seg3d2
/*
******** nrrdSpatialResample()
**
** general-purpose array-resampler: resamples a nrrd of any type
** (except block) and any dimension along any or all of its axes, with
** any combination of up- or down-sampling along the axes, with any
** kernel (specified by callback), with potentially a different kernel
** for each axis.  Whether or not to resample along axis d is
** controlled by the non-NULL-ity of info->kernel[ai].  Where to sample
** on the axis is controlled by info->min[ai] and info->max[ai]; these
** specify a range of "positions" aka "world space" positions, as 
** determined by the per-axis min and max of the input nrrd, which must
** be set for every resampled axis.
** 
** we cyclically permute those axes being resampled, and never touch
** the position (in axis ordering) of axes along which we are not
** resampling.  This strategy is certainly not the most intelligent
** one possible, but it does mean that the axis along which we're
** currently resampling-- the one along which we'll have to look at
** multiple adjecent samples-- is that resampling axis which is
** currently most contiguous in memory.  It may make sense to precede
** the resampling with an axis permutation which bubbles all the
** resampled axes to the front (most contiguous) end of the axis list,
** and then puts them back in place afterwards, depending on the cost
** of such axis permutation overhead.
*/
int
nrrdSpatialResample(Nrrd *nout, const Nrrd *nin,
                    const NrrdResampleInfo *info) {
  char me[]="nrrdSpatialResample", func[]="resample", err[BIFF_STRLEN];
  nrrdResample_t
    *array[NRRD_DIM_MAX],      /* intermediate copies of the input data
                                  undergoing resampling; we don't need a full-
                                  fledged nrrd for these.  Only about two of
                                  these arrays will be allocated at a time;
                                  intermediate results will be free()d when not
                                  needed */
    *_inVec,                   /* current input vector being resampled;
                                  not necessarily contiguous in memory
                                  (if strideIn != 1) */
    *inVec,                    /* buffer for input vector; contiguous */
    *_outVec;                  /* output vector in context of volume;
                                  never contiguous */
  double tmpF;
  double ratio,                /* factor by which or up or downsampled */
    ratios[NRRD_DIM_MAX];      /* record of "ratio" for all resampled axes,
                                  used to compute new spacing in output */

  Nrrd *floatNin;              /* if the input nrrd type is not nrrdResample_t,
                                  then we convert it and keep it here */
  unsigned int ai,
    pi,                        /* current pass */
    topLax,
    permute[NRRD_DIM_MAX],     /* how to permute axes of last pass to get
                                  axes for current pass */
    ax[NRRD_DIM_MAX+1][NRRD_DIM_MAX],  /* axis ordering on each pass */
    passes;                    /* # of passes needed to resample all axes */
  int i, s, e,
    topRax,                    /* the lowest index of an axis which is
                                  resampled.  If all axes are being resampled,
                                  then this is 0.  If for some reason the
                                  "x" axis (fastest stride) is not being
                                  resampled, but "y" is, then topRax is 1 */
    botRax,                    /* index of highest axis being resampled */
    typeIn, typeOut;           /* types of input and output of resampling */
  size_t sz[NRRD_DIM_MAX+1][NRRD_DIM_MAX];
                               /* how many samples along each
                                  axis, changing on each pass */

  /* all these variables have to do with the spacing of elements in
     memory for the current pass of resampling, and they (except
     strideIn) are re-set at the beginning of each pass */
  nrrdResample_t
    *weight;                  /* sample weights */
  unsigned int ci[NRRD_DIM_MAX+1],
    co[NRRD_DIM_MAX+1];
  int 
    sizeIn, sizeOut,          /* lengths of input and output vectors */
    dotLen,                   /* # input samples to dot with weights to get
                                 one output sample */
    doRound,                  /* actually do rounding on output: we DO NOT
                                 round when info->round but the output 
                                 type is not integral */
    *index;                   /* dotLen*sizeOut 2D array of input indices */
  size_t 
    I,                        /* swiss-army int */
    strideIn,                 /* the stride between samples in the input
                                 "scanline" being resampled */
    strideOut,                /* stride between samples in output 
                                 "scanline" from resampling */
    L, LI, LO, numLines,      /* top secret */
    numOut;                   /* # of _samples_, total, in output volume;
                                 this is for allocating the output */
  airArray *mop;              /* for cleaning up */
  
  if (!(nout && nin && info)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdBoundaryUnknown == info->boundary) {
    sprintf(err, "%s: need to specify a boundary behavior", me);
    biffAdd(NRRD, err); return 1;
  }

  typeIn = nin->type;
  typeOut = nrrdTypeDefault == info->type ? typeIn : info->type;

  if (_nrrdResampleCheckInfo(nin, info)) {
    sprintf(err, "%s: problem with arguments", me);
    biffAdd(NRRD, err); return 1;
  }
  
  _nrrdResampleComputePermute(permute, ax, sz,
                              &topRax, &botRax, &passes,
                              nin, info);
  topLax = topRax ? 0 : 1;

  /* not sure where else to put this:
     (want to put it before 0 == passes branch)
     We have to assume some centering when doing resampling, and it would
     be stupid to not record it in the outgoing nrrd, since the value of
     nrrdDefaultCenter could always change. */
  for (ai=0; ai<nin->dim; ai++) {
    if (info->kernel[ai]) {
      nout->axis[ai].center = _nrrdCenter(nin->axis[ai].center);
    }
  }

  if (0 == passes) {
    /* actually, no resampling was desired.  Copy input to output,
       but with the clamping that we normally do at the end of resampling */
    nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, sz[0]);
    if (nrrdMaybeAlloc_nva(nout, typeOut, nin->dim, sz[0])) {
      sprintf(err, "%s: couldn't allocate output", me);
      biffAdd(NRRD, err); return 1;
    }
    numOut = nrrdElementNumber(nout);
    for (I=0; I<numOut; I++) {
      tmpF = nrrdDLookup[nin->type](nin->data, I);
      tmpF = nrrdDClamp[typeOut](tmpF);
      nrrdDInsert[typeOut](nout->data, I, tmpF);
    }
    nrrdAxisInfoCopy(nout, nin, NULL, NRRD_AXIS_INFO_NONE);
    /* HEY: need to create textual representation of resampling parameters */
    if (nrrdContentSet_va(nout, func, nin, "")) {
      sprintf(err, "%s:", me);
      biffAdd(NRRD, err); return 1;
    }
    if (nrrdBasicInfoCopy(nout, nin,
                          NRRD_BASIC_INFO_DATA_BIT
                          | NRRD_BASIC_INFO_TYPE_BIT
                          | NRRD_BASIC_INFO_BLOCKSIZE_BIT
                          | NRRD_BASIC_INFO_DIMENSION_BIT
                          | NRRD_BASIC_INFO_CONTENT_BIT
                          | NRRD_BASIC_INFO_COMMENTS_BIT
                          | (nrrdStateKeyValuePairsPropagate
                             ? 0
                             : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) {
      sprintf(err, "%s:", me);
      biffAdd(NRRD, err); return 1;
    }
    return 0;
  }

  mop = airMopNew();
  /* convert input nrrd to nrrdResample_t if necessary */
  if (nrrdResample_nrrdType != typeIn) {
    if (nrrdConvert(floatNin = nrrdNew(), nin, nrrdResample_nrrdType)) {
      sprintf(err, "%s: couldn't create float copy of input", me);
      biffAdd(NRRD, err); airMopError(mop); return 1;
    }
    array[0] = (nrrdResample_t*)floatNin->data;
    airMopAdd(mop, floatNin, (airMopper)nrrdNuke, airMopAlways);
  } else {
    floatNin = NULL;
    array[0] = (nrrdResample_t*)nin->data;
  }
  
  /* compute strideIn; this is actually the same for every pass
     because (strictly speaking) in every pass we are resampling
     the same axis, and axes with lower indices are constant length */
  strideIn = 1;
  for (ai=0; ai<(unsigned int)topRax; ai++) { /* HEY scrutinize casts */
    strideIn *= nin->axis[ai].size;
  }
  /*
  printf("%s: strideIn = " _AIR_SIZE_T_CNV "\n", me, strideIn);
  */

  /* go! */
  for (pi=0; pi<passes; pi++) {
    /*
    printf("%s: --- pass %d --- \n", me, pi);
    */
    numLines = strideOut = 1;
    for (ai=0; ai<nin->dim; ai++) {
      if (ai < (unsigned int)botRax) {   /* HEY scrutinize cast */
        strideOut *= sz[pi+1][ai];
      }
      if (ai != (unsigned int)topRax) {  /* HEY scrutinize cast */
        numLines *= sz[pi][ai];
      }
    }
    sizeIn = sz[pi][topRax];
    sizeOut = sz[pi+1][botRax];
    numOut = numLines*sizeOut;
    /* for the rest of the loop body, d is the original "dimension"
       for the axis being resampled */
    ai = ax[pi][topRax];
    /*
    printf("%s(%d): numOut = " _AIR_SIZE_T_CNV "\n", me, pi, numOut);
    printf("%s(%d): numLines = " _AIR_SIZE_T_CNV "\n", me, pi, numLines);
    printf("%s(%d): stride: In=%d, Out=%d\n", me, pi, 
           (int)strideIn, (int)strideOut);
    printf("%s(%d): sizeIn = %d\n", me, pi, sizeIn);
    printf("%s(%d): sizeOut = %d\n", me, pi, sizeOut);
    */

    /* we can free the input to the previous pass 
       (if its not the given data) */
    if (pi > 0) {
      if (pi == 1) {
        if (array[0] != nin->data) {
          airMopSub(mop, floatNin, (airMopper)nrrdNuke);
          floatNin = nrrdNuke(floatNin);
          array[0] = NULL;
          /*
          printf("%s: pi %d: freeing array[0]\n", me, pi);
          */
        }
      } else {
        airMopSub(mop, array[pi-1], airFree);
        array[pi-1] = (nrrdResample_t*)airFree(array[pi-1]);
        /*
        printf("%s: pi %d: freeing array[%d]\n", me, pi, pi-1);
        */
      }
    }

    /* allocate output volume */
    array[pi+1] = (nrrdResample_t*)calloc(numOut, sizeof(nrrdResample_t));
    if (!array[pi+1]) {
      sprintf(err, "%s: couldn't create array of " _AIR_SIZE_T_CNV 
              " nrrdResample_t's for output of pass %d",
              me, numOut, pi);
      biffAdd(NRRD, err); airMopError(mop); return 1;
    }
    airMopAdd(mop, array[pi+1], airFree, airMopAlways);
    /*
    printf("%s: allocated array[%d]\n", me, pi+1);
    */

    /* allocate contiguous input scanline buffer, we alloc one more
       than needed to provide a place for the pad value.  That is, in
       fact, the over-riding reason to copy a scanline to a local
       array: so that there is a simple consistent (non-branchy) way
       to incorporate the pad values */
    inVec = (nrrdResample_t *)calloc(sizeIn+1, sizeof(nrrdResample_t));
    airMopAdd(mop, inVec, airFree, airMopAlways);
    inVec[sizeIn] = AIR_CAST(nrrdResample_t, info->padValue);

    dotLen = _nrrdResampleMakeWeightIndex(&weight, &index, &ratio,
                                          nin, info, ai);
    if (!dotLen) {
      sprintf(err, "%s: trouble creating weight and index vector arrays", me);
      biffAdd(NRRD, err); airMopError(mop); return 1;
    }
    ratios[ai] = ratio;
    airMopAdd(mop, weight, airFree, airMopAlways);
    airMopAdd(mop, index, airFree, airMopAlways);

    /* the skinny: resample all the scanlines */
    _inVec = array[pi];
    _outVec = array[pi+1];
    memset(ci, 0, (NRRD_DIM_MAX+1)*sizeof(int));
    memset(co, 0, (NRRD_DIM_MAX+1)*sizeof(int));
    for (L=0; L<numLines; L++) {
      /* calculate the index to get to input and output scanlines,
         according the coordinates of the start of the scanline */
      NRRD_INDEX_GEN(LI, ci, sz[pi], nin->dim);
      NRRD_INDEX_GEN(LO, co, sz[pi+1], nin->dim);
      _inVec = array[pi] + LI;
      _outVec = array[pi+1] + LO;
      
      /* read input scanline into contiguous array */
      for (i=0; i<sizeIn; i++) {
        inVec[i] = _inVec[i*strideIn];
      }

      /* do the weighting */
      for (i=0; i<sizeOut; i++) {
        tmpF = 0.0;
        /*
        fprintf(stderr, "%s: i = %d (tmpF=0)\n", me, (int)i);
        */
        for (s=0; s<dotLen; s++) {
          tmpF += inVec[index[s + dotLen*i]]*weight[s + dotLen*i];
          /*
          fprintf(stderr, "  tmpF += %g*%g == %g\n",
                  inVec[index[s + dotLen*i]], weight[s + dotLen*i], tmpF);
          */
        }
        _outVec[i*strideOut] = tmpF;
        /*
        fprintf(stderr, "--> out[%d] = %g\n",
                i*strideOut, _outVec[i*strideOut]);
        */
      }
 
      /* update the coordinates for the scanline starts.  We don't
         use the usual NRRD_COORD macros because we're subject to
         the unusual constraint that ci[topRax] and co[permute[topRax]]
         must stay exactly zero */
      e = topLax;
      ci[e]++; 
      co[permute[e]]++;
      while (L < numLines-1 && ci[e] == sz[pi][e]) {
        ci[e] = co[permute[e]] = 0;
        e++;
        e += e == topRax;
        ci[e]++; 
        co[permute[e]]++;
      }
    }

    /* pass-specific clean up */
    airMopSub(mop, weight, airFree);
    airMopSub(mop, index, airFree);
    airMopSub(mop, inVec, airFree);
    weight = (nrrdResample_t*)airFree(weight);
    index = (int*)airFree(index);
    inVec = (nrrdResample_t*)airFree(inVec);
  }

  /* clean up second-to-last array and scanline buffers */
  if (passes > 1) {
    airMopSub(mop, array[passes-1], airFree);
    array[passes-1] = (nrrdResample_t*)airFree(array[passes-1]);
    /*
    printf("%s: now freeing array[%d]\n", me, passes-1);
    */
  } else if (array[passes-1] != nin->data) {
    airMopSub(mop, floatNin, (airMopper)nrrdNuke);
    floatNin = nrrdNuke(floatNin);
  }
  array[passes-1] = NULL;
  
  /* create output nrrd and set axis info */
  if (nrrdMaybeAlloc_nva(nout, typeOut, nin->dim, sz[passes])) {
    sprintf(err, "%s: couldn't allocate final output nrrd", me);
    biffAdd(NRRD, err); airMopError(mop); return 1;
  }
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopOnError);
  nrrdAxisInfoCopy(nout, nin, NULL, 
                   (NRRD_AXIS_INFO_SIZE_BIT
                    | NRRD_AXIS_INFO_MIN_BIT
                    | NRRD_AXIS_INFO_MAX_BIT
                    | NRRD_AXIS_INFO_SPACING_BIT
                    | NRRD_AXIS_INFO_SPACEDIRECTION_BIT  /* see below */
                    | NRRD_AXIS_INFO_THICKNESS_BIT
                    | NRRD_AXIS_INFO_KIND_BIT));
  for (ai=0; ai<nin->dim; ai++) {
    if (info->kernel[ai]) {
      /* we do resample this axis */
      nout->axis[ai].spacing = nin->axis[ai].spacing/ratios[ai];
      /* no way to usefully update thickness: we could be doing blurring
         but maintaining the number of samples: thickness increases, or
         we could be downsampling, in which the relationship between the
         sampled and the skipped regions of space becomes complicated:
         no single scalar can represent it, or we could be upsampling,
         in which the notion of "skip" could be rendered meaningless */
      nout->axis[ai].thickness = AIR_NAN;
      nout->axis[ai].min = info->min[ai];
      nout->axis[ai].max = info->max[ai];
      /*
        HEY: this is currently a bug: all this code was written long
        before there were space directions, so min/max are always 
        set, regardless of whethere there are incoming space directions
        which then disallows output space directions on the same axes
      _nrrdSpaceVecScale(nout->axis[ai].spaceDirection,
                         1.0/ratios[ai], nin->axis[ai].spaceDirection);
      */
      nout->axis[ai].kind = _nrrdKindAltered(nin->axis[ai].kind, AIR_TRUE);
    } else {
      /* this axis remains untouched */
      nout->axis[ai].min = nin->axis[ai].min;
      nout->axis[ai].max = nin->axis[ai].max;
      nout->axis[ai].spacing = nin->axis[ai].spacing;
      nout->axis[ai].thickness = nin->axis[ai].thickness;
      nout->axis[ai].kind = nin->axis[ai].kind;
    }
  }
  /* HEY: need to create textual representation of resampling parameters */
  if (nrrdContentSet_va(nout, func, nin, "")) {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err); return 1;
  }

  /* copy the resampling final result into the output nrrd, maybe
     rounding as we go to make sure that 254.9999 is saved as 255
     in uchar output, and maybe clamping as we go to insure that
     integral results don't have unexpected wrap-around. */
  if (info->round) {
    if (nrrdTypeInt == typeOut ||
        nrrdTypeUInt == typeOut ||
        nrrdTypeLLong == typeOut ||
        nrrdTypeULLong == typeOut) {
      fprintf(stderr, "%s: WARNING: possible erroneous output with "
              "rounding of %s output type due to int-based implementation "
              "of rounding\n", me, airEnumStr(nrrdType, typeOut));
    }
    doRound = nrrdTypeIsIntegral[typeOut];
  } else {
    doRound = AIR_FALSE;
  }
  numOut = nrrdElementNumber(nout);
  for (I=0; I<numOut; I++) {
    tmpF = array[passes][I];
    if (doRound) {
      tmpF = AIR_CAST(nrrdResample_t, AIR_ROUNDUP(tmpF));
    }
    if (info->clamp) {
      tmpF = nrrdDClamp[typeOut](tmpF);
    }
    nrrdDInsert[typeOut](nout->data, I, tmpF);
  }

  if (nrrdBasicInfoCopy(nout, nin,
                        NRRD_BASIC_INFO_DATA_BIT
                        | NRRD_BASIC_INFO_TYPE_BIT
                        | NRRD_BASIC_INFO_BLOCKSIZE_BIT
                        | NRRD_BASIC_INFO_DIMENSION_BIT
                        | NRRD_BASIC_INFO_CONTENT_BIT
                        | NRRD_BASIC_INFO_COMMENTS_BIT
                        | (nrrdStateKeyValuePairsPropagate
                           ? 0
                           : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err); return 1;
  }

  /* enough already */
  airMopOkay(mop);
  return 0;
}
コード例 #19
0
/*
******** nrrdApply1DIrregMap()
**
** Linear interpolation between irregularly spaced control points.
** Obviously, the location of the control point has to be given
** explicitly.  The map nrrd must have dimension 2, and each 
** control point is represented by a scanline along axis 0.  The
** first value is the position of the control point, and the remaining
** value(s) are linearly weighted according to the position of the
** input value among the control point locations.
**
** To allow "coloring" of non-existant values -inf, NaN, and +inf, if
** the very first value of the map (the location of the first control
** point) is non-existant, then the first three control point locations
** must be -inf, NaN, and +inf, in that order, and the information
** about these points will be used for corresponding input values.
** Doing this makes everything slower, however, because airFPClass_f()
** is called on every single value.
**
** This assumes that nrrd1DIrregMapCheck has been called on "nmap",
** and that nrrd1DIrregAclCheck has been called on "nacl" (if it is
** non-NULL).
*/
int
nrrdApply1DIrregMap(Nrrd *nout, const Nrrd *nin, const NrrdRange *_range,
                    const Nrrd *nmap, const Nrrd *nacl,
                    int typeOut, int rescale) {
  char me[]="nrrdApply1DIrregMap", err[BIFF_STRLEN];
  size_t N, I;
  int i, *acl, entLen, posLen, aclLen, mapIdx, aclIdx,
    entSize, colSize, inSize, lo, hi, baseI;
  double val, *pos, domMin, domMax, mapIdxFrac,
    (*mapLup)(const void *v, size_t I),
    (*inLoad)(const void *v), (*outInsert)(void *v, size_t I, double d);
  char *inData, *outData, *entData0, *entData1;
  NrrdRange *range;
  airArray *mop;

  if (!(nout && nmap && nin)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  mop = airMopNew();
  if (_range) {
    range = nrrdRangeCopy(_range);
    nrrdRangeSafeSet(range, nin, nrrdBlind8BitRangeState);
  } else {
    range = nrrdRangeNewSet(nin, nrrdBlind8BitRangeState);
  }
  airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
  if (_nrrdApply1DSetUp(nout, nin, range, nmap,
                        kindImap, typeOut, rescale, AIR_FALSE)) {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err); airMopError(mop); return 1;
  }
  if (nacl && nrrd1DIrregAclCheck(nacl)) {
    sprintf(err, "%s: given acl isn't valid", me);
    biffAdd(NRRD, err); airMopError(mop); return 1;
  }
  
  if (nacl) {
    acl = (int *)nacl->data;
    aclLen = nacl->axis[1].size;
  } else {
    acl = NULL;
    aclLen = 0;
  }
  pos = _nrrd1DIrregMapDomain(&posLen, &baseI, nmap);
  if (!pos) {
    sprintf(err, "%s: couldn't determine domain", me); 
    biffAdd(NRRD, err); airMopError(mop); return 1;
  }
  airMopAdd(mop, pos, airFree, airMopAlways);
  mapLup = nrrdDLookup[nmap->type];
  
  inData = (char *)nin->data;
  inLoad = nrrdDLoad[nin->type];
  inSize = nrrdElementSize(nin);
  mapLup = nrrdDLookup[nmap->type];
  entLen = nmap->axis[0].size;    /* entLen is really 1 + entry length */
  entSize = entLen*nrrdElementSize(nmap);
  colSize = (entLen-1)*nrrdTypeSize[typeOut];
  outData = (char *)nout->data;
  outInsert = nrrdDInsert[nout->type];
  domMin = pos[0];
  domMax = pos[posLen-1];
  
  N = nrrdElementNumber(nin);
  for (I=0;
       I<N;
       I++, inData += inSize, outData += colSize) {
    val = inLoad(inData);
    /* _VV = ( (AIR_EXISTS(val) && (21 == (int)(-val))) 
       || 22400 < I ); */
    /* if (_VV)
       fprintf(stderr, "##%s: (%d) val = % 31.15f\n", me, (int)I, val); */
    if (!AIR_EXISTS(val)) {
      /* got a non-existant value */
      if (baseI) {
        /* and we know how to deal with them */
        switch (airFPClass_d(val)) {
        case airFP_NEG_INF:
          mapIdx = 0;
          break;
        case airFP_SNAN:
        case airFP_QNAN:
          mapIdx = 1;
          break;
        case airFP_POS_INF:
          mapIdx = 2;
          break;
        default:
          mapIdx = 0;
          fprintf(stderr, "%s: PANIC: non-existant value/class %g/%d "
                  "not handled\n",
                  me, val, airFPClass_d(val));
          exit(1);
        }
        entData0 = (char*)(nmap->data) + mapIdx*entSize;
        for (i=1; i<entLen; i++) {
          outInsert(outData, i-1, mapLup(entData0, i));
        }
        continue;  /* we're done! (with this value) */
      } else {
        /* we don't know how to properly deal with this non-existant value:
           we use the first entry, and then fall through to code below */
        mapIdx = 0;
        mapIdxFrac = 0.0;
      }
    } else {
      /* we have an existant value */
      if (rescale) {
        val = AIR_AFFINE(range->min, val, range->max, domMin, domMax);
        /* if (_VV) fprintf(stderr, "   rescaled --> % 31.15f\n", val); */
      }
      val = AIR_CLAMP(domMin, val, domMax);
      if (acl) {
        aclIdx = airIndex(domMin, val, domMax, aclLen);
        lo = acl[0 + 2*aclIdx];
        hi = acl[1 + 2*aclIdx];
      } else {
        lo = 0;
        hi = posLen-2;
      }
      if (lo < hi) {
        mapIdx = _nrrd1DIrregFindInterval(pos, val, lo, hi);
      } else {
        /* acl did its job ==> lo == hi */
        mapIdx = lo;
      }
    }
    mapIdxFrac = AIR_AFFINE(pos[mapIdx], val, pos[mapIdx+1], 0.0, 1.0);
    /* if (_VV) fprintf(stderr, "##%s: val=\n% 31.15f --> "
                     "mapIdx,frac = %d,\n% 31.15f\n",
                     me, val, mapIdx, mapIdxFrac); */
    entData0 = (char*)(nmap->data) + (baseI+mapIdx)*entSize;
    entData1 = (char*)(nmap->data) + (baseI+mapIdx+1)*entSize;
    /* if (_VV) fprintf(stderr, "##%s: 2; %d/\n% 31.15f --> entLen=%d "
                     "baseI=%d -->\n",
                     me, mapIdx, mapIdxFrac, entLen, baseI); */
    for (i=1; i<entLen; i++) {
      val = ((1-mapIdxFrac)*mapLup(entData0, i) +
             mapIdxFrac*mapLup(entData1, i));
      /* if (_VV) fprintf(stderr, "% 31.15f\n", val); */
      outInsert(outData, i-1, val);
    }
    /* if (_VV) fprintf(stderr, "##%s: 3\n", me); */
  }
  airMopOkay(mop);
  return 0;
}
コード例 #20
0
/*
******** nrrdApply1DSubstitution
**
** A "subst" is a substitution table, i.e. a list of pairs that
** describes what values should be substituted with what (substitution
** rules).  So, nsubst must be a scalar 2xN array.  The output is a
** copy of the input with values substituted using this table.
**
** Unlike with lookup tables and maps (irregular and regular), we
** aren't at liberty to change the dimensionality of the data (can't
** substitute a grayscale with a color).  The ability to apply
** substitutions to non-scalar data will be in a different function.
** Also unlike lookup tables and maps, the output type is the SAME as
** the input type; the output does NOT inherit the type of the
** substitution
*/
int
nrrdApply1DSubstitution(Nrrd *nout, const Nrrd *nin, const Nrrd *_nsubst) {
  char me[]="nrrdApply1DSubstitution", err[BIFF_STRLEN];
  double (*lup)(const void *, size_t);
  double (*ins)(void *, size_t, double);
  Nrrd *nsubst;
  double val, *subst;
  size_t ii, num;
  int jj, asize0, asize1, changed;
  airArray *mop;

  if (!(nout && _nsubst && nin)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdTypeBlock == nin->type || nrrdTypeBlock == _nsubst->type) {
    sprintf(err, "%s: input or substitution type is %s, need scalar",
            me, airEnumStr(nrrdType, nrrdTypeBlock));
    biffAdd(NRRD, err); return 1;
  }
  if (2 != _nsubst->dim) {
    sprintf(err, "%s: substitution table has to be 2-D, not %d-D",
            me, _nsubst->dim);
    biffAdd(NRRD, err); return 1;
  }
  nrrdAxisInfoGet_va(_nsubst, nrrdAxisInfoSize, &asize0, &asize1);
  if (2 != asize0) {
    sprintf(err, "%s: substitution table has to be 2xN, not %dxN",
            me, asize0);
    biffAdd(NRRD, err); return 1;
  }
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      sprintf(err, "%s: couldn't initialize by copy to output", me);
      biffAdd(NRRD, err); return 1;
    }
  }

  mop = airMopNew();
  nsubst = nrrdNew();
  airMopAdd(mop, nsubst, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdConvert(nsubst, _nsubst, nrrdTypeDouble)) {
    sprintf(err, "%s: couldn't create double copy of substitution table", me);
    biffAdd(NRRD, err); airMopError(mop); return 1;
  }
  lup = nrrdDLookup[nout->type];
  ins = nrrdDInsert[nout->type];
  subst = (double *)nsubst->data;
  num = nrrdElementNumber(nout);
  for (ii=0; ii<num; ii++) {
    val = lup(nout->data, ii);
    changed = AIR_FALSE;
    for (jj=0; jj<asize1; jj++) {
      if (val == subst[jj*2+0]) {
        val = subst[jj*2+1];
        changed = AIR_TRUE;
      }
    }
    if (changed) {
      ins(nout->data, ii, val);
    }
  }

  airMopOkay(mop);
  return 0;
}
コード例 #21
0
ファイル: coreAlan.c プロジェクト: SCIInstitute/Cleaver
int 
alanInit(alanContext *actx, const Nrrd *nlevInit, const Nrrd *nparmInit) {
  char me[]="alanInit", err[BIFF_STRLEN];
  alan_t *levInit=NULL, *lev0, *parmInit=NULL, *parm;
  size_t I, N;

  if (_alanCheck(actx)) {
    sprintf(err, "%s: ", me);
    biffAdd(ALAN, err); return 1;
  }
  if (!( actx->_nlev[0] && actx->_nlev[0] && actx->nparm )) {
    sprintf(err, "%s: _nlev[0,1] not allocated: call alanUpdate", me);
    biffAdd(ALAN, err); return 1;
  }
  
  if (nlevInit) {
    if (nrrdCheck(nlevInit)) {
      sprintf(err, "%s: given nlevInit has problems", me);
      biffMove(ALAN, err, NRRD); return 1;
    }
    if (!( alan_nt == nlevInit->type 
           && nlevInit->dim == 1 + actx->dim
           && actx->_nlev[0]->axis[0].size == nlevInit->axis[0].size
           && actx->size[0] == nlevInit->axis[1].size
           && actx->size[1] == nlevInit->axis[2].size 
           && (2 == actx->dim || actx->size[2] == nlevInit->axis[3].size) )) {
      sprintf(err, "%s: type/size mismatch with given nlevInit", me);
      biffAdd(ALAN, err); return 1;
    }
    levInit = (alan_t*)(nlevInit->data);
  }
  if (nparmInit) {
    if (nrrdCheck(nparmInit)) {
      sprintf(err, "%s: given nparmInit has problems", me);
      biffMove(ALAN, err, NRRD); return 1;
    }
    if (!( alan_nt == nparmInit->type 
           && nparmInit->dim == 1 + actx->dim
           && 3 == nparmInit->axis[0].size
           && actx->size[0] == nparmInit->axis[1].size
           && actx->size[1] == nparmInit->axis[2].size 
           && (2 == actx->dim || actx->size[2] == nparmInit->axis[3].size) )) {
      sprintf(err, "%s: type/size mismatch with given nparmInit", me);
      biffAdd(ALAN, err); return 1;
    }
    parmInit = (alan_t*)(nparmInit->data);
  }

#define RAND AIR_AFFINE(0, airDrandMT(), 1, -actx->randRange, actx->randRange)

  N = nrrdElementNumber(actx->_nlev[0])/actx->_nlev[0]->axis[0].size;
  lev0 = (alan_t*)(actx->_nlev[0]->data);
  parm = (alan_t*)(actx->nparm->data);
  for (I=0; I<N; I++) {
    if (levInit) {
      lev0[0 + 2*I] = levInit[0 + 2*I];
      lev0[1 + 2*I] = levInit[1 + 2*I];
    } else {
      /* NOTE: the random number stuff here is OUTSIDE the multi-threaded
         segment of the program- only the init thread does this */
      lev0[0 + 2*I] = AIR_CAST(alan_t, actx->initA + RAND);
      lev0[1 + 2*I] = AIR_CAST(alan_t, actx->initB + RAND);
    }
    if (parmInit) {
      parm[0 + 3*I] = parmInit[0 + 3*I];
      parm[1 + 3*I] = parmInit[1 + 3*I];
      parm[2 + 3*I] = parmInit[2 + 3*I];
    } else {
      parm[0 + 3*I] = actx->deltaT;
      parm[1 + 3*I] = actx->alpha;
      parm[2 + 3*I] = actx->beta;
    }
  }
  return 0;
}
コード例 #22
0
ファイル: fftNrrd.c プロジェクト: CIBC-Internal/teem
/*
******** nrrdFFT
**
** First pass at a wrapper around FFTW.  This was implemented out of need for a
** specific project; and better decisions and different interfaces will become
** apparent with time and experience; these can be in Teem 2.0.
**
** currently *requires* that input be complex-valued, in that axis 0 has to
** have size 2.  nrrdKindComplex would be sensible for input axis 0 but we don't
** require it, though it is set on the output.
*/
int
nrrdFFT(Nrrd *nout, const Nrrd *_nin,
        unsigned int *axes, unsigned int axesNum,
        int sign, int rescale, int rigor) {
  static const char me[]="nrrdFFT";
  size_t inSize[NRRD_DIM_MAX], II, NN, nprod;
  double *inData, *outData;
  airArray *mop;
  Nrrd *nin;
  unsigned int axi, axisDo[NRRD_DIM_MAX];
  fftw_plan plan;
  void *dataBef;
  unsigned int txfRank, howRank, flags;
  size_t stride;
  fftw_iodim txfDims[NRRD_DIM_MAX], howDims[NRRD_DIM_MAX];

  if (!(nout && _nin && axes)) {
    biffAddf(NRRD, "%s: got NULL pointer", me);
    return 1;
  }
  if (!( _nin->dim > 1 && 2 == _nin->axis[0].size )) {
    biffAddf(NRRD, "%s: nin doesn't look like a complex-valued array", me);
    return 1;
  }
  if (!( axesNum >= 1 )) {
    biffAddf(NRRD, "%s: axesNum 0, no axes to transform?", me);
    return 1;
  }
  for (axi=0; axi<_nin->dim; axi++) {
    axisDo[axi] = 0;
  }
  for (axi=0; axi<axesNum; axi++) {
    if (0 == axes[axi]) {
      biffAddf(NRRD, "%s: can't transform axis 0 (axes[%u]) for "
               "real/complex values", me, axi);
      return 1;
    }
    if (!( axes[axi] < _nin->dim )) {
      biffAddf(NRRD, "%s: axis %u (axes[%u]) out of range [1,%u]", me,
               axes[axi], axi, _nin->dim-1);
      return 1;
    }
    axisDo[axes[axi]]++;
    if (2 == axisDo[axes[axi]]) {
      biffAddf(NRRD, "%s: axis %u (axes[%u]) already transformed",
               me, axes[axi], axi);
      return 1;
    }
  }

  NN = nrrdElementNumber(_nin);
  /* We always make a new buffer to hold the double-type copy of input for two
     reasons: if input is not double we have to convert it, and we want input
     to be const, and we can't have const with the plan creation over-writing
     the input (except with FFTW_ESTIMATE).  Given that, we might as well use
     the memory-alignment-savvy fftw_malloc; the freeing is handled by both
     _nrrdFftwFreeWrapper and nrrdNix. */
  /* (NN = 2 * number of complex values) */
  inData = AIR_CAST(double *, fftw_malloc(NN*sizeof(double)));
  if (!inData) {
    biffAddf(NRRD, "%s: couldn't allocate input data copy", me);
    return 1;
  }
  mop = airMopNew();
  airMopAdd(mop, inData, _nrrdFftwFreeWrapper, airMopAlways);
  nin = nrrdNew();
  airMopAdd(mop, nin, (airMopper)nrrdNix /* NOT Nuke */, airMopAlways);
  nrrdAxisInfoGet_nva(_nin, nrrdAxisInfoSize, inSize);
  /* we don't copy data yet; it may be over-written during plan creation */
  if (nrrdWrap_nva(nin, inData, nrrdTypeDouble, _nin->dim, inSize)) {
    biffAddf(NRRD, "%s: couldn't wrap or copy input", me);
    airMopError(mop);
    return 1;
  }
  /* But on the output, we just use regular malloc, because we don't (yet) have
     a way of telling nrrd to use fftw_malloc/fftw_free instead of the generic
     malloc/free, and we don't want two whole copies of the output (one that is
     memory-aligned, internal to this function, and one that isn't, in nout) */
  if (nrrdMaybeAlloc_nva(nout, nrrdTypeDouble, _nin->dim, inSize)) {
    biffAddf(NRRD, "%s: couldn't allocate output", me);
    airMopError(mop);
    return 1;
  }
  outData = AIR_CAST(double *, nout->data);

  /* As far as GLK can tell, the guru interface is needed, and the "advanced"
     fftw_plan_many_dft won't work, because its simplistic accounting of stride
     can't handle having non-contiguous non-transformed axes (e.g. transforming
     only axes 2 and not 1, 3 in a 3-D complex-valued array) */
  txfRank = howRank = 0;
  stride = 1;
  nprod = 1;
  for (axi=1; axi<nin->dim; axi++) {
    if (axisDo[axi]) {
      txfDims[txfRank].n = AIR_CAST(int, inSize[axi]);
      txfDims[txfRank].is = txfDims[txfRank].os = AIR_CAST(int, stride);
      nprod *= inSize[axi];
      txfRank++;
    } else {
      howDims[howRank].n = AIR_CAST(int, inSize[axi]);
      howDims[howRank].is = howDims[howRank].os = AIR_CAST(int, stride);
      howRank++;
    }
    stride *= inSize[axi];
  }
コード例 #23
0
ファイル: histogram.c プロジェクト: sinkpoint/hodaie-teem
/*
******** nrrdHisto()
**
** makes a 1D histogram of a given size and type
**
** pre-NrrdRange policy:
** this looks at nin->min and nin->max to see if they are both non-NaN.
** If so, it uses these as the range of the histogram, otherwise it
** finds the min and max present in the volume.  If nin->min and nin->max
** are being used as the histogram range, then values which fall outside
** this are ignored (they don't contribute to the histogram).
**
** post-NrrdRange policy:
*/
int
nrrdHisto(Nrrd *nout, const Nrrd *nin, const NrrdRange *_range,
          const Nrrd *nwght, size_t bins, int type) {
  static const char me[]="nrrdHisto", func[]="histo";
  size_t I, num, idx;
  airArray *mop;
  NrrdRange *range;
  double min, max, eps, val, count, incr, (*lup)(const void *v, size_t I);

  if (!(nin && nout)) {
    /* _range and nwght can be NULL */
    biffAddf(NRRD, "%s: got NULL pointer", me);
    return 1;
  }
  if (nout == nin) {
    biffAddf(NRRD, "%s: nout==nin disallowed", me);
    return 1;
  }
  if (!(bins > 0)) {
    biffAddf(NRRD, "%s: bins value (" _AIR_SIZE_T_CNV ") invalid", me, bins);
    return 1;
  }
  if (airEnumValCheck(nrrdType, type) || nrrdTypeBlock == type) {
    biffAddf(NRRD, "%s: invalid nrrd type %d", me, type);
    return 1;
  }
  if (nwght) {
    if (nout==nwght) {
      biffAddf(NRRD, "%s: nout==nwght disallowed", me);
      return 1;
    }
    if (nrrdTypeBlock == nwght->type) {
      biffAddf(NRRD, "%s: nwght type %s invalid", me,
               airEnumStr(nrrdType, nrrdTypeBlock));
      return 1;
    }
    if (!nrrdSameSize(nin, nwght, AIR_TRUE)) {
      biffAddf(NRRD, "%s: nwght size mismatch with nin", me);
      return 1;
    }
    lup = nrrdDLookup[nwght->type];
  } else {
    lup = NULL;
  }

  if (nrrdMaybeAlloc_va(nout, type, 1, bins)) {
    biffAddf(NRRD, "%s: failed to alloc histo array (len " _AIR_SIZE_T_CNV
             ")", me, bins);
    return 1;
  }
  mop = airMopNew();
  /* nout->axis[0].size set */
  nout->axis[0].spacing = AIR_NAN;
  nout->axis[0].thickness = AIR_NAN;
  if (nout && AIR_EXISTS(nout->axis[0].min) && AIR_EXISTS(nout->axis[0].max)) {
    /* HEY: total hack to externally nail down min and max of histogram:
       use the min and max already set on axis[0] */
    /* HEY: shouldn't this blatent hack be further restricted by also 
       checking the existence of range->min and range->max ? */
    min = nout->axis[0].min;
    max = nout->axis[0].max;
  } else {
    if (_range) {
      range = nrrdRangeCopy(_range);
      nrrdRangeSafeSet(range, nin, nrrdBlind8BitRangeState);
    } else {
      range = nrrdRangeNewSet(nin, nrrdBlind8BitRangeState);
    }
    airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
    min = range->min;
    max = range->max;
    nout->axis[0].min = min;
    nout->axis[0].max = max;
  }
  eps = (min == max ? 1.0 : 0.0);
  nout->axis[0].center = nrrdCenterCell;
  /* nout->axis[0].label set below */
  
  /* make histogram */
  num = nrrdElementNumber(nin);
  for (I=0; I<num; I++) {
    val = nrrdDLookup[nin->type](nin->data, I);
    if (AIR_EXISTS(val)) {
      if (val < min || val > max+eps) {
        /* value is outside range; ignore it */
        continue;
      }
      if (AIR_IN_CL(min, val, max)) {
        idx = airIndex(min, val, max+eps, AIR_CAST(unsigned int, bins));
        /*
        printf("!%s: %d: index(%g, %g, %g, %d) = %d\n", 
               me, (int)I, min, val, max, bins, idx);
        */
        /* count is a double in order to simplify clamping the
           hit values to the representable range for nout->type */
        count = nrrdDLookup[nout->type](nout->data, idx);
        incr = nwght ? lup(nwght->data, I) : 1;
        count = nrrdDClamp[nout->type](count + incr);
        nrrdDInsert[nout->type](nout->data, idx, count);
      }
    }
  }

  if (nrrdContentSet_va(nout, func, nin, "%d", bins)) {
    biffAddf(NRRD, "%s:", me);
    airMopError(mop); return 1;
  }
  nout->axis[0].label = (char *)airFree(nout->axis[0].label);
  nout->axis[0].label = (char *)airStrdup(nout->content);
  if (!nrrdStateKindNoop) {
    nout->axis[0].kind = nrrdKindDomain;
  }

  airMopOkay(mop);
  return 0;
}
コード例 #24
0
ファイル: formatVTK.c プロジェクト: CIBC-Internal/teem
int
_nrrdFormatVTK_read(FILE *file, Nrrd *nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdReadVTK";
  char *three[3];
  int sx, sy, sz, ret, N;
  double xm=0.0, ym=0.0, zm=0.0, xs=1.0, ys=1.0, zs=1.0;
  airArray *mop;
  unsigned int llen;

  if (!_nrrdFormatVTK_contentStartsLike(nio)) {
    biffAddf(NRRD, "%s: this doesn't look like a %s file", me,
             nrrdFormatVTK->name);
    return 1;
  }

#define GETLINE(what)                                        \
  do {                                                       \
    ret = _nrrdOneLine(&llen, nio, file);                    \
  } while (!ret && (1 == llen));                             \
  if (ret || !llen) {                                        \
    biffAddf(NRRD, "%s: couldn't get " #what " line", me);   \
    return 1;                                                \
  }

  /* read in content */
  GETLINE(content);
  if (strcmp(NRRD_UNKNOWN, nio->line)) {
    if (!(nrrd->content = airStrdup(nio->line))) {
      biffAddf(NRRD, "%s: couldn't read or copy content string", me);
      return 1;
    }
  }
  GETLINE(encoding); airToUpper(nio->line);
  if (!strcmp("ASCII", nio->line)) {
    nio->encoding = nrrdEncodingAscii;
  } else if (!strcmp("BINARY", nio->line)) {
    nio->encoding = nrrdEncodingRaw;
  } else {
    biffAddf(NRRD, "%s: encoding \"%s\" wasn't \"ASCII\" or \"BINARY\"",
             me, nio->line);
    return 1;
  }
  GETLINE(DATASET); airToUpper(nio->line);
  if (!strstr(nio->line, "STRUCTURED_POINTS")) {
    biffAddf(NRRD,
             "%s: sorry, only STRUCTURED_POINTS data is nrrd-ready", me);
    return 1;
  }
  GETLINE(DIMENSIONS); airToUpper(nio->line);
  if (!strstr(nio->line, "DIMENSIONS")
      || 3 != sscanf(nio->line, "DIMENSIONS %d %d %d", &sx, &sy, &sz)) {
    biffAddf(NRRD, "%s: couldn't parse DIMENSIONS line (\"%s\")",
             me, nio->line);
    return 1;
  }
  GETLINE(next); airToUpper(nio->line);
  while (!strstr(nio->line, "POINT_DATA")) {
    if (strstr(nio->line, "ORIGIN")) {
      if (3 != sscanf(nio->line, "ORIGIN %lf %lf %lf", &xm, &ym, &zm)) {
        biffAddf(NRRD, "%s: couldn't parse ORIGIN line (\"%s\")",
                 me, nio->line);
        return 1;
      }
    } else if (strstr(nio->line, "SPACING")) {
      if (3 != sscanf(nio->line, "SPACING %lf %lf %lf",
                      &xs, &ys, &zs)) {
        biffAddf(NRRD, "%s: couldn't parse SPACING line (\"%s\")",
                 me, nio->line);
        return 1;
      }
    } else if (strstr(nio->line, "ASPECT_RATIO")) {
      if (3 != sscanf(nio->line, "ASPECT_RATIO %lf %lf %lf",
                      &xs, &ys, &zs)) {
        biffAddf(NRRD, "%s: couldn't parse ASPECT_RATIO line (\"%s\")",
                 me, nio->line);
        return 1;
      }
    }
    GETLINE(next); airToUpper(nio->line);
  }
  if (1 != sscanf(nio->line, "POINT_DATA %d", &N)) {
    biffAddf(NRRD, "%s: couldn't parse POINT_DATA line (\"%s\")",
             me, nio->line);
    return 1;
  }
  if (N != sx*sy*sz) {
    biffAddf(NRRD,
             "%s: product of sizes (%d*%d*%d == %d) != # elements (%d)",
             me, sx, sy, sz, sx*sy*sz, N);
    return 1;
  }
  GETLINE(attribute declaration);
  mop = airMopNew();
  if (3 != airParseStrS(three, nio->line, AIR_WHITESPACE, 3, AIR_FALSE)) {
    biffAddf(NRRD,
             "%s: didn't see three words in attribute declaration \"%s\"",
             me, nio->line);
    return 1;
  }
  airMopAdd(mop, three[0], airFree, airMopAlways);
  airMopAdd(mop, three[1], airFree, airMopAlways);
  airMopAdd(mop, three[2], airFree, airMopAlways);
  airToLower(three[2]);
  if (!strcmp(three[2], "bit")) {
    if (nrrdEncodingAscii == nio->encoding) {
      fprintf(stderr, "%s: WARNING: \"bit\"-type data will be read in as "
              "unsigned char\n", me);
      nrrd->type = nrrdTypeUChar;
    } else {
      biffAddf(NRRD, "%s: can't read in \"bit\"-type data as BINARY", me);
      return 1;
    }
  } else if (!strcmp(three[2], "unsigned_char")) {
    nrrd->type = nrrdTypeUChar;
  } else if (!strcmp(three[2], "char")) {
    nrrd->type = nrrdTypeChar;
  } else if (!strcmp(three[2], "unsigned_short")) {
    nrrd->type = nrrdTypeUShort;
  } else if (!strcmp(three[2], "short")) {
    nrrd->type = nrrdTypeShort;
  } else if (!strcmp(three[2], "unsigned_int")) {
    nrrd->type = nrrdTypeUInt;
  } else if (!strcmp(three[2], "int")) {
    nrrd->type = nrrdTypeInt;
  } else if (!strcmp(three[2], "float")) {
    nrrd->type = nrrdTypeFloat;
  } else if (!strcmp(three[2], "double")) {
    nrrd->type = nrrdTypeDouble;
  } else {
    /* "unsigned_long" and "long" fall in here- I don't know what
       the VTK people mean by these types, since always mean different
       things on 32-bit versus 64-bit architectures */
    biffAddf(NRRD, "%s: type \"%s\" not recognized", me, three[2]);
    airMopError(mop); return 1;
  }
  airToUpper(three[0]);
  if (!strncmp("SCALARS", three[0], strlen("SCALARS"))) {
    GETLINE(LOOKUP_TABLE); airToUpper(nio->line);
    if (strcmp(nio->line, "LOOKUP_TABLE DEFAULT")) {
      biffAddf(NRRD,
               "%s: sorry, can only deal with default LOOKUP_TABLE", me);
      airMopError(mop); return 1;
    }
    nrrd->dim = 3;
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize,
                       AIR_CAST(size_t, sx),
                       AIR_CAST(size_t, sy),
                       AIR_CAST(size_t, sz));
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, xs, ys, zs);
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, xm, ym, zm);
  } else if (!strncmp("VECTORS", three[0], strlen("VECTORS"))) {
    nrrd->dim = 4;
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize,
                       AIR_CAST(size_t, 3),
                       AIR_CAST(size_t, sx),
                       AIR_CAST(size_t, sy),
                       AIR_CAST(size_t, sz));
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, AIR_NAN, xs, ys, zs);
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, AIR_NAN, xm, ym, zm);
    nrrd->axis[0].kind = nrrdKind3Vector;
  } else if (!strncmp("TENSORS", three[0], strlen("TENSORS"))) {
    nrrd->dim = 4;
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize,
                       AIR_CAST(size_t, 9),
                       AIR_CAST(size_t, sx),
                       AIR_CAST(size_t, sy),
                       AIR_CAST(size_t, sz));
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, AIR_NAN, xs, ys, zs);
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, AIR_NAN, xm, ym, zm);
    nrrd->axis[0].kind = nrrdKind3DMatrix;
  } else {
    biffAddf(NRRD,
             "%s: sorry, can only deal with SCALARS, VECTORS, and TENSORS "
             "currently, so couldn't parse attribute declaration \"%s\"",
             me, nio->line);
    airMopError(mop); return 1;
  }
  if (!nio->skipData) {
    if (_nrrdCalloc(nrrd, nio, file)) {
      biffAddf(NRRD, "%s: couldn't allocate memory for data", me);
      return 1;
    }
    if (nio->encoding->read(file, nrrd->data, nrrdElementNumber(nrrd),
                            nrrd, nio)) {
      biffAddf(NRRD, "%s:", me);
      return 1;
    }
    if (1 < nrrdElementSize(nrrd)
        && nio->encoding->endianMatters
        && airMyEndian() != airEndianBig) {
      /* encoding exposes endianness, and its big, but we aren't */
      nrrdSwapEndian(nrrd);
    }
  } else {
    nrrd->data = NULL;
  }

  airMopOkay(mop);
  return 0;
}
コード例 #25
0
ファイル: apply2D.c プロジェクト: rblake/seg3d2
/*
** _nrrdApply2DLutOrRegMap()
**
** the guts of nrrdApply2DLut and nrrdApply2DRegMap
**
** yikes, does NOT use biff, since we're only supposed to be called
** after copious error checking.  
**
** FOR INSTANCE, this allows nout == nin, which could be a big
** problem if mapAxis == 1.
**
** we don't need a typeOut arg because nout has already been allocated
** as some specific type; we'll look at that.
**
** NOTE: non-existant values get passed through regular maps and luts
** "unchanged".  However, if the output type is integral, the results
** are probaby undefined.  HEY: there is currently no warning message
** or error handling based on nrrdStateDisallowIntegerNonExist, but
** there really should be.
*/
int
_nrrdApply2DLutOrRegMap(Nrrd *nout, const Nrrd *nin,
                        const NrrdRange *range0, const NrrdRange *range1,
                        const Nrrd *nmap, int ramps,
                        int rescale0, int rescale1) {
  char me[]="_nrrdApply2DLutOrRegMap";
  char *inData, *outData, *mapData, *entData;
  size_t N, I;
  double (*inLoad)(const void *v), (*mapLup)(const void *v, size_t I),
    (*outInsert)(void *v, size_t I, double d),
    val0, val1, domMin0, domMax0, domMin1, domMax1;
  unsigned int i, mapAxis, mapLen0, mapLen1, mapIdx0, mapIdx1,
    entSize, entLen, inSize, outSize;

  mapAxis = nmap->dim - 2;             /* axis of nmap containing entries */
  mapData = (char *)nmap->data;        /* map data, as char* */
                                       /* low end of map domain */
  domMin0 = _nrrdApplyDomainMin(nmap, ramps, mapAxis + 0);
  domMin1 = _nrrdApplyDomainMin(nmap, ramps, mapAxis + 1);
                                       /* high end of map domain */
  domMax0 = _nrrdApplyDomainMax(nmap, ramps, mapAxis + 0);
  domMax1 = _nrrdApplyDomainMax(nmap, ramps, mapAxis + 1);
  mapLen0 = nmap->axis[mapAxis+0].size;   /* number of entries in map axis 0 */
  mapLen1 = nmap->axis[mapAxis+1].size;   /* number of entries in map axis 1 */
  mapLup = nrrdDLookup[nmap->type];    /* how to get doubles out of map */
  inData = (char *)nin->data;          /* input data, as char* */
  inLoad = nrrdDLoad[nin->type];       /* how to get doubles out of nin */
  inSize = nrrdElementSize(nin);       /* size of one input value */
  outData = (char *)nout->data;        /* output data, as char* */
  outInsert = nrrdDInsert[nout->type]; /* putting doubles into output */
  entLen = (mapAxis                    /* number of elements in one entry */
            ? nmap->axis[0].size
            : 1);
  outSize = entLen*nrrdElementSize(nout); /* size of entry in output */
  entSize = entLen*nrrdElementSize(nmap); /* size of entry in map */

  /*
  fprintf(stderr, "!%s: entLen = %u, mapLen = %u,%u\n", me,
          entLen, mapLen0, mapLen1);
  */

  N = nrrdElementNumber(nin)/2;       /* number of value pairs to be mapped */
  /* _VV = 1; */
  if (ramps) {
    fprintf(stderr, "%s: PANIC: unimplemented\n", me);
    exit(1);
  } else {
    /* lookup table */
    for (I=0; I<N; I++) {
      val0 = inLoad(inData + 0*inSize);
      val1 = inLoad(inData + 1*inSize);
      if (rescale0) {
        val0 = AIR_AFFINE(range0->min, val0, range0->max, domMin0, domMax0);
      }
      if (rescale1) {
        val1 = AIR_AFFINE(range1->min, val1, range1->max, domMin1, domMax1);
      }
      if (AIR_EXISTS(val0) && AIR_EXISTS(val1)) {
        mapIdx0 = airIndexClamp(domMin0, val0, domMax0, mapLen0);
        mapIdx1 = airIndexClamp(domMin1, val1, domMax1, mapLen1);
        entData = mapData + entSize*(mapIdx0 + mapLen0*mapIdx1);
        for (i=0; i<entLen; i++) {
          outInsert(outData, i, mapLup(entData, i));
        }
      } else {
        /* copy non-existant values from input to output */
        for (i=0; i<entLen; i++) {
          outInsert(outData, i, val0 + val1);  /* HEY this is weird */
        }
      }
      inData += 2*inSize;
      outData += outSize;
    }
  }

  return 0;
}
コード例 #26
0
ファイル: bvec.c プロジェクト: SCIInstitute/Cleaver
/*
******** tenBVecNonLinearFit
**
** Assuming that axis 0 represents a sequence of DWI measurements at a 
** range of b values (as described by bb[i]), do non-linear least-squares
** fitting of those measurements, governed by weights ww[i] (with at
** most iterMax interations, or terminated when L2 norm change < eps).
**
** Based on model fit amp*exp(-b*dec), output nrrd's axis 0 has three values:
** 0: amp
** 1: dec
** 2: error of fit
** and all other axes are unchanged from input.  Output type is always double.
*/
int
tenBVecNonLinearFit(Nrrd *nout, const Nrrd *nin, 
                    double *bb, double *ww, int iterMax, double eps) {
  char me[]="tenBVecNonLinearFit", err[BIFF_STRLEN];
  int map[NRRD_DIM_MAX], vecSize, iter;
  size_t ii, size[NRRD_DIM_MAX], vecI, vecNum;
  char *vec;
  double *out, ss[AIR_STRLEN_SMALL], amp, dec, d_amp, d_dec, error, diff,
    (*vecLup)(const void *v, size_t I);

  if (!( nout && nin && bb && ww )) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(TEN, err); return 1;
  }
  
  if (!( nin->dim >= 2 )) {
    sprintf(err, "%s: nin->dim (%d) not >= 2", me, nin->dim);
    biffAdd(TEN, err); return 1;
  }
  if (!( nin->axis[0].size < AIR_STRLEN_SMALL )) {
    sprintf(err, "%s: sorry need nin->axis[0].size (" 
            _AIR_SIZE_T_CNV ") < %d", 
            me, nin->axis[0].size, AIR_STRLEN_SMALL);
    biffAdd(TEN, err); return 1;
  }

  /* allocate/set-up output */
  nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, size);
  size[0] = 3;
  if (nrrdMaybeAlloc_nva(nout, nrrdTypeDouble, nin->dim, size)) {
    sprintf(err, "%s: couldn't allocate output", me);
    biffMove(TEN, err, NRRD); return 1;
  }
  for (ii=1; ii<nin->dim; ii++) {
    map[ii] = ii;
  }
  map[0] = -1;
  if (nrrdAxisInfoCopy(nout, nin, map, NRRD_AXIS_INFO_NONE)) {
    sprintf(err, "%s: couldn't copy axis info", me);
    biffMove(TEN, err, NRRD); return 1;
  }

  /* process all b vectors */
  vecSize = nin->axis[0].size*nrrdTypeSize[nin->type];
  vecNum = nrrdElementNumber(nin)/nin->axis[0].size;
  vecLup = nrrdDLookup[nin->type];
  vec = (char*)nin->data;
  out = (double*)nout->data;
  for (vecI=0; vecI<vecNum; vecI++) {
    /* copy DWI signal values */
    for (ii=0; ii<nin->axis[0].size; ii++) {
      ss[ii] = vecLup(vec, ii);
    }
    /* start with linear fit */
    tenBVecNonLinearFit_linear(&amp, &dec, bb, ss, ww, nin->axis[0].size);
    error = tenBVecNonLinearFit_error(bb, ss, ww, nin->axis[0].size, amp, dec);
    /* possibly refine with gauss-newton */
    if (iterMax > 0) {
      iter = 0;
      do {
        iter++;
        tenBVecNonLinearFit_GNstep(&d_amp, &d_dec,
                                   bb, ss, ww, nin->axis[0].size, amp, dec);
        amp += 0.3*d_amp;
        dec += 0.3*d_dec;
        diff = d_amp*d_amp + d_dec*d_dec;
      } while (iter < iterMax && diff > eps);
    }
    error = tenBVecNonLinearFit_error(bb, ss, ww, nin->axis[0].size, amp, dec);
    out[0] = amp;
    out[1] = dec;
    out[2] = error;
    vec += vecSize;
    out += 3;
  }
  
  return 0;
}
コード例 #27
0
ファイル: methodsNrrd.c プロジェクト: ewong718/freesurfer
/*
******** nrrdMaybeAlloc_nva
**
** calls nrrdAlloc_nva if the requested space is different than
** what is currently held
**
** also subscribes to the "don't mess with peripheral information" philosophy
*/
int
nrrdMaybeAlloc_nva(Nrrd *nrrd, int type,
                   unsigned int dim, const size_t *size)
{
  char me[]="nrrdMaybeAlloc_nva", err[BIFF_STRLEN];
  size_t sizeWant, sizeHave, numWant, elementSizeWant;
  int need;
  unsigned int ai;

  if (!nrrd)
  {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err);
    return 1;
  }
  if (airEnumValCheck(nrrdType, type))
  {
    sprintf(err, "%s: type (%d) is invalid", me, type);
    biffAdd(NRRD, err);
    return 1;
  }
  if (nrrdTypeBlock == type)
  {
    if (nrrdTypeBlock == nrrd->type)
    {
      sprintf(err, "%s: can't change from one block nrrd to another", me);
      biffAdd(NRRD, err);
      return 1;
    }
    if (!(0 < nrrd->blockSize))
    {
      sprintf(err, "%s: given nrrd->blockSize " _AIR_SIZE_T_CNV " invalid",
              me, nrrd->blockSize);
      biffAdd(NRRD, err);
      return 1;
    }
    elementSizeWant = nrrd->blockSize;
  }
  else
  {
    elementSizeWant = nrrdTypeSize[type];
  }
  if (_nrrdSizeCheck(size, dim, AIR_TRUE))
  {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err);
    return 1;
  }

  if (!(nrrd->data))
  {
    need = 1;
  }
  else
  {
    numWant = 1;
    for (ai=0; ai<dim; ai++)
    {
      numWant *= size[ai];
    }
    if (!nrrdElementSize(nrrd))
    {
      sprintf(err, "%s: nrrd reports zero element size!", me);
      biffAdd(NRRD, err);
      return 1;
    }
    sizeHave = nrrdElementNumber(nrrd) * nrrdElementSize(nrrd);
    /* fprintf(stderr, "##%s: sizeHave = %d * %d = %d\n", me,
            (int)(nrrdElementNumber(nrrd)),
            (int)(nrrdElementSize(nrrd)), (int)sizeHave); */
    sizeWant = numWant * elementSizeWant;
    /* fprintf(stderr, "##%s: sizeWant = %d * %d = %d\n", me,
            (int)(numWant),
            (int)(elementSizeWant), (int)sizeWant); */
    need = sizeHave != sizeWant;
    /* fprintf(stderr, "##%s: need = %d\n", me, need); */
  }
  if (need)
  {
    if (nrrdAlloc_nva(nrrd, type, dim, size))
    {
      sprintf(err, "%s:", me);
      biffAdd(NRRD, err);
      return 1;
    }
  }
  else
  {
    if (nrrdWrap_nva(nrrd, nrrd->data, type, dim, size))
    {
      sprintf(err, "%s:", me);
      biffAdd(NRRD, err);
      return 1;
    }
    /* but we do have to initialize memory! */
    memset(nrrd->data, 0, nrrdElementNumber(nrrd)*nrrdElementSize(nrrd));
  }

  return 0;
}
コード例 #28
0
ファイル: probeMulti.c プロジェクト: BRAINSia/teem
int
main() {
  airArray *mop, *submop;
  char *err;

  int typi;
  unsigned int supi, probePass, cti /* context copy index */,
    pvlIdx[NRRD_TYPE_MAX+1], sx, sy, sz, subnum;
  size_t sizes[3] = {42,61,50} /* one of these must be even */,
    ii, nn;
  Nrrd *norigScl, *nucharScl, *nunquant, *nqdiff,
    *nconvScl[NRRD_TYPE_MAX+1];
  unsigned char *ucharScl;
  gageContext *gctx[2][KERN_SIZE_MAX+1];
  gagePerVolume *gpvl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1];
  const double *vansScl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1],
    *gansScl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1],
    *hansScl[2][NRRD_TYPE_MAX+1][KERN_SIZE_MAX+1];
  double *origScl, omin, omax,  dsx, dsy, dsz,
    spcOrig[NRRD_SPACE_DIM_MAX] = {0.0, 0.0, 0.0},
    spcVec[3][NRRD_SPACE_DIM_MAX] = {
      {1.1, 0.0, 0.0},
      {0.0, 2.2, 0.0},
      {0.0, 0.0, 3.3}};

  mop = airMopNew();

#define NRRD_NEW(name, mop)                                     \
  (name) = nrrdNew();                                           \
  airMopAdd((mop), (name), (airMopper)nrrdNuke, airMopAlways)

  /* --------------------------------------------------------------- */
  /* Creating initial volume */
  NRRD_NEW(norigScl, mop);
  if (nrrdMaybeAlloc_nva(norigScl, nrrdTypeDouble, 3, sizes)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "trouble allocating:\n%s", err);
    airMopError(mop); return 1;
  }
  origScl = AIR_CAST(double *, norigScl->data);
  nn = nrrdElementNumber(norigScl);
  airSrandMT(42*42);
  for (ii=0; ii<nn/2; ii++) {
    airNormalRand(origScl + 2*ii + 0, origScl + 2*ii + 1);
  }
  /* learn real range */
  omin = omax = origScl[0];
  for (ii=1; ii<nn; ii++) {
    omin = AIR_MIN(omin, origScl[ii]);
    omax = AIR_MAX(omax, origScl[ii]);
  }
  ELL_3V_SET(spcOrig, 0.0, 0.0, 0.0);
  if (nrrdSpaceSet(norigScl, nrrdSpaceRightAnteriorSuperior)
      || nrrdSpaceOriginSet(norigScl, spcOrig)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "trouble setting space:\n%s", err);
    airMopError(mop); return 1;
  }
  nrrdAxisInfoSet_nva(norigScl, nrrdAxisInfoSpaceDirection, spcVec);
  dsx = AIR_CAST(double, sizes[0]);
  dsy = AIR_CAST(double, sizes[1]);
  dsz = AIR_CAST(double, sizes[2]);
  sx = AIR_CAST(unsigned int, sizes[0]);
  sy = AIR_CAST(unsigned int, sizes[1]);
  sz = AIR_CAST(unsigned int, sizes[2]);
  subnum = AIR_CAST(unsigned int, PROBE_NUM*0.9);


  /* --------------------------------------------------------------- */
  /* Quantizing to 8-bits and checking */
  submop = airMopNew();
  NRRD_NEW(nucharScl, mop);
  NRRD_NEW(nunquant, submop);
  NRRD_NEW(nqdiff, submop);
  if (nrrdQuantize(nucharScl, norigScl, NULL, 8)
      || nrrdUnquantize(nunquant, nucharScl, nrrdTypeDouble)
      || nrrdArithBinaryOp(nqdiff, nrrdBinaryOpSubtract,
                           norigScl, nunquant)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "trouble quantizing and back:\n%s", err);
    airMopError(submop); airMopError(mop); return 1;
  }
  if (!( nucharScl->oldMin == omin
         && nucharScl->oldMax == omax )) {
    fprintf(stderr, "quantization range [%g,%g] != real range [%g,%g]\n",
            nucharScl->oldMin, nucharScl->oldMax, omin, omax);
    airMopError(submop); airMopError(mop); return 1;
  }
  {
    double *qdiff, *unquant;
    /* empirically determined tolerance, which had to be increased in
       order to work under valgrind (!)- perhaps because of a
       difference in the use of 80-bit registers */
    double epsilon=0.50000000000004;
    qdiff = AIR_CAST(double *, nqdiff->data);
    unquant = AIR_CAST(double *, nunquant->data);
    for (ii=0; ii<nn; ii++) {
      double dd;
      /* with infinite precision, the max difference between original and
         quantized values should be exactly half the width (in value)
         of 1/256 of value range  ==> dd = 0.5 */
      dd = qdiff[ii]*256/(omax - omin);
      if (AIR_ABS(dd) > epsilon) {
        unsigned int ui;
        ui = AIR_CAST(unsigned int, ii);
        fprintf(stderr, "|orig[%u]=%.17g - unquant=%.17g|*256/%.17g "
                "= %.17g > %.17g!\n", ui, origScl[ii], unquant[ii],
                omax - omin, AIR_ABS(dd), epsilon);
        airMopError(submop); airMopError(mop); return 1;
      }
    }
  }
コード例 #29
0
/*
** _nrrdApply1DLutOrRegMap()
**
** the guts of nrrdApply1DLut and nrrdApply1DRegMap
**
** yikes, does NOT use biff, since we're only supposed to be called
** after copious error checking.  
**
** FOR INSTANCE, this allows nout == nin, which could be a big
** problem if mapAxis == 1.
**
** we don't need a typeOut arg because nout has already been allocated
** as some specific type; we'll look at that.
**
** NOTE: non-existant values get passed through regular maps and luts
** "unchanged".  However, if the output type is integral, the results
** are probaby undefined.  HEY: there is currently no warning message
** or error handling based on nrrdStateDisallowIntegerNonExist, but
** there really should be.
*/
int
_nrrdApply1DLutOrRegMap(Nrrd *nout, const Nrrd *nin, const NrrdRange *range, 
                        const Nrrd *nmap, int ramps, int rescale, int multi) {
  /* char me[]="_nrrdApply1DLutOrRegMap"; */
  char *inData, *outData, *mapData, *entData0, *entData1;
  size_t N, I;
  double (*inLoad)(const void *v), (*mapLup)(const void *v, size_t I),
    (*outInsert)(void *v, size_t I, double d),
    val, mapIdxFrac, domMin, domMax;
  unsigned int i, mapAxis, mapLen, mapIdx, entSize, entLen, inSize, outSize;

  if (!multi) {
    mapAxis = nmap->dim - 1;           /* axis of nmap containing entries */
  } else {
    mapAxis = nmap->dim - nin->dim - 1;
  }
  mapData = (char *)nmap->data;        /* map data, as char* */
                                       /* low end of map domain */
  domMin = _nrrdApplyDomainMin(nmap, ramps, mapAxis);
                                       /* high end of map domain */
  domMax = _nrrdApplyDomainMax(nmap, ramps, mapAxis);
  mapLen = nmap->axis[mapAxis].size;   /* number of entries in map */
  mapLup = nrrdDLookup[nmap->type];    /* how to get doubles out of map */
  inData = (char *)nin->data;          /* input data, as char* */
  inLoad = nrrdDLoad[nin->type];       /* how to get doubles out of nin */
  inSize = nrrdElementSize(nin);       /* size of one input value */
  outData = (char *)nout->data;        /* output data, as char* */
  outInsert = nrrdDInsert[nout->type]; /* putting doubles into output */
  entLen = (mapAxis                    /* number of elements in one entry */
            ? nmap->axis[0].size
            : 1);
  outSize = entLen*nrrdElementSize(nout); /* size of entry in output */
  entSize = entLen*nrrdElementSize(nmap); /* size of entry in map */

  N = nrrdElementNumber(nin);       /* the number of values to be mapped */
  if (ramps) {
    /* regular map */
    for (I=0; I<N; I++) {
      /* ...
      if (!(I % 100)) fprintf(stderr, "I = %d\n", (int)I);
      ... */
      val = inLoad(inData);
      /* ...
      fprintf(stderr, "##%s: val = \na% 31.15f --> ", me, val);
      ... */
      if (rescale) {
        val = AIR_AFFINE(range->min, val, range->max, domMin, domMax);
        /* ...
        fprintf(stderr, "\nb% 31.15f (min,max = %g,%g)--> ", val,
                range->min, range->max);
        ... */
      }
      /* ...
      fprintf(stderr, "\nc% 31.15f --> clamp(%g,%g), %d --> ",
              val, domMin, domMax, mapLen);
      ... */
      if (AIR_EXISTS(val)) {
        val = AIR_CLAMP(domMin, val, domMax);
        mapIdxFrac = AIR_AFFINE(domMin, val, domMax, 0, mapLen-1);
        /* ...
        fprintf(stderr, "mapIdxFrac = \nd% 31.15f --> ",
                mapIdxFrac);
        ... */
        mapIdx = (unsigned int)mapIdxFrac;
        mapIdx -= mapIdx == mapLen-1;
        mapIdxFrac -= mapIdx;
        /* ...
        fprintf(stderr, "%s: (%d,\ne% 31.15f) --> \n",
                me, mapIdx, mapIdxFrac); 
        ... */
        entData0 = mapData + mapIdx*entSize;
        entData1 = mapData + (mapIdx+1)*entSize;
        for (i=0; i<entLen; i++) {
          val = ((1-mapIdxFrac)*mapLup(entData0, i) + 
                 mapIdxFrac*mapLup(entData1, i));
          outInsert(outData, i, val);
          /* ...
          fprintf(stderr, "f% 31.15f\n", val); 
          ... */
        }
      } else {
        /* copy non-existant values from input to output */
        for (i=0; i<entLen; i++) {
          outInsert(outData, i, val);
        }
      }
      inData += inSize;
      outData += outSize;
      if (multi) {
        mapData += mapLen*entSize;
      }
    }    
  } else {
    /* lookup table */
    for (I=0; I<N; I++) {
      val = inLoad(inData);
      if (rescale) {
        val = AIR_AFFINE(range->min, val, range->max, domMin, domMax);
      }
      if (AIR_EXISTS(val)) {
        mapIdx = airIndexClamp(domMin, val, domMax, mapLen);
        entData0 = mapData + mapIdx*entSize;
        for (i=0; i<entLen; i++) {
          outInsert(outData, i, mapLup(entData0, i));
        }
      } else {
        /* copy non-existant values from input to output */
        for (i=0; i<entLen; i++) {
          outInsert(outData, i, val);
        }
      }
      inData += inSize;
      outData += outSize;
      if (multi) {
        mapData += mapLen*entSize;
      }
    }
  }

  return 0;
}
コード例 #30
0
/*
** _nrrdSprintFieldInfo
**
** this prints "<prefix><field>: <info>" into *strP (after allocating it for
** big enough, usually with a stupidly big margin of error), in a form
** suitable to be written to NRRD or other image headers.  This will always
** print something (for valid inputs), even stupid <info>s like
** "(unknown endian)".  It is up to the caller to decide which fields
** are worth writing, via _nrrdFieldInteresting().
**
** NOTE: some of these fields make sense in non-NRRD files (e.g. all
** the per-axis information), but many only make sense in NRRD files.
** This is just one example of NRRD-format-specific stuff that is not
** in formatNRRD.c
*/
void
_nrrdSprintFieldInfo(char **strP, const char *prefix,
                     const Nrrd *nrrd, NrrdIoState *nio, int field) {
  static const char me[]="_nrrdSprintFieldInfo";
  char buff[AIR_STRLEN_MED], *fnb, stmp[AIR_STRLEN_SMALL],
    *strtmp=NULL;
  double colvec[NRRD_SPACE_DIM_MAX];
  const char *fs;
  unsigned int ii, dd,
    uintStrlen = 11,
    size_tStrlen = 33,
    doubleStrlen = 513;
  size_t fslen, fdlen, maxl;
  int endi;

  if (!( strP && prefix
         && nrrd
         && AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX)
         && AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) )) {
    return;
  }
  /* As of Sun Dec  2 01:57:48 CST 2012 (revision 5832) the only
     places where this function is called is when it has been guarded
     by "if (_nrrdFieldInteresting())" (except for in formatText.c when
     its called on the dimension field, which is always interesting).
     So, the following:

     if (!_nrrdFieldInteresting(nrrd, nio, field)) {
       *strP = airStrdup("");
     }

     was redundant and confusingly created the appearance of a memory
     leak waiting to happen.  We now let the default switch statement
     set *strP to NULL (all the other cases set it), to smoke out
     errors in how this function is called */

  fs = airEnumStr(nrrdField, field);
  fslen = strlen(prefix) + strlen(fs) + strlen(": ") + 1;
  switch (field) {
  case nrrdField_comment:
  case nrrdField_keyvalue:
    fprintf(stderr, "%s: CONFUSION: why are you calling me on \"%s\"?\n", me,
            airEnumStr(nrrdField, nrrdField_comment));
    *strP = airStrdup("");
    break;
  case nrrdField_content:
    strtmp = airOneLinify(airStrdup(nrrd->content));
    *strP = AIR_CALLOC(fslen + strlen(strtmp), char);
    sprintf(*strP, "%s%s: %s", prefix, fs, strtmp);
    airFree(strtmp); strtmp = NULL;
    break;
  case nrrdField_number:
    *strP = AIR_CALLOC(fslen + size_tStrlen, char);
    sprintf(*strP, "%s%s: %s", prefix, fs,
            airSprintSize_t(stmp, nrrdElementNumber(nrrd)));
    break;
  case nrrdField_type:
    *strP = AIR_CALLOC(fslen + strlen(airEnumStr(nrrdType, nrrd->type)), char);
    sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdType, nrrd->type));
    break;
  case nrrdField_block_size:
    *strP = AIR_CALLOC(fslen + size_tStrlen, char);
    sprintf(*strP, "%s%s: %s", prefix, fs,
            airSprintSize_t(stmp, nrrd->blockSize));
    break;
  case nrrdField_dimension:
    *strP = AIR_CALLOC(fslen + uintStrlen, char);
    sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->dim);
    break;
  case nrrdField_space:
    *strP = AIR_CALLOC(fslen
                       + strlen(airEnumStr(nrrdSpace, nrrd->space)), char);
    sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdSpace, nrrd->space));
    break;
  case nrrdField_space_dimension:
    *strP = AIR_CALLOC(fslen + uintStrlen, char);
    sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->spaceDim);
    break;
    /* ---- begin per-axis fields ---- */
  case nrrdField_sizes:
    *strP = AIR_CALLOC(fslen + nrrd->dim*(size_tStrlen + 1), char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      sprintf(buff, " %s", airSprintSize_t(stmp, nrrd->axis[ii].size));
      strcat(*strP, buff);
    }
    break;
  case nrrdField_spacings:
    *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].spacing);
      strcat(*strP, buff);
    }
    break;
  case nrrdField_thicknesses:
    *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].thickness);
      strcat(*strP, buff);
    }
    break;
  case nrrdField_axis_mins:
    *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].min);
      strcat(*strP, buff);
    }
    break;
  case nrrdField_axis_maxs:
    *strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].max);
      strcat(*strP, buff);
    }
    break;
  case nrrdField_space_directions:
    *strP = AIR_CALLOC(fslen
                       + nrrd->dim*nrrd->spaceDim*(doubleStrlen
                                                   + strlen("(,) ")), char);
    sprintf(*strP, "%s%s: ", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim,
                             nrrd->axis[ii].spaceDirection);
      if (ii < nrrd->dim-1) {
        strcat(*strP, " ");
      }
    }
    break;
  case nrrdField_centers:
    fdlen = 0;
    for (ii=0; ii<nrrd->dim; ii++) {
      fdlen += 1 + airStrlen(nrrd->axis[ii].center
                             ? airEnumStr(nrrdCenter, nrrd->axis[ii].center)
                             : NRRD_UNKNOWN);
    }
    *strP = AIR_CALLOC(fslen + fdlen, char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      sprintf(buff, " %s",
              (nrrd->axis[ii].center
               ? airEnumStr(nrrdCenter, nrrd->axis[ii].center)
               : NRRD_UNKNOWN));
      strcat(*strP, buff);
    }
    break;
  case nrrdField_kinds:
    fdlen = 0;
    for (ii=0; ii<nrrd->dim; ii++) {
      fdlen += 1 + airStrlen(nrrd->axis[ii].kind
                             ? airEnumStr(nrrdKind, nrrd->axis[ii].kind)
                             : NRRD_UNKNOWN);
    }
    *strP = AIR_CALLOC(fslen + fdlen, char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      sprintf(buff, " %s",
              (nrrd->axis[ii].kind
               ? airEnumStr(nrrdKind, nrrd->axis[ii].kind)
               : NRRD_UNKNOWN));
      strcat(*strP, buff);
    }
    break;
  case nrrdField_labels:
  case nrrdField_units:
#define LABEL_OR_UNITS (nrrdField_labels == field \
                        ? nrrd->axis[ii].label \
                        : nrrd->axis[ii].units)
    fdlen = 0;
    for (ii=0; ii<nrrd->dim; ii++) {
      /* The "2*" is because at worst every character needs escaping.
         The "+ 3" for the |" "| between each part */
      fdlen += 2*airStrlen(LABEL_OR_UNITS) + 3;
    }
    fdlen += 1; /* for '\0' */
    *strP = AIR_CALLOC(fslen + fdlen, char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->dim; ii++) {
      strcat(*strP, " \"");
      if (airStrlen(nrrd->axis[ii].label)) {
        _nrrdWriteEscaped(NULL, *strP, LABEL_OR_UNITS,
                          "\"", _NRRD_WHITESPACE_NOTAB);
      }
      strcat(*strP, "\"");
    }
#undef LABEL_OR_UNITS
    break;
    /* ---- end per-axis fields ---- */
  case nrrdField_min:
  case nrrdField_max:
    /* we're basically a no-op, now that these fields became meaningless */
    *strP = AIR_CALLOC(fslen + doubleStrlen, char);
    sprintf(*strP, "%s%s: 0.0", prefix, fs);
    strcat(*strP, buff);
    break;
  case nrrdField_old_min:
    *strP = AIR_CALLOC(fslen + doubleStrlen, char);
    sprintf(*strP, "%s%s: ", prefix, fs);
    airSinglePrintf(NULL, buff, "%.17g", nrrd->oldMin);
    strcat(*strP, buff);
    break;
  case nrrdField_old_max:
    *strP = AIR_CALLOC(fslen + doubleStrlen, char);
    sprintf(*strP, "%s%s: ", prefix, fs);
    airSinglePrintf(NULL, buff, "%.17g", nrrd->oldMax);
    strcat(*strP, buff);
    break;
  case nrrdField_endian:
    if (airEndianUnknown != nio->endian) {
      /* we know a specific endianness because either it was recorded as
         part of "unu make -h", or it was set (and data was possibly
         altered) as part of "unu save" */
      endi = nio->endian;
    } else {
      /* we record our current architecture's endian because we're
         going to writing out data */
      endi = airMyEndian();
    }
    *strP = AIR_CALLOC(fslen + strlen(airEnumStr(airEndian, endi)), char);
    sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(airEndian, endi));
    break;
  case nrrdField_encoding:
    *strP = AIR_CALLOC(fslen + strlen(nio->encoding->name), char);
    sprintf(*strP, "%s%s: %s", prefix, fs, nio->encoding->name);
    break;
  case nrrdField_line_skip:
    *strP = AIR_CALLOC(fslen + uintStrlen, char);
    sprintf(*strP, "%s%s: %d", prefix, fs, nio->lineSkip);
    break;
  case nrrdField_byte_skip:
    *strP = AIR_CALLOC(fslen + uintStrlen, char);
    sprintf(*strP, "%s%s: %ld", prefix, fs, nio->byteSkip);
    break;
  case nrrdField_sample_units:
    strtmp = airOneLinify(airStrdup(nrrd->sampleUnits));
    *strP = AIR_CALLOC(fslen + strlen(strtmp), char);
    sprintf(*strP, "%s%s: \"%s\"", prefix, fs, strtmp);
    airFree(strtmp); strtmp = NULL;
    break;
  case nrrdField_space_units:
    fdlen = 0;
    for (ii=0; ii<nrrd->spaceDim; ii++) {
      /* The "2*" is because at worst every character needs escaping.
         See note in formatNRRD.c about how even though its not part
         of the format, we have worst-case scenario of having to
         escape a space units which is nothing but ". The "+ 3" for
         the |" "| between each part */
      fdlen += 2*airStrlen(nrrd->spaceUnits[ii]) + 3;
    }
    fdlen += 1; /* for '\0' */
    *strP = AIR_CALLOC(fslen + fdlen, char);
    sprintf(*strP, "%s%s:", prefix, fs);
    for (ii=0; ii<nrrd->spaceDim; ii++) {
      strcat(*strP, " \"");
      if (airStrlen(nrrd->spaceUnits[ii])) {
        _nrrdWriteEscaped(NULL, *strP, nrrd->spaceUnits[ii],
                          "\"", _NRRD_WHITESPACE_NOTAB);
      }
      strcat(*strP, "\"");
    }
    break;
  case nrrdField_space_origin:
    *strP = AIR_CALLOC(fslen + nrrd->spaceDim*(doubleStrlen
                                               + strlen("(,) ")), char);
    sprintf(*strP, "%s%s: ", prefix, fs);
    _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, nrrd->spaceOrigin);
    break;
  case nrrdField_measurement_frame:
    *strP = AIR_CALLOC(fslen + (nrrd->spaceDim*
                                nrrd->spaceDim*(doubleStrlen
                                                + strlen("(,) "))), char);
    sprintf(*strP, "%s%s: ", prefix, fs);
    for (dd=0; dd<nrrd->spaceDim; dd++) {
      for (ii=0; ii<nrrd->spaceDim; ii++) {
        colvec[ii] = nrrd->measurementFrame[dd][ii];
      }
      _nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, colvec);
      if (dd < nrrd->spaceDim-1) {
        strcat(*strP, " ");
      }
    }
    break;
  case nrrdField_data_file:
    /* NOTE: this comes last (nrrdField_data_file is the highest-valued
       member of the nrrdField* enum) because the "LIST" form of the
       data file specification requires that the following lines be
       the filenames */
    /* error checking elsewhere: assumes there is data file info */
    if (nio->dataFNFormat) {
      *strP = AIR_CALLOC(fslen + strlen(nio->dataFNFormat) + 4*uintStrlen,
                         char);
      if (nio->dataFileDim == nrrd->dim-1) {
        sprintf(*strP, "%s%s: %s %d %d %d", prefix, fs, nio->dataFNFormat,
                nio->dataFNMin, nio->dataFNMax, nio->dataFNStep);
      } else {
        sprintf(*strP, "%s%s: %s %d %d %d %u", prefix, fs, nio->dataFNFormat,
                nio->dataFNMin, nio->dataFNMax, nio->dataFNStep,
                nio->dataFileDim);
      }
    } else if (nio->dataFNArr->len > 1) {