| File: | src/mite/txf.c |
| Location: | line 554, column 16 |
| Description: | Call to 'calloc' has an allocation size of 0 bytes |
| 1 | /* | |||||
| 2 | Teem: Tools to process and visualize scientific data and images . | |||||
| 3 | Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago | |||||
| 4 | Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann | |||||
| 5 | Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah | |||||
| 6 | ||||||
| 7 | This library is free software; you can redistribute it and/or | |||||
| 8 | modify it under the terms of the GNU Lesser General Public License | |||||
| 9 | (LGPL) as published by the Free Software Foundation; either | |||||
| 10 | version 2.1 of the License, or (at your option) any later version. | |||||
| 11 | The terms of redistributing and/or modifying this software also | |||||
| 12 | include exceptions to the LGPL that facilitate static linking. | |||||
| 13 | ||||||
| 14 | This library is distributed in the hope that it will be useful, | |||||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
| 17 | Lesser General Public License for more details. | |||||
| 18 | ||||||
| 19 | You should have received a copy of the GNU Lesser General Public License | |||||
| 20 | along with this library; if not, write to Free Software Foundation, Inc., | |||||
| 21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||||
| 22 | */ | |||||
| 23 | ||||||
| 24 | /* learned: don't confuse allocate an array of structs with an array | |||||
| 25 | of pointers to structs. Don't be surprised when you bus error | |||||
| 26 | because of the difference | |||||
| 27 | */ | |||||
| 28 | ||||||
| 29 | #include "mite.h" | |||||
| 30 | #include "privateMite.h" | |||||
| 31 | ||||||
| 32 | char | |||||
| 33 | miteRangeChar[MITE_RANGE_NUM9+1] = "ARGBEadsp"; | |||||
| 34 | ||||||
| 35 | const char * | |||||
| 36 | _miteStageOpStr[] = { | |||||
| 37 | "(unknown miteStageOp)", | |||||
| 38 | "min", | |||||
| 39 | "max", | |||||
| 40 | "add", | |||||
| 41 | "multiply" | |||||
| 42 | }; | |||||
| 43 | ||||||
| 44 | const int | |||||
| 45 | _miteStageOpVal[] = { | |||||
| 46 | miteStageOpUnknown, | |||||
| 47 | miteStageOpMin, | |||||
| 48 | miteStageOpMax, | |||||
| 49 | miteStageOpAdd, | |||||
| 50 | miteStageOpMultiply | |||||
| 51 | }; | |||||
| 52 | ||||||
| 53 | const char * | |||||
| 54 | _miteStageOpStrEqv[] = { | |||||
| 55 | "min", | |||||
| 56 | "max", | |||||
| 57 | "add", "+", | |||||
| 58 | "multiply", "*", "x", | |||||
| 59 | "" | |||||
| 60 | }; | |||||
| 61 | ||||||
| 62 | const int | |||||
| 63 | _miteStageOpValEqv[] = { | |||||
| 64 | miteStageOpMin, | |||||
| 65 | miteStageOpMax, | |||||
| 66 | miteStageOpAdd, miteStageOpAdd, | |||||
| 67 | miteStageOpMultiply, miteStageOpMultiply, miteStageOpMultiply | |||||
| 68 | }; | |||||
| 69 | ||||||
| 70 | const airEnum | |||||
| 71 | _miteStageOp = { | |||||
| 72 | "miteStageOp", | |||||
| 73 | MITE_STAGE_OP_MAX4, | |||||
| 74 | _miteStageOpStr, _miteStageOpVal, | |||||
| 75 | NULL((void*)0), | |||||
| 76 | _miteStageOpStrEqv, _miteStageOpValEqv, | |||||
| 77 | AIR_FALSE0 | |||||
| 78 | }; | |||||
| 79 | const airEnum *const | |||||
| 80 | miteStageOp = &_miteStageOp; | |||||
| 81 | ||||||
| 82 | /* | |||||
| 83 | ******** miteVariableParse() | |||||
| 84 | ** | |||||
| 85 | ** takes a string (usually the label from a nrrd axis) and parses it | |||||
| 86 | ** to determine the gageItemSpec from it (which means finding the | |||||
| 87 | ** kind and item). The valid formats are: | |||||
| 88 | ** | |||||
| 89 | ** "" : NULL kind, 0 item | |||||
| 90 | ** <item> : miteValGageKind (DEPRECATED) | |||||
| 91 | ** mite(<item>) : miteValGageKind | |||||
| 92 | ** gage(<item>) : gageKindScl (DEPRECATED) | |||||
| 93 | ** gage(scalar:<item>) : gageKindScl | |||||
| 94 | ** gage(vector:<item>) : gageKindVec | |||||
| 95 | ** gage(tensor:<item>) : tenGageKind | |||||
| 96 | ** | |||||
| 97 | ** Notice that "scalar", "vector", and "tensor" do NOT refer to the type | |||||
| 98 | ** of the quantity being measured, but rather to the type of volume in | |||||
| 99 | ** which quantity is measured (i.e., the gageKind used) | |||||
| 100 | */ | |||||
| 101 | int | |||||
| 102 | miteVariableParse(gageItemSpec *isp, const char *label) { | |||||
| 103 | static const char me[]="miteVariableParse"; | |||||
| 104 | ||||||
| 105 | char *buff, *endparen, *kqstr, *col, *kstr, *qstr; | |||||
| 106 | airArray *mop; | |||||
| 107 | ||||||
| 108 | if (!( isp && label )) { | |||||
| 109 | biffAddf(MITEmiteBiffKey, "%s: got NULL pointer", me); | |||||
| 110 | return 1; | |||||
| 111 | } | |||||
| 112 | if (0 == strlen(label)) { | |||||
| 113 | /* nothing was specified; we try to indicate that by mimicking | |||||
| 114 | the return of gageItemSpecNew() */ | |||||
| 115 | isp->item = 0; | |||||
| 116 | isp->kind = NULL((void*)0); | |||||
| 117 | return 0; | |||||
| 118 | } | |||||
| 119 | /* else given string was non-empty */ | |||||
| 120 | mop = airMopNew(); | |||||
| 121 | buff = airStrdup(label); | |||||
| 122 | if (!buff) { | |||||
| 123 | biffAddf(MITEmiteBiffKey, "%s: couldn't strdup label!", me); | |||||
| 124 | airMopError(mop); return 1; | |||||
| 125 | } | |||||
| 126 | airMopAdd(mop, buff, airFree, airMopAlways); | |||||
| 127 | if (strstr(buff, "gage(") == buff) { | |||||
| 128 | /* txf domain variable is to be measured directly by gage */ | |||||
| 129 | if (!(endparen = strstr(buff, ")"))) { | |||||
| 130 | biffAddf(MITEmiteBiffKey, "%s: didn't see close paren after \"gage(\"", me); | |||||
| 131 | airMopError(mop); return 1; | |||||
| 132 | } | |||||
| 133 | *endparen = 0; | |||||
| 134 | kqstr = buff + strlen("gage("); | |||||
| 135 | /* first see if its a (deprecated) gageKindScl specification */ | |||||
| 136 | isp->item = airEnumVal(gageScl, kqstr); | |||||
| 137 | if (0 != isp->item) { | |||||
| 138 | isp->kind = gageKindScl; | |||||
| 139 | fprintf(stderr__stderrp, "\n%s: WARNING: deprecated use of txf domain " | |||||
| 140 | "\"gage(%s)\" without explicit gage kind specification; " | |||||
| 141 | "should use \"gage(%s:%s)\" instead\n\n", | |||||
| 142 | me, kqstr, gageKindScl->name, kqstr); | |||||
| 143 | } else { | |||||
| 144 | /* should be of form "<kind>:<item>" */ | |||||
| 145 | col = strstr(kqstr, ":"); | |||||
| 146 | if (!col) { | |||||
| 147 | biffAddf(MITEmiteBiffKey, "%s: didn't see \":\" separator between gage " | |||||
| 148 | "kind and item", me); | |||||
| 149 | airMopError(mop); return 1; | |||||
| 150 | } | |||||
| 151 | *col = 0; | |||||
| 152 | kstr = kqstr; | |||||
| 153 | qstr = col+1; | |||||
| 154 | if (!strcmp(gageKindScl->name, kstr)) { | |||||
| 155 | isp->kind = gageKindScl; | |||||
| 156 | } else if (!strcmp(gageKindVec->name, kstr)) { | |||||
| 157 | isp->kind = gageKindVec; | |||||
| 158 | } else if (!strcmp(tenGageKind->name, kstr)) { | |||||
| 159 | isp->kind = tenGageKind; | |||||
| 160 | } else { | |||||
| 161 | biffAddf(MITEmiteBiffKey, "%s: don't recognized \"%s\" gage kind", me, kstr); | |||||
| 162 | airMopError(mop); return 1; | |||||
| 163 | } | |||||
| 164 | isp->item = airEnumVal(isp->kind->enm, qstr); | |||||
| 165 | if (0 == isp->item) { | |||||
| 166 | biffAddf(MITEmiteBiffKey, "%s: couldn't parse \"%s\" as a %s variable", | |||||
| 167 | me, qstr, isp->kind->name); | |||||
| 168 | airMopError(mop); return 1; | |||||
| 169 | } | |||||
| 170 | } | |||||
| 171 | } else if (strstr(buff, "mite(") == buff) { | |||||
| 172 | /* txf domain variable is *not* directly measured by gage */ | |||||
| 173 | if (!(endparen = strstr(buff, ")"))) { | |||||
| 174 | biffAddf(MITEmiteBiffKey, "%s: didn't see close paren after \"mite(\"", me); | |||||
| 175 | airMopError(mop); return 1; | |||||
| 176 | } | |||||
| 177 | *endparen = 0; | |||||
| 178 | qstr = buff + strlen("mite("); | |||||
| 179 | isp->item = airEnumVal(miteVal, qstr); | |||||
| 180 | if (0 == isp->item) { | |||||
| 181 | biffAddf(MITEmiteBiffKey, "%s: couldn't parse \"%s\" as a miteVal variable", | |||||
| 182 | me, qstr); | |||||
| 183 | airMopError(mop); return 1; | |||||
| 184 | } | |||||
| 185 | isp->kind = miteValGageKind; | |||||
| 186 | } else { | |||||
| 187 | /* didn't start with "gage(" or "mite(" */ | |||||
| 188 | isp->item = airEnumVal(miteVal, label); | |||||
| 189 | if (0 != isp->item) { | |||||
| 190 | /* its measured by mite */ | |||||
| 191 | isp->kind = miteValGageKind; | |||||
| 192 | fprintf(stderr__stderrp, "\n%s: WARNING: deprecated use of txf domain " | |||||
| 193 | "\"%s\"; should use \"mite(%s)\" instead\n\n", | |||||
| 194 | me, label, label); | |||||
| 195 | } else { | |||||
| 196 | biffAddf(MITEmiteBiffKey, "%s: \"%s\" not a recognized variable", me, label); | |||||
| 197 | airMopError(mop); return 1; | |||||
| 198 | } | |||||
| 199 | } | |||||
| 200 | airMopOkay(mop); | |||||
| 201 | return 0; | |||||
| 202 | } | |||||
| 203 | ||||||
| 204 | void | |||||
| 205 | miteVariablePrint(char *buff, const gageItemSpec *isp) { | |||||
| 206 | static const char me[]="miteVariablePrint"; | |||||
| 207 | ||||||
| 208 | if (!(isp->kind)) { | |||||
| 209 | strcpy(buff, "")__builtin___strcpy_chk (buff, "", __builtin_object_size (buff , 2 > 1 ? 1 : 0)); | |||||
| 210 | } else if (gageKindScl == isp->kind | |||||
| 211 | || gageKindVec == isp->kind | |||||
| 212 | || tenGageKind == isp->kind) { | |||||
| 213 | sprintf(buff, "gage(%s:%s)", isp->kind->name,__builtin___sprintf_chk (buff, 0, __builtin_object_size (buff , 2 > 1 ? 1 : 0), "gage(%s:%s)", isp->kind->name, airEnumStr (isp->kind->enm, isp->item)) | |||||
| 214 | airEnumStr(isp->kind->enm, isp->item))__builtin___sprintf_chk (buff, 0, __builtin_object_size (buff , 2 > 1 ? 1 : 0), "gage(%s:%s)", isp->kind->name, airEnumStr (isp->kind->enm, isp->item)); | |||||
| 215 | } else if (miteValGageKind == isp->kind) { | |||||
| 216 | sprintf(buff, "%s(%s)", isp->kind->name,__builtin___sprintf_chk (buff, 0, __builtin_object_size (buff , 2 > 1 ? 1 : 0), "%s(%s)", isp->kind->name, airEnumStr (isp->kind->enm, isp->item)) | |||||
| 217 | airEnumStr(isp->kind->enm, isp->item))__builtin___sprintf_chk (buff, 0, __builtin_object_size (buff , 2 > 1 ? 1 : 0), "%s(%s)", isp->kind->name, airEnumStr (isp->kind->enm, isp->item)); | |||||
| 218 | } else { | |||||
| 219 | sprintf(buff, "(%s: unknown gageKind!)", me)__builtin___sprintf_chk (buff, 0, __builtin_object_size (buff , 2 > 1 ? 1 : 0), "(%s: unknown gageKind!)", me); | |||||
| 220 | } | |||||
| 221 | return; | |||||
| 222 | } | |||||
| 223 | ||||||
| 224 | int | |||||
| 225 | miteNtxfCheck(const Nrrd *ntxf) { | |||||
| 226 | static const char me[]="miteNtxfCheck"; | |||||
| 227 | char *rangeStr, *domStr; | |||||
| 228 | gageItemSpec isp; | |||||
| 229 | unsigned int rii, axi; | |||||
| 230 | int ilog2; | |||||
| 231 | ||||||
| 232 | if (nrrdCheck(ntxf)) { | |||||
| 233 | biffMovef(MITEmiteBiffKey, NRRDnrrdBiffKey, "%s: basic nrrd validity check failed", me); | |||||
| 234 | return 1; | |||||
| 235 | } | |||||
| 236 | if (!( nrrdTypeFloat == ntxf->type || | |||||
| 237 | nrrdTypeDouble == ntxf->type || | |||||
| 238 | nrrdTypeUChar == ntxf->type )) { | |||||
| 239 | biffAddf(MITEmiteBiffKey, "%s: need a type %s, %s or %s nrrd (not %s)", me, | |||||
| 240 | airEnumStr(nrrdType, nrrdTypeFloat), | |||||
| 241 | airEnumStr(nrrdType, nrrdTypeDouble), | |||||
| 242 | airEnumStr(nrrdType, nrrdTypeUChar), | |||||
| 243 | airEnumStr(nrrdType, ntxf->type)); | |||||
| 244 | return 1; | |||||
| 245 | } | |||||
| 246 | if (!( 2 <= ntxf->dim )) { | |||||
| 247 | biffAddf(MITEmiteBiffKey, "%s: nrrd dim (%d) isn't at least 2 (for a 1-D txf)", | |||||
| 248 | me, ntxf->dim); | |||||
| 249 | return 1; | |||||
| 250 | } | |||||
| 251 | rangeStr = ntxf->axis[0].label; | |||||
| 252 | if (0 == airStrlen(rangeStr)) { | |||||
| 253 | biffAddf(MITEmiteBiffKey, "%s: axis[0]'s label doesn't specify txf range", me); | |||||
| 254 | return 1; | |||||
| 255 | } | |||||
| 256 | if (airStrlen(rangeStr) != ntxf->axis[0].size) { | |||||
| 257 | char stmp1[AIR_STRLEN_SMALL(128+1)], stmp2[AIR_STRLEN_SMALL(128+1)]; | |||||
| 258 | biffAddf(MITEmiteBiffKey, "%s: axis[0]'s size %s, but label specifies %s values", me, | |||||
| 259 | airSprintSize_t(stmp1, ntxf->axis[0].size), | |||||
| 260 | airSprintSize_t(stmp2, airStrlen(rangeStr))); | |||||
| 261 | return 1; | |||||
| 262 | } | |||||
| 263 | for (rii=0; rii<airStrlen(rangeStr); rii++) { | |||||
| 264 | if (!strchr(miteRangeChar, rangeStr[rii])) { | |||||
| 265 | biffAddf(MITEmiteBiffKey, "%s: char %d of axis[0]'s label (\"%c\") isn't a valid " | |||||
| 266 | "transfer function range specifier (not in \"%s\")", | |||||
| 267 | me, rii, rangeStr[rii], miteRangeChar); | |||||
| 268 | return 1; | |||||
| 269 | } | |||||
| 270 | } | |||||
| 271 | for (axi=1; axi<ntxf->dim; axi++) { | |||||
| 272 | if (1 == ntxf->axis[axi].size) { | |||||
| 273 | biffAddf(MITEmiteBiffKey, "%s: # samples on axis %d must be > 1", me, axi); | |||||
| 274 | return 1; | |||||
| 275 | } | |||||
| 276 | domStr = ntxf->axis[axi].label; | |||||
| 277 | if (0 == airStrlen(domStr)) { | |||||
| 278 | biffAddf(MITEmiteBiffKey, "%s: axis[%d] of txf didn't specify a domain variable", | |||||
| 279 | me, axi); | |||||
| 280 | return 1; | |||||
| 281 | } | |||||
| 282 | if (miteVariableParse(&isp, domStr)) { | |||||
| 283 | biffAddf(MITEmiteBiffKey, "%s: couldn't parse txf domain \"%s\" for axis %d\n", | |||||
| 284 | me, domStr, axi); | |||||
| 285 | return 1; | |||||
| 286 | } | |||||
| 287 | if (!( 1 == isp.kind->table[isp.item].answerLength || | |||||
| 288 | 3 == isp.kind->table[isp.item].answerLength )) { | |||||
| 289 | biffAddf(MITEmiteBiffKey, "%s: %s (item %d) not a scalar or vector " | |||||
| 290 | "(answerLength = %d): " | |||||
| 291 | "can't be a txf domain variable", me, domStr, isp.item, | |||||
| 292 | isp.kind->table[isp.item].answerLength); | |||||
| 293 | return 1; | |||||
| 294 | } | |||||
| 295 | if (3 == isp.kind->table[isp.item].answerLength) { | |||||
| 296 | /* has to be right length for one of the quantization schemes */ | |||||
| 297 | ilog2 = airLog2(ntxf->axis[axi].size); | |||||
| 298 | if (-1 == ilog2) { | |||||
| 299 | char stmp[AIR_STRLEN_SMALL(128+1)]; | |||||
| 300 | biffAddf(MITEmiteBiffKey, "%s: txf axis size for %s must be power of 2 (not %s)", | |||||
| 301 | me, domStr, airSprintSize_t(stmp, ntxf->axis[axi].size)); | |||||
| 302 | return 1; | |||||
| 303 | } else { | |||||
| 304 | if (!( AIR_IN_CL(8, ilog2, 16)((8) <= (ilog2) && (ilog2) <= (16)) )) { | |||||
| 305 | biffAddf(MITEmiteBiffKey, "%s: log_2 of txf axis size for %s should be in " | |||||
| 306 | "range [8,16] (not %d)", me, domStr, ilog2); | |||||
| 307 | return 1; | |||||
| 308 | } | |||||
| 309 | } | |||||
| 310 | } else { | |||||
| 311 | if (!( AIR_EXISTS(ntxf->axis[axi].min)(((int)(!((ntxf->axis[axi].min) - (ntxf->axis[axi].min) )))) && | |||||
| 312 | AIR_EXISTS(ntxf->axis[axi].max)(((int)(!((ntxf->axis[axi].max) - (ntxf->axis[axi].max) )))) )) { | |||||
| 313 | biffAddf(MITEmiteBiffKey, "%s: min and max of axis %d aren't both set", me, axi); | |||||
| 314 | return 1; | |||||
| 315 | } | |||||
| 316 | if (!( ntxf->axis[axi].min < ntxf->axis[axi].max )) { | |||||
| 317 | biffAddf(MITEmiteBiffKey, "%s: min (%g) not less than max (%g) on axis %d", | |||||
| 318 | me, ntxf->axis[axi].min, ntxf->axis[axi].max, axi); | |||||
| 319 | return 1; | |||||
| 320 | } | |||||
| 321 | } | |||||
| 322 | } | |||||
| 323 | ||||||
| 324 | return 0; | |||||
| 325 | } | |||||
| 326 | ||||||
| 327 | /* | |||||
| 328 | ******** miteQueryAdd() | |||||
| 329 | ** | |||||
| 330 | ** This looks a given gageItemSpec and sets the bits in the | |||||
| 331 | ** gageKindScl and tenGageKind queries that are required to calculate | |||||
| 332 | ** the quantity | |||||
| 333 | ** | |||||
| 334 | ** NOTE: This does NOT initialize the query{Scl,Vec,Ten}: it | |||||
| 335 | ** just adds on new items to the existing queries | |||||
| 336 | ** | |||||
| 337 | ** HEY: this is really unfortunate: each new gage type use for | |||||
| 338 | ** volume rendering in mite will have to explicitly added as | |||||
| 339 | ** arguments here, which is part of the reason that mite may end | |||||
| 340 | ** up explicitly depending on the libraries supplying those gageKinds | |||||
| 341 | ** (like how mite now must depend on ten) | |||||
| 342 | ** | |||||
| 343 | ** The queryMite argument is a little odd- its not a real gage kind, | |||||
| 344 | ** but we use it to organize which of the miteVal quantities we take | |||||
| 345 | ** the time to compute in miteSample(). | |||||
| 346 | */ | |||||
| 347 | void | |||||
| 348 | miteQueryAdd(gageQuery queryScl, gageQuery queryVec, | |||||
| 349 | gageQuery queryTen, gageQuery queryMite, | |||||
| 350 | gageItemSpec *isp) { | |||||
| 351 | static const char me[]="miteQueryAdd"; | |||||
| 352 | ||||||
| 353 | if (NULL((void*)0) == isp->kind) { | |||||
| 354 | /* nothing to add */ | |||||
| 355 | } else if (gageKindScl == isp->kind) { | |||||
| 356 | GAGE_QUERY_ITEM_ON(queryScl, isp->item)(queryScl[isp->item/8] |= (1 << (isp->item % 8))); | |||||
| 357 | } else if (gageKindVec == isp->kind) { | |||||
| 358 | GAGE_QUERY_ITEM_ON(queryVec, isp->item)(queryVec[isp->item/8] |= (1 << (isp->item % 8))); | |||||
| 359 | } else if (tenGageKind == isp->kind) { | |||||
| 360 | GAGE_QUERY_ITEM_ON(queryTen, isp->item)(queryTen[isp->item/8] |= (1 << (isp->item % 8))); | |||||
| 361 | } else if (miteValGageKind == isp->kind) { | |||||
| 362 | /* regardless of whether the mite query requires scl, vec, or ten | |||||
| 363 | queries, we add it to the quantites that have to be computed | |||||
| 364 | per-sample */ | |||||
| 365 | GAGE_QUERY_ITEM_ON(queryMite, isp->item)(queryMite[isp->item/8] |= (1 << (isp->item % 8)) ); | |||||
| 366 | /* HEY: some these have useful analogs for tensor data, but I | |||||
| 367 | won't be able to express them. This means that while Phong | |||||
| 368 | shading of *scalar* volumes can be implemented with transfer | |||||
| 369 | functions, it is currently not possible in *tensor* volumes | |||||
| 370 | (for instance, using the gradient of fractional anisotropy) */ | |||||
| 371 | switch(isp->item) { | |||||
| 372 | case miteValVrefN: | |||||
| 373 | case miteValNdotV: | |||||
| 374 | case miteValNdotL: | |||||
| 375 | /* the "N" can be a normalized vector from any of the | |||||
| 376 | available kinds (except miteValGageKind!), and its | |||||
| 377 | associated query will be handled elsewhere, so there's | |||||
| 378 | nothing to add here */ | |||||
| 379 | break; | |||||
| 380 | case miteValGTdotV: | |||||
| 381 | GAGE_QUERY_ITEM_ON(queryScl, gageSclGeomTens)(queryScl[gageSclGeomTens/8] |= (1 << (gageSclGeomTens % 8))); | |||||
| 382 | break; | |||||
| 383 | case miteValVdefT: | |||||
| 384 | GAGE_QUERY_ITEM_ON(queryTen, tenGageTensor)(queryTen[tenGageTensor/8] |= (1 << (tenGageTensor % 8) )); | |||||
| 385 | case miteValVdefTdotV: | |||||
| 386 | GAGE_QUERY_ITEM_ON(queryTen, tenGageTensor)(queryTen[tenGageTensor/8] |= (1 << (tenGageTensor % 8) )); | |||||
| 387 | break; | |||||
| 388 | } | |||||
| 389 | } else { | |||||
| 390 | fprintf(stderr__stderrp, "%s: PANIC: unrecognized non-NULL gageKind\n", me); | |||||
| 391 | exit(1); | |||||
| 392 | } | |||||
| 393 | return; | |||||
| 394 | } | |||||
| 395 | ||||||
| 396 | int | |||||
| 397 | _miteNtxfCopy(miteRender *mrr, miteUser *muu) { | |||||
| 398 | static const char me[]="_miteNtxfCopy"; | |||||
| 399 | int ni, E; | |||||
| 400 | ||||||
| 401 | mrr->ntxf = AIR_CALLOC(muu->ntxfNum, Nrrd *)(Nrrd **)(calloc((muu->ntxfNum), sizeof(Nrrd *))); | |||||
| 402 | if (!mrr->ntxf) { | |||||
| 403 | biffAddf(MITEmiteBiffKey, "%s: couldn't calloc %d ntxf pointers", me, muu->ntxfNum); | |||||
| 404 | return 1; | |||||
| 405 | } | |||||
| 406 | mrr->ntxfNum = muu->ntxfNum; | |||||
| 407 | airMopAdd(mrr->rmop, mrr->ntxf, airFree, airMopAlways); | |||||
| 408 | E = 0; | |||||
| 409 | for (ni=0; ni<mrr->ntxfNum; ni++) { | |||||
| 410 | mrr->ntxf[ni] = nrrdNew(); | |||||
| 411 | if (!E) airMopAdd(mrr->rmop, mrr->ntxf[ni], | |||||
| 412 | (airMopper)nrrdNuke, airMopAlways); | |||||
| 413 | if (!( nrrdTypeUChar == muu->ntxf[ni]->type | |||||
| 414 | || nrrdTypeFloat == muu->ntxf[ni]->type | |||||
| 415 | || nrrdTypeDouble == muu->ntxf[ni]->type )) { | |||||
| 416 | biffAddf(MITEmiteBiffKey, | |||||
| 417 | "%s: sorry, can't handle txf of type %s (only %s, %s, %s)", | |||||
| 418 | me, airEnumStr(nrrdType, muu->ntxf[ni]->type), | |||||
| 419 | airEnumStr(nrrdType, nrrdTypeUChar), | |||||
| 420 | airEnumStr(nrrdType, nrrdTypeFloat), | |||||
| 421 | airEnumStr(nrrdType, nrrdTypeDouble)); | |||||
| 422 | return 1; | |||||
| 423 | } | |||||
| 424 | /* note that key/values need to be copied for the sake of | |||||
| 425 | identifying a non-default miteStageOp */ | |||||
| 426 | switch(muu->ntxf[ni]->type) { | |||||
| 427 | case nrrdTypeUChar: | |||||
| 428 | if (!E) E |= nrrdUnquantize(mrr->ntxf[ni], muu->ntxf[ni], nrrdTypeUChar); | |||||
| 429 | if (!E) E |= nrrdKeyValueCopy(mrr->ntxf[ni], muu->ntxf[ni]); | |||||
| 430 | break; | |||||
| 431 | case mite_ntnrrdTypeDouble: | |||||
| 432 | if (!E) E |= nrrdCopy(mrr->ntxf[ni], muu->ntxf[ni]); | |||||
| 433 | break; | |||||
| 434 | default: /* will be either float or double (whatever mite_nt isn't) */ | |||||
| 435 | if (!E) E |= nrrdConvert(mrr->ntxf[ni], muu->ntxf[ni], mite_ntnrrdTypeDouble); | |||||
| 436 | if (!E) E |= nrrdKeyValueCopy(mrr->ntxf[ni], muu->ntxf[ni]); | |||||
| 437 | break; | |||||
| 438 | } | |||||
| 439 | } | |||||
| 440 | if (E) { | |||||
| 441 | biffMovef(MITEmiteBiffKey, NRRDnrrdBiffKey, "%s: troubling copying/converting all ntxfs", me); | |||||
| 442 | return 1; | |||||
| 443 | } | |||||
| 444 | return 0; | |||||
| 445 | } | |||||
| 446 | ||||||
| 447 | int | |||||
| 448 | _miteNtxfAlphaAdjust(miteRender *mrr, miteUser *muu) { | |||||
| 449 | static const char me[]="_miteNtxfAlphaAdjust"; | |||||
| 450 | int ni, ei, ri, nnum, rnum; | |||||
| 451 | Nrrd *ntxf; | |||||
| 452 | mite_t *data, alpha, frac; | |||||
| 453 | ||||||
| 454 | if (_miteNtxfCopy(mrr, muu)) { | |||||
| 455 | biffAddf(MITEmiteBiffKey, "%s: trouble copying/converting transfer functions", me); | |||||
| 456 | return 1; | |||||
| 457 | } | |||||
| 458 | frac = muu->rayStep/muu->refStep; | |||||
| 459 | for (ni=0; ni<mrr->ntxfNum; ni++) { | |||||
| 460 | ntxf = mrr->ntxf[ni]; | |||||
| 461 | if (!strchr(ntxf->axis[0].label, miteRangeChar[miteRangeAlpha])) { | |||||
| 462 | continue; | |||||
| 463 | } | |||||
| 464 | /* else this txf sets opacity */ | |||||
| 465 | data = (mite_t *)ntxf->data; | |||||
| 466 | rnum = ntxf->axis[0].size; | |||||
| 467 | nnum = nrrdElementNumber(ntxf)/rnum; | |||||
| 468 | for (ei=0; ei<nnum; ei++) { | |||||
| 469 | for (ri=0; ri<rnum; ri++) { | |||||
| 470 | if (ntxf->axis[0].label[ri] == miteRangeChar[miteRangeAlpha]) { | |||||
| 471 | alpha = data[ri + rnum*ei]; | |||||
| 472 | data[ri + rnum*ei] = 1 - pow(AIR_MAX(0, 1-alpha)((0) > (1-alpha) ? (0) : (1-alpha)), frac); | |||||
| 473 | } | |||||
| 474 | } | |||||
| 475 | } | |||||
| 476 | } | |||||
| 477 | return 0; | |||||
| 478 | } | |||||
| 479 | ||||||
| 480 | int | |||||
| 481 | _miteStageNum(miteRender *mrr) { | |||||
| 482 | int num, ni; | |||||
| 483 | ||||||
| 484 | num = 0; | |||||
| 485 | for (ni=0; ni<mrr->ntxfNum; ni++) { | |||||
| 486 | num += mrr->ntxf[ni]->dim - 1; | |||||
| 487 | } | |||||
| 488 | return num; | |||||
| 489 | } | |||||
| 490 | ||||||
| 491 | void | |||||
| 492 | _miteStageInit(miteStage *stage) { | |||||
| 493 | int rii; | |||||
| 494 | ||||||
| 495 | stage->val = NULL((void*)0); | |||||
| 496 | stage->size = -1; | |||||
| 497 | stage->op = miteStageOpUnknown; | |||||
| 498 | stage->qn = NULL((void*)0); | |||||
| 499 | stage->min = stage->max = AIR_NAN(airFloatQNaN.f); | |||||
| 500 | stage->data = NULL((void*)0); | |||||
| 501 | for (rii=0; rii<=MITE_RANGE_NUM9-1; rii++) { | |||||
| 502 | stage->rangeIdx[rii] = -1; | |||||
| 503 | } | |||||
| 504 | stage->rangeNum = -1; | |||||
| 505 | stage->label = NULL((void*)0); | |||||
| 506 | return; | |||||
| 507 | } | |||||
| 508 | ||||||
| 509 | double * | |||||
| 510 | _miteAnswerPointer(miteThread *mtt, gageItemSpec *isp) { | |||||
| 511 | static const char me[]="_miteAnswerPointer"; | |||||
| 512 | double *ret; | |||||
| 513 | ||||||
| 514 | if (!isp->kind) { | |||||
| 515 | /* we got a NULL kind (as happens with output of | |||||
| 516 | gageItemSpecNew(), or miteVariableParse of an | |||||
| 517 | empty string); only NULL return is sensible */ | |||||
| 518 | return NULL((void*)0); | |||||
| 519 | } | |||||
| 520 | ||||||
| 521 | if (gageKindScl == isp->kind) { | |||||
| 522 | ret = mtt->ansScl; | |||||
| 523 | } else if (gageKindVec == isp->kind) { | |||||
| 524 | ret = mtt->ansVec; | |||||
| 525 | } else if (tenGageKind == isp->kind) { | |||||
| 526 | ret = mtt->ansTen; | |||||
| 527 | } else if (miteValGageKind == isp->kind) { | |||||
| 528 | ret = mtt->ansMiteVal; | |||||
| 529 | } else { | |||||
| 530 | fprintf(stderr__stderrp, "\nPANIC: %s: unknown gageKind!\n", me); | |||||
| 531 | exit(1); | |||||
| 532 | } | |||||
| 533 | ret += gageKindAnswerOffset(isp->kind, isp->item); | |||||
| 534 | return ret; | |||||
| 535 | } | |||||
| 536 | ||||||
| 537 | /* | |||||
| 538 | ** _miteStageSet | |||||
| 539 | ** | |||||
| 540 | ** ALLOCATES and initializes stage array in a miteThread | |||||
| 541 | */ | |||||
| 542 | int | |||||
| 543 | _miteStageSet(miteThread *mtt, miteRender *mrr) { | |||||
| 544 | static const char me[]="_miteStageSet"; | |||||
| 545 | char *value; | |||||
| 546 | int ni, di, stageIdx, rii, stageNum, ilog2; | |||||
| 547 | Nrrd *ntxf; | |||||
| 548 | miteStage *stage; | |||||
| 549 | gageItemSpec isp; | |||||
| 550 | char rc; | |||||
| 551 | ||||||
| 552 | stageNum = _miteStageNum(mrr); | |||||
| ||||||
| 553 | /* fprintf(stderr, "!%s: stageNum = %d\n", me, stageNum); */ | |||||
| 554 | mtt->stage = AIR_CALLOC(stageNum, miteStage)(miteStage*)(calloc((stageNum), sizeof(miteStage))); | |||||
| ||||||
| 555 | if (!mtt->stage) { | |||||
| 556 | biffAddf(MITEmiteBiffKey, "%s: couldn't alloc array of %d stages", me, stageNum); | |||||
| 557 | return 1; | |||||
| 558 | } | |||||
| 559 | airMopAdd(mtt->rmop, mtt->stage, airFree, airMopAlways); | |||||
| 560 | mtt->stageNum = stageNum; | |||||
| 561 | stageIdx = 0; | |||||
| 562 | for (ni=0; ni<mrr->ntxfNum; ni++) { | |||||
| 563 | ntxf = mrr->ntxf[ni]; | |||||
| 564 | for (di=ntxf->dim-1; di>=1; di--) { | |||||
| 565 | stage = mtt->stage + stageIdx; | |||||
| 566 | _miteStageInit(stage); | |||||
| 567 | miteVariableParse(&isp, ntxf->axis[di].label); | |||||
| 568 | stage->val = _miteAnswerPointer(mtt, &isp); | |||||
| 569 | stage->label = ntxf->axis[di].label; | |||||
| 570 | /* | |||||
| 571 | fprintf(stderr, "!%s: ans=%p + offset[%d]=%d == %p\n", me, | |||||
| 572 | mtt->ans, dom, kind->ansOffset[dom], stage->val); | |||||
| 573 | */ | |||||
| 574 | stage->size = ntxf->axis[di].size; | |||||
| 575 | stage->min = ntxf->axis[di].min; | |||||
| 576 | stage->max = ntxf->axis[di].max; | |||||
| 577 | if (di > 1) { | |||||
| 578 | stage->data = NULL((void*)0); | |||||
| 579 | } else { | |||||
| 580 | stage->data = (mite_t *)ntxf->data; | |||||
| 581 | value = nrrdKeyValueGet(ntxf, "miteStageOp"); | |||||
| 582 | if (value) { | |||||
| 583 | stage->op = airEnumVal(miteStageOp, value); | |||||
| 584 | if (miteStageOpUnknown == stage->op) { | |||||
| 585 | stage->op = miteStageOpMultiply; | |||||
| 586 | } | |||||
| 587 | } else { | |||||
| 588 | stage->op = miteStageOpMultiply; | |||||
| 589 | } | |||||
| 590 | if (1 == isp.kind->table[isp.item].answerLength) { | |||||
| 591 | stage->qn = NULL((void*)0); | |||||
| 592 | } else if (3 == isp.kind->table[isp.item].answerLength) { | |||||
| 593 | char stmp[AIR_STRLEN_SMALL(128+1)]; | |||||
| 594 | ilog2 = airLog2(ntxf->axis[di].size); | |||||
| 595 | switch(ilog2) { | |||||
| 596 | case 8: stage->qn = limnVtoQN_d[ limnQN8octa]; break; | |||||
| 597 | case 9: stage->qn = limnVtoQN_d[ limnQN9octa]; break; | |||||
| 598 | case 10: stage->qn = limnVtoQN_d[limnQN10octa]; break; | |||||
| 599 | case 11: stage->qn = limnVtoQN_d[limnQN11octa]; break; | |||||
| 600 | case 12: stage->qn = limnVtoQN_d[limnQN12octa]; break; | |||||
| 601 | case 13: stage->qn = limnVtoQN_d[limnQN13octa]; break; | |||||
| 602 | case 14: stage->qn = limnVtoQN_d[limnQN14octa]; break; | |||||
| 603 | case 15: stage->qn = limnVtoQN_d[limnQN15octa]; break; | |||||
| 604 | case 16: stage->qn = limnVtoQN_d[limnQN16octa]; break; | |||||
| 605 | default: | |||||
| 606 | biffAddf(MITEmiteBiffKey, "%s: txf axis %d size %s not usable for " | |||||
| 607 | "vector txf domain variable %s", me, di, | |||||
| 608 | airSprintSize_t(stmp, ntxf->axis[di].size), | |||||
| 609 | ntxf->axis[di].label); | |||||
| 610 | return 1; | |||||
| 611 | break; | |||||
| 612 | } | |||||
| 613 | } else { | |||||
| 614 | biffAddf(MITEmiteBiffKey, "%s: %s not scalar or vector (len = %d): can't be " | |||||
| 615 | "a txf domain variable", me, | |||||
| 616 | ntxf->axis[di].label, | |||||
| 617 | isp.kind->table[isp.item].answerLength); | |||||
| 618 | return 1; | |||||
| 619 | } | |||||
| 620 | stage->rangeNum = ntxf->axis[0].size; | |||||
| 621 | for (rii=0; rii<stage->rangeNum; rii++) { | |||||
| 622 | rc = ntxf->axis[0].label[rii]; | |||||
| 623 | stage->rangeIdx[rii] = strchr(miteRangeChar, rc) - miteRangeChar; | |||||
| 624 | /* | |||||
| 625 | fprintf(stderr, "!%s: range: %c -> %d\n", "_miteStageSet", | |||||
| 626 | ntxf->axis[0].label[rii], stage->rangeIdx[rii]); | |||||
| 627 | */ | |||||
| 628 | } | |||||
| 629 | } | |||||
| 630 | stageIdx++; | |||||
| 631 | } | |||||
| 632 | } | |||||
| 633 | return 0; | |||||
| 634 | } | |||||
| 635 | ||||||
| 636 | void | |||||
| 637 | _miteStageRun(miteThread *mtt, miteUser *muu) { | |||||
| 638 | static const char me[]="_miteStageRun"; | |||||
| 639 | int stageIdx, ri, rii; | |||||
| 640 | unsigned int txfIdx, finalIdx; | |||||
| 641 | miteStage *stage; | |||||
| 642 | mite_t *rangeData; | |||||
| 643 | double *dbg=NULL((void*)0); | |||||
| 644 | ||||||
| 645 | finalIdx = 0; | |||||
| 646 | if (mtt->verbose) { | |||||
| 647 | dbg = muu->debug + muu->debugIdx; | |||||
| 648 | } | |||||
| 649 | for (stageIdx=0; stageIdx<mtt->stageNum; stageIdx++) { | |||||
| 650 | stage = &(mtt->stage[stageIdx]); | |||||
| 651 | if (stage->qn) { | |||||
| 652 | /* its a vector-valued txf domain variable */ | |||||
| 653 | txfIdx = stage->qn(stage->val); | |||||
| 654 | /* right now, we can't store vector-valued txf domain variables */ | |||||
| 655 | } else { | |||||
| 656 | /* its a scalar txf domain variable */ | |||||
| 657 | txfIdx = airIndexClamp(stage->min, *(stage->val), | |||||
| 658 | stage->max, stage->size); | |||||
| 659 | if (mtt->verbose) { | |||||
| 660 | fprintf(stderr__stderrp, "!%s: %s=%g in [%g,%g]/%u -> %u\n", me, | |||||
| 661 | stage->label, *(stage->val), | |||||
| 662 | stage->min, stage->max, stage->size, txfIdx); | |||||
| 663 | dbg[0 + 2*stageIdx] = *(stage->val); | |||||
| 664 | } | |||||
| 665 | } | |||||
| 666 | finalIdx = stage->size*finalIdx + txfIdx; | |||||
| 667 | if (mtt->verbose) { | |||||
| 668 | dbg[1 + 2*stageIdx] = txfIdx; | |||||
| 669 | } | |||||
| 670 | if (stage->data) { | |||||
| 671 | rangeData = stage->data + stage->rangeNum*finalIdx; | |||||
| 672 | for (rii=0; rii<stage->rangeNum; rii++) { | |||||
| 673 | ri = stage->rangeIdx[rii]; | |||||
| 674 | switch(stage->op) { | |||||
| 675 | case miteStageOpMin: | |||||
| 676 | mtt->range[ri] = AIR_MIN(mtt->range[ri], rangeData[rii])((mtt->range[ri]) < (rangeData[rii]) ? (mtt->range[ri ]) : (rangeData[rii])); | |||||
| 677 | break; | |||||
| 678 | case miteStageOpMax: | |||||
| 679 | mtt->range[ri] = AIR_MAX(mtt->range[ri], rangeData[rii])((mtt->range[ri]) > (rangeData[rii]) ? (mtt->range[ri ]) : (rangeData[rii])); | |||||
| 680 | break; | |||||
| 681 | case miteStageOpAdd: | |||||
| 682 | mtt->range[ri] += rangeData[rii]; | |||||
| 683 | break; | |||||
| 684 | case miteStageOpMultiply: | |||||
| 685 | default: | |||||
| 686 | mtt->range[ri] *= rangeData[rii]; | |||||
| 687 | break; | |||||
| 688 | } | |||||
| 689 | } | |||||
| 690 | finalIdx = 0; | |||||
| 691 | } | |||||
| 692 | } | |||||
| 693 | return; | |||||
| 694 | } |