int nrrdHistoCheck(const Nrrd *nhist) { static const char me[]="nrrdHistoCheck"; if (!nhist) { biffAddf(NRRD, "%s: got NULL pointer", me); return 1; } if (nrrdTypeBlock == nhist->type) { biffAddf(NRRD, "%s: has non-scalar %s type", me, airEnumStr(nrrdType, nrrdTypeBlock)); return 1; } if (nrrdHasNonExist(nhist)) { biffAddf(NRRD, "%s: has non-existent values", me); return 1; } if (1 != nhist->dim) { biffAddf(NRRD, "%s: dim == %u != 1", me, nhist->dim); return 1; } if (!(nhist->axis[0].size > 1)) { biffAddf(NRRD, "%s: has single sample along sole axis", me); return 1; } return 0; }
/* ** _nrrdApply2DSetUp() ** ** some error checking and initializing needed for 2D LUTS and regular ** maps. The intent is that if this succeeds, then there is no need ** for any further error checking. ** ** The only thing this function DOES is allocate the output nrrd, and ** set meta information. The rest is just error checking. ** ** The given NrrdRange has to be fleshed out by the caller: it can't ** be NULL, and both range->min and range->max must exist. */ int _nrrdApply2DSetUp(Nrrd *nout, const Nrrd *nin, const NrrdRange *range0, const NrrdRange *range1, const Nrrd *nmap, int kind, int typeOut, int rescale0, int rescale1) { char me[]="_nrrdApply2DSetUp", err[BIFF_STRLEN], *mapcnt; char nounStr[][AIR_STRLEN_SMALL]={"2D lut", "2D regular map"}; char verbStr[][AIR_STRLEN_SMALL]={"lut2", "rmap2"}; int mapAxis, copyMapAxis0=AIR_FALSE, axisMap[NRRD_DIM_MAX]; unsigned int dim, entLen; size_t size[NRRD_DIM_MAX]; double domMin, domMax; if (nout == nin) { sprintf(err, "%s: due to laziness, nout==nin always disallowed", me); biffAdd(NRRD, err); return 1; } if (airEnumValCheck(nrrdType, typeOut)) { sprintf(err, "%s: invalid requested output type %d", me, typeOut); biffAdd(NRRD, err); return 1; } if (nrrdTypeBlock == nin->type || nrrdTypeBlock == typeOut) { sprintf(err, "%s: input or requested output type is %s, need scalar", me, airEnumStr(nrrdType, nrrdTypeBlock)); biffAdd(NRRD, err); return 1; } if (!(2 == nin->axis[0].size)) { sprintf(err, "%s: input axis[0] must have size 2 (not " _AIR_SIZE_T_CNV ")", me, nin->axis[0].size); biffAdd(NRRD, err); return 1; } if (!(nin->dim > 1)) { sprintf(err, "%s: input dimension must be > 1 (not %u)", me, nin->dim); biffAdd(NRRD, err); return 1; } if (rescale0 && !(range0 && AIR_EXISTS(range0->min) && AIR_EXISTS(range0->max))) { sprintf(err, "%s: want axis 0 rescaling but didn't get range, or " "not both range->{min,max} exist", me); biffAdd(NRRD, err); return 1; } if (rescale1 && !(range1 && AIR_EXISTS(range1->min) && AIR_EXISTS(range1->max))) { sprintf(err, "%s: want axis 1 rescaling but didn't get range, or " "not both range->{min,max} exist", me); biffAdd(NRRD, err); return 1; } mapAxis = nmap->dim - 2; if (!(0 == mapAxis || 1 == mapAxis)) { sprintf(err, "%s: dimension of %s should be 2 or 3, not %d", me, nounStr[kind], nmap->dim); biffAdd(NRRD, err); return 1; } copyMapAxis0 = (1 == mapAxis); domMin = _nrrdApplyDomainMin(nmap, AIR_FALSE, mapAxis); domMax = _nrrdApplyDomainMax(nmap, AIR_FALSE, mapAxis); if (!( domMin < domMax )) { sprintf(err, "%s: (axis %d) domain min (%g) not less than max (%g)", me, mapAxis, domMin, domMax); biffAdd(NRRD, err); return 1; } domMin = _nrrdApplyDomainMin(nmap, AIR_FALSE, mapAxis+1); domMax = _nrrdApplyDomainMax(nmap, AIR_FALSE, mapAxis+1); if (!( domMin < domMax )) { sprintf(err, "%s: (axis %d) domain min (%g) not less than max (%g)", me, mapAxis+1, domMin, domMax); biffAdd(NRRD, err); return 1; } if (nrrdHasNonExist(nmap)) { sprintf(err, "%s: %s nrrd has non-existent values", me, nounStr[kind]); biffAdd(NRRD, err); return 1; } entLen = mapAxis ? nmap->axis[0].size : 1; if (mapAxis + nin->dim - 1 > NRRD_DIM_MAX) { sprintf(err, "%s: input nrrd dim %d through non-scalar %s exceeds " "NRRD_DIM_MAX %d", me, nin->dim, nounStr[kind], NRRD_DIM_MAX); biffAdd(NRRD, err); return 1; } if (mapAxis) { size[0] = entLen; axisMap[0] = -1; } for (dim=1; dim<nin->dim; dim++) { size[dim-1+mapAxis] = nin->axis[dim].size; axisMap[dim-1+mapAxis] = dim; } /* fprintf(stderr, "##%s: pre maybe alloc: nout->data = %p\n", me, nout->data); for (dim=0; dim<mapAxis + nin->dim - 1; dim++) { fprintf(stderr, " size[%d] = %d\n", dim, (int)size[dim]); } fprintf(stderr, " nout->dim = %u; nout->type = %d = %s; sizes = %u,%u\n", nout->dim, nout->type, airEnumStr(nrrdType, nout->type), AIR_CAST(unsigned int, nout->axis[0].size), AIR_CAST(unsigned int, nout->axis[1].size)); fprintf(stderr, " typeOut = %d = %s\n", typeOut, airEnumStr(nrrdType, typeOut)); */ if (nrrdMaybeAlloc_nva(nout, typeOut, nin->dim - 1 + mapAxis, size)) { sprintf(err, "%s: couldn't allocate output nrrd", me); biffAdd(NRRD, err); return 1; } /* fprintf(stderr, " nout->dim = %d; nout->type = %d = %s\n", nout->dim, nout->type, airEnumStr(nrrdType, nout->type)); for (dim=0; dim<nout->dim; dim++) { fprintf(stderr, " size[%d] = %d\n", dim, (int)nout->axis[dim].size); } fprintf(stderr, "##%s: post maybe alloc: nout->data = %p\n", me, nout->data); */ if (nrrdAxisInfoCopy(nout, nin, axisMap, NRRD_AXIS_INFO_NONE)) { sprintf(err, "%s: trouble copying axis info", me); biffAdd(NRRD, err); return 1; } if (copyMapAxis0) { _nrrdAxisInfoCopy(nout->axis + 0, nmap->axis + 0, NRRD_AXIS_INFO_SIZE_BIT); } mapcnt = _nrrdContentGet(nmap); if (nrrdContentSet_va(nout, verbStr[kind], nin, "%s", mapcnt)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); free(mapcnt); return 1; } free(mapcnt); nrrdBasicInfoInit(nout, (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)); return 0; }
/* ** _nrrdApply1DSetUp() ** ** some error checking and initializing needed for 1D LUTS, regular, ** and irregular maps. The intent is that if this succeeds, then ** there is no need for any further error checking. ** ** The only thing this function DOES is allocate the output nrrd, and ** set meta information. The rest is just error checking. ** ** The given NrrdRange has to be fleshed out by the caller: it can't ** be NULL, and both range->min and range->max must exist. */ int _nrrdApply1DSetUp(Nrrd *nout, const Nrrd *nin, const NrrdRange *range, const Nrrd *nmap, int kind, int typeOut, int rescale, int multi) { char me[]="_nrrdApply1DSetUp", err[BIFF_STRLEN], *mapcnt; char nounStr[][AIR_STRLEN_SMALL]={"lut", "regular map", "irregular map"}; char mnounStr[][AIR_STRLEN_SMALL]={"multi lut", "multi regular map", "multi irregular map"}; /* wishful thinking */ char verbStr[][AIR_STRLEN_SMALL]={"lut", "rmap", "imap"}; char mverbStr[][AIR_STRLEN_SMALL]={"mlut", "mrmap", "mimap"}; /* wishful thinking */ int mapAxis, copyMapAxis0=AIR_FALSE, axisMap[NRRD_DIM_MAX]; unsigned int ax, dim, entLen; size_t size[NRRD_DIM_MAX]; double domMin, domMax; if (nout == nin) { sprintf(err, "%s: due to laziness, nout==nin always disallowed", me); biffAdd(NRRD, err); return 1; } if (airEnumValCheck(nrrdType, typeOut)) { sprintf(err, "%s: invalid requested output type %d", me, typeOut); biffAdd(NRRD, err); return 1; } if (nrrdTypeBlock == nin->type || nrrdTypeBlock == typeOut) { sprintf(err, "%s: input or requested output type is %s, need scalar", me, airEnumStr(nrrdType, nrrdTypeBlock)); biffAdd(NRRD, err); return 1; } if (rescale && !(range && AIR_EXISTS(range->min) && AIR_EXISTS(range->max))) { sprintf(err, "%s: want rescaling but didn't get a range, or " "not both range->{min,max} exist", me); biffAdd(NRRD, err); return 1; } if (kindLut == kind || kindRmap == kind) { if (!multi) { mapAxis = nmap->dim - 1; if (!(0 == mapAxis || 1 == mapAxis)) { sprintf(err, "%s: dimension of %s should be 1 or 2, not %d", me, nounStr[kind], nmap->dim); biffAdd(NRRD, err); return 1; } copyMapAxis0 = (1 == mapAxis); } else { mapAxis = nmap->dim - nin->dim - 1; if (!(0 == mapAxis || 1 == mapAxis)) { sprintf(err, "%s: dimension of %s should be %d or %d, not %d", me, mnounStr[kind], nin->dim + 1, nin->dim + 2, nmap->dim); biffAdd(NRRD, err); return 1; } copyMapAxis0 = (1 == mapAxis); /* need to make sure the relevant sizes match */ for (ax=0; ax<nin->dim; ax++) { if (nin->axis[ax].size != nmap->axis[mapAxis + 1 + ax].size) { sprintf(err, "%s: input and mmap don't have compatible sizes: " "nin->axis[%d].size (" _AIR_SIZE_T_CNV ") " "!= nmap->axis[%d].size (" _AIR_SIZE_T_CNV "): ", me, ax, nin->axis[ax].size, mapAxis + 1 + ax, nmap->axis[mapAxis + 1 + ax].size); biffAdd(NRRD, err); return 1; } } } domMin = _nrrdApplyDomainMin(nmap, AIR_FALSE, mapAxis); domMax = _nrrdApplyDomainMax(nmap, AIR_FALSE, mapAxis); if (!( domMin < domMax )) { sprintf(err, "%s: (axis %d) domain min (%g) not less than max (%g)", me, mapAxis, domMin, domMax); biffAdd(NRRD, err); return 1; } if (nrrdHasNonExist(nmap)) { sprintf(err, "%s: %s nrrd has non-existent values", me, multi ? mnounStr[kind] : nounStr[kind]); biffAdd(NRRD, err); return 1; } entLen = mapAxis ? nmap->axis[0].size : 1; } else { if (multi) { sprintf(err, "%s: sorry, multi irregular maps not implemented", me); biffAdd(NRRD, err); return 1; } /* its an irregular map */ if (nrrd1DIrregMapCheck(nmap)) { sprintf(err, "%s: problem with irregular map", me); biffAdd(NRRD, err); return 1; } /* mapAxis has no meaning for irregular maps, but we'll pretend ... */ mapAxis = nmap->axis[0].size == 2 ? 0 : 1; copyMapAxis0 = AIR_TRUE; entLen = nmap->axis[0].size-1; } if (mapAxis + nin->dim > NRRD_DIM_MAX) { sprintf(err, "%s: input nrrd dim %d through non-scalar %s exceeds " "NRRD_DIM_MAX %d", me, nin->dim, multi ? mnounStr[kind] : nounStr[kind], NRRD_DIM_MAX); biffAdd(NRRD, err); return 1; } nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, size+mapAxis); if (mapAxis) { size[0] = entLen; axisMap[0] = -1; } for (dim=0; dim<nin->dim; dim++) { axisMap[dim+mapAxis] = dim; } /* fprintf(stderr, "##%s: pre maybe alloc: nout->data = %p\n", me, nout->data); for (dim=0; dim<mapAxis + nin->dim; dim++) { fprintf(stderr, " size[%d] = %d\n", d, (int)size[d]); } fprintf(stderr, " nout->dim = %d; nout->type = %d = %s; sizes = %d,%d\n", nout->dim, nout->type, airEnumStr(nrrdType, nout->type)); fprintf(stderr, " typeOut = %d = %s\n", typeOut, airEnumStr(nrrdType, typeOut)); */ if (nrrdMaybeAlloc_nva(nout, typeOut, mapAxis + nin->dim, size)) { sprintf(err, "%s: couldn't allocate output nrrd", me); biffAdd(NRRD, err); return 1; } /* fprintf(stderr, " nout->dim = %d; nout->type = %d = %s\n", nout->dim, nout->type, airEnumStr(nrrdType, nout->type), nout->axis[0].size, nout->axis[1].size); for (d=0; d<nout->dim; d++) { fprintf(stderr, " size[%d] = %d\n", d, (int)nout->axis[d].size); } fprintf(stderr, "##%s: post maybe alloc: nout->data = %p\n", me, nout->data); */ if (nrrdAxisInfoCopy(nout, nin, axisMap, NRRD_AXIS_INFO_NONE)) { sprintf(err, "%s: trouble copying axis info", me); biffAdd(NRRD, err); return 1; } if (copyMapAxis0) { _nrrdAxisInfoCopy(nout->axis + 0, nmap->axis + 0, NRRD_AXIS_INFO_SIZE_BIT); } mapcnt = _nrrdContentGet(nmap); if (nrrdContentSet_va(nout, multi ? mverbStr[kind] : verbStr[kind], nin, "%s", mapcnt)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); free(mapcnt); return 1; } free(mapcnt); 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 | (nrrdStateKeyValuePairsPropagate ? 0 : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { sprintf(err, "%s:", me); biffAdd(NRRD, err); return 1; } return 0; }
/* ******** nrrd1DIrregMapCheck() ** ** return zero only for the valid forms of 1D irregular map. ** imap must be 2D, both sizes >= 2, non-block-type, no non-existant ** values in range. If the first point's position is non-existant, ** than the first three points positions must be -inf, NaN, and +inf, ** and none of the other points locations can be non-existant, and ** they must increase monotonically. There must be at least two ** points with existant positions. */ int nrrd1DIrregMapCheck(const Nrrd *nmap) { char me[]="nrrd1DIrregMapCheck", err[BIFF_STRLEN]; double (*mapLup)(const void *v, size_t I); int i, entLen, mapLen, baseI; size_t min[2], max[2]; Nrrd *nrange; if (!nmap) { sprintf(err, "%s: got NULL pointer", me); biffAdd(NRRD, err); return 1; } if (nrrdCheck(nmap)) { sprintf(err, "%s: ", me); biffAdd(NRRD, err); return 1; } if (nrrdTypeBlock == nmap->type) { sprintf(err, "%s: map is %s type, need scalar", me, airEnumStr(nrrdType, nrrdTypeBlock)); biffAdd(NRRD, err); return 1; } if (2 != nmap->dim) { sprintf(err, "%s: map needs to have dimension 2, not %d", me, nmap->dim); biffAdd(NRRD, err); return 1; } entLen = nmap->axis[0].size; mapLen = nmap->axis[1].size; if (!( entLen >= 2 && mapLen >= 2 )) { sprintf(err, "%s: both map's axes sizes should be >= 2 (not %d,%d)", me, entLen, mapLen); biffAdd(NRRD, err); return 1; } min[0] = 1; max[0] = nmap->axis[0].size-1; min[1] = 0; max[1] = nmap->axis[1].size-1; if (nrrdCrop(nrange=nrrdNew(), nmap, min, max)) { sprintf(err, "%s: couldn't crop to isolate range of map", me); biffAdd(NRRD, err); nrrdNuke(nrange); return 1; } if (nrrdHasNonExist(nrange)) { sprintf(err, "%s: map has non-existent values in its range", me); biffAdd(NRRD, err); nrrdNuke(nrange); return 1; } nrrdNuke(nrange); mapLup = nrrdDLookup[nmap->type]; if (AIR_EXISTS(mapLup(nmap->data, 0))) { baseI = 0; } else { baseI = 3; if (!( mapLen >= 5 )) { sprintf(err, "%s: length of map w/ non-existant locations must " "be >= 5 (not %d)", me, mapLen); biffAdd(NRRD, err); return 1; } if (!( airFP_NEG_INF == airFPClass_d(mapLup(nmap->data, 0*entLen)) && airFP_QNAN == airFPClass_d(mapLup(nmap->data, 1*entLen)) && airFP_POS_INF == airFPClass_d(mapLup(nmap->data, 2*entLen)) )) { sprintf(err, "%s: 1st entry's position non-existant, but position " "of 1st three entries not -inf, NaN, and +inf", me); biffAdd(NRRD, err); return 1; } } for (i=baseI; i<mapLen; i++) { if (!AIR_EXISTS(mapLup(nmap->data, i*entLen))) { sprintf(err, "%s: entry %d has non-existant position", me, i); biffAdd(NRRD, err); return 1; } } for (i=baseI; i<mapLen-1; i++) { if (!( mapLup(nmap->data, i*entLen) < mapLup(nmap->data, (i+1)*entLen) )) { sprintf(err, "%s: map entry %d pos (%g) not < entry %d pos (%g)", me, i, mapLup(nmap->data, i*entLen), i+1, mapLup(nmap->data, (i+1)*entLen)); biffAdd(NRRD, err); return 1; } } return 0; }