예제 #1
0
int
main(int argc, char *argv[]) {
  Nrrd *map, *ppm;
  NrrdRange *range;

  AIR_UNUSED(argc);
  me = argv[0];

  if (limnEnvMapFill(map=nrrdNew(), cb, limnQN16checker, NULL)) {
    fprintf(stderr, "%s: trouble:\n%s", me, biffGet(LIMN));
    exit(1);
  }
  range = nrrdRangeNew(0, 1);
  if (nrrdQuantize(ppm=nrrdNew(), map, range, 8)) {
    fprintf(stderr, "%s: trouble:\n%s", me, biffGet(NRRD));
    exit(1);
  }
  if (nrrdSave("map.ppm", ppm, NULL)) {
    fprintf(stderr, "%s: trouble:\n%s", me, biffGet(NRRD));
    exit(1);
  }

  nrrdNuke(map);
  nrrdNuke(ppm);
  nrrdRangeNix(range);
  exit(0);
}
예제 #2
0
파일: range.c 프로젝트: rblake/seg3d2
NrrdRange *
nrrdRangeNewSet(const Nrrd *nrrd, int blind8BitRange) {
  NrrdRange *range;

  range = nrrdRangeNew(0, 0);  /* doesn't matter what values are used here */
  nrrdRangeSet(range, nrrd, blind8BitRange);
  return range;
}
예제 #3
0
파일: range.c 프로젝트: rblake/seg3d2
NrrdRange *
nrrdRangeCopy(const NrrdRange *rin) {
  NrrdRange *rout=NULL;

  if (rin) {
    rout = nrrdRangeNew(rin->min, rin->max);
    rout->hasNonExist = rin->hasNonExist;
  }
  return rout;
}
예제 #4
0
int
unrrdu_histaxMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nout;
  int type, bins, pret, blind8BitRange;
  unsigned int axis;
  double min, max;
  airArray *mop;
  NrrdRange *range;

  OPT_ADD_AXIS(axis, "axis to histogram along");
  hestOptAdd(&opt, "b,bin", "bins", airTypeInt, 1, 1, &bins, NULL,
             "# of bins in histogram");
  OPT_ADD_TYPE(type, "output type", "uchar");
  hestOptAdd(&opt, "min,minimum", "value", airTypeDouble, 1, 1, &min, "nan",
             "Value at low end of histogram. Defaults to lowest value "
             "found in input nrrd.");
  hestOptAdd(&opt, "max,maximum", "value", airTypeDouble, 1, 1, &max, "nan",
             "Value at high end of histogram. Defaults to highest value "
             "found in input nrrd.");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "Whether to know the range of 8-bit data blindly "
             "(uchar is always [0,255], signed char is [-128,127]).");
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_histaxInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  range = nrrdRangeNew(min, max);
  airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
  nrrdRangeSafeSet(range, nin, blind8BitRange);
  if (nrrdHistoAxis(nout, nin, range, axis, bins, type)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error doing axis histogramming:\n%s", me, err);
    airMopError(mop);
    return 1;
  }
  

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #5
0
파일: gamma.c 프로젝트: CIBC-Internal/teem
int
unrrdu_gammaMain(int argc, const char **argv, const char *me,
                 hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nout;
  double min, max, gamma;
  airArray *mop;
  int pret, blind8BitRange;
  NrrdRange *range;

  hestOptAdd(&opt, "g,gamma", "gamma", airTypeDouble, 1, 1, &gamma, NULL,
             "gamma > 1.0 brightens; gamma < 1.0 darkens. "
             "Negative gammas invert values (like in xv). ");
  hestOptAdd(&opt, "min,minimum", "value", airTypeDouble, 1, 1, &min, "nan",
             "Value to implicitly map to 0.0 prior to calling pow(). "
             "Defaults to lowest value found in input nrrd.");
  hestOptAdd(&opt, "max,maximum", "value", airTypeDouble, 1, 1, &max, "nan",
             "Value to implicitly map to 1.0 prior to calling pow(). "
             "Defaults to highest value found in input nrrd.");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "Whether to know the range of 8-bit data blindly "
             "(uchar is always [0,255], signed char is [-128,127]).");
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_gammaInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  range = nrrdRangeNew(min, max);
  airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
  nrrdRangeSafeSet(range, nin, blind8BitRange);
  if (nrrdArithGamma(nout, nin, range, gamma)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error doing gamma:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #6
0
파일: histax.c 프로젝트: BRAINSia/teem
int
unrrdu_histaxMain(int argc, const char **argv, const char *me,
                  hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nout;
  char *minStr, *maxStr;
  int type, pret, blind8BitRange;
  unsigned int axis, bins;
  airArray *mop;
  NrrdRange *range;

  OPT_ADD_AXIS(axis, "axis to histogram along");
  hestOptAdd(&opt, "b,bin", "bins", airTypeUInt, 1, 1, &bins, NULL,
             "# of bins in histogram");
  OPT_ADD_TYPE(type, "output type", "uchar");
  /* HEY copy and paste from unrrdu/quantize.c */
  hestOptAdd(&opt, "min,minimum", "value", airTypeString, 1, 1,
             &minStr, "nan",
             "The value to map to zero, given explicitly as a regular number, "
             "*or*, if the number is given with a \"" NRRD_MINMAX_PERC_SUFF
             "\" suffix, this "
             "minimum is specified in terms of the percentage of samples in "
             "input that are lower. "
             "\"0" NRRD_MINMAX_PERC_SUFF "\" means the "
             "lowest input value is used, "
             "\"1" NRRD_MINMAX_PERC_SUFF "\" means that the "
             "1% of the lowest values are all mapped to zero. "
             "By default (not using this option), the lowest input value is "
             "used.");
  hestOptAdd(&opt, "max,maximum", "value", airTypeString, 1, 1,
             &maxStr, "nan",
             "The value to map to the highest unsigned integral value, given "
             "explicitly as a regular number, "
             "*or*, if the number is given with "
             "a \"" NRRD_MINMAX_PERC_SUFF "\" suffix, "
             "this maximum is specified "
             "in terms of the percentage of samples in input that are higher. "
             "\"0" NRRD_MINMAX_PERC_SUFF "\" means the highest input value is "
             "used, which is also the default "
             "behavior (same as not using this option).");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "Whether to know the range of 8-bit data blindly "
             "(uchar is always [0,255], signed char is [-128,127]).");
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_histaxInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  range = nrrdRangeNew(AIR_NAN, AIR_NAN);
  airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdRangePercentileFromStringSet(range, nin, minStr, maxStr,
                                       10*bins /* HEY magic */,
                                       blind8BitRange)
      || nrrdHistoAxis(nout, nin, range, axis, bins, type)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error doing axis histogramming:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #7
0
파일: imap.c 프로젝트: rblake/seg3d2
int
unrrdu_imapMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nmap, *nacl, *nout;
  airArray *mop;
  NrrdRange *range=NULL;
  unsigned int aclLen;
  int typeOut, rescale, pret, blind8BitRange;
  double min, max;

  hestOptAdd(&opt, "m,map", "map", airTypeOther, 1, 1, &nmap, NULL,
             "irregular map to map input nrrd through",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&opt, "l,length", "aclLen", airTypeUInt, 1, 1, &aclLen, "0",
             "length of accelerator array, used to try to speed-up "
             "task of finding between which pair of control points "
             "a given value lies.  Not terribly useful for small maps "
             "(about 10 points or less).  Use 0 to turn accelorator off. ");
  hestOptAdd(&opt, "r,rescale", NULL, airTypeInt, 0, 0, &rescale, NULL,
             "rescale the input values from the input range to the "
             "map domain");
  hestOptAdd(&opt, "min,minimum", "value", airTypeDouble, 1, 1, &min, "nan",
             "Low end of input range. Defaults to lowest value "
             "found in input nrrd.  Explicitly setting this is useful "
             "only with rescaling (\"-r\")");
  hestOptAdd(&opt, "max,maximum", "value", airTypeDouble, 1, 1, &max, "nan",
             "High end of input range. Defaults to highest value "
             "found in input nrrd.  Explicitly setting this is useful "
             "only with rescaling (\"-r\")");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "Whether to know the range of 8-bit data blindly "
             "(uchar is always [0,255], signed char is [-128,127]). "
             "Explicitly setting this is useful only with rescaling (\"-r\")");
  hestOptAdd(&opt, "t,type", "type", airTypeOther, 1, 1, &typeOut, "default",
             "specify the type (\"int\", \"float\", etc.) of the "
             "output nrrd. "
             "By default (not using this option), the output type "
             "is the map's type.",
             NULL, NULL, &unrrduHestMaybeTypeCB);
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_imapInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  if (aclLen) {
    nacl = nrrdNew();
    airMopAdd(mop, nacl, (airMopper)nrrdNuke, airMopAlways);
    if (nrrd1DIrregAclGenerate(nacl, nmap, aclLen)) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble generating accelerator:\n%s", me, err);
      airMopError(mop);
      return 1;
    }
  } else {
    nacl = NULL;
  }
  if (rescale) {
    range = nrrdRangeNew(min, max);
    airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
    nrrdRangeSafeSet(range, nin, blind8BitRange);
  }
  if (nrrdTypeDefault == typeOut) {
    typeOut = nmap->type;
  }
  /* some very non-exhaustive tests seemed to indicate that the
     accelerator does not in fact reliably speed anything up.
     This of course depends on the size of the imap (# points),
     but chances are most imaps will have only a handful of points,
     in which case the binary search in _nrrd1DIrregFindInterval()
     will finish quickly ... */
  if (nrrdApply1DIrregMap(nout, nin, range, nmap, nacl, typeOut, rescale)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble applying map:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #8
0
int
unrrdu_lutMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nlut, *nout;
  airArray *mop;
  int typeOut, rescale, pret, blind8BitRange;
  double min, max;
  NrrdRange *range=NULL;

  hestOptAdd(&opt, "m,map", "lut", airTypeOther, 1, 1, &nlut, NULL,
             "lookup table to map input nrrd through",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&opt, "r,rescale", NULL, airTypeInt, 0, 0, &rescale, NULL,
             "rescale the input values from the input range to the "
             "lut domain.  The lut domain is either explicitly "
             "defined by the axis min,max along axis 0 or 1, or, it "
             "is implicitly defined as zero to the length of that axis "
             "minus one.");
  hestOptAdd(&opt, "min,minimum", "value", airTypeDouble, 1, 1, &min, "nan",
             "Low end of input range. Defaults to lowest value "
             "found in input nrrd.  Explicitly setting this is useful "
             "only with rescaling (\"-r\")");
  hestOptAdd(&opt, "max,maximum", "value", airTypeDouble, 1, 1, &max, "nan",
             "High end of input range. Defaults to highest value "
             "found in input nrrd.  Explicitly setting this is useful "
             "only with rescaling (\"-r\")");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "Whether to know the range of 8-bit data blindly "
             "(uchar is always [0,255], signed char is [-128,127]). "
             "Explicitly setting this is useful only with rescaling (\"-r\")");
  hestOptAdd(&opt, "t,type", "type", airTypeOther, 1, 1, &typeOut, "default",
             "specify the type (\"int\", \"float\", etc.) of the "
             "output nrrd. "
             "By default (not using this option), the output type "
             "is the lut's type.",
             NULL, NULL, &unrrduHestMaybeTypeCB);
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_lutInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  /* see comment rmap.c */
  if (!( AIR_EXISTS(nlut->axis[nlut->dim - 1].min) && 
         AIR_EXISTS(nlut->axis[nlut->dim - 1].max) )) {
    rescale = AIR_TRUE;
  }
  if (rescale) {
    range = nrrdRangeNew(min, max);
    airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
    nrrdRangeSafeSet(range, nin, blind8BitRange);
  }

  if (nrrdTypeDefault == typeOut) {
    typeOut = nlut->type;
  }
  if (nrrdApply1DLut(nout, nin, range, nlut, typeOut, rescale)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble applying LUT:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #9
0
파일: rmap.c 프로젝트: rblake/seg3d2
int
unrrdu_rmapMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nmap, *nout;
  airArray *mop;
  NrrdRange *range=NULL;
  int typeOut, rescale, pret, blind8BitRange;
  double min, max;

  hestOptAdd(&opt, "m,map", "map", airTypeOther, 1, 1, &nmap, NULL,
             "regular map to map input nrrd through",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&opt, "r,rescale", NULL, airTypeInt, 0, 0, &rescale, NULL,
             "rescale the input values from the input range to the "
             "map domain.  The map domain is either explicitly "
             "defined by the axis min,max along axis 0 or 1, or, it "
             "is implicitly defined as zero to the length of "
             "that axis minus one.");
  hestOptAdd(&opt, "min,minimum", "value", airTypeDouble, 1, 1, &min, "nan",
             "Low end of input range. Defaults to lowest value "
             "found in input nrrd.  Explicitly setting this is useful "
             "only with rescaling (\"-r\") or if the map domain is only "
             "implicitly defined");
  hestOptAdd(&opt, "max,maximum", "value", airTypeDouble, 1, 1, &max, "nan",
             "High end of input range. Defaults to highest value "
             "found in input nrrd.  Explicitly setting this is useful "
             "only with rescaling (\"-r\") or if the map domain is only "
             "implicitly defined");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "Whether to know the range of 8-bit data blindly "
             "(uchar is always [0,255], signed char is [-128,127]). "
             "Explicitly setting this is useful "
             "only with rescaling (\"-r\") or if the map domain is only "
             "implicitly defined");
  hestOptAdd(&opt, "t,type", "type", airTypeOther, 1, 1, &typeOut, "default",
             "specify the type (\"int\", \"float\", etc.) of the "
             "output nrrd. "
             "By default (not using this option), the output type "
             "is the map's type.",
             NULL, NULL, &unrrduHestMaybeTypeCB);
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_rmapInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  /* here is a big difference between unu and nrrd: we enforce
     rescaling any time that the map domain is implicit.  This
     is how the pre-1.6 functionality is recreated.  Also, whenever
     there is rescaling we pass a NrrdRange to reflect the (optional)
     user range specification, instead of letting nrrdApply1DRegMap
     find the input range itself (by passing a NULL NrrdRange).
  */
  if (!( AIR_EXISTS(nmap->axis[nmap->dim - 1].min) && 
         AIR_EXISTS(nmap->axis[nmap->dim - 1].max) )) {
    rescale = AIR_TRUE;
  }
  if (rescale) {
    range = nrrdRangeNew(min, max);
    airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
    nrrdRangeSafeSet(range, nin, blind8BitRange);
  }

  if (nrrdTypeDefault == typeOut) {
    typeOut = nmap->type;
  }
  if (nrrdApply1DRegMap(nout, nin, range, nmap, typeOut, rescale)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble applying map:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #10
0
파일: histo.c 프로젝트: CIBC-Internal/teem
int
unrrdu_histoMain(int argc, const char **argv, const char *me,
                 hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nout, *nwght;
  char *minStr, *maxStr;
  int type, pret, blind8BitRange;
  unsigned int bins;
  NrrdRange *range;
  airArray *mop;

  hestOptAdd(&opt, "b,bins", "num", airTypeUInt, 1, 1, &bins, NULL,
             "# of bins in histogram");
  hestOptAdd(&opt, "w,weight", "nweight", airTypeOther, 1, 1, &nwght, "",
             "how to weigh contributions to histogram.  By default "
             "(not using this option), the increment is one bin count per "
             "sample, but by giving a nrrd, the value in the nrrd at the "
             "corresponding location will be the bin count increment ",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&opt, "min,minimum", "value", airTypeString, 1, 1,
             &minStr, "nan",
             "Value at low end of histogram, given explicitly as a "
             "regular number, "
             "*or*, if the number is given with a \"" NRRD_MINMAX_PERC_SUFF
             "\" suffix, this "
             "minimum is specified in terms of the percentage of samples in "
             "input that are lower. "
             "By default (not using this option), the lowest value "
             "found in input nrrd.");
  hestOptAdd(&opt, "max,maximum", "value", airTypeString, 1, 1,
             &maxStr, "nan",
             "Value at high end of histogram, given "
             "explicitly as a regular number, "
             "*or*, if the number is given with "
             "a \"" NRRD_MINMAX_PERC_SUFF "\" suffix, "
             "this maximum is specified "
             "in terms of the percentage of samples in input that are higher. "
             "Defaults to highest value found in input nrrd.");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "Whether to know the range of 8-bit data blindly "
             "(uchar is always [0,255], signed char is [-128,127]).");
  OPT_ADD_TYPE(type, "type to use for bins in output histogram", "uint");
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_histoInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  range = nrrdRangeNew(AIR_NAN, AIR_NAN);
  airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdRangePercentileFromStringSet(range, nin, minStr, maxStr,
                                       10*bins /* HEY magic */,
                                       blind8BitRange)
      || nrrdHisto(nout, nin, range, nwght, bins, type)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error with range or quantizing:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #11
0
int
unrrdu_mlutMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, **_nmlut, *nmlut, *nout;
  airArray *mop;
  int typeOut, rescale, pret, blind8BitRange;
  unsigned int _nmlutLen, mapAxis;
  double min, max;
  NrrdRange *range=NULL;

  hestOptAdd(&opt, "m,map", "mlut", airTypeOther, 1, -1, &_nmlut, NULL,
             "one nrrd of lookup tables to map input nrrd through, or, "
             "list of nrrds which contain the individual entries of "
             "the lookup table at each voxel, which will be joined together.",
             &_nmlutLen, NULL, nrrdHestNrrd);
  hestOptAdd(&opt, "r,rescale", NULL, airTypeInt, 0, 0, &rescale, NULL,
             "rescale the input values from the input range to the "
             "lut domain.  The lut domain is either explicitly "
             "defined by the axis min,max along axis 0 or 1, or, it "
             "is implicitly defined as zero to the length of that axis "
             "minus one.");
  hestOptAdd(&opt, "min,minimum", "value", airTypeDouble, 1, 1, &min, "nan",
             "Low end of input range. Defaults to lowest value "
             "found in input nrrd.  Explicitly setting this is useful "
             "only with rescaling (\"-r\")");
  hestOptAdd(&opt, "max,maximum", "value", airTypeDouble, 1, 1, &max, "nan",
             "High end of input range. Defaults to highest value "
             "found in input nrrd.  Explicitly setting this is useful "
             "only with rescaling (\"-r\")");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "Whether to know the range of 8-bit data blindly "
             "(uchar is always [0,255], signed char is [-128,127]). "
             "Explicitly setting this is useful only with rescaling (\"-r\")");
  hestOptAdd(&opt, "t,type", "type", airTypeOther, 1, 1, &typeOut, "default",
             "specify the type (\"int\", \"float\", etc.) of the "
             "output nrrd. "
             "By default (not using this option), the output type "
             "is the lut's type.",
             NULL, NULL, &unrrduHestMaybeTypeCB);
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_mlutInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  /* by the end of this block we need to have nmlut and mapAxis */
  if (1 == _nmlutLen) {
    /* we got the mlut as a single nrrd */
    nmlut = _nmlut[0];
    mapAxis = nmlut->dim - nin->dim - 1;
    /* its not our job to do real error checking ... */
    mapAxis = AIR_MIN(mapAxis, nmlut->dim - 1);
  } else {
    /* we have to join together multiple nrrds to get the mlut */
    nmlut = nrrdNew();
    airMopAdd(mop, nmlut, (airMopper)nrrdNuke, airMopAlways);
    /* assume that mlut component nrrds are all compatible sizes,
       nrrdJoin will fail if they aren't */
    mapAxis = _nmlut[0]->dim - nin->dim;
    if (nrrdJoin(nmlut, (const Nrrd**)_nmlut, _nmlutLen, mapAxis, AIR_TRUE)) {
      airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
      fprintf(stderr, "%s: trouble joining mlut:\n%s", me, err);
      airMopError(mop);
      return 1;
    }
    /* set these if they were given, they'll be NaN otherwise */
    nmlut->axis[mapAxis].min = min;
    nmlut->axis[mapAxis].max = max;
  }

  if (!( AIR_EXISTS(nmlut->axis[mapAxis].min) && 
         AIR_EXISTS(nmlut->axis[mapAxis].max) )) {
    rescale = AIR_TRUE;
  }
  if (rescale) {
    range = nrrdRangeNew(min, max);
    airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
    nrrdRangeSafeSet(range, nin, blind8BitRange);
  }

  if (nrrdTypeDefault == typeOut) {
    typeOut = nmlut->type;
  }
  if (nrrdApplyMulti1DLut(nout, nin, range, nmlut, typeOut, rescale)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble applying multi-LUT:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #12
0
파일: jhisto.c 프로젝트: rblake/seg3d2
int
unrrdu_jhistoMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd **nin;
  Nrrd *nout, *nwght;
  size_t *bin;
  int type, clamp[NRRD_DIM_MAX], pret;
  unsigned int binLen, minLen, maxLen, ninLen, ai;
  airArray *mop;
  double *min, *max;
  NrrdRange **range;

  hestOptAdd(&opt, "b,bin", "bins0 bins1", airTypeSize_t, 2, -1, &bin, NULL,
             "bins<i> is the number of bins to use along axis i (of joint "
             "histogram), which represents the values of nin<i> ",
             &binLen);
  hestOptAdd(&opt, "w,weight", "nweight", airTypeOther, 1, 1, &nwght, "",
             "how to weigh contributions to joint histogram.  By default "
             "(not using this option), the increment is one bin count per "
             "sample, but by giving a nrrd, the value in the nrrd at the "
             "corresponding location will be the bin count increment ",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&opt, "min,minimum", "min0 min1", airTypeDouble, 2, -1,
             &min, "nan nan",
             "min<i> is the low range of values to be quantized along "
             "axis i; use \"nan\" to represent lowest value present ",
             &minLen);
  hestOptAdd(&opt, "max,maximum", "max0 max1", airTypeDouble, 2, -1,
             &max, "nan nan",
             "max<i> is the high range of values to be quantized along "
             "axis i; use \"nan\" to represent highest value present ",
             &maxLen);
  OPT_ADD_TYPE(type, "type to use for output (the type used to store hit "
               "counts in the joint histogram).  Clamping is done on hit "
               "counts so that they never overflow a fixed-point type",
               "uint");
  hestOptAdd(&opt, "i,input", "nin0 nin1", airTypeOther, 2, -1, &nin, NULL,
             "All input nrrds",
             &ninLen, NULL, nrrdHestNrrd);
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_jhistoInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  if (ninLen != binLen) {
    fprintf(stderr, "%s: # input nrrds (%d) != # bin specifications (%d)\n",
            me, ninLen, binLen);
    airMopError(mop);
    return 1;
  }
  range = (NrrdRange **)calloc(ninLen, sizeof(NrrdRange*));
  airMopAdd(mop, range, airFree, airMopAlways);
  for (ai=0; ai<ninLen; ai++) {
    range[ai] = nrrdRangeNew(AIR_NAN, AIR_NAN);
    airMopAdd(mop, range[ai], (airMopper)nrrdRangeNix, airMopAlways);
  }
  if (2 != minLen || (AIR_EXISTS(min[0]) || AIR_EXISTS(min[1]))) {
    if (minLen != ninLen) {
      fprintf(stderr, "%s: # mins (%d) != # input nrrds (%d)\n", me,
              minLen, ninLen);
      airMopError(mop); return 1;
    }
    for (ai=0; ai<ninLen; ai++) {
      range[ai]->min = min[ai];
    }
  }
  if (2 != maxLen || (AIR_EXISTS(max[0]) || AIR_EXISTS(max[1]))) {
    if (maxLen != ninLen) {
      fprintf(stderr, "%s: # maxs (%d) != # input nrrds (%d)\n", me,
              maxLen, ninLen);
      airMopError(mop); return 1;
    }
    for (ai=0; ai<ninLen; ai++) {
      range[ai]->max = max[ai];
    }
  }
  for (ai=0; ai<ninLen; ai++) {
    clamp[ai] = 0;
  }

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  if (nrrdHistoJoint(nout, (const Nrrd**)nin, (const NrrdRange**)range,
                     ninLen, nwght, bin, type, clamp)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error doing joint histogram:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #13
0
int
unrrdu_quantizeMain(int argc, const char **argv, const char *me,
                    hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nout;
  char *minStr, *maxStr;
  int pret, blind8BitRange;
  unsigned int bits, hbins;
  NrrdRange *range;
  airArray *mop;

  hestOptAdd(&opt, "b,bits", "bits", airTypeOther, 1, 1, &bits, NULL,
             "Number of bits to quantize down to; determines the type "
             "of the output nrrd:\n "
             "\b\bo \"8\": unsigned char\n "
             "\b\bo \"16\": unsigned short\n "
             "\b\bo \"32\": unsigned int",
             NULL, NULL, &unrrduHestBitsCB);
  hestOptAdd(&opt, "min,minimum", "value", airTypeString, 1, 1,
             &minStr, "nan",
             "The value to map to zero, given explicitly as a regular number, "
             "*or*, if the number is given with a \"" NRRD_MINMAX_PERC_SUFF
             "\" suffix, this "
             "minimum is specified in terms of the percentage of samples in "
             "input that are lower. "
             "\"0" NRRD_MINMAX_PERC_SUFF "\" means the "
             "lowest input value is used, "
             "\"1" NRRD_MINMAX_PERC_SUFF "\" means that the "
             "1% of the lowest values are all mapped to zero. "
             "By default (not using this option), the lowest input value is "
             "used.");
  hestOptAdd(&opt, "max,maximum", "value", airTypeString, 1, 1,
             &maxStr, "nan",
             "The value to map to the highest unsigned integral value, given "
             "explicitly as a regular number, "
             "*or*, if the number is given with "
             "a \"" NRRD_MINMAX_PERC_SUFF "\" suffix, "
             "this maximum is specified "
             "in terms of the percentage of samples in input that are higher. "
             "\"0" NRRD_MINMAX_PERC_SUFF "\" means the highest input value is "
             "used, which is also the default "
             "behavior (same as not using this option).");
  hestOptAdd(&opt, "hb,bins", "bins", airTypeUInt, 1, 1, &hbins, "5000",
             "number of bins in histogram of values, for determining min "
             "or max by percentiles.  This has to be large enough so that "
             "any errant very high or very low values do not compress the "
             "interesting part of the histogram to an inscrutably small "
             "number of bins.");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "if not using \"-min\" or \"-max\", whether to know "
             "the range of 8-bit data blindly (uchar is always [0,255], "
             "signed char is [-128,127])");
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_quantizeInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  range = nrrdRangeNew(AIR_NAN, AIR_NAN);
  airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  if (nrrdRangePercentileFromStringSet(range, nin, minStr, maxStr,
                                       hbins, blind8BitRange)
      || nrrdQuantize(nout, nin, range, bits)) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: error with range or quantizing:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #14
0
int
unrrdu_histoMain(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nout, *nwght;
  int type, pret, blind8BitRange;
  unsigned int bins;
  double min, max;
  NrrdRange *range;
  airArray *mop;

  hestOptAdd(&opt, "b,bins", "num", airTypeUInt, 1, 1, &bins, NULL,
             "# of bins in histogram");
  hestOptAdd(&opt, "w,weight", "nweight", airTypeOther, 1, 1, &nwght, "",
             "how to weigh contributions to histogram.  By default "
             "(not using this option), the increment is one bin count per "
             "sample, but by giving a nrrd, the value in the nrrd at the "
             "corresponding location will be the bin count increment ",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&opt, "min,minimum", "value", airTypeDouble, 1, 1, &min, "nan",
             "Value at low end of histogram. Defaults to lowest value "
             "found in input nrrd.");
  hestOptAdd(&opt, "max,maximum", "value", airTypeDouble, 1, 1, &max, "nan",
             "Value at high end of histogram. Defaults to highest value "
             "found in input nrrd.");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "Whether to know the range of 8-bit data blindly "
             "(uchar is always [0,255], signed char is [-128,127]).");
  OPT_ADD_TYPE(type, "type to use for bins in output histogram", "uint");
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_histoInfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);
  
  /* If the input nrrd never specified min and max, then they'll be
     AIR_NAN, and nrrdRangeSafeSet will find them, and will do so
     according to blind8BitRange */
  range = nrrdRangeNew(min, max);
  airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
  nrrdRangeSafeSet(range, nin, blind8BitRange);
  if (nrrdHisto(nout, nin, range, nwght, bins, type)) {
    err = biffGet(NRRD);
    fprintf(stderr, "%s: error calculating histogram:\n%s", me, err);
    free(err);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}
예제 #15
0
seekContext *
seekContextNew(void) {
  seekContext *sctx;
  unsigned int fi;

  sctx = (seekContext *)calloc(1, sizeof(seekContext));
  if (sctx) {
    sctx->verbose = 0;
    sctx->ninscl = NULL;
    sctx->gctx = NULL;
    sctx->pvl = NULL;
    sctx->type = seekTypeUnknown;
    sctx->sclvItem = -1;
    sctx->normItem = -1;
    sctx->gradItem = -1;
    sctx->evalItem = -1;
    sctx->evecItem = -1;
    sctx->stngItem = -1;
    sctx->hessItem = -1;
    sctx->lowerInside = AIR_FALSE;
    sctx->normalsFind = AIR_FALSE;
    sctx->strengthUse = AIR_FALSE;
    sctx->strengthSign = 1;
    sctx->isovalue = AIR_NAN;
    sctx->evalDiffThresh = 1.0; /* roughly reasonable for uchar data;
                                 * really should depend on dynamic range */
    sctx->strength = 0.0;
    ELL_3V_SET(sctx->samples, 0, 0, 0);
    /* these two magic values assume a certain level of surface smoothness,
       which certainly does not apply to all cases */
    sctx->facesPerVoxel = 2.15;
    sctx->vertsPerVoxel = 1.15;
    sctx->pldArrIncr = 2048;

    sctx->nin = NULL;
    sctx->flag = AIR_CAST(int *, calloc(flagLast, sizeof(int)));
    for (fi=flagUnknown+1; fi<flagLast; fi++) {
      sctx->flag[fi] = AIR_FALSE;
    }
    sctx->baseDim = 0;
    sctx->_shape = gageShapeNew();
    sctx->shape = NULL;
    sctx->nsclDerived = nrrdNew();
    sctx->sclvAns = NULL;
    sctx->normAns = NULL;
    sctx->gradAns = NULL;
    sctx->evalAns = NULL;
    sctx->evecAns = NULL;
    sctx->stngAns = NULL;
    sctx->hessAns = NULL;
    sctx->reverse = AIR_FALSE;
    ELL_3M_IDENTITY_SET(sctx->txfNormal);
    sctx->spanSize = 300;
    sctx->nspanHist = nrrdNew();
    sctx->range = nrrdRangeNew(AIR_NAN, AIR_NAN);
    sctx->sx = 0;
    sctx->sy = 0;
    sctx->sz = 0;
    ELL_4M_IDENTITY_SET(sctx->txfIdx);
    sctx->nvidx = nrrdNew();
    sctx->nsclv = nrrdNew();
    sctx->ngrad = nrrdNew();
    sctx->neval = nrrdNew();
    sctx->nevec = nrrdNew();
    sctx->nflip = nrrdNew();
    sctx->nstng = nrrdNew();
    sctx->nhess = nrrdNew();
    sctx->nt = nrrdNew();
    sctx->nfacevidx = nrrdNew();
    sctx->nedgealpha = nrrdNew();
    sctx->nedgenorm = nrrdNew();
    sctx->nedgeicoord = nrrdNew();
    sctx->nfacecoord = nrrdNew();
    sctx->nfacenorm = nrrdNew();
    sctx->nfaceicoord = nrrdNew();
    sctx->npairs = nrrdNew();
    sctx->ngradcontext = nrrdNew();
    sctx->nhesscontext = nrrdNew();
    sctx->ntcontext = nrrdNew();
    sctx->nstngcontext = nrrdNew();
    sctx->ntreated = nrrdNew();
    sctx->vidx = NULL;
    sctx->sclv = NULL;
    sctx->grad = NULL;
    sctx->eval = NULL;
    sctx->evec = NULL;
    sctx->flip = NULL;
    sctx->stng = NULL;
    sctx->voxNum = 0;
    sctx->vertNum = 0;
    sctx->faceNum = 0;
    sctx->strengthSeenMax = AIR_NAN;
    sctx->time = AIR_NAN;
  }
  return sctx;
}
예제 #16
0
파일: lut2.c 프로젝트: SCIInstitute/Cleaver
int
unrrdu_lut2Main(int argc, char **argv, char *me, hestParm *hparm) {
  hestOpt *opt = NULL;
  char *out, *err;
  Nrrd *nin, *nlut, *nout, *ntmp[2];
  airArray *mop;
  int typeOut, rescale[2], pret, blind8BitRange;
  double min[2], max[2];
  NrrdRange *range[2]={NULL,NULL};
  unsigned int mapAxis, rai;

  hestOptAdd(&opt, "m,map", "lut", airTypeOther, 1, 1, &nlut, NULL,
             "lookup table to map input nrrd through",
             NULL, NULL, nrrdHestNrrd);
  hestOptAdd(&opt, "r,rescale", "bool bool", airTypeBool, 2, 2, rescale,
             "false false",
             "rescale one or both of the input values from the "
             "input range to the lut domain.  The lut domain is either "
             "explicitly defined by the axis min,max along axis 0 or 1, "
             "or, it is implicitly defined as zero to the length of that axis "
             "minus one.");
  hestOptAdd(&opt, "min,minimum", "min0 min1", airTypeDouble, 2, 2, min,
             "nan nan",
             "Low ends of input range. Defaults to lowest values "
             "found in input nrrd.  Explicitly setting this is useful "
             "only with rescaling (\"-r\")");
  hestOptAdd(&opt, "max,maximum", "max0 max1", airTypeDouble, 2, 2, max,
             "nan nan",
             "High end of input range. Defaults to highest values "
             "found in input nrrd.  Explicitly setting this is useful "
             "only with rescaling (\"-r\")");
  hestOptAdd(&opt, "blind8", "bool", airTypeBool, 1, 1, &blind8BitRange,
             nrrdStateBlind8BitRange ? "true" : "false",
             "Whether to know the range of 8-bit data blindly "
             "(uchar is always [0,255], signed char is [-128,127]). "
             "Explicitly setting this is useful only with rescaling (\"-r\")");
  hestOptAdd(&opt, "t,type", "type", airTypeOther, 1, 1, &typeOut, "default",
             "specify the type (\"int\", \"float\", etc.) of the "
             "output nrrd. "
             "By default (not using this option), the output type "
             "is the lut's type.",
             NULL, NULL, &unrrduHestMaybeTypeCB);
  OPT_ADD_NIN(nin, "input nrrd");
  OPT_ADD_NOUT(out, "output nrrd");

  mop = airMopNew();
  airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways);

  USAGE(_unrrdu_lut2InfoL);
  PARSE();
  airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways);

  nout = nrrdNew();
  airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways);

  if (!( nin->dim > 1 && 2 == nin->axis[0].size )) {
    fprintf(stderr, "%s: input nrrd dim must be > 1, and axis[0].size "
            "must be 2 (not " _AIR_SIZE_T_CNV ")", me, nin->axis[0].size);
    airMopError(mop);
    return 1;
  }
  mapAxis = nlut->dim - 2;
  if (!(0 == mapAxis || 1 == mapAxis)) {
    fprintf(stderr, "%s: dimension of lut should be 2 or 3, not %d", 
            me, nlut->dim);
    airMopError(mop);
    return 1;
  }

  /* see comment in rmap.c */
  for (rai=0; rai<=1; rai++) {
    if (!( AIR_EXISTS(nlut->axis[mapAxis + rai].min) && 
           AIR_EXISTS(nlut->axis[mapAxis + rai].max) )) {
      rescale[rai] = AIR_TRUE;
    }
    if (rescale[rai]) {
      ntmp[rai] = nrrdNew();
      airMopAdd(mop, ntmp[rai], AIR_CAST(airMopper, nrrdNuke), airMopAlways);
      if (nrrdSlice(ntmp[rai], nin, 0, rai)) {
        airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
        fprintf(stderr, "%s: trouble slicing input value %u:\n%s",
                me, rai, err);
        airMopError(mop);
        return 1;
      }
      range[rai] = nrrdRangeNew(min[rai], max[rai]);
      airMopAdd(mop, range[rai], (airMopper)nrrdRangeNix, airMopAlways);
      nrrdRangeSafeSet(range[rai], ntmp[rai], blind8BitRange);
    }
  }
  if (nrrdTypeDefault == typeOut) {
    typeOut = nlut->type;
  }
  if (nrrdApply2DLut(nout, nin, 0, range[0], range[1], nlut, typeOut,
                     rescale[0], rescale[1])) {
    airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways);
    fprintf(stderr, "%s: trouble applying 2-D LUT:\n%s", me, err);
    airMopError(mop);
    return 1;
  }

  SAVE(out, nout, NULL);

  airMopOkay(mop);
  return 0;
}