GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
Teem: Tools to process and visualize scientific data and images . |
||
3 |
Copyright (C) 2015, 2014, 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 |
#include "nrrd.h" |
||
25 |
#include "privateNrrd.h" |
||
26 |
|||
27 |
#include <limits.h> |
||
28 |
|||
29 |
/* The "/ *Teem:" (without space) comments in here are an experiment */ |
||
30 |
|||
31 |
const char * |
||
32 |
nrrdBiffKey = "nrrd"; |
||
33 |
|||
34 |
/* |
||
35 |
******** nrrdSpaceDimension |
||
36 |
** |
||
37 |
** returns expected dimension of given space (from nrrdSpace* enum), or, |
||
38 |
** 0 if there is no expected dimension. |
||
39 |
** |
||
40 |
** The expected behavior here is to return 0 for nrrdSpaceUnknown, because |
||
41 |
** that is the right answer, not because its an error of any kind. |
||
42 |
*/ |
||
43 |
unsigned int |
||
44 |
nrrdSpaceDimension(int space) { |
||
45 |
static const char me[]="nrrdSpaceDimension"; |
||
46 |
unsigned int ret; |
||
47 |
|||
48 |
✗✓ | 62198 |
if (!( AIR_IN_OP(nrrdSpaceUnknown, space, nrrdSpaceLast) )) { |
49 |
/* they gave us invalid or unknown space */ |
||
50 |
return 0; |
||
51 |
} |
||
52 |
✗✗✗✗ ✗✗✗✓ ✗✗✗✗ ✗✗✗ |
31099 |
switch (space) { |
53 |
case nrrdSpaceRightUp: |
||
54 |
case nrrdSpaceRightDown: |
||
55 |
ret = 2; |
||
56 |
break; |
||
57 |
case nrrdSpaceRightAnteriorSuperior: |
||
58 |
case nrrdSpaceLeftAnteriorSuperior: |
||
59 |
case nrrdSpaceLeftPosteriorSuperior: |
||
60 |
case nrrdSpaceScannerXYZ: |
||
61 |
case nrrdSpace3DRightHanded: |
||
62 |
case nrrdSpace3DLeftHanded: |
||
63 |
ret = 3; |
||
64 |
31099 |
break; |
|
65 |
case nrrdSpaceRightAnteriorSuperiorTime: |
||
66 |
case nrrdSpaceLeftAnteriorSuperiorTime: |
||
67 |
case nrrdSpaceLeftPosteriorSuperiorTime: |
||
68 |
case nrrdSpaceScannerXYZTime: |
||
69 |
case nrrdSpace3DRightHandedTime: |
||
70 |
case nrrdSpace3DLeftHandedTime: |
||
71 |
ret = 4; |
||
72 |
break; |
||
73 |
default: |
||
74 |
fprintf(stderr, "%s: PANIC: nrrdSpace %d not implemented!\n", me, space); |
||
75 |
ret = UINT_MAX; /* exit(1); */ |
||
76 |
break; |
||
77 |
} |
||
78 |
31099 |
return ret; |
|
79 |
31099 |
} |
|
80 |
|||
81 |
/* |
||
82 |
******** nrrdSpaceSet |
||
83 |
** |
||
84 |
** What to use to set space, when a value from nrrdSpace enum is known, |
||
85 |
** or, to nullify all space-related information when passed nrrdSpaceUnknown |
||
86 |
*/ |
||
87 |
int |
||
88 |
nrrdSpaceSet(Nrrd *nrrd, int space) { |
||
89 |
static const char me[]="nrrdSpaceSet"; |
||
90 |
unsigned axi, saxi; |
||
91 |
|||
92 |
✗✓ | 94 |
if (!nrrd) { |
93 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
94 |
return 1; |
||
95 |
} |
||
96 |
✗✓ | 47 |
if (nrrdSpaceUnknown == space) { |
97 |
nrrd->space = nrrdSpaceUnknown; |
||
98 |
nrrd->spaceDim = 0; |
||
99 |
for (axi=0; axi<NRRD_DIM_MAX; axi++) { |
||
100 |
nrrdSpaceVecSetNaN(nrrd->axis[axi].spaceDirection); |
||
101 |
} |
||
102 |
for (saxi=0; saxi<NRRD_SPACE_DIM_MAX; saxi++) { |
||
103 |
airFree(nrrd->spaceUnits[saxi]); |
||
104 |
nrrd->spaceUnits[saxi] = NULL; |
||
105 |
} |
||
106 |
nrrdSpaceVecSetNaN(nrrd->spaceOrigin); |
||
107 |
} else { |
||
108 |
✗✓ | 47 |
if (airEnumValCheck(nrrdSpace, space)) { |
109 |
biffAddf(NRRD, "%s: given space (%d) not valid", me, space); |
||
110 |
return 1; |
||
111 |
} |
||
112 |
47 |
nrrd->space = space; |
|
113 |
47 |
nrrd->spaceDim = nrrdSpaceDimension(space); |
|
114 |
} |
||
115 |
47 |
return 0; |
|
116 |
47 |
} |
|
117 |
|||
118 |
/* |
||
119 |
******** nrrdSpaceDimensionSet |
||
120 |
** |
||
121 |
** What to use to set space, based on spaceDim alone (nrrd->space set to |
||
122 |
** nrrdSpaceUnknown) |
||
123 |
*/ |
||
124 |
int |
||
125 |
nrrdSpaceDimensionSet(Nrrd *nrrd, unsigned int spaceDim) { |
||
126 |
static const char me[]="nrrdSpaceDimensionSet"; |
||
127 |
|||
128 |
if (!nrrd) { |
||
129 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
130 |
return 1; |
||
131 |
} |
||
132 |
if (!( spaceDim <= NRRD_SPACE_DIM_MAX )) { |
||
133 |
biffAddf(NRRD, "%s: given spaceDim (%u) not valid", me, spaceDim); |
||
134 |
return 1; |
||
135 |
} |
||
136 |
nrrd->space = nrrdSpaceUnknown; |
||
137 |
nrrd->spaceDim = spaceDim; |
||
138 |
return 0; |
||
139 |
} |
||
140 |
|||
141 |
/* |
||
142 |
******** nrrdSpaceOriginGet |
||
143 |
** |
||
144 |
** retrieves the spaceOrigin from given nrrd, and returns spaceDim |
||
145 |
** Indices 0 through spaceDim-1 are set in given vector[] to coords |
||
146 |
** of space origin, and all further indices are set to NaN. That is, |
||
147 |
** this really does write to all NRRD_SPACE_DIM_MAX elements of vector[] |
||
148 |
*/ |
||
149 |
unsigned int |
||
150 |
nrrdSpaceOriginGet(const Nrrd *nrrd, |
||
151 |
double vector[NRRD_SPACE_DIM_MAX]) { |
||
152 |
unsigned int sdi, ret; |
||
153 |
|||
154 |
✓✗ | 1388 |
if (nrrd && vector) { |
155 |
✓✓ | 5552 |
for (sdi=0; sdi<nrrd->spaceDim; sdi++) { |
156 |
2082 |
vector[sdi] = nrrd->spaceOrigin[sdi]; |
|
157 |
} |
||
158 |
✓✓ | 8328 |
for (sdi=nrrd->spaceDim; sdi<NRRD_SPACE_DIM_MAX; sdi++) { |
159 |
3470 |
vector[sdi] = AIR_NAN; |
|
160 |
} |
||
161 |
694 |
ret = nrrd->spaceDim; |
|
162 |
694 |
} else { |
|
163 |
ret = 0; |
||
164 |
} |
||
165 |
694 |
return ret; |
|
166 |
} |
||
167 |
|||
168 |
/* |
||
169 |
******** nrrdSpaceOriginSet |
||
170 |
** |
||
171 |
** convenience function for setting spaceOrigin. |
||
172 |
** Note: space (or spaceDim) must be already set. |
||
173 |
** The given "vector" is only read for spaceDim elements |
||
174 |
** |
||
175 |
** returns 1 if there were problems, 0 otherwise |
||
176 |
*/ |
||
177 |
int |
||
178 |
nrrdSpaceOriginSet(Nrrd *nrrd, const double *vector) { |
||
179 |
static const char me[]="nrrdSpaceOriginSet"; |
||
180 |
unsigned int sdi; |
||
181 |
|||
182 |
✗✓ | 78 |
if (!( nrrd && vector )) { |
183 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
184 |
return 1; |
||
185 |
} |
||
186 |
✓✗✗✓ |
78 |
if (!( 0 < nrrd->spaceDim && nrrd->spaceDim <= NRRD_SPACE_DIM_MAX )) { |
187 |
biffAddf(NRRD, "%s: set spaceDim %d not valid", me, nrrd->spaceDim); |
||
188 |
return 1; |
||
189 |
} |
||
190 |
|||
191 |
✓✓ | 312 |
for (sdi=0; sdi<nrrd->spaceDim; sdi++) { |
192 |
117 |
nrrd->spaceOrigin[sdi] = vector[sdi]; |
|
193 |
} |
||
194 |
✓✓ | 468 |
for (sdi=nrrd->spaceDim; sdi<NRRD_SPACE_DIM_MAX; sdi++) { |
195 |
195 |
nrrd->spaceOrigin[sdi] = AIR_NAN; |
|
196 |
} |
||
197 |
39 |
return 0; |
|
198 |
39 |
} |
|
199 |
|||
200 |
/* |
||
201 |
******** nrrdOriginCalculate |
||
202 |
** |
||
203 |
** makes an effort to calculate something like an "origin" (as in |
||
204 |
** nrrd->spaceOrigin) from the per-axis min, max, or spacing, when |
||
205 |
** there is no real space information. Like the spaceOrigin, this |
||
206 |
** location is supposed to be THE CENTER of the first sample. To |
||
207 |
** avoid making assumptions about the nrrd or the caller, a default |
||
208 |
** sample centering (defaultCenter) has to be provided (use either |
||
209 |
** nrrdCenterNode or nrrdCenterCell). The axes that are used |
||
210 |
** for the origin calculation have to be given explicitly- but they |
||
211 |
** are likely the return of nrrdDomainAxesGet |
||
212 |
** |
||
213 |
** The computed origin is put into the given vector (origin). The return |
||
214 |
** value takes on values from the nrrdOriginStatus* enum: |
||
215 |
** |
||
216 |
** nrrdOriginStatusUnknown: invalid arguments (e.g. NULL pointer, or |
||
217 |
** axis values out of range) |
||
218 |
** |
||
219 |
** nrrdOriginStatusDirection: the chosen axes have spaceDirection set, |
||
220 |
** which means caller should instead be using |
||
221 |
** nrrdSpaceOriginGet |
||
222 |
** |
||
223 |
** nrrdOriginStatusNoMin: can't compute "origin" without axis->min |
||
224 |
** |
||
225 |
** nrrdOriginStatusNoMaxOrSpacing: can't compute origin without (axis->min |
||
226 |
** and) either axis->max or axis->spacing |
||
227 |
** |
||
228 |
** nrrdOriginStatusOkay: all is well |
||
229 |
*/ |
||
230 |
int |
||
231 |
nrrdOriginCalculate(const Nrrd *nrrd, |
||
232 |
unsigned int *axisIdx, unsigned int axisIdxNum, |
||
233 |
int defaultCenter, double *origin) { |
||
234 |
const NrrdAxisInfo *axis[NRRD_SPACE_DIM_MAX]; |
||
235 |
int center, okay, gotSpace, gotMin, gotMaxOrSpacing; |
||
236 |
unsigned int ai; |
||
237 |
double min, spacing; |
||
238 |
|||
239 |
#define ERROR \ |
||
240 |
if (origin) { \ |
||
241 |
for (ai=0; ai<axisIdxNum; ai++) { \ |
||
242 |
origin[ai] = AIR_NAN; \ |
||
243 |
} \ |
||
244 |
} |
||
245 |
|||
246 |
if (!( nrrd |
||
247 |
&& (nrrdCenterCell == defaultCenter |
||
248 |
|| nrrdCenterNode == defaultCenter) |
||
249 |
&& origin )) { |
||
250 |
ERROR; |
||
251 |
return nrrdOriginStatusUnknown; |
||
252 |
} |
||
253 |
|||
254 |
okay = AIR_TRUE; |
||
255 |
for (ai=0; ai<axisIdxNum; ai++) { |
||
256 |
okay &= axisIdx[ai] < nrrd->dim; |
||
257 |
} |
||
258 |
if (!okay) { |
||
259 |
ERROR; |
||
260 |
return nrrdOriginStatusUnknown; |
||
261 |
} |
||
262 |
|||
263 |
/* learn axisInfo pointers */ |
||
264 |
for (ai=0; ai<axisIdxNum; ai++) { |
||
265 |
axis[ai] = nrrd->axis + axisIdx[ai]; |
||
266 |
} |
||
267 |
|||
268 |
gotSpace = AIR_FALSE; |
||
269 |
for (ai=0; ai<axisIdxNum; ai++) { |
||
270 |
gotSpace |= AIR_EXISTS(axis[ai]->spaceDirection[0]); |
||
271 |
} |
||
272 |
if (nrrd->spaceDim > 0 && gotSpace) { |
||
273 |
ERROR; |
||
274 |
return nrrdOriginStatusDirection; |
||
275 |
} |
||
276 |
|||
277 |
gotMin = AIR_TRUE; |
||
278 |
for (ai=0; ai<axisIdxNum; ai++) { |
||
279 |
gotMin &= AIR_EXISTS(axis[0]->min); |
||
280 |
} |
||
281 |
if (!gotMin) { |
||
282 |
ERROR; |
||
283 |
return nrrdOriginStatusNoMin; |
||
284 |
} |
||
285 |
|||
286 |
gotMaxOrSpacing = AIR_TRUE; |
||
287 |
for (ai=0; ai<axisIdxNum; ai++) { |
||
288 |
gotMaxOrSpacing &= (AIR_EXISTS(axis[ai]->max) |
||
289 |
|| AIR_EXISTS(axis[ai]->spacing)); |
||
290 |
} |
||
291 |
if (!gotMaxOrSpacing) { |
||
292 |
ERROR; |
||
293 |
return nrrdOriginStatusNoMaxOrSpacing; |
||
294 |
} |
||
295 |
|||
296 |
for (ai=0; ai<axisIdxNum; ai++) { |
||
297 |
size_t size; |
||
298 |
double denom; |
||
299 |
size = axis[ai]->size; |
||
300 |
min = axis[ai]->min; |
||
301 |
center = (nrrdCenterUnknown != axis[ai]->center |
||
302 |
? axis[ai]->center |
||
303 |
: defaultCenter); |
||
304 |
denom = AIR_CAST(double, nrrdCenterCell == center ? size : size-1); |
||
305 |
spacing = (AIR_EXISTS(axis[ai]->spacing) |
||
306 |
? axis[ai]->spacing |
||
307 |
: (axis[ai]->max - min)/denom); |
||
308 |
origin[ai] = min + (nrrdCenterCell == center ? spacing/2 : 0); |
||
309 |
} |
||
310 |
return nrrdOriginStatusOkay; |
||
311 |
} |
||
312 |
|||
313 |
void |
||
314 |
nrrdSpaceVecCopy(double dst[NRRD_SPACE_DIM_MAX], |
||
315 |
const double src[NRRD_SPACE_DIM_MAX]) { |
||
316 |
unsigned int ii; |
||
317 |
|||
318 |
✓✓ | 3952 |
for (ii=0; ii<NRRD_SPACE_DIM_MAX; ii++) { |
319 |
1664 |
dst[ii] = src[ii]; |
|
320 |
} |
||
321 |
208 |
} |
|
322 |
|||
323 |
/* |
||
324 |
** NOTE: since this was created until Wed Sep 21 13:34:17 EDT 2005, |
||
325 |
** nrrdSpaceVecScaleAdd2 and nrrdSpaceVecScale would treat a |
||
326 |
** non-existent vector coefficient as 0.0. The reason for this had |
||
327 |
** to do with how the function is used. For example, in nrrdCrop |
||
328 |
** |
||
329 |
** _nrrdSpaceVecCopy(nout->spaceOrigin, nin->spaceOrigin); |
||
330 |
** for (ai=0; ai<nin->dim; ai++) { |
||
331 |
** _nrrdSpaceVecScaleAdd2(nout->spaceOrigin, |
||
332 |
** 1.0, nout->spaceOrigin, |
||
333 |
** min[ai], nin->axis[ai].spaceDirection); |
||
334 |
** } |
||
335 |
** |
||
336 |
** but the problem with this is that non-spatial axes end up clobbering |
||
337 |
** the existance of otherwise existing spaceOrigin and spaceDirections. |
||
338 |
** It was decided, however, that this logic should be outside the |
||
339 |
** arithmetic functions below, not inside. NOTE: the old functionality |
||
340 |
** is stuck in ITK 2.2, via NrrdIO. |
||
341 |
*/ |
||
342 |
|||
343 |
void |
||
344 |
nrrdSpaceVecScaleAdd2(double sum[NRRD_SPACE_DIM_MAX], |
||
345 |
double sclA, const double vecA[NRRD_SPACE_DIM_MAX], |
||
346 |
double sclB, const double vecB[NRRD_SPACE_DIM_MAX]) { |
||
347 |
unsigned int ii; |
||
348 |
|||
349 |
✓✓ | 1368 |
for (ii=0; ii<NRRD_SPACE_DIM_MAX; ii++) { |
350 |
576 |
sum[ii] = sclA*vecA[ii] + sclB*vecB[ii]; |
|
351 |
} |
||
352 |
72 |
} |
|
353 |
|||
354 |
void |
||
355 |
nrrdSpaceVecScale(double out[NRRD_SPACE_DIM_MAX], |
||
356 |
double scl, const double vec[NRRD_SPACE_DIM_MAX]) { |
||
357 |
unsigned int ii; |
||
358 |
|||
359 |
✓✓ | 39558 |
for (ii=0; ii<NRRD_SPACE_DIM_MAX; ii++) { |
360 |
16656 |
out[ii] = scl*vec[ii]; |
|
361 |
} |
||
362 |
2082 |
} |
|
363 |
|||
364 |
double |
||
365 |
nrrdSpaceVecNorm(unsigned int sdim, const double vec[NRRD_SPACE_DIM_MAX]) { |
||
366 |
unsigned int di; |
||
367 |
double nn; |
||
368 |
|||
369 |
nn = 0; |
||
370 |
✓✓ | 18954 |
for (di=0; di<sdim; di++) { |
371 |
6318 |
nn += vec[di]*vec[di]; |
|
372 |
} |
||
373 |
2106 |
return sqrt(nn); |
|
374 |
} |
||
375 |
|||
376 |
void |
||
377 |
nrrdSpaceVecSetNaN(double vec[NRRD_SPACE_DIM_MAX]) { |
||
378 |
unsigned int di; |
||
379 |
|||
380 |
for (di=0; di<NRRD_SPACE_DIM_MAX; di++) { |
||
381 |
vec[di] = AIR_NAN; |
||
382 |
} |
||
383 |
return; |
||
384 |
} |
||
385 |
|||
386 |
/* ---- BEGIN non-NrrdIO */ |
||
387 |
|||
388 |
void |
||
389 |
nrrdSpaceVecSetZero(double vec[NRRD_SPACE_DIM_MAX]) { |
||
390 |
int di; |
||
391 |
|||
392 |
for (di=0; di<NRRD_SPACE_DIM_MAX; di++) { |
||
393 |
vec[di] = 0; |
||
394 |
} |
||
395 |
return; |
||
396 |
} |
||
397 |
/* ---- END non-NrrdIO */ |
||
398 |
|||
399 |
/* |
||
400 |
** _nrrdContentGet |
||
401 |
** |
||
402 |
** ALLOCATES a string for the content of a given nrrd |
||
403 |
** panics if allocation failed |
||
404 |
*/ |
||
405 |
char * |
||
406 |
_nrrdContentGet(const Nrrd *nin) { |
||
407 |
static const char me[]="_nrrdContentGet"; |
||
408 |
char *ret; |
||
409 |
|||
410 |
✓✗✓✓ |
1395 |
ret = ((nin && nin->content) |
411 |
164 |
? airStrdup(nin->content) |
|
412 |
115 |
: airStrdup(nrrdStateUnknownContent)); |
|
413 |
✗✓ | 279 |
if (!ret) { |
414 |
fprintf(stderr, "%s: PANIC: content strdup failed!\n", me); |
||
415 |
return NULL; |
||
416 |
} |
||
417 |
279 |
return ret; |
|
418 |
279 |
} |
|
419 |
|||
420 |
int |
||
421 |
_nrrdContentSet_nva(Nrrd *nout, const char *func, |
||
422 |
char *content, const char *format, va_list arg) { |
||
423 |
static const char me[]="_nrrdContentSet_nva"; |
||
424 |
char *buff; |
||
425 |
|||
426 |
✗✓ | 540 |
if (nrrdStateDisableContent) { |
427 |
/* we kill content always */ |
||
428 |
nout->content = (char *)airFree(nout->content); |
||
429 |
return 0; |
||
430 |
} |
||
431 |
270 |
buff = (char *)malloc(128*AIR_STRLEN_HUGE); |
|
432 |
✗✓ | 270 |
if (!buff) { |
433 |
biffAddf(NRRD, "%s: couln't alloc buffer!", me); |
||
434 |
return 1; |
||
435 |
} |
||
436 |
270 |
nout->content = (char *)airFree(nout->content); |
|
437 |
|||
438 |
/* we are currently praying that this won't overflow the "buff" array */ |
||
439 |
/* HEY: replace with vsnprintf or whatever when its available */ |
||
440 |
270 |
vsprintf(buff, format, arg); |
|
441 |
|||
442 |
270 |
nout->content = (char *)calloc(strlen("(,)") |
|
443 |
270 |
+ airStrlen(func) |
|
444 |
270 |
+ 1 /* '(' */ |
|
445 |
270 |
+ airStrlen(content) |
|
446 |
270 |
+ 1 /* ',' */ |
|
447 |
270 |
+ airStrlen(buff) |
|
448 |
270 |
+ 1 /* ')' */ |
|
449 |
270 |
+ 1, sizeof(char)); /* '\0' */ |
|
450 |
✗✓ | 270 |
if (!nout->content) { |
451 |
biffAddf(NRRD, "%s: couln't alloc output content!", me); |
||
452 |
airFree(buff); return 1; |
||
453 |
} |
||
454 |
270 |
sprintf(nout->content, "%s(%s%s%s)", func, content, |
|
455 |
airStrlen(buff) ? "," : "", buff); |
||
456 |
270 |
airFree(buff); /* no NULL assignment, else compile warnings */ |
|
457 |
270 |
return 0; |
|
458 |
270 |
} |
|
459 |
|||
460 |
int |
||
461 |
_nrrdContentSet_va(Nrrd *nout, const char *func, |
||
462 |
char *content, const char *format, ...) { |
||
463 |
static const char me[]="_nrrdContentSet_va"; |
||
464 |
34 |
va_list ap; |
|
465 |
|||
466 |
17 |
va_start(ap, format); |
|
467 |
✗✓ | 17 |
if (_nrrdContentSet_nva(nout, func, content, format, ap)) { |
468 |
biffAddf(NRRD, "%s:", me); |
||
469 |
free(content); return 1; |
||
470 |
} |
||
471 |
17 |
va_end(ap); |
|
472 |
|||
473 |
/* free(content); */ |
||
474 |
17 |
return 0; |
|
475 |
17 |
} |
|
476 |
|||
477 |
/* |
||
478 |
******** nrrdContentSet |
||
479 |
** |
||
480 |
** Kind of like sprintf, but for the content string of the nrrd. |
||
481 |
** |
||
482 |
** Whether or not we write a new content for an old nrrd ("nin") with |
||
483 |
** NULL content is decided here, according to |
||
484 |
** nrrdStateAlwaysSetContent. |
||
485 |
** |
||
486 |
** Does the string allocation and some attempts at error detection. |
||
487 |
** Does allow nout==nin, which requires some care. |
||
488 |
*/ |
||
489 |
int |
||
490 |
nrrdContentSet_va(Nrrd *nout, const char *func, |
||
491 |
const Nrrd *nin, const char *format, ...) { |
||
492 |
static const char me[]="nrrdContentSet_va"; |
||
493 |
506 |
va_list ap; |
|
494 |
char *content; |
||
495 |
|||
496 |
✗✓ | 253 |
if (!(nout && func && nin && format)) { |
497 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
498 |
return 1; |
||
499 |
} |
||
500 |
✗✓ | 253 |
if (nrrdStateDisableContent) { |
501 |
/* we kill content always */ |
||
502 |
nout->content = (char *)airFree(nout->content); |
||
503 |
return 0; |
||
504 |
} |
||
505 |
✗✓ | 253 |
if (!nin->content && !nrrdStateAlwaysSetContent) { |
506 |
/* there's no input content, and we're not supposed to invent any |
||
507 |
content, so after freeing nout's content we're done */ |
||
508 |
nout->content = (char *)airFree(nout->content); |
||
509 |
return 0; |
||
510 |
} |
||
511 |
/* we copy the input nrrd content first, before blowing away the |
||
512 |
output content, in case nout == nin */ |
||
513 |
253 |
content = _nrrdContentGet(nin); |
|
514 |
253 |
va_start(ap, format); |
|
515 |
✗✓ | 253 |
if (_nrrdContentSet_nva(nout, func, content, format, ap)) { |
516 |
biffAddf(NRRD, "%s:", me); |
||
517 |
va_end(ap); free(content); return 1; |
||
518 |
} |
||
519 |
253 |
va_end(ap); |
|
520 |
253 |
free(content); |
|
521 |
|||
522 |
253 |
return 0; |
|
523 |
253 |
} |
|
524 |
|||
525 |
/* |
||
526 |
******** nrrdDescribe |
||
527 |
** |
||
528 |
** writes verbose description of nrrd to given file |
||
529 |
*/ |
||
530 |
void |
||
531 |
nrrdDescribe(FILE *file, const Nrrd *nrrd) { |
||
532 |
unsigned int ai; |
||
533 |
char stmp[AIR_STRLEN_SMALL]; |
||
534 |
|||
535 |
if (file && nrrd) { |
||
536 |
fprintf(file, "Nrrd at 0x%p:\n", AIR_CVOIDP(nrrd)); |
||
537 |
fprintf(file, "Data at 0x%p is %s elements of type %s.\n", nrrd->data, |
||
538 |
airSprintSize_t(stmp, nrrdElementNumber(nrrd)), |
||
539 |
airEnumStr(nrrdType, nrrd->type)); |
||
540 |
if (nrrdTypeBlock == nrrd->type) { |
||
541 |
fprintf(file, "The blocks have size %s\n", |
||
542 |
airSprintSize_t(stmp, nrrd->blockSize)); |
||
543 |
} |
||
544 |
if (airStrlen(nrrd->content)) { |
||
545 |
fprintf(file, "Content = \"%s\"\n", nrrd->content); |
||
546 |
} |
||
547 |
fprintf(file, "%d-dimensional array, with axes:\n", nrrd->dim); |
||
548 |
for (ai=0; ai<nrrd->dim; ai++) { |
||
549 |
if (airStrlen(nrrd->axis[ai].label)) { |
||
550 |
fprintf(file, "%d: (\"%s\") ", ai, nrrd->axis[ai].label); |
||
551 |
} else { |
||
552 |
fprintf(file, "%d: ", ai); |
||
553 |
} |
||
554 |
fprintf(file, "%s-centered, size=%s, ", |
||
555 |
airEnumStr(nrrdCenter, nrrd->axis[ai].center), |
||
556 |
airSprintSize_t(stmp, nrrd->axis[ai].size)); |
||
557 |
airSinglePrintf(file, NULL, "spacing=%lg, \n", nrrd->axis[ai].spacing); |
||
558 |
airSinglePrintf(file, NULL, "thickness=%lg, \n", |
||
559 |
nrrd->axis[ai].thickness); |
||
560 |
airSinglePrintf(file, NULL, " axis(Min,Max) = (%lg,", |
||
561 |
nrrd->axis[ai].min); |
||
562 |
airSinglePrintf(file, NULL, "%lg)\n", nrrd->axis[ai].max); |
||
563 |
if (airStrlen(nrrd->axis[ai].units)) { |
||
564 |
fprintf(file, "units=%s, \n", nrrd->axis[ai].units); |
||
565 |
} |
||
566 |
} |
||
567 |
/* |
||
568 |
airSinglePrintf(file, NULL, "The min, max values are %lg", |
||
569 |
nrrd->min); |
||
570 |
airSinglePrintf(file, NULL, ", %lg\n", nrrd->max); |
||
571 |
*/ |
||
572 |
airSinglePrintf(file, NULL, "The old min, old max values are %lg", |
||
573 |
nrrd->oldMin); |
||
574 |
airSinglePrintf(file, NULL, ", %lg\n", nrrd->oldMax); |
||
575 |
/* fprintf(file, "hasNonExist = %d\n", nrrd->hasNonExist); */ |
||
576 |
if (nrrd->cmtArr->len) { |
||
577 |
fprintf(file, "Comments:\n"); |
||
578 |
for (ai=0; ai<nrrd->cmtArr->len; ai++) { |
||
579 |
fprintf(file, "%s\n", nrrd->cmt[ai]); |
||
580 |
} |
||
581 |
} |
||
582 |
fprintf(file, "\n"); |
||
583 |
} |
||
584 |
} |
||
585 |
|||
586 |
int |
||
587 |
nrrdSpaceVecExists(unsigned int sdim, const double vec[NRRD_SPACE_DIM_MAX]) { |
||
588 |
int exists; |
||
589 |
unsigned int ii; |
||
590 |
|||
591 |
exists = AIR_EXISTS(vec[0]); |
||
592 |
for (ii=1; ii<sdim; ii++) { |
||
593 |
exists &= AIR_EXISTS(vec[ii]); |
||
594 |
} |
||
595 |
return exists; |
||
596 |
} |
||
597 |
|||
598 |
/* |
||
599 |
** asserts all the properties associated with orientation information |
||
600 |
** |
||
601 |
** The most important part of this is asserting the per-axis mutual |
||
602 |
** exclusion of min/max/spacing/units versus using spaceDirection. |
||
603 |
*/ |
||
604 |
static int |
||
605 |
_nrrdFieldCheckSpaceInfo(const Nrrd *nrrd, int useBiff) { |
||
606 |
static const char me[]="_nrrdFieldCheckSpaceInfo"; |
||
607 |
unsigned int dd, ii; |
||
608 |
int exists; |
||
609 |
|||
610 |
✓✓✗✓ |
97312 |
if (!( !nrrd->space || !airEnumValCheck(nrrdSpace, nrrd->space) )) { |
611 |
biffMaybeAddf(useBiff, NRRD, "%s: space %d invalid", |
||
612 |
me, nrrd->space); |
||
613 |
return 1; |
||
614 |
} |
||
615 |
✗✓ | 33130 |
if (!( nrrd->spaceDim <= NRRD_SPACE_DIM_MAX )) { |
616 |
biffMaybeAddf(useBiff, NRRD, "%s: space dimension %d is outside " |
||
617 |
"valid range [0,NRRD_SPACE_DIM_MAX] = [0,%d]", |
||
618 |
me, nrrd->dim, NRRD_SPACE_DIM_MAX); |
||
619 |
return 1; |
||
620 |
} |
||
621 |
✓✓✓✓ |
66260 |
if (nrrd->spaceDim) { |
622 |
✓✓ | 65042 |
if (nrrd->space) { |
623 |
✗✓ | 31052 |
if (nrrdSpaceDimension(nrrd->space) != nrrd->spaceDim) { |
624 |
biffMaybeAddf(useBiff, NRRD, |
||
625 |
"%s: space %s has dimension %d but spaceDim is %d", |
||
626 |
me, airEnumStr(nrrdSpace, nrrd->space), |
||
627 |
nrrdSpaceDimension(nrrd->space), nrrd->spaceDim); |
||
628 |
return 1; |
||
629 |
} |
||
630 |
} |
||
631 |
/* check that all coeffs of spaceOrigin have consistent existance */ |
||
632 |
31912 |
exists = AIR_EXISTS(nrrd->spaceOrigin[0]); |
|
633 |
✓✓ | 255296 |
for (ii=0; ii<nrrd->spaceDim; ii++) { |
634 |
✗✓ | 95736 |
if (exists ^ AIR_EXISTS(nrrd->spaceOrigin[ii])) { |
635 |
biffMaybeAddf(useBiff, NRRD, |
||
636 |
"%s: existance of space origin coefficients must " |
||
637 |
"be consistent (val[0] not like val[%d])", me, ii); |
||
638 |
return 1; |
||
639 |
} |
||
640 |
} |
||
641 |
/* check that all coeffs of measurementFrame have consistent existance */ |
||
642 |
31912 |
exists = AIR_EXISTS(nrrd->measurementFrame[0][0]); |
|
643 |
✓✓ | 255296 |
for (dd=0; dd<nrrd->spaceDim; dd++) { |
644 |
✓✓ | 765888 |
for (ii=0; ii<nrrd->spaceDim; ii++) { |
645 |
✗✓ | 287208 |
if (exists ^ AIR_EXISTS(nrrd->measurementFrame[dd][ii])) { |
646 |
biffMaybeAddf(useBiff, NRRD, |
||
647 |
"%s: existance of measurement frame coefficients " |
||
648 |
"must be consistent: [col][row] [%d][%d] not " |
||
649 |
"like [0][0])", me, dd, ii); |
||
650 |
return 1; |
||
651 |
} |
||
652 |
} |
||
653 |
} |
||
654 |
/* check on space directions */ |
||
655 |
✓✓ | 260320 |
for (dd=0; dd<nrrd->dim; dd++) { |
656 |
98248 |
exists = AIR_EXISTS(nrrd->axis[dd].spaceDirection[0]); |
|
657 |
✓✓ | 589488 |
for (ii=1; ii<nrrd->spaceDim; ii++) { |
658 |
✗✓ | 196496 |
if (exists ^ AIR_EXISTS(nrrd->axis[dd].spaceDirection[ii])) { |
659 |
biffMaybeAddf(useBiff, NRRD, |
||
660 |
"%s: existance of space direction %d coefficients " |
||
661 |
"must be consistent (val[0] not like val[%d])", me, |
||
662 |
dd, ii); return 1; |
||
663 |
} |
||
664 |
} |
||
665 |
✓✓ | 98248 |
if (exists) { |
666 |
✗✓ | 191406 |
if (AIR_EXISTS(nrrd->axis[dd].min) |
667 |
✓✗ | 191406 |
|| AIR_EXISTS(nrrd->axis[dd].max) |
668 |
✓✗ | 191406 |
|| AIR_EXISTS(nrrd->axis[dd].spacing) |
669 |
✓✗ | 191406 |
|| !!airStrlen(nrrd->axis[dd].units)) { |
670 |
biffMaybeAddf(useBiff, NRRD, |
||
671 |
"%s: axis[%d] has a direction vector, and so can't " |
||
672 |
"have min, max, spacing, or units set", me, dd); |
||
673 |
return 1; |
||
674 |
} |
||
675 |
} |
||
676 |
} |
||
677 |
} else { |
||
678 |
/* else there's not supposed to be anything in "space" */ |
||
679 |
✗✓ | 1218 |
if (nrrd->space) { |
680 |
biffMaybeAddf(useBiff, NRRD, |
||
681 |
"%s: space %s can't be set with spaceDim %d", |
||
682 |
me, airEnumStr(nrrdSpace, nrrd->space), |
||
683 |
nrrd->spaceDim); |
||
684 |
return 1; |
||
685 |
} |
||
686 |
/* -------- */ |
||
687 |
exists = AIR_FALSE; |
||
688 |
✓✓ | 21924 |
for (dd=0; dd<NRRD_SPACE_DIM_MAX; dd++) { |
689 |
9744 |
exists |= !!airStrlen(nrrd->spaceUnits[dd]); |
|
690 |
} |
||
691 |
✗✓ | 1218 |
if (exists) { |
692 |
biffMaybeAddf(useBiff, NRRD, |
||
693 |
"%s: spaceDim is 0, but space units is set", me); |
||
694 |
return 1; |
||
695 |
} |
||
696 |
/* -------- */ |
||
697 |
exists = AIR_FALSE; |
||
698 |
✓✓ | 21924 |
for (dd=0; dd<NRRD_SPACE_DIM_MAX; dd++) { |
699 |
9744 |
exists |= AIR_EXISTS(nrrd->spaceOrigin[dd]); |
|
700 |
} |
||
701 |
✗✓ | 1218 |
if (exists) { |
702 |
biffMaybeAddf(useBiff, NRRD, |
||
703 |
"%s: spaceDim is 0, but space origin is set", me); |
||
704 |
return 1; |
||
705 |
} |
||
706 |
/* -------- */ |
||
707 |
exists = AIR_FALSE; |
||
708 |
✓✓ | 21924 |
for (dd=0; dd<NRRD_SPACE_DIM_MAX; dd++) { |
709 |
✓✓ | 331296 |
for (ii=0; ii<NRRD_DIM_MAX; ii++) { |
710 |
155904 |
exists |= AIR_EXISTS(nrrd->axis[ii].spaceDirection[dd]); |
|
711 |
} |
||
712 |
} |
||
713 |
✗✓ | 1218 |
if (exists) { |
714 |
biffMaybeAddf(useBiff, NRRD, |
||
715 |
"%s: spaceDim is 0, but space directions are set", me); |
||
716 |
return 1; |
||
717 |
} |
||
718 |
} |
||
719 |
33130 |
return 0; |
|
720 |
33130 |
} |
|
721 |
|||
722 |
/* --------------------- per-field checks ---------------- |
||
723 |
** |
||
724 |
** Strictly speacking, these checks only apply to the nrrd itself, not |
||
725 |
** to a potentially incomplete nrrd in the process of being read, so |
||
726 |
** the NrrdIoState stuff is not an issue. This limits the utility of |
||
727 |
** these to the field parsers for handling the more complex state |
||
728 |
** involved in parsing some of the NRRD fields (like units). |
||
729 |
** |
||
730 |
** return 0 if it is valid, and 1 if there is an error |
||
731 |
*/ |
||
732 |
|||
733 |
static int |
||
734 |
_nrrdFieldCheck_noop(const Nrrd *nrrd, int useBiff) { |
||
735 |
|||
736 |
AIR_UNUSED(nrrd); |
||
737 |
AIR_UNUSED(useBiff); |
||
738 |
72776 |
return 0; |
|
739 |
} |
||
740 |
|||
741 |
static int |
||
742 |
_nrrdFieldCheck_type(const Nrrd *nrrd, int useBiff) { |
||
743 |
static const char me[]="_nrrdFieldCheck_type"; |
||
744 |
|||
745 |
✗✓ | 6662 |
if (airEnumValCheck(nrrdType, nrrd->type)) { |
746 |
biffMaybeAddf(useBiff, NRRD, |
||
747 |
"%s: type (%d) is not valid", me, nrrd->type); |
||
748 |
return 1; |
||
749 |
} |
||
750 |
3331 |
return 0; |
|
751 |
3331 |
} |
|
752 |
|||
753 |
static int |
||
754 |
_nrrdFieldCheck_block_size(const Nrrd *nrrd, int useBiff) { |
||
755 |
static const char me[]="_nrrdFieldCheck_block_size"; |
||
756 |
6616 |
char stmp[AIR_STRLEN_SMALL]; |
|
757 |
|||
758 |
✗✓✗✗ |
3308 |
if (nrrdTypeBlock == nrrd->type && (!(0 < nrrd->blockSize)) ) { |
759 |
biffMaybeAddf(useBiff, NRRD, |
||
760 |
"%s: type is %s but nrrd->blockSize (%s) invalid", me, |
||
761 |
airEnumStr(nrrdType, nrrdTypeBlock), |
||
762 |
airSprintSize_t(stmp, nrrd->blockSize)); return 1; |
||
763 |
} |
||
764 |
✓✗✗✓ |
6616 |
if (nrrdTypeBlock != nrrd->type && (0 < nrrd->blockSize)) { |
765 |
biffMaybeAddf(useBiff, NRRD, |
||
766 |
"%s: type is %s (not block) but blockSize is %s", me, |
||
767 |
airEnumStr(nrrdType, nrrd->type), |
||
768 |
airSprintSize_t(stmp, nrrd->blockSize)); |
||
769 |
return 1; |
||
770 |
} |
||
771 |
3308 |
return 0; |
|
772 |
3308 |
} |
|
773 |
|||
774 |
static int |
||
775 |
_nrrdFieldCheck_dimension(const Nrrd *nrrd, int useBiff) { |
||
776 |
static const char me[]="_nrrdFieldCheck_dimension"; |
||
777 |
|||
778 |
✓✗✗✓ |
9993 |
if (!AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX)) { |
779 |
biffMaybeAddf(useBiff, NRRD, |
||
780 |
"%s: dimension %u is outside valid range [1,%d]", |
||
781 |
me, nrrd->dim, NRRD_DIM_MAX); |
||
782 |
return 1; |
||
783 |
} |
||
784 |
3331 |
return 0; |
|
785 |
3331 |
} |
|
786 |
|||
787 |
static int |
||
788 |
_nrrdFieldCheck_space(const Nrrd *nrrd, int useBiff) { |
||
789 |
static const char me[]="_nrrdFieldCheck_space"; |
||
790 |
|||
791 |
✗✓ | 6632 |
if (_nrrdFieldCheckSpaceInfo(nrrd, useBiff)) { |
792 |
biffMaybeAddf(useBiff, NRRD, "%s: trouble", me); |
||
793 |
return 1; |
||
794 |
} |
||
795 |
3316 |
return 0; |
|
796 |
3316 |
} |
|
797 |
|||
798 |
static int |
||
799 |
_nrrdFieldCheck_space_dimension(const Nrrd *nrrd, int useBiff) { |
||
800 |
static const char me[]="_nrrdFieldCheck_space_dimension"; |
||
801 |
|||
802 |
✗✓ | 6622 |
if (_nrrdFieldCheckSpaceInfo(nrrd, useBiff)) { |
803 |
biffMaybeAddf(useBiff, NRRD, "%s: trouble", me); |
||
804 |
return 1; |
||
805 |
} |
||
806 |
3311 |
return 0; |
|
807 |
3311 |
} |
|
808 |
|||
809 |
static int |
||
810 |
_nrrdFieldCheck_sizes(const Nrrd *nrrd, int useBiff) { |
||
811 |
static const char me[]="_nrrdFieldCheck_sizes"; |
||
812 |
6662 |
size_t size[NRRD_DIM_MAX]; |
|
813 |
|||
814 |
3331 |
nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoSize, size); |
|
815 |
✗✓ | 3331 |
if (_nrrdSizeCheck(size, nrrd->dim, useBiff)) { |
816 |
biffMaybeAddf(useBiff, NRRD, "%s: trouble with array sizes", me); |
||
817 |
return 1; |
||
818 |
} |
||
819 |
3331 |
return 0; |
|
820 |
3331 |
} |
|
821 |
|||
822 |
static int |
||
823 |
_nrrdFieldCheck_spacings(const Nrrd *nrrd, int useBiff) { |
||
824 |
static const char me[]="_nrrdFieldCheck_spacings"; |
||
825 |
6616 |
double val[NRRD_DIM_MAX]; |
|
826 |
unsigned int ai; |
||
827 |
|||
828 |
3308 |
nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoSpacing, val); |
|
829 |
✓✓ | 26722 |
for (ai=0; ai<nrrd->dim; ai++) { |
830 |
✓✗✗✓ ✗✗ |
20106 |
if (!( !airIsInf_d(val[ai]) && (airIsNaN(val[ai]) || (0 != val[ai])) )) { |
831 |
biffMaybeAddf(useBiff, NRRD, |
||
832 |
"%s: axis %d spacing (%g) invalid", me, ai, val[ai]); |
||
833 |
return 1; |
||
834 |
} |
||
835 |
} |
||
836 |
✗✓ | 3308 |
if (_nrrdFieldCheckSpaceInfo(nrrd, useBiff)) { |
837 |
biffMaybeAddf(useBiff, NRRD, "%s: trouble", me); |
||
838 |
return 1; |
||
839 |
} |
||
840 |
3308 |
return 0; |
|
841 |
3308 |
} |
|
842 |
|||
843 |
static int |
||
844 |
_nrrdFieldCheck_thicknesses(const Nrrd *nrrd, int useBiff) { |
||
845 |
static const char me[]="_nrrdFieldCheck_thicknesses"; |
||
846 |
6616 |
double val[NRRD_DIM_MAX]; |
|
847 |
unsigned int ai; |
||
848 |
|||
849 |
3308 |
nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoThickness, val); |
|
850 |
✓✓ | 26722 |
for (ai=0; ai<nrrd->dim; ai++) { |
851 |
/* note that unlike spacing, we allow zero thickness, |
||
852 |
but it makes no sense to be negative */ |
||
853 |
✓✗✗✓ ✗✗ |
20106 |
if (!( !airIsInf_d(val[ai]) && (airIsNaN(val[ai]) || (0 <= val[ai])) )) { |
854 |
biffMaybeAddf(useBiff, NRRD, |
||
855 |
"%s: axis %d thickness (%g) invalid", me, ai, val[ai]); |
||
856 |
return 1; |
||
857 |
} |
||
858 |
} |
||
859 |
3308 |
return 0; |
|
860 |
3308 |
} |
|
861 |
|||
862 |
static int |
||
863 |
_nrrdFieldCheck_axis_mins(const Nrrd *nrrd, int useBiff) { |
||
864 |
static const char me[]="_nrrdFieldCheck_axis_mins"; |
||
865 |
6624 |
double val[NRRD_DIM_MAX]; |
|
866 |
unsigned int ai; |
||
867 |
int ret; |
||
868 |
|||
869 |
3312 |
nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoMin, val); |
|
870 |
✓✓ | 26742 |
for (ai=0; ai<nrrd->dim; ai++) { |
871 |
✗✓ | 10059 |
if ((ret=airIsInf_d(val[ai]))) { |
872 |
biffMaybeAddf(useBiff, NRRD, "%s: axis %d min %sinf invalid", |
||
873 |
me, ai, 1==ret ? "+" : "-"); |
||
874 |
return 1; |
||
875 |
} |
||
876 |
} |
||
877 |
✗✓ | 3312 |
if (_nrrdFieldCheckSpaceInfo(nrrd, useBiff)) { |
878 |
biffMaybeAddf(useBiff, NRRD, "%s: trouble", me); |
||
879 |
return 1; |
||
880 |
} |
||
881 |
/* HEY: contemplate checking min != max, but what about stub axes ... */ |
||
882 |
3312 |
return 0; |
|
883 |
3312 |
} |
|
884 |
|||
885 |
static int |
||
886 |
_nrrdFieldCheck_axis_maxs(const Nrrd *nrrd, int useBiff) { |
||
887 |
static const char me[]="_nrrdFieldCheck_axis_maxs"; |
||
888 |
6624 |
double val[NRRD_DIM_MAX]; |
|
889 |
unsigned int ai; |
||
890 |
int ret; |
||
891 |
|||
892 |
3312 |
nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoMax, val); |
|
893 |
✓✓ | 26742 |
for (ai=0; ai<nrrd->dim; ai++) { |
894 |
✗✓ | 10059 |
if ((ret=airIsInf_d(val[ai]))) { |
895 |
biffMaybeAddf(useBiff, NRRD, "%s: axis %d max %sinf invalid", |
||
896 |
me, ai, 1==ret ? "+" : "-"); |
||
897 |
return 1; |
||
898 |
} |
||
899 |
} |
||
900 |
✗✓ | 3312 |
if (_nrrdFieldCheckSpaceInfo(nrrd, useBiff)) { |
901 |
biffMaybeAddf(useBiff, NRRD, "%s: trouble", me); |
||
902 |
return 1; |
||
903 |
} |
||
904 |
/* HEY: contemplate checking min != max, but what about stub axes ... */ |
||
905 |
3312 |
return 0; |
|
906 |
3312 |
} |
|
907 |
|||
908 |
static int |
||
909 |
_nrrdFieldCheck_space_directions(const Nrrd *nrrd, int useBiff) { |
||
910 |
static const char me[]="_nrrdFieldCheck_space_directions"; |
||
911 |
|||
912 |
✗✓ | 6638 |
if (_nrrdFieldCheckSpaceInfo(nrrd, useBiff)) { |
913 |
biffMaybeAddf(useBiff, NRRD, "%s: space info problem", me); |
||
914 |
return 1; |
||
915 |
} |
||
916 |
3319 |
return 0; |
|
917 |
3319 |
} |
|
918 |
|||
919 |
static int |
||
920 |
_nrrdFieldCheck_centers(const Nrrd *nrrd, int useBiff) { |
||
921 |
static const char me[]="_nrrdFieldCheck_centers"; |
||
922 |
unsigned int ai; |
||
923 |
6646 |
int val[NRRD_DIM_MAX]; |
|
924 |
|||
925 |
3323 |
nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoCenter, val); |
|
926 |
✓✓ | 26846 |
for (ai=0; ai<nrrd->dim; ai++) { |
927 |
✗✓ | 16973 |
if (!( nrrdCenterUnknown == val[ai] |
928 |
✓✓ | 16973 |
|| !airEnumValCheck(nrrdCenter, val[ai]) )) { |
929 |
biffMaybeAddf(useBiff, NRRD, "%s: axis %d center %d invalid", |
||
930 |
me, ai, val[ai]); |
||
931 |
return 1; |
||
932 |
} |
||
933 |
} |
||
934 |
3323 |
return 0; |
|
935 |
3323 |
} |
|
936 |
|||
937 |
static int |
||
938 |
_nrrdFieldCheck_kinds(const Nrrd *nrrd, int useBiff) { |
||
939 |
static const char me[]="_nrrdFieldCheck_kinds"; |
||
940 |
6616 |
int val[NRRD_DIM_MAX]; |
|
941 |
unsigned int wantLen, ai; |
||
942 |
|||
943 |
3308 |
nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoKind, val); |
|
944 |
✓✓ | 26722 |
for (ai=0; ai<nrrd->dim; ai++) { |
945 |
✗✓ | 16239 |
if (!( nrrdKindUnknown == val[ai] |
946 |
✓✓ | 16239 |
|| !airEnumValCheck(nrrdKind, val[ai]) )) { |
947 |
biffMaybeAddf(useBiff, NRRD, |
||
948 |
"%s: axis %d kind %d invalid", me, ai, val[ai]); |
||
949 |
return 1; |
||
950 |
} |
||
951 |
10053 |
wantLen = nrrdKindSize(val[ai]); |
|
952 |
✓✓✗✓ |
10149 |
if (wantLen && wantLen != nrrd->axis[ai].size) { |
953 |
char stmp[AIR_STRLEN_SMALL]; |
||
954 |
biffMaybeAddf(useBiff, NRRD, |
||
955 |
"%s: axis %d kind %s requires size %u, but have %s", me, |
||
956 |
ai, airEnumStr(nrrdKind, val[ai]), wantLen, |
||
957 |
airSprintSize_t(stmp, nrrd->axis[ai].size)); |
||
958 |
return 1; |
||
959 |
} |
||
960 |
} |
||
961 |
3308 |
return 0; |
|
962 |
3308 |
} |
|
963 |
|||
964 |
static int |
||
965 |
_nrrdFieldCheck_labels(const Nrrd *nrrd, int useBiff) { |
||
966 |
/* char me[]="_nrrdFieldCheck_labels"; */ |
||
967 |
|||
968 |
AIR_UNUSED(nrrd); |
||
969 |
AIR_UNUSED(useBiff); |
||
970 |
|||
971 |
/* don't think there's anything to do here: the label strings are |
||
972 |
either NULL (which is okay) or non-NULL, but we have no restrictions |
||
973 |
on the validity of the strings */ |
||
974 |
|||
975 |
6626 |
return 0; |
|
976 |
} |
||
977 |
|||
978 |
static int |
||
979 |
_nrrdFieldCheck_units(const Nrrd *nrrd, int useBiff) { |
||
980 |
static const char me[]="_nrrdFieldCheck_units"; |
||
981 |
|||
982 |
/* as with labels- the strings themselves don't need checking themselves */ |
||
983 |
/* but per-axis units cannot be set for axes with space directions ... */ |
||
984 |
✗✓ | 6616 |
if (_nrrdFieldCheckSpaceInfo(nrrd, useBiff)) { |
985 |
biffMaybeAddf(useBiff, NRRD, "%s: space info problem", me); |
||
986 |
return 1; |
||
987 |
} |
||
988 |
3308 |
return 0; |
|
989 |
3308 |
} |
|
990 |
|||
991 |
static int |
||
992 |
_nrrdFieldCheck_old_min(const Nrrd *nrrd, int useBiff) { |
||
993 |
static const char me[]="_nrrdFieldCheck_old_min"; |
||
994 |
int ret; |
||
995 |
|||
996 |
✗✓ | 6616 |
if ((ret=airIsInf_d(nrrd->oldMin))) { |
997 |
biffMaybeAddf(useBiff, NRRD, |
||
998 |
"%s: old min %sinf invalid", me, 1==ret ? "+" : "-"); |
||
999 |
return 1; |
||
1000 |
} |
||
1001 |
/* oldMin == oldMax is perfectly valid */ |
||
1002 |
3308 |
return 0; |
|
1003 |
3308 |
} |
|
1004 |
|||
1005 |
static int |
||
1006 |
_nrrdFieldCheck_old_max(const Nrrd *nrrd, int useBiff) { |
||
1007 |
static const char me[]="_nrrdFieldCheck_old_max"; |
||
1008 |
int ret; |
||
1009 |
|||
1010 |
✗✓ | 6616 |
if ((ret=airIsInf_d(nrrd->oldMax))) { |
1011 |
biffMaybeAddf(useBiff, NRRD, |
||
1012 |
"%s: old max %sinf invalid", me, 1==ret ? "+" : "-"); |
||
1013 |
return 1; |
||
1014 |
} |
||
1015 |
/* oldMin == oldMax is perfectly valid */ |
||
1016 |
3308 |
return 0; |
|
1017 |
3308 |
} |
|
1018 |
|||
1019 |
static int |
||
1020 |
_nrrdFieldCheck_keyvalue(const Nrrd *nrrd, int useBiff) { |
||
1021 |
/* char me[]="_nrrdFieldCheck_keyvalue"; */ |
||
1022 |
|||
1023 |
AIR_UNUSED(nrrd); |
||
1024 |
AIR_UNUSED(useBiff); |
||
1025 |
|||
1026 |
/* nrrdKeyValueAdd() ensures that keys aren't repeated, |
||
1027 |
not sure what other kind of checking can be done */ |
||
1028 |
|||
1029 |
6616 |
return 0; |
|
1030 |
} |
||
1031 |
|||
1032 |
static int |
||
1033 |
_nrrdFieldCheck_space_units(const Nrrd *nrrd, int useBiff) { |
||
1034 |
static const char me[]="_nrrdFieldCheck_space_units"; |
||
1035 |
|||
1036 |
/* not sure if there's anything to specifically check for the |
||
1037 |
space units themselves ... */ |
||
1038 |
✗✓ | 6618 |
if (_nrrdFieldCheckSpaceInfo(nrrd, useBiff)) { |
1039 |
biffMaybeAddf(useBiff, NRRD, "%s: space info problem", me); |
||
1040 |
return 1; |
||
1041 |
} |
||
1042 |
3309 |
return 0; |
|
1043 |
3309 |
} |
|
1044 |
|||
1045 |
static int |
||
1046 |
_nrrdFieldCheck_space_origin(const Nrrd *nrrd, int useBiff) { |
||
1047 |
static const char me[]="_nrrdFieldCheck_space_origin"; |
||
1048 |
|||
1049 |
/* pre-Fri Feb 11 04:25:36 EST 2005, I thought that |
||
1050 |
the spaceOrigin must be known to describe the |
||
1051 |
space/orientation stuff, but that's too restrictive, |
||
1052 |
which is why below says AIR_FALSE instead of AIR_TRUE */ |
||
1053 |
✗✓ | 6638 |
if (_nrrdFieldCheckSpaceInfo(nrrd, useBiff)) { |
1054 |
biffMaybeAddf(useBiff, NRRD, "%s: space info problem", me); |
||
1055 |
return 1; |
||
1056 |
} |
||
1057 |
3319 |
return 0; |
|
1058 |
3319 |
} |
|
1059 |
|||
1060 |
static int |
||
1061 |
_nrrdFieldCheck_measurement_frame(const Nrrd *nrrd, int useBiff) { |
||
1062 |
static const char me[]="_nrrdFieldCheck_measurement_frame"; |
||
1063 |
|||
1064 |
✗✓ | 6632 |
if (_nrrdFieldCheckSpaceInfo(nrrd, useBiff)) { |
1065 |
biffMaybeAddf(useBiff, NRRD, "%s: space info problem", me); |
||
1066 |
return 1; |
||
1067 |
} |
||
1068 |
3316 |
return 0; |
|
1069 |
3316 |
} |
|
1070 |
|||
1071 |
int |
||
1072 |
(*_nrrdFieldCheck[NRRD_FIELD_MAX+1])(const Nrrd *, int useBiff) = { |
||
1073 |
_nrrdFieldCheck_noop, /* nonfield */ |
||
1074 |
_nrrdFieldCheck_noop, /* comment */ |
||
1075 |
_nrrdFieldCheck_noop, /* content */ |
||
1076 |
_nrrdFieldCheck_noop, /* number */ |
||
1077 |
_nrrdFieldCheck_type, |
||
1078 |
_nrrdFieldCheck_block_size, |
||
1079 |
_nrrdFieldCheck_dimension, |
||
1080 |
_nrrdFieldCheck_space, |
||
1081 |
_nrrdFieldCheck_space_dimension, |
||
1082 |
_nrrdFieldCheck_sizes, |
||
1083 |
_nrrdFieldCheck_spacings, |
||
1084 |
_nrrdFieldCheck_thicknesses, |
||
1085 |
_nrrdFieldCheck_axis_mins, |
||
1086 |
_nrrdFieldCheck_axis_maxs, |
||
1087 |
_nrrdFieldCheck_space_directions, |
||
1088 |
_nrrdFieldCheck_centers, |
||
1089 |
_nrrdFieldCheck_kinds, |
||
1090 |
_nrrdFieldCheck_labels, |
||
1091 |
_nrrdFieldCheck_units, |
||
1092 |
_nrrdFieldCheck_noop, /* min */ |
||
1093 |
_nrrdFieldCheck_noop, /* max */ |
||
1094 |
_nrrdFieldCheck_old_min, |
||
1095 |
_nrrdFieldCheck_old_max, |
||
1096 |
_nrrdFieldCheck_noop, /* endian */ |
||
1097 |
_nrrdFieldCheck_noop, /* encoding */ |
||
1098 |
_nrrdFieldCheck_noop, /* line_skip */ |
||
1099 |
_nrrdFieldCheck_noop, /* byte_skip */ |
||
1100 |
_nrrdFieldCheck_keyvalue, |
||
1101 |
_nrrdFieldCheck_noop, /* sample units */ |
||
1102 |
_nrrdFieldCheck_space_units, |
||
1103 |
_nrrdFieldCheck_space_origin, |
||
1104 |
_nrrdFieldCheck_measurement_frame, |
||
1105 |
_nrrdFieldCheck_noop, /* data_file */ |
||
1106 |
}; |
||
1107 |
|||
1108 |
int |
||
1109 |
_nrrdCheck(const Nrrd *nrrd, int checkData, int useBiff) { |
||
1110 |
static const char me[]="_nrrdCheck"; |
||
1111 |
int fi; |
||
1112 |
|||
1113 |
✗✓ | 6616 |
if (!nrrd) { |
1114 |
biffMaybeAddf(useBiff, NRRD, "%s: got NULL pointer", me); |
||
1115 |
return 1; |
||
1116 |
} |
||
1117 |
✓✓ | 3308 |
if (checkData) { |
1118 |
✗✓ | 1201 |
if (!(nrrd->data)) { |
1119 |
biffMaybeAddf(useBiff, NRRD, "%s: nrrd %p has NULL data pointer", |
||
1120 |
me, AIR_CVOIDP(nrrd)); |
||
1121 |
return 1; |
||
1122 |
} |
||
1123 |
} |
||
1124 |
✓✓ | 218328 |
for (fi=nrrdField_unknown+1; fi<nrrdField_last; fi++) { |
1125 |
/* yes, this will call _nrrdFieldCheckSpaceInfo() many many times */ |
||
1126 |
✗✓ | 105856 |
if (_nrrdFieldCheck[fi](nrrd, AIR_TRUE)) { |
1127 |
biffMaybeAddf(useBiff, NRRD, "%s: trouble with %s field", me, |
||
1128 |
airEnumStr(nrrdField, fi)); |
||
1129 |
return 1; |
||
1130 |
} |
||
1131 |
} |
||
1132 |
3308 |
return 0; |
|
1133 |
3308 |
} |
|
1134 |
|||
1135 |
/* |
||
1136 |
******** nrrdCheck() |
||
1137 |
** |
||
1138 |
** does some consistency checks for things that can go wrong in a nrrd |
||
1139 |
** returns non-zero if there is a problem, zero if no problem. |
||
1140 |
** |
||
1141 |
** You might think that this should be merged with _nrrdHeaderCheck(), |
||
1142 |
** but that is really only for testing sufficiency of information |
||
1143 |
** required to do the data reading. |
||
1144 |
*/ |
||
1145 |
int /*Teem: biff if (ret) */ |
||
1146 |
nrrdCheck(const Nrrd *nrrd) { |
||
1147 |
static const char me[]="nrrdCheck"; |
||
1148 |
|||
1149 |
✗✓ | 2402 |
if (_nrrdCheck(nrrd, AIR_TRUE, AIR_TRUE)) { |
1150 |
biffAddf(NRRD, "%s: trouble", me); |
||
1151 |
return 1; |
||
1152 |
} |
||
1153 |
1201 |
return 0; |
|
1154 |
1201 |
} |
|
1155 |
|||
1156 |
/* |
||
1157 |
******** nrrdSameSize() |
||
1158 |
** |
||
1159 |
** returns 1 iff given two nrrds have same dimension and axes sizes. |
||
1160 |
** This does NOT look at the type of the elements. |
||
1161 |
** |
||
1162 |
** The intended user of this is someone who really wants the nrrds to be |
||
1163 |
** the same size, so that if they aren't, some descriptive (error) message |
||
1164 |
** can be generated according to useBiff |
||
1165 |
*/ |
||
1166 |
int /*Teem: biff?2 if (!ret) */ |
||
1167 |
nrrdSameSize(const Nrrd *n1, const Nrrd *n2, int useBiff) { |
||
1168 |
static const char me[]="nrrdSameSize"; |
||
1169 |
unsigned int ai; |
||
1170 |
2 |
char stmp[2][AIR_STRLEN_SMALL]; |
|
1171 |
|||
1172 |
✗✓ | 1 |
if (!(n1 && n2)) { |
1173 |
biffMaybeAddf(useBiff, NRRD, "%s: got NULL pointer", me); |
||
1174 |
return 0; |
||
1175 |
} |
||
1176 |
✗✓ | 1 |
if (n1->dim != n2->dim) { |
1177 |
biffMaybeAddf(useBiff, NRRD, "%s: n1->dim (%u) != n2->dim (%u)", |
||
1178 |
me, n1->dim, n2->dim); |
||
1179 |
return 0; |
||
1180 |
} |
||
1181 |
✓✓ | 8 |
for (ai=0; ai<n1->dim; ai++) { |
1182 |
✗✓ | 3 |
if (n1->axis[ai].size != n2->axis[ai].size) { |
1183 |
biffMaybeAddf(useBiff, NRRD, "%s: n1->axis[%d].size (%s) " |
||
1184 |
"!= n2->axis[%d].size (%s)", me, ai, |
||
1185 |
airSprintSize_t(stmp[0], n1->axis[ai].size), ai, |
||
1186 |
airSprintSize_t(stmp[1], n2->axis[ai].size)); |
||
1187 |
return 0; |
||
1188 |
} |
||
1189 |
} |
||
1190 |
1 |
return 1; |
|
1191 |
1 |
} |
|
1192 |
|||
1193 |
/* |
||
1194 |
******** nrrdElementSize() |
||
1195 |
** |
||
1196 |
** So just how many bytes long is one element in this nrrd? This is |
||
1197 |
** needed (over the simple nrrdTypeSize[] array) because some nrrds |
||
1198 |
** may be of "block" type, and because it does bounds checking on |
||
1199 |
** nrrd->type. Returns 0 if given a bogus nrrd->type, or if the block |
||
1200 |
** size isn't greater than zero (in which case it sets nrrd->blockSize |
||
1201 |
** to 0, just out of spite). This function never returns a negative |
||
1202 |
** value; using (!nrrdElementSize(nrrd)) is a sufficient check for |
||
1203 |
** invalidity. |
||
1204 |
** |
||
1205 |
** Besides learning how many bytes long one element is, this function |
||
1206 |
** is useful as a way of detecting an invalid blocksize on a block nrrd. |
||
1207 |
*/ |
||
1208 |
size_t |
||
1209 |
nrrdElementSize (const Nrrd *nrrd) { |
||
1210 |
|||
1211 |
✓✗✗✓ |
5199 |
if (!( nrrd && !airEnumValCheck(nrrdType, nrrd->type) )) { |
1212 |
return 0; |
||
1213 |
} |
||
1214 |
✓✗ | 1733 |
if (nrrdTypeBlock != nrrd->type) { |
1215 |
1733 |
return nrrdTypeSize[nrrd->type]; |
|
1216 |
} |
||
1217 |
/* else its block type */ |
||
1218 |
if (nrrd->blockSize > 0) { |
||
1219 |
return nrrd->blockSize; |
||
1220 |
} |
||
1221 |
/* else we got an invalid block size */ |
||
1222 |
/* nrrd->blockSize = 0; */ |
||
1223 |
return 0; |
||
1224 |
1733 |
} |
|
1225 |
|||
1226 |
/* |
||
1227 |
******** nrrdElementNumber() |
||
1228 |
** |
||
1229 |
** takes the place of old "nrrd->num": the number of elements in the |
||
1230 |
** nrrd, which is just the product of the axis sizes. A return of 0 |
||
1231 |
** means there's a problem. Negative numbers are never returned. |
||
1232 |
** |
||
1233 |
** does NOT use biff |
||
1234 |
*/ |
||
1235 |
size_t |
||
1236 |
nrrdElementNumber (const Nrrd *nrrd) { |
||
1237 |
2106 |
size_t num, size[NRRD_DIM_MAX]; |
|
1238 |
unsigned int ai; |
||
1239 |
|||
1240 |
✗✓ | 1053 |
if (!nrrd) { |
1241 |
return 0; |
||
1242 |
} |
||
1243 |
/* else */ |
||
1244 |
1053 |
nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoSize, size); |
|
1245 |
✗✓ | 1053 |
if (_nrrdSizeCheck(size, nrrd->dim, AIR_FALSE)) { |
1246 |
/* the nrrd's size information is invalid, can't proceed */ |
||
1247 |
return 0; |
||
1248 |
} |
||
1249 |
num = 1; |
||
1250 |
✓✓ | 7640 |
for (ai=0; ai<nrrd->dim; ai++) { |
1251 |
/* negative numbers and overflow were caught by _nrrdSizeCheck() */ |
||
1252 |
2767 |
num *= size[ai]; |
|
1253 |
} |
||
1254 |
1053 |
return num; |
|
1255 |
1053 |
} |
|
1256 |
|||
1257 |
/* |
||
1258 |
** obviously, this requires that the per-axis size fields have been set |
||
1259 |
*/ |
||
1260 |
void |
||
1261 |
_nrrdSplitSizes(size_t *pieceSize, size_t *pieceNum, Nrrd *nrrd, |
||
1262 |
unsigned int split) { |
||
1263 |
unsigned int ai; |
||
1264 |
size_t size[NRRD_DIM_MAX]; |
||
1265 |
|||
1266 |
nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoSize, size); |
||
1267 |
*pieceSize = 1; |
||
1268 |
for (ai=0; ai<split; ai++) { |
||
1269 |
*pieceSize *= size[ai]; |
||
1270 |
} |
||
1271 |
*pieceNum = 1; |
||
1272 |
for (ai=split; ai<nrrd->dim; ai++) { |
||
1273 |
*pieceNum *= size[ai]; |
||
1274 |
} |
||
1275 |
return; |
||
1276 |
} |
||
1277 |
|||
1278 |
/* |
||
1279 |
******** nrrdHasNonExistSet() |
||
1280 |
** |
||
1281 |
** This function will always (assuming type is valid) set the value of |
||
1282 |
** nrrd->hasNonExist to either nrrdNonExistTrue or nrrdNonExistFalse, |
||
1283 |
** and it will return that value. For lack of a more sophisticated |
||
1284 |
** policy, blocks are currently always considered to be existent |
||
1285 |
** values (because nrrdTypeIsIntegral[nrrdTypeBlock] is currently true). |
||
1286 |
** This function will ALWAYS determine the correct answer and set the |
||
1287 |
** value of nrrd->hasNonExist: it ignores the value of |
||
1288 |
** nrrd->hasNonExist on the input nrrd. Exception: if nrrd is null or |
||
1289 |
** type is bogus, no action is taken and nrrdNonExistUnknown is |
||
1290 |
** returned. |
||
1291 |
** |
||
1292 |
** Because this will return either nrrdNonExistTrue or nrrdNonExistFalse, |
||
1293 |
** and because the C boolean value of these are true and false (respectively), |
||
1294 |
** it is possible (and encouraged) to use the return of this function |
||
1295 |
** as the expression of a conditional: |
||
1296 |
** |
||
1297 |
** if (nrrdHasNonExistSet(nrrd)) { |
||
1298 |
** ... handle existance of non-existent values ... |
||
1299 |
** } |
||
1300 |
*/ |
||
1301 |
/* |
||
1302 |
int |
||
1303 |
nrrdHasNonExistSet(Nrrd *nrrd) { |
||
1304 |
size_t I, N; |
||
1305 |
float val; |
||
1306 |
|||
1307 |
if (!( nrrd && !airEnumValCheck(nrrdType, nrrd->type) )) |
||
1308 |
return nrrdNonExistUnknown; |
||
1309 |
|||
1310 |
if (nrrdTypeIsIntegral[nrrd->type]) { |
||
1311 |
nrrd->hasNonExist = nrrdNonExistFalse; |
||
1312 |
} else { |
||
1313 |
nrrd->hasNonExist = nrrdNonExistFalse; |
||
1314 |
N = nrrdElementNumber(nrrd); |
||
1315 |
for (I=0; I<N; I++) { |
||
1316 |
val = nrrdFLookup[nrrd->type](nrrd->data, I); |
||
1317 |
if (!AIR_EXISTS(val)) { |
||
1318 |
nrrd->hasNonExist = nrrdNonExistTrue; |
||
1319 |
break; |
||
1320 |
} |
||
1321 |
} |
||
1322 |
} |
||
1323 |
return nrrd->hasNonExist; |
||
1324 |
} |
||
1325 |
*/ |
||
1326 |
|||
1327 |
static int |
||
1328 |
_nrrdCheckEnums(void) { |
||
1329 |
static const char me[]="_nrrdCheckEnums"; |
||
1330 |
char which[AIR_STRLEN_SMALL]; |
||
1331 |
|||
1332 |
if (nrrdFormatTypeLast-1 != NRRD_FORMAT_TYPE_MAX) { |
||
1333 |
strcpy(which, "nrrdFormat"); goto err; |
||
1334 |
} |
||
1335 |
if (nrrdTypeLast-1 != NRRD_TYPE_MAX) { |
||
1336 |
strcpy(which, "nrrdType"); goto err; |
||
1337 |
} |
||
1338 |
if (nrrdEncodingTypeLast-1 != NRRD_ENCODING_TYPE_MAX) { |
||
1339 |
strcpy(which, "nrrdEncodingType"); goto err; |
||
1340 |
} |
||
1341 |
if (nrrdCenterLast-1 != NRRD_CENTER_MAX) { |
||
1342 |
strcpy(which, "nrrdCenter"); goto err; |
||
1343 |
} |
||
1344 |
if (nrrdAxisInfoLast-1 != NRRD_AXIS_INFO_MAX) { |
||
1345 |
strcpy(which, "nrrdAxisInfo"); goto err; |
||
1346 |
} |
||
1347 |
/* can't really check on endian enum */ |
||
1348 |
if (nrrdField_last-1 != NRRD_FIELD_MAX) { |
||
1349 |
strcpy(which, "nrrdField"); goto err; |
||
1350 |
} |
||
1351 |
if (nrrdHasNonExistLast-1 != NRRD_HAS_NON_EXIST_MAX) { |
||
1352 |
strcpy(which, "nrrdHasNonExist"); goto err; |
||
1353 |
} |
||
1354 |
/* ---- BEGIN non-NrrdIO */ |
||
1355 |
if (nrrdBoundaryLast-1 != NRRD_BOUNDARY_MAX) { |
||
1356 |
strcpy(which, "nrrdBoundary"); goto err; |
||
1357 |
} |
||
1358 |
if (nrrdMeasureLast-1 != NRRD_MEASURE_MAX) { |
||
1359 |
strcpy(which, "nrrdMeasure"); goto err; |
||
1360 |
} |
||
1361 |
if (nrrdUnaryOpLast-1 != NRRD_UNARY_OP_MAX) { |
||
1362 |
strcpy(which, "nrrdUnaryOp"); goto err; |
||
1363 |
} |
||
1364 |
if (nrrdBinaryOpLast-1 != NRRD_BINARY_OP_MAX) { |
||
1365 |
strcpy(which, "nrrdBinaryOp"); goto err; |
||
1366 |
} |
||
1367 |
if (nrrdTernaryOpLast-1 != NRRD_TERNARY_OP_MAX) { |
||
1368 |
strcpy(which, "nrrdTernaryOp"); goto err; |
||
1369 |
} |
||
1370 |
/* ---- END non-NrrdIO */ |
||
1371 |
|||
1372 |
/* no errors so far */ |
||
1373 |
return 0; |
||
1374 |
|||
1375 |
err: |
||
1376 |
biffAddf(NRRD, "%s: Last vs. MAX incompatibility for %s enum", me, which); |
||
1377 |
return 1; |
||
1378 |
40 |
} |
|
1379 |
|||
1380 |
/* |
||
1381 |
****** nrrdSanity |
||
1382 |
** |
||
1383 |
** makes sure that all the basic assumptions of nrrd hold for |
||
1384 |
** the architecture/etc which we're currently running on. |
||
1385 |
** |
||
1386 |
** returns 1 if all is okay, 0 if there is a problem |
||
1387 |
*/ |
||
1388 |
int /*Teem: biff if (!ret) */ |
||
1389 |
nrrdSanity(void) { |
||
1390 |
static const char me[]="nrrdSanity"; |
||
1391 |
int aret, type; |
||
1392 |
size_t maxsize; |
||
1393 |
airLLong tmpLLI; |
||
1394 |
airULLong tmpULLI; |
||
1395 |
static int _nrrdSanity = 0; |
||
1396 |
|||
1397 |
✓✓ | 54 |
if (_nrrdSanity) { |
1398 |
/* we've been through this once before and things looked okay ... */ |
||
1399 |
/* Is this thread-safe? I think so. If we assume that any two |
||
1400 |
threads are going to compute the same value, isn't it the case |
||
1401 |
that, at worse, both of them will go through all the tests and |
||
1402 |
then set _nrrdSanity to the same thing? */ |
||
1403 |
7 |
return 1; |
|
1404 |
} |
||
1405 |
|||
1406 |
20 |
aret = airSanity(); |
|
1407 |
✗✓ | 20 |
if (aret != airInsane_not) { |
1408 |
biffAddf(NRRD, "%s: airSanity() failed: %s", me, |
||
1409 |
airInsaneErr(aret)); |
||
1410 |
return 0; |
||
1411 |
} |
||
1412 |
|||
1413 |
/* ---- BEGIN non-NrrdIO */ |
||
1414 |
/* Odd: this sanity checker isn't part of airSanity, nor can it be |
||
1415 |
without adding to airInsaneErr's list of what can go wrong, but |
||
1416 |
someone should be calling it, since we have no other correctness |
||
1417 |
test of the Mersenne-Twister code within Teem (not counting the |
||
1418 |
CTests in teem/Testing) */ |
||
1419 |
✗✓ | 20 |
if (!airRandMTSanity()) { |
1420 |
biffAddf(NRRD, "%s: airRandMTSanity failed", me); |
||
1421 |
return 0; |
||
1422 |
} |
||
1423 |
/* ---- END non-NrrdIO */ |
||
1424 |
|||
1425 |
✗✓ | 20 |
if (airEnumValCheck(nrrdEncodingType, nrrdDefaultWriteEncodingType)) { |
1426 |
biffAddf(NRRD, |
||
1427 |
"%s: nrrdDefaultWriteEncodingType (%d) not in valid " |
||
1428 |
"range [%d,%d]", me, nrrdDefaultWriteEncodingType, |
||
1429 |
nrrdEncodingTypeUnknown+1, nrrdEncodingTypeLast-1); |
||
1430 |
return 0; |
||
1431 |
} |
||
1432 |
✗✓ | 20 |
if (airEnumValCheck(nrrdCenter, nrrdDefaultCenter)) { |
1433 |
biffAddf(NRRD, |
||
1434 |
"%s: nrrdDefaultCenter (%d) not in valid range [%d,%d]", |
||
1435 |
me, nrrdDefaultCenter, |
||
1436 |
nrrdCenterUnknown+1, nrrdCenterLast-1); |
||
1437 |
return 0; |
||
1438 |
} |
||
1439 |
/* ---- BEGIN non-NrrdIO */ |
||
1440 |
✗✗ | 20 |
if (!( nrrdTypeDefault == nrrdDefaultResampleType |
1441 |
✗✓ | 20 |
|| !airEnumValCheck(nrrdType, nrrdDefaultResampleType) )) { |
1442 |
biffAddf(NRRD, |
||
1443 |
"%s: nrrdDefaultResampleType (%d) not in valid range [%d,%d]", |
||
1444 |
me, nrrdDefaultResampleType, |
||
1445 |
nrrdTypeUnknown, nrrdTypeLast-1); |
||
1446 |
return 0; |
||
1447 |
} |
||
1448 |
✗✓ | 20 |
if (airEnumValCheck(nrrdBoundary, nrrdDefaultResampleBoundary)) { |
1449 |
biffAddf(NRRD, "%s: nrrdDefaultResampleBoundary (%d) " |
||
1450 |
"not in valid range [%d,%d]", |
||
1451 |
me, nrrdDefaultResampleBoundary, |
||
1452 |
nrrdBoundaryUnknown+1, nrrdBoundaryLast-1); |
||
1453 |
return 0; |
||
1454 |
} |
||
1455 |
✗✓ | 20 |
if (airEnumValCheck(nrrdType, nrrdStateMeasureType)) { |
1456 |
biffAddf(NRRD, |
||
1457 |
"%s: nrrdStateMeasureType (%d) not in valid range [%d,%d]", |
||
1458 |
me, nrrdStateMeasureType, |
||
1459 |
nrrdTypeUnknown+1, nrrdTypeLast-1); |
||
1460 |
return 0; |
||
1461 |
} |
||
1462 |
✗✓ | 20 |
if (airEnumValCheck(nrrdType, nrrdStateMeasureHistoType)) { |
1463 |
biffAddf(NRRD, |
||
1464 |
"%s: nrrdStateMeasureHistoType (%d) not in " |
||
1465 |
"valid range [%d,%d]", me, nrrdStateMeasureType, |
||
1466 |
nrrdTypeUnknown+1, nrrdTypeLast-1); |
||
1467 |
return 0; |
||
1468 |
} |
||
1469 |
/* ---- END non-NrrdIO */ |
||
1470 |
|||
1471 |
20 |
if (!( nrrdTypeSize[nrrdTypeChar] == sizeof(char) |
|
1472 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓ |
180 |
&& nrrdTypeSize[nrrdTypeUChar] == sizeof(unsigned char) |
1473 |
20 |
&& nrrdTypeSize[nrrdTypeShort] == sizeof(short) |
|
1474 |
20 |
&& nrrdTypeSize[nrrdTypeUShort] == sizeof(unsigned short) |
|
1475 |
20 |
&& nrrdTypeSize[nrrdTypeInt] == sizeof(int) |
|
1476 |
20 |
&& nrrdTypeSize[nrrdTypeUInt] == sizeof(unsigned int) |
|
1477 |
20 |
&& nrrdTypeSize[nrrdTypeLLong] == sizeof(airLLong) |
|
1478 |
20 |
&& nrrdTypeSize[nrrdTypeULLong] == sizeof(airULLong) |
|
1479 |
20 |
&& nrrdTypeSize[nrrdTypeFloat] == sizeof(float) |
|
1480 |
20 |
&& nrrdTypeSize[nrrdTypeDouble] == sizeof(double) )) { |
|
1481 |
biffAddf(NRRD, "%s: sizeof() for nrrd types has problem: " |
||
1482 |
"expected (%u,%u,%u,%u,%u,%u,%u,%u,%u,%u) " |
||
1483 |
"but got (%u,%u,%u,%u,%u,%u,%u,%u,%u,%u)", me, |
||
1484 |
AIR_CAST(unsigned int, nrrdTypeSize[nrrdTypeChar]), |
||
1485 |
AIR_CAST(unsigned int, nrrdTypeSize[nrrdTypeUChar]), |
||
1486 |
AIR_CAST(unsigned int, nrrdTypeSize[nrrdTypeShort]), |
||
1487 |
AIR_CAST(unsigned int, nrrdTypeSize[nrrdTypeUShort]), |
||
1488 |
AIR_CAST(unsigned int, nrrdTypeSize[nrrdTypeInt]), |
||
1489 |
AIR_CAST(unsigned int, nrrdTypeSize[nrrdTypeUInt]), |
||
1490 |
AIR_CAST(unsigned int, nrrdTypeSize[nrrdTypeLLong]), |
||
1491 |
AIR_CAST(unsigned int, nrrdTypeSize[nrrdTypeULLong]), |
||
1492 |
AIR_CAST(unsigned int, nrrdTypeSize[nrrdTypeFloat]), |
||
1493 |
AIR_CAST(unsigned int, nrrdTypeSize[nrrdTypeDouble]), |
||
1494 |
AIR_CAST(unsigned int, sizeof(char)), |
||
1495 |
AIR_CAST(unsigned int, sizeof(unsigned char)), |
||
1496 |
AIR_CAST(unsigned int, sizeof(short)), |
||
1497 |
AIR_CAST(unsigned int, sizeof(unsigned short)), |
||
1498 |
AIR_CAST(unsigned int, sizeof(int)), |
||
1499 |
AIR_CAST(unsigned int, sizeof(unsigned int)), |
||
1500 |
AIR_CAST(unsigned int, sizeof(airLLong)), |
||
1501 |
AIR_CAST(unsigned int, sizeof(airULLong)), |
||
1502 |
AIR_CAST(unsigned int, sizeof(float)), |
||
1503 |
AIR_CAST(unsigned int, sizeof(double))); |
||
1504 |
return 0; |
||
1505 |
} |
||
1506 |
|||
1507 |
/* check on NRRD_TYPE_SIZE_MAX */ |
||
1508 |
maxsize = 0; |
||
1509 |
✓✓ | 440 |
for (type=nrrdTypeUnknown+1; type<=nrrdTypeLast-2; type++) { |
1510 |
✓✓ | 600 |
maxsize = AIR_MAX(maxsize, nrrdTypeSize[type]); |
1511 |
} |
||
1512 |
✗✓ | 20 |
if (maxsize != NRRD_TYPE_SIZE_MAX) { |
1513 |
biffAddf(NRRD, |
||
1514 |
"%s: actual max type size is %u != %u == NRRD_TYPE_SIZE_MAX", |
||
1515 |
me, AIR_CAST(unsigned int, maxsize), NRRD_TYPE_SIZE_MAX); |
||
1516 |
return 0; |
||
1517 |
} |
||
1518 |
|||
1519 |
/* check on NRRD_TYPE_BIGGEST */ |
||
1520 |
✗✓ | 20 |
if (maxsize != sizeof(NRRD_TYPE_BIGGEST)) { |
1521 |
biffAddf(NRRD, "%s: actual max type size is %u != " |
||
1522 |
"%u == sizeof(NRRD_TYPE_BIGGEST)", |
||
1523 |
me, AIR_CAST(unsigned int, maxsize), |
||
1524 |
AIR_CAST(unsigned int, sizeof(NRRD_TYPE_BIGGEST))); |
||
1525 |
return 0; |
||
1526 |
} |
||
1527 |
|||
1528 |
/* nrrd-defined min/max values for 64-bit integral types */ |
||
1529 |
/* NOTE: because signed integral overflow is undefined in C, the tests for |
||
1530 |
signed long long no longer use overflow (and an assumption of two's |
||
1531 |
complement representation) to assess the correctness of NRRD_LLONG_MAX |
||
1532 |
and NRRD_LLONG_MIN. We merely test that these values can be stored, |
||
1533 |
which we do via indirect (perhaps needlessly so) means. |
||
1534 |
(h/t Sean McBride for pointing this out) */ |
||
1535 |
20 |
tmpLLI = _nrrdLLongMaxHelp(_nrrdLLongMaxHelp(_NRRD_LLONG_MAX_HELP)); |
|
1536 |
✗✓ | 20 |
if (!( tmpLLI > 0 && NRRD_LLONG_MAX == tmpLLI )) { |
1537 |
biffAddf(NRRD, "%s: long long int can't hold NRRD_LLONG_MAX (" |
||
1538 |
AIR_LLONG_FMT ")", me, |
||
1539 |
NRRD_LLONG_MAX); |
||
1540 |
return 0; |
||
1541 |
} |
||
1542 |
20 |
tmpLLI = _nrrdLLongMinHelp(_nrrdLLongMinHelp(_NRRD_LLONG_MIN_HELP)); |
|
1543 |
✗✓ | 20 |
if (!( tmpLLI < 0 && NRRD_LLONG_MIN == tmpLLI )) { |
1544 |
biffAddf(NRRD, "%s: long long int can't hold NRRD_LLONG_MIN (" |
||
1545 |
AIR_LLONG_FMT ")", me, |
||
1546 |
NRRD_LLONG_MIN); |
||
1547 |
return 0; |
||
1548 |
} |
||
1549 |
20 |
tmpULLI = _nrrdULLongMaxHelp(NRRD_ULLONG_MAX); |
|
1550 |
✗✓ | 20 |
if (tmpULLI != 0) { |
1551 |
biffAddf(NRRD, |
||
1552 |
"%s: unsigned long long int max (" AIR_ULLONG_FMT |
||
1553 |
") incorrect", me, NRRD_ULLONG_MAX); |
||
1554 |
return 0; |
||
1555 |
} |
||
1556 |
|||
1557 |
✗✓ | 20 |
if (_nrrdCheckEnums()) { |
1558 |
biffAddf(NRRD, "%s: problem with enum definition", me); |
||
1559 |
return 0; |
||
1560 |
} |
||
1561 |
|||
1562 |
if (!( NRRD_DIM_MAX >= 3 )) { |
||
1563 |
biffAddf(NRRD, |
||
1564 |
"%s: NRRD_DIM_MAX == %u seems awfully small, doesn't it?", |
||
1565 |
me, NRRD_DIM_MAX); |
||
1566 |
return 0; |
||
1567 |
} |
||
1568 |
|||
1569 |
✗✓ | 20 |
if (!nrrdTypeIsIntegral[nrrdTypeBlock]) { |
1570 |
biffAddf(NRRD, |
||
1571 |
"%s: nrrdTypeInteger[nrrdTypeBlock] is not true, things " |
||
1572 |
"could get wacky", me); |
||
1573 |
return 0; |
||
1574 |
} |
||
1575 |
|||
1576 |
/* HEY: any other assumptions built into Teem? */ |
||
1577 |
|||
1578 |
20 |
_nrrdSanity = 1; |
|
1579 |
20 |
return 1; |
|
1580 |
27 |
} |
|
1581 |
|||
1582 |
/* ---- BEGIN non-NrrdIO */ |
||
1583 |
|||
1584 |
void |
||
1585 |
nrrdSanityOrDie(const char *me) { |
||
1586 |
char *err; |
||
1587 |
|||
1588 |
if (!nrrdSanity()) { |
||
1589 |
fprintf(stderr, "******************************************\n"); |
||
1590 |
fprintf(stderr, "******************************************\n"); |
||
1591 |
fprintf(stderr, "\n"); |
||
1592 |
fprintf(stderr, " %s: Nrrd sanity check failed.\n", me); |
||
1593 |
fprintf(stderr, "\n"); |
||
1594 |
fprintf(stderr, " This probably means that there was an error\n"); |
||
1595 |
fprintf(stderr, " in the configuration, compilation, or basic\n"); |
||
1596 |
fprintf(stderr, " variable definitions used for building Teem.\n"); |
||
1597 |
fprintf(stderr, " Error message:\n"); |
||
1598 |
fprintf(stderr, "%s\n", err = biffGetDone(NRRD)); |
||
1599 |
fprintf(stderr, "\n"); |
||
1600 |
fprintf(stderr, "******************************************\n"); |
||
1601 |
fprintf(stderr, "******************************************\n"); |
||
1602 |
free(err); |
||
1603 |
exit(1); |
||
1604 |
} |
||
1605 |
} |
||
1606 |
|||
1607 |
void |
||
1608 |
nrrdSetZero(Nrrd *nout) { |
||
1609 |
|||
1610 |
if (!_nrrdCheck(nout, AIR_TRUE, AIR_FALSE)) { |
||
1611 |
memset(nout->data, 0, nrrdElementNumber(nout)*nrrdElementSize(nout)); |
||
1612 |
} |
||
1613 |
return; |
||
1614 |
} |
||
1615 |
|||
1616 |
void |
||
1617 |
nrrdSetNaN(Nrrd *nout) { |
||
1618 |
|||
1619 |
if (_nrrdCheck(nout, AIR_TRUE, AIR_FALSE)) { |
||
1620 |
/* bad nrrd, oh well */ |
||
1621 |
return; |
||
1622 |
} |
||
1623 |
/* HEY if Half is ever added we'll have to check for it here */ |
||
1624 |
size_t II, NN = nrrdElementNumber(nout); |
||
1625 |
if (nrrdTypeFloat == nout->type) { |
||
1626 |
float *ff = AIR_CAST(float *, nout->data); |
||
1627 |
for (II=0; II<NN; II++) { |
||
1628 |
ff[II] = AIR_NAN; |
||
1629 |
} |
||
1630 |
} else if (nrrdTypeDouble == nout->type) { |
||
1631 |
double *dd = AIR_CAST(double *, nout->data); |
||
1632 |
for (II=0; II<NN; II++) { |
||
1633 |
dd[II] = AIR_NAN; |
||
1634 |
} |
||
1635 |
} |
||
1636 |
return; |
||
1637 |
} |
||
1638 |
/* ---- END non-NrrdIO */ |
Generated by: GCOVR (Version 3.3) |