/* ** _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; }
/* ** _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; }
/* ** _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; }