int pullScaleTracePlotAdd(pullContext *pctx, Nrrd *nwild, Nrrd *nccd, Nrrd *nmask, double mth, airArray *insideArr, double velHalf, pullTrace *pts) { static const char me[]="pullScaleTracePlotAdd"; double ssr[2], *pos, *velo, *wild, *ccd, *mask; unsigned int pnum, pidx, sizeS, sizeV; if (!(pctx && nwild && nccd && pts)) { biffAddf(PULL, "%s: got NULL pointer", me); return 1; } if (!nrrdSameSize(nwild, nccd, AIR_TRUE)) { biffMovef(PULL, NRRD, "%s: nwild not same size as nccd", me); return 1; } if (nmask || insideArr) { if (!insideArr) { biffAddf(PULL, "%s: got nmask but not insideArr", me); return 1; } if (!nmask) { biffAddf(PULL, "%s: got insideArr but not nmask", me); return 1; } if (nrrdTypeDouble != nmask->type) { biffAddf(PULL, "%s: nmask has type %s but want %s", me, airEnumStr(nrrdType, nmask->type), airEnumStr(nrrdType, nrrdTypeDouble)); return 1; } if (!nrrdSameSize(nwild, nmask, AIR_TRUE)) { biffMovef(PULL, NRRD, "%s: nwild not same size as nmask", me); return 1; } if (!nrrdSameSize(nccd, nmask, AIR_TRUE)) { biffMovef(PULL, NRRD, "%s: nccd not same size as nmask", me); return 1; } if (!AIR_EXISTS(mth)) { biffAddf(PULL, "%s: got non-existent mask thresh %g", me, mth); return 1; } } ssr[0] = nwild->axis[0].min; ssr[1] = nwild->axis[0].max; sizeS = AIR_CAST(unsigned int, nwild->axis[0].size); sizeV = AIR_CAST(unsigned int, nwild->axis[1].size); wild = AIR_CAST(double *, nwild->data); ccd = AIR_CAST(double *, nccd->data); if (nmask) { mask = AIR_CAST(double *, nmask->data); } else {
/* ******** nrrdArithTerneryOp ** ** HEY: UNTESTED UNTESTED UNTESTED UNTESTED UNTESTED UNTESTED UNTESTED ** ** this is a simplified version of nrrdArithIterTernaryOp, written after ** that, in a hurry, to operate directly on three nrrds, instead with ** the NrrdIter nonsense */ int nrrdArithTernaryOp(Nrrd *nout, int op, const Nrrd *ninA, const Nrrd *ninB, const Nrrd *ninC) { static const char me[]="nrrdArithTernaryOp"; char *contA, *contB, *contC; size_t N, I, size[NRRD_DIM_MAX]; double (*ins)(void *v, size_t I, double d), (*lupA)(const void *v, size_t I), (*lupB)(const void *v, size_t I), (*lupC)(const void *v, size_t I), (*top)(double a, double b, double c), valA, valB, valC; if (!( nout && !nrrdCheck(ninA) && !nrrdCheck(ninB) && !nrrdCheck(ninC) )) { biffAddf(NRRD, "%s: NULL pointer or invalid args", me); return 1; } if (!( nrrdSameSize(ninA, ninB, AIR_TRUE) && nrrdSameSize(ninA, ninC, AIR_TRUE) )) { biffAddf(NRRD, "%s: size mismatch between arguments", me); return 1; } if (airEnumValCheck(nrrdTernaryOp, op)) { biffAddf(NRRD, "%s: ternary op %d invalid", me, op); return 1; } nrrdAxisInfoGet_nva(ninA, nrrdAxisInfoSize, size); if (!( nout == ninA || nout == ninB || nout == ninC)) { if (_nrrdMaybeAllocMaybeZero_nva(nout, ninA->type, ninA->dim, size, AIR_FALSE /* zero when no realloc */)) { biffAddf(NRRD, "%s: couldn't allocate output nrrd", me); return 1; } if (nrrdAxisInfoCopy(nout, ninA, NULL, NRRD_AXIS_INFO_NONE)) { biffAddf(NRRD, "%s:", me); return 1; } nrrdBasicInfoCopy(nout, ninA, (NRRD_BASIC_INFO_DATA_BIT | NRRD_BASIC_INFO_TYPE_BIT | NRRD_BASIC_INFO_DIMENSION_BIT | NRRD_BASIC_INFO_CONTENT_BIT | NRRD_BASIC_INFO_COMMENTS_BIT | (nrrdStateKeyValuePairsPropagate ? 0 : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))); } nrrdBasicInfoInit(nout, NRRD_BASIC_INFO_ALL ^ (NRRD_BASIC_INFO_OLDMIN_BIT | NRRD_BASIC_INFO_OLDMAX_BIT)); top = _nrrdTernaryOp[op]; N = nrrdElementNumber(ninA); lupA = nrrdDLookup[ninA->type]; lupB = nrrdDLookup[ninB->type]; lupC = nrrdDLookup[ninC->type]; ins = nrrdDInsert[nout->type]; for (I=0; I<N; I++) { /* HEY: there is a loss of precision issue here with 64-bit ints */ valA = lupA(ninA->data, I); valB = lupB(ninB->data, I); valC = lupC(ninC->data, I); ins(nout->data, I, top(valA, valB, valC)); } contA = _nrrdContentGet(ninA); contB = _nrrdContentGet(ninB); contC = _nrrdContentGet(ninC); if (_nrrdContentSet_va(nout, airEnumStr(nrrdTernaryOp, op), contA, "%s,%s", contB, contC)) { biffAddf(NRRD, "%s:", me); free(contA); free(contB); free(contC); return 1; } free(contA); free(contB); free(contC); return 0; }
/* ******** 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; }
int main(int argc, const char *argv[]) { const char *me; hestOpt *hopt; hestParm *hparm; airArray *mop; char **ninStr, *err, *outS, doneStr[13]; Nrrd *nin0, *nin, *nrgb, *nout, *nhist[2], *npreout, *nhproj[3]; float *rgb; float *out, *preout, *hist[2], maxSum, upSample, overSampleScale; unsigned int size0, sX, sY, sH, ninLen, ti, overSampleNum; NrrdResampleContext *rsmc; NrrdKernelSpec *ksp; me = argv[0]; mop = airMopNew(); hopt = NULL; hparm = hestParmNew(); airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways); hparm->respFileEnable = AIR_TRUE; hestOptAdd(&hopt, "i", "images", airTypeString, 1, -1, &ninStr, NULL, "input image sequence", &ninLen, NULL, NULL); hestOptAdd(&hopt, "sh", "histo size", airTypeUInt, 1, 1, &sH, "500", "histogram size"); hestOptAdd(&hopt, "k", "kern", airTypeOther, 1, 1, &ksp, "tent", "kernel for upsampling images", NULL, NULL, nrrdHestKernelSpec); hestOptAdd(&hopt, "us", "upsampling", airTypeFloat, 1, 1, &upSample, "1", "amount of upsampling of image"); hestOptAdd(&hopt, "osn", "# oversmp", airTypeUInt, 1, 1, &overSampleNum, "1", "number of sample per (upsampled) pixel"); hestOptAdd(&hopt, "osc", "scaling", airTypeFloat, 1, 1, &overSampleScale, "1", "scaling with oversampling"); hestOptAdd(&hopt, "ms", "max sum", airTypeFloat, 1, 1, &maxSum, "10", "per-hue histogram summation is non-linearly and " "asymptotically clamped to this maximum"); hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", "output filename", NULL); hestParseOrDie(hopt, argc-1, argv+1, hparm, me, mchistInfo, AIR_TRUE, AIR_TRUE, AIR_TRUE); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); if (0 == overSampleNum) { fprintf(stderr, "%s: overSampleNum must be > 0\n", me); airMopError(mop); return 1; } nin0 = nrrdNew(); airMopAdd(mop, nin0, (airMopper)nrrdNuke, airMopAlways); if (nrrdLoad(nin0, ninStr[0], NULL)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: couldn't load first image:\n%s", me, err); airMopError(mop); return 1; } if (!( (3 == nin0->axis[0].size || 4 == nin0->axis[0].size) && 3 == nin0->dim && nrrdTypeUChar == nin0->type )) { fprintf(stderr, "%s: 1st image not 3D (3-or-4)-by-X-by-Y %s array " "(got %u-D %s array)\n", me, airEnumStr(nrrdType, nrrdTypeUChar), nin0->dim, airEnumStr(nrrdType, nin0->type)); airMopError(mop); return 1; } rsmc = nrrdResampleContextNew(); airMopAdd(mop, rsmc, (airMopper)nrrdResampleContextNix, airMopAlways); size0 = AIR_CAST(unsigned int, nin0->axis[0].size); sX = AIR_CAST(unsigned int, upSample*nin0->axis[1].size); sY = AIR_CAST(unsigned int, upSample*nin0->axis[2].size); nrgb = nrrdNew(); airMopAdd(mop, nrgb, (airMopper)nrrdNuke, airMopAlways); if (nrrdResampleDefaultCenterSet(rsmc, nrrdCenterCell) || nrrdResampleInputSet(rsmc, nin0) || nrrdResampleKernelSet(rsmc, 1, ksp->kernel, ksp->parm) || nrrdResampleKernelSet(rsmc, 2, ksp->kernel, ksp->parm) || nrrdResampleSamplesSet(rsmc, 1, sX) || nrrdResampleSamplesSet(rsmc, 2, sY) || nrrdResampleRangeFullSet(rsmc, 1) || nrrdResampleRangeFullSet(rsmc, 2) || nrrdResampleTypeOutSet(rsmc, nrrdTypeFloat) || nrrdResampleRenormalizeSet(rsmc, AIR_TRUE) || nrrdResampleExecute(rsmc, nrgb)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error resampling slice:\n%s", me, err); airMopError(mop); return 1; } nhist[0] = nrrdNew(); airMopAdd(mop, nhist[0], (airMopper)nrrdNuke, airMopAlways); nhist[1] = nrrdNew(); airMopAdd(mop, nhist[1], (airMopper)nrrdNuke, airMopAlways); if (nrrdMaybeAlloc_va(nhist[0], nrrdTypeFloat, 2, AIR_CAST(size_t, sH), AIR_CAST(size_t, sH)) || nrrdMaybeAlloc_va(nhist[1], nrrdTypeFloat, 2, AIR_CAST(size_t, sH), AIR_CAST(size_t, sH))) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error allocating histos:\n%s", me, err); airMopError(mop); return 1; } nhist[0]->axis[0].min = nhist[0]->axis[1].min = 0.0; nhist[0]->axis[0].max = nhist[0]->axis[1].max = 1.0; nhist[1]->axis[0].min = nhist[1]->axis[1].min = 0.0; nhist[1]->axis[0].max = nhist[1]->axis[1].max = 1.0; nhproj[0] = nrrdNew(); airMopAdd(mop, nhproj[0], (airMopper)nrrdNix, airMopAlways); nhproj[1] = nrrdNew(); airMopAdd(mop, nhproj[1], (airMopper)nrrdNix, airMopAlways); nhproj[2] = nrrdNew(); airMopAdd(mop, nhproj[2], (airMopper)nrrdNix, airMopAlways); printf("working ... "); hist[0] = AIR_CAST(float *, nhist[0]->data); hist[1] = AIR_CAST(float *, nhist[1]->data); nin = nrrdNew(); airMopAdd(mop, nin, (airMopper)nrrdNuke, airMopAlways); npreout = nrrdNew(); airMopAdd(mop, npreout, (airMopper)nrrdNuke, airMopAlways); if (nrrdMaybeAlloc_va(npreout, nrrdTypeFloat, 3, AIR_CAST(size_t, 3), AIR_CAST(size_t, sH), AIR_CAST(size_t, ninLen))) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error allocating pre-output:\n%s", me, err); airMopError(mop); return 1; } preout = AIR_CAST(float *, npreout->data); for (ti=0; ti<ninLen; ti++) { printf("%s", airDoneStr(0, ti, ninLen, doneStr)); fflush(stdout); if (nrrdLoad(nin, ninStr[ti], NULL)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: couldn't load image[%u]:\n%s", me, ti, err); airMopError(mop); return 1; } if (!nrrdSameSize(nin0, nin, AIR_TRUE)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: nin[%u] not like nin[0]:\n%s", me, ti, err); airMopError(mop); return 1; } if (nrrdResampleInputSet(rsmc, nin) || nrrdResampleExecute(rsmc, nrgb)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble resampling nin[%u]:\n%s", me, ti, err); airMopError(mop); return 1; } if (nrrdWrap_va(nhproj[0], preout + 0*sH, nrrdTypeFloat, 1, AIR_CAST(size_t, sH)) || nrrdWrap_va(nhproj[1], preout + 1*sH, nrrdTypeFloat, 1, AIR_CAST(size_t, sH)) || nrrdWrap_va(nhproj[2], preout + 2*sH, nrrdTypeFloat, 1, AIR_CAST(size_t, sH))) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: trouble wrapping output[%u]:\n%s", me, ti, err); airMopError(mop); return 1; } rgb = AIR_CAST(float *, nrgb->data); imageProc(nhproj, nhist, sH, rgb, size0, sX*sY, overSampleNum, overSampleScale); preout += 3*sH; } printf("%s\n", airDoneStr(0, ti, ninLen, doneStr)); fflush(stdout); nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 3, AIR_CAST(size_t, 3), AIR_CAST(size_t, sH), AIR_CAST(size_t, ninLen))) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error allocating output:\n%s", me, err); airMopError(mop); return 1; } out = AIR_CAST(float *, nout->data); preout = AIR_CAST(float *, npreout->data); for (ti=0; ti<ninLen; ti++) { unsigned int hi; float hh, vv, ss, scl; for (hi=0; hi<sH; hi++) { hh = AIR_AFFINE(0, hi, sH, 0, 1); if (!preout[hi + 2*sH]) { ELL_3V_SET(out + 3*hi, 0, 0, 0); } else { ss = preout[hi + 2*sH]; scl = ss/(maxSum + ss); vv = scl*preout[hi + 1*sH]; dyeHSVtoRGB(out + 0 + 3*hi, out + 1 + 3*hi, out + 2 + 3*hi, hh, preout[hi + 0*sH], vv); } } out += 3*sH; preout += 3*sH; } if (nrrdSave(outS, nout, NULL)) { airMopAdd(mop, err=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error saving output:\n%s", me, err); airMopError(mop); return 1; } airMopOkay(mop); return 0; }