43 |
char *err; |
char *err; |
44 |
Nrrd *nin, *nout; |
Nrrd *nin, *nout; |
45 |
NrrdIoState *nio; |
NrrdIoState *nio; |
46 |
int kindIn, kindOut, headerOnly, haveMM, trivialOrient; |
int kindIn, kindOut, headerOnly, haveMM, trivialOrient, recenter; |
47 |
unsigned int kindAxis, axi, si, sj; |
unsigned int kindAxis, axi, si, sj; |
48 |
|
double sscl; |
49 |
|
|
50 |
me = argv[0]; |
me = argv[0]; |
51 |
mop = airMopNew(); |
mop = airMopNew(); |
59 |
"even if the input nrrd comes with full orientation or " |
"even if the input nrrd comes with full orientation or " |
60 |
"per-axis min-max info, ignore it and instead assert the " |
"per-axis min-max info, ignore it and instead assert the " |
61 |
"most trivial mapping between index and world space"); |
"most trivial mapping between index and world space"); |
62 |
|
hestOptAdd(&hopt, "c", NULL, airTypeInt, 0, 0, &recenter, NULL, |
63 |
|
"re-locate output spaceOrigin so that field is centered " |
64 |
|
"around origin of space coordinates"); |
65 |
|
hestOptAdd(&hopt, "s", "scl", airTypeDouble, 1, 1, &sscl, "1.0", |
66 |
|
"when contriving orientation information, distance between " |
67 |
|
"samples to use"); |
68 |
hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nin, NULL, |
hestOptAdd(&hopt, "i", "nin", airTypeOther, 1, 1, &nin, NULL, |
69 |
"input image", NULL, NULL, nrrdHestNrrd); |
"input image", NULL, NULL, nrrdHestNrrd); |
70 |
hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", |
hestOptAdd(&hopt, "o", "nout", airTypeString, 1, 1, &outS, "-", |
211 |
if (!nrrdSpaceVecExists(nout->spaceDim, |
if (!nrrdSpaceVecExists(nout->spaceDim, |
212 |
nout->axis[axi].spaceDirection)) { |
nout->axis[axi].spaceDirection)) { |
213 |
nrrdSpaceVecSetZero(nout->axis[axi].spaceDirection); |
nrrdSpaceVecSetZero(nout->axis[axi].spaceDirection); |
214 |
nout->axis[axi].spaceDirection[saxi] = 1.0; |
nout->axis[axi].spaceDirection[saxi] = sscl; |
215 |
} |
} |
216 |
saxi++; |
saxi++; |
217 |
} else { |
} else { |
243 |
nout->axis[axi].spaceDirection[saxi] |
nout->axis[axi].spaceDirection[saxi] |
244 |
= (AIR_EXISTS(nin->axis[axi].spacing) |
= (AIR_EXISTS(nin->axis[axi].spacing) |
245 |
? nin->axis[axi].spacing |
? nin->axis[axi].spacing |
246 |
: 1.0); |
: sscl); |
247 |
saxi++; |
saxi++; |
248 |
} else { |
} else { |
249 |
nrrdSpaceVecSetNaN(nout->axis[axi].spaceDirection); |
nrrdSpaceVecSetNaN(nout->axis[axi].spaceDirection); |
262 |
airMopError(mop); exit(1); |
airMopError(mop); exit(1); |
263 |
} |
} |
264 |
|
|
265 |
|
if (recenter) { |
266 |
|
/* sets field's origin so field is centered on the origin. capiche? */ |
267 |
|
/* this code was tacked on later than the stuff above, so its |
268 |
|
logic could probably be moved up there, but it seems cleaner to |
269 |
|
have it as a separate post-process */ |
270 |
|
double mean[NRRD_SPACE_DIM_MAX]; |
271 |
|
nrrdSpaceVecSetZero(mean); |
272 |
|
for (axi=0; axi<nout->dim; axi++) { |
273 |
|
if (nrrdKindUnknown == kindOut || kindAxis != axi) { |
274 |
|
nrrdSpaceVecScaleAdd2(mean, 1.0, mean, |
275 |
|
0.5*(nout->axis[axi].size - 1), |
276 |
|
nout->axis[axi].spaceDirection); |
277 |
|
} |
278 |
|
} |
279 |
|
nrrdSpaceVecScaleAdd2(mean, 1.0, mean, |
280 |
|
1.0, nout->spaceOrigin); |
281 |
|
/* now mean is the center of the field */ |
282 |
|
nrrdSpaceVecScaleAdd2(nout->spaceOrigin, |
283 |
|
1.0, nout->spaceOrigin, |
284 |
|
-1.0, mean); |
285 |
|
} |
286 |
|
|
287 |
if (nrrdSave(outS, nout, nio)) { |
if (nrrdSave(outS, nout, nio)) { |
288 |
airMopAdd(mop, err = biffGet(NRRD), airFree, airMopAlways); |
airMopAdd(mop, err = biffGet(NRRD), airFree, airMopAlways); |
289 |
fprintf(stderr, "%s: trouble saving \"%s\":\n%s", |
fprintf(stderr, "%s: trouble saving \"%s\":\n%s", |