GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
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 |
#include "nrrd.h" |
||
25 |
#include "privateNrrd.h" |
||
26 |
|||
27 |
/* |
||
28 |
#include <sys/types.h> |
||
29 |
#include <unistd.h> |
||
30 |
*/ |
||
31 |
|||
32 |
int |
||
33 |
nrrdIoStateSet(NrrdIoState *nio, int parm, int value) { |
||
34 |
static const char me[]="nrrdIoStateSet"; |
||
35 |
|||
36 |
if (!nio) { |
||
37 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
38 |
return 1; |
||
39 |
} |
||
40 |
if (!( AIR_IN_OP(nrrdIoStateUnknown, parm, nrrdIoStateLast) )) { |
||
41 |
biffAddf(NRRD, "%s: identifier %d not in valid range [%d,%d]", me, |
||
42 |
parm, nrrdIoStateUnknown+1, nrrdIoStateLast-1); |
||
43 |
return 1; |
||
44 |
} |
||
45 |
switch (parm) { |
||
46 |
case nrrdIoStateDetachedHeader: |
||
47 |
nio->detachedHeader = !!value; |
||
48 |
break; |
||
49 |
case nrrdIoStateBareText: |
||
50 |
nio->bareText = !!value; |
||
51 |
break; |
||
52 |
case nrrdIoStateCharsPerLine: |
||
53 |
if (value < 40) { |
||
54 |
biffAddf(NRRD, "%s: %d charsPerLine is awfully small", me, value); |
||
55 |
return 1; |
||
56 |
} |
||
57 |
/* cast won't lose info because "value" must be positive */ |
||
58 |
nio->charsPerLine = AIR_CAST(unsigned int, value); |
||
59 |
break; |
||
60 |
case nrrdIoStateValsPerLine: |
||
61 |
if (value < 4) { |
||
62 |
biffAddf(NRRD, "%s: %d valsPerLine is awfully small", me, value); |
||
63 |
return 1; |
||
64 |
} |
||
65 |
/* cast won't lose info because "value" must be positive */ |
||
66 |
nio->valsPerLine = AIR_CAST(unsigned int, value); |
||
67 |
break; |
||
68 |
case nrrdIoStateSkipData: |
||
69 |
nio->skipData = !!value; |
||
70 |
break; |
||
71 |
case nrrdIoStateKeepNrrdDataFileOpen: |
||
72 |
nio->keepNrrdDataFileOpen = !!value; |
||
73 |
break; |
||
74 |
case nrrdIoStateZlibLevel: |
||
75 |
if (!( AIR_IN_CL(-1, value, 9) )) { |
||
76 |
biffAddf(NRRD, "%s: zlibLevel %d invalid", me, value); |
||
77 |
return 1; |
||
78 |
} |
||
79 |
nio->zlibLevel = value; |
||
80 |
break; |
||
81 |
case nrrdIoStateZlibStrategy: |
||
82 |
if (!( AIR_IN_OP(nrrdZlibStrategyUnknown, value, nrrdZlibStrategyLast) )) { |
||
83 |
biffAddf(NRRD, "%s: zlibStrategy %d invalid", me, value); |
||
84 |
return 1; |
||
85 |
} |
||
86 |
nio->zlibStrategy = value; |
||
87 |
break; |
||
88 |
case nrrdIoStateBzip2BlockSize: |
||
89 |
if (!( AIR_IN_CL(-1, value, 9) )) { |
||
90 |
biffAddf(NRRD, "%s: bzip2BlockSize %d invalid", me, value); |
||
91 |
return 1; |
||
92 |
} |
||
93 |
nio->bzip2BlockSize = value; |
||
94 |
break; |
||
95 |
default: |
||
96 |
fprintf(stderr, "!%s: PANIC: didn't recognize parm %d\n", me, parm); |
||
97 |
return 1; |
||
98 |
} |
||
99 |
return 0; |
||
100 |
} |
||
101 |
|||
102 |
int |
||
103 |
nrrdIoStateEncodingSet(NrrdIoState *nio, const NrrdEncoding *encoding) { |
||
104 |
static const char me[]="nrrdIoStateEncodingSet"; |
||
105 |
|||
106 |
if (!( nio && encoding )) { |
||
107 |
if (nio) { |
||
108 |
nio->encoding = nrrdEncodingUnknown; |
||
109 |
} |
||
110 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
111 |
return 1; |
||
112 |
} |
||
113 |
if (!encoding->available()) { |
||
114 |
nio->encoding = nrrdEncodingUnknown; |
||
115 |
biffAddf(NRRD, "%s: %s encoding isn't actually available", me, |
||
116 |
encoding->name); |
||
117 |
return 1; |
||
118 |
} |
||
119 |
nio->encoding = encoding; |
||
120 |
return 0; |
||
121 |
} |
||
122 |
|||
123 |
int |
||
124 |
nrrdIoStateFormatSet(NrrdIoState *nio, const NrrdFormat *format) { |
||
125 |
static const char me[]="nrrdIoStateFormatSet"; |
||
126 |
|||
127 |
if (!( nio && format )) { |
||
128 |
if (nio) { |
||
129 |
nio->format = nrrdFormatUnknown; |
||
130 |
} |
||
131 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
132 |
return 1; |
||
133 |
} |
||
134 |
if (!format->available()) { |
||
135 |
nio->format = nrrdFormatUnknown; |
||
136 |
biffAddf(NRRD, "%s: %s format isn't actually available", me, |
||
137 |
format->name); |
||
138 |
return 1; |
||
139 |
} |
||
140 |
nio->format = format; |
||
141 |
return 0; |
||
142 |
} |
||
143 |
|||
144 |
/* |
||
145 |
** no biff |
||
146 |
*/ |
||
147 |
int |
||
148 |
nrrdIoStateGet(NrrdIoState *nio, int parm) { |
||
149 |
static const char me[]="nrrdIoStateGet"; |
||
150 |
int value; |
||
151 |
|||
152 |
if (!nio) { |
||
153 |
/* got NULL pointer */ |
||
154 |
return -1; |
||
155 |
} |
||
156 |
if (!( AIR_IN_OP(nrrdIoStateUnknown, parm, nrrdIoStateLast) )) { |
||
157 |
/* got bogus parameter identifier */ |
||
158 |
return -1; |
||
159 |
} |
||
160 |
switch (parm) { |
||
161 |
case nrrdIoStateDetachedHeader: |
||
162 |
value = !!nio->detachedHeader; |
||
163 |
break; |
||
164 |
case nrrdIoStateBareText: |
||
165 |
value = !!nio->bareText; |
||
166 |
break; |
||
167 |
case nrrdIoStateCharsPerLine: |
||
168 |
/* HEY: this cast is a bad because nio->charsPerLine is unsigned */ |
||
169 |
value = AIR_CAST(int, nio->charsPerLine); |
||
170 |
break; |
||
171 |
case nrrdIoStateValsPerLine: |
||
172 |
/* HEY: this cast is a bad because nio->valsPerLine is unsigned */ |
||
173 |
value = AIR_CAST(int, nio->valsPerLine); |
||
174 |
break; |
||
175 |
case nrrdIoStateSkipData: |
||
176 |
value = !!nio->skipData; |
||
177 |
break; |
||
178 |
case nrrdIoStateKeepNrrdDataFileOpen: |
||
179 |
value = !!nio->keepNrrdDataFileOpen; |
||
180 |
break; |
||
181 |
case nrrdIoStateZlibLevel: |
||
182 |
value = nio->zlibLevel; |
||
183 |
break; |
||
184 |
case nrrdIoStateZlibStrategy: |
||
185 |
value = nio->zlibStrategy; |
||
186 |
break; |
||
187 |
case nrrdIoStateBzip2BlockSize: |
||
188 |
value = nio->bzip2BlockSize; |
||
189 |
break; |
||
190 |
default: |
||
191 |
fprintf(stderr, "!%s: PANIC: didn't recognize parm %d\n", me, parm); |
||
192 |
return -1; |
||
193 |
} |
||
194 |
return value; |
||
195 |
} |
||
196 |
|||
197 |
/* |
||
198 |
** no biff |
||
199 |
*/ |
||
200 |
const NrrdEncoding * |
||
201 |
nrrdIoStateEncodingGet(NrrdIoState *nio) { |
||
202 |
|||
203 |
return nio ? nio->encoding : nrrdEncodingUnknown; |
||
204 |
} |
||
205 |
|||
206 |
/* |
||
207 |
** no biff |
||
208 |
*/ |
||
209 |
const NrrdFormat * |
||
210 |
nrrdIoStateFormatGet(NrrdIoState *nio) { |
||
211 |
|||
212 |
return nio ? nio->format : nrrdFormatUnknown; |
||
213 |
} |
||
214 |
|||
215 |
void |
||
216 |
_nrrdStrcatSpaceVector(char *str, unsigned int spaceDim, |
||
217 |
const double val[NRRD_SPACE_DIM_MAX]) { |
||
218 |
136 |
char buff[AIR_STRLEN_MED]; /* bad Gordon */ |
|
219 |
unsigned int dd; |
||
220 |
|||
221 |
✓✓✓✓ |
136 |
if (AIR_EXISTS(val[0])) { |
222 |
128 |
strcat(str, "("); |
|
223 |
✓✓ | 480 |
for (dd=0; dd<spaceDim; dd++) { |
224 |
180 |
strcpy(buff, ""); |
|
225 |
180 |
airSinglePrintf(NULL, buff, "%.17g", val[dd]); |
|
226 |
180 |
strcat(str, buff); |
|
227 |
180 |
sprintf(buff, "%s", dd+1 < spaceDim ? "," : ")"); |
|
228 |
180 |
strcat(str, buff); |
|
229 |
} |
||
230 |
} else { |
||
231 |
8 |
strcat(str, _nrrdNoSpaceVector); |
|
232 |
} |
||
233 |
return; |
||
234 |
68 |
} |
|
235 |
|||
236 |
int |
||
237 |
_nrrdFieldInteresting(const Nrrd *nrrd, NrrdIoState *nio, int field) { |
||
238 |
int ret; |
||
239 |
unsigned int ai; |
||
240 |
|||
241 |
792 |
if (!( nrrd |
|
242 |
✓✗✓✗ |
1188 |
&& AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX) |
243 |
✓✗ | 396 |
&& nio |
244 |
396 |
&& nio->encoding |
|
245 |
✗✓ | 396 |
&& AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) )) { |
246 |
return 0; |
||
247 |
} |
||
248 |
|||
249 |
ret = 0; |
||
250 |
✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✗✓✓✓ ✓✓✓✓ ✓✓✓✓ ✓✓ |
757 |
switch (field) { |
251 |
case nrrdField_comment: |
||
252 |
/* comments and key/value pairs are always handled differently (by |
||
253 |
being printed explicity), so they are never "interesting" */ |
||
254 |
break; |
||
255 |
case nrrdField_content: |
||
256 |
12 |
ret = !!(airStrlen(nrrd->content)); |
|
257 |
12 |
break; |
|
258 |
case nrrdField_number: |
||
259 |
/* "number" is entirely redundant with "sizes", which is a |
||
260 |
required field. Absolutely nothing is lost in eliding "number" |
||
261 |
from the header, so "number" is NEVER interesting. Should this |
||
262 |
judgement later be found in error, this is the one place where |
||
263 |
the policy change can be implemented */ |
||
264 |
break; |
||
265 |
case nrrdField_type: |
||
266 |
/* this is vital */ |
||
267 |
ret = 1; |
||
268 |
11 |
break; |
|
269 |
case nrrdField_block_size: |
||
270 |
11 |
ret = (nrrdTypeBlock == nrrd->type); |
|
271 |
11 |
break; |
|
272 |
case nrrdField_dimension: |
||
273 |
/* this is vital */ |
||
274 |
ret = 1; |
||
275 |
11 |
break; |
|
276 |
case nrrdField_space: |
||
277 |
/* its interesting if its known */ |
||
278 |
15 |
ret = (nrrdSpaceUnknown != nrrd->space); |
|
279 |
15 |
break; |
|
280 |
case nrrdField_space_dimension: |
||
281 |
/* its interesting if its non-zero and if space is not known */ |
||
282 |
✓✓ | 40 |
ret = (nrrd->spaceDim > 0 && nrrdSpaceUnknown == nrrd->space); |
283 |
15 |
break; |
|
284 |
case nrrdField_sizes: |
||
285 |
/* this is vital */ |
||
286 |
ret = 1; |
||
287 |
11 |
break; |
|
288 |
case nrrdField_spacings: |
||
289 |
✓✓ | 102 |
for (ai=0; ai<nrrd->dim; ai++) { |
290 |
39 |
ret |= AIR_EXISTS(nrrd->axis[ai].spacing); |
|
291 |
} |
||
292 |
break; |
||
293 |
case nrrdField_thicknesses: |
||
294 |
✓✓ | 118 |
for (ai=0; ai<nrrd->dim; ai++) { |
295 |
44 |
ret |= AIR_EXISTS(nrrd->axis[ai].thickness); |
|
296 |
} |
||
297 |
break; |
||
298 |
case nrrdField_axis_mins: |
||
299 |
✓✓ | 102 |
for (ai=0; ai<nrrd->dim; ai++) { |
300 |
39 |
ret |= AIR_EXISTS(nrrd->axis[ai].min); |
|
301 |
} |
||
302 |
break; |
||
303 |
case nrrdField_axis_maxs: |
||
304 |
✓✓ | 102 |
for (ai=0; ai<nrrd->dim; ai++) { |
305 |
39 |
ret |= AIR_EXISTS(nrrd->axis[ai].max); |
|
306 |
} |
||
307 |
break; |
||
308 |
case nrrdField_space_directions: |
||
309 |
12 |
ret = nrrd->spaceDim > 0; |
|
310 |
12 |
break; |
|
311 |
case nrrdField_centers: |
||
312 |
✓✓ | 102 |
for (ai=0; ai<nrrd->dim; ai++) { |
313 |
39 |
ret |= (nrrdCenterUnknown != nrrd->axis[ai].center); |
|
314 |
} |
||
315 |
break; |
||
316 |
case nrrdField_kinds: |
||
317 |
✓✓ | 110 |
for (ai=0; ai<nrrd->dim; ai++) { |
318 |
41 |
ret |= (nrrdKindUnknown != nrrd->axis[ai].kind); |
|
319 |
} |
||
320 |
break; |
||
321 |
case nrrdField_labels: |
||
322 |
✓✓ | 102 |
for (ai=0; ai<nrrd->dim; ai++) { |
323 |
39 |
ret |= !!(airStrlen(nrrd->axis[ai].label)); |
|
324 |
} |
||
325 |
break; |
||
326 |
case nrrdField_units: |
||
327 |
✓✓ | 102 |
for (ai=0; ai<nrrd->dim; ai++) { |
328 |
39 |
ret |= !!(airStrlen(nrrd->axis[ai].units)); |
|
329 |
} |
||
330 |
break; |
||
331 |
case nrrdField_min: |
||
332 |
case nrrdField_max: |
||
333 |
/* these no longer exist in the Nrrd struct; we never write them */ |
||
334 |
ret = AIR_FALSE; |
||
335 |
22 |
break; |
|
336 |
case nrrdField_old_min: |
||
337 |
12 |
ret = AIR_EXISTS(nrrd->oldMin); |
|
338 |
12 |
break; |
|
339 |
case nrrdField_old_max: |
||
340 |
12 |
ret = AIR_EXISTS(nrrd->oldMax); |
|
341 |
12 |
break; |
|
342 |
case nrrdField_endian: |
||
343 |
✓✗ | 33 |
ret = nio->encoding->endianMatters && 1 < nrrdElementSize(nrrd); |
344 |
11 |
break; |
|
345 |
case nrrdField_encoding: |
||
346 |
/* this is vital */ |
||
347 |
ret = 1; |
||
348 |
11 |
break; |
|
349 |
case nrrdField_line_skip: |
||
350 |
11 |
ret = nio->lineSkip > 0; |
|
351 |
11 |
break; |
|
352 |
case nrrdField_byte_skip: |
||
353 |
11 |
ret = nio->byteSkip != 0; |
|
354 |
11 |
break; |
|
355 |
case nrrdField_keyvalue: |
||
356 |
/* comments and key/value pairs are always handled differently (by |
||
357 |
being printed explicity), so they are never "interesting" */ |
||
358 |
break; |
||
359 |
case nrrdField_sample_units: |
||
360 |
14 |
ret = !!airStrlen(nrrd->sampleUnits); |
|
361 |
14 |
break; |
|
362 |
case nrrdField_space_units: |
||
363 |
✓✓ | 78 |
for (ai=0; ai<nrrd->spaceDim; ai++) { |
364 |
27 |
ret |= !!(airStrlen(nrrd->spaceUnits[ai])); |
|
365 |
} |
||
366 |
break; |
||
367 |
case nrrdField_space_origin: |
||
368 |
/* we're trusting other validity checks to ensure that |
||
369 |
all the coeffs exist or not, together */ |
||
370 |
12 |
ret = (nrrd->spaceDim > 0 |
|
371 |
✓✓ | 33 |
&& AIR_EXISTS(nrrd->spaceOrigin[0])); |
372 |
12 |
break; |
|
373 |
case nrrdField_measurement_frame: |
||
374 |
/* we're trusting other validity checks to ensure that |
||
375 |
all the coeffs exist or not, together */ |
||
376 |
23 |
ret = (nrrd->spaceDim > 0 |
|
377 |
✓✓ | 64 |
&& AIR_EXISTS(nrrd->measurementFrame[0][0])); |
378 |
23 |
break; |
|
379 |
case nrrdField_data_file: |
||
380 |
/* detached header was either requested or is required */ |
||
381 |
11 |
ret = (nio->detachedHeader |
|
382 |
✓✗ | 22 |
|| nio->dataFNFormat |
383 |
✓✗ | 33 |
|| nio->dataFNArr->len > 1); |
384 |
11 |
break; |
|
385 |
} |
||
386 |
|||
387 |
396 |
return ret; |
|
388 |
396 |
} |
|
389 |
|||
390 |
/* |
||
391 |
** _nrrdSprintFieldInfo |
||
392 |
** |
||
393 |
** this prints "<prefix><field>: <info>" into *strP (after allocating it for |
||
394 |
** big enough, usually with a stupidly big margin of error), in a form |
||
395 |
** suitable to be written to NRRD or other image headers. This will always |
||
396 |
** print something (for valid inputs), even stupid <info>s like |
||
397 |
** "(unknown endian)". It is up to the caller to decide which fields |
||
398 |
** are worth writing, via _nrrdFieldInteresting(). |
||
399 |
** |
||
400 |
** NOTE: some of these fields make sense in non-NRRD files (e.g. all |
||
401 |
** the per-axis information), but many only make sense in NRRD files. |
||
402 |
** This is just one example of NRRD-format-specific stuff that is not |
||
403 |
** in formatNRRD.c |
||
404 |
*/ |
||
405 |
void |
||
406 |
_nrrdSprintFieldInfo(char **strP, const char *prefix, |
||
407 |
const Nrrd *nrrd, NrrdIoState *nio, int field, |
||
408 |
int dropAxis0) { |
||
409 |
static const char me[]="_nrrdSprintFieldInfo"; |
||
410 |
242 |
char buff[AIR_STRLEN_MED], *fnb, stmp[AIR_STRLEN_SMALL], |
|
411 |
*strtmp=NULL; |
||
412 |
121 |
double colvec[NRRD_SPACE_DIM_MAX]; |
|
413 |
const char *fs; |
||
414 |
unsigned int ii, dd, |
||
415 |
uintStrlen = 11, |
||
416 |
size_tStrlen = 33, |
||
417 |
doubleStrlen = 513; |
||
418 |
size_t fslen, fdlen, maxl; |
||
419 |
int endi; |
||
420 |
|||
421 |
✓✗✓✗ |
242 |
if (!( strP && prefix |
422 |
121 |
&& nrrd |
|
423 |
✓✗ | 242 |
&& AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX) |
424 |
✗✓ | 121 |
&& AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) )) { |
425 |
return; |
||
426 |
} |
||
427 |
/* As of Sun Dec 2 01:57:48 CST 2012 (revision 5832) the only |
||
428 |
places where this function is called is when it has been guarded |
||
429 |
by "if (_nrrdFieldInteresting())" (except for in formatText.c when |
||
430 |
its called on the dimension field, which is always interesting). |
||
431 |
So, the following: |
||
432 |
|||
433 |
if (!_nrrdFieldInteresting(nrrd, nio, field)) { |
||
434 |
*strP = airStrdup(""); |
||
435 |
} |
||
436 |
|||
437 |
was redundant and confusingly created the appearance of a memory |
||
438 |
leak waiting to happen. We now let the default switch statement |
||
439 |
set *strP to NULL (all the other cases set it), to smoke out |
||
440 |
errors in how this function is called */ |
||
441 |
|||
442 |
121 |
fs = airEnumStr(nrrdField, field); |
|
443 |
121 |
fslen = strlen(prefix) + strlen(fs) + strlen(": ") + 1; |
|
444 |
✗✗✓✗ ✓✗✓✓ ✓✓✗✗ ✓✓✓✓ ✓✗✓✗ ✗✗✗✓ ✓✗✗✗ ✓✓✓✗ ✗ |
121 |
switch (field) { |
445 |
case nrrdField_comment: |
||
446 |
case nrrdField_keyvalue: |
||
447 |
fprintf(stderr, "%s: CONFUSION: why are you calling me on \"%s\"?\n", me, |
||
448 |
airEnumStr(nrrdField, nrrdField_comment)); |
||
449 |
*strP = airStrdup(""); |
||
450 |
break; |
||
451 |
case nrrdField_content: |
||
452 |
2 |
strtmp = airOneLinify(airStrdup(nrrd->content)); |
|
453 |
2 |
*strP = AIR_CALLOC(fslen + strlen(strtmp), char); |
|
454 |
2 |
sprintf(*strP, "%s%s: %s", prefix, fs, strtmp); |
|
455 |
2 |
airFree(strtmp); strtmp = NULL; |
|
456 |
2 |
break; |
|
457 |
case nrrdField_number: |
||
458 |
*strP = AIR_CALLOC(fslen + size_tStrlen, char); |
||
459 |
sprintf(*strP, "%s%s: %s", prefix, fs, |
||
460 |
airSprintSize_t(stmp, nrrdElementNumber(nrrd))); |
||
461 |
break; |
||
462 |
case nrrdField_type: |
||
463 |
11 |
*strP = AIR_CALLOC(fslen + strlen(airEnumStr(nrrdType, nrrd->type)), char); |
|
464 |
11 |
sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdType, nrrd->type)); |
|
465 |
11 |
break; |
|
466 |
case nrrdField_block_size: |
||
467 |
*strP = AIR_CALLOC(fslen + size_tStrlen, char); |
||
468 |
sprintf(*strP, "%s%s: %s", prefix, fs, |
||
469 |
airSprintSize_t(stmp, nrrd->blockSize)); |
||
470 |
break; |
||
471 |
case nrrdField_dimension: |
||
472 |
11 |
*strP = AIR_CALLOC(fslen + uintStrlen, char); |
|
473 |
11 |
sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->dim); |
|
474 |
11 |
break; |
|
475 |
case nrrdField_space: |
||
476 |
8 |
*strP = AIR_CALLOC(fslen |
|
477 |
+ strlen(airEnumStr(nrrdSpace, nrrd->space)), char); |
||
478 |
8 |
sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(nrrdSpace, nrrd->space)); |
|
479 |
8 |
break; |
|
480 |
case nrrdField_space_dimension: |
||
481 |
1 |
*strP = AIR_CALLOC(fslen + uintStrlen, char); |
|
482 |
1 |
sprintf(*strP, "%s%s: %d", prefix, fs, nrrd->spaceDim); |
|
483 |
1 |
break; |
|
484 |
/* ---- begin per-axis fields ---- */ |
||
485 |
case nrrdField_sizes: |
||
486 |
11 |
*strP = AIR_CALLOC(fslen + nrrd->dim*(size_tStrlen + 1), char); |
|
487 |
11 |
sprintf(*strP, "%s%s:", prefix, fs); |
|
488 |
✓✓ | 96 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
489 |
37 |
sprintf(buff, " %s", airSprintSize_t(stmp, nrrd->axis[ii].size)); |
|
490 |
37 |
strcat(*strP, buff); |
|
491 |
} |
||
492 |
break; |
||
493 |
case nrrdField_spacings: |
||
494 |
*strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char); |
||
495 |
sprintf(*strP, "%s%s:", prefix, fs); |
||
496 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
||
497 |
airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].spacing); |
||
498 |
strcat(*strP, buff); |
||
499 |
} |
||
500 |
break; |
||
501 |
case nrrdField_thicknesses: |
||
502 |
*strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char); |
||
503 |
sprintf(*strP, "%s%s:", prefix, fs); |
||
504 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
||
505 |
airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].thickness); |
||
506 |
strcat(*strP, buff); |
||
507 |
} |
||
508 |
break; |
||
509 |
case nrrdField_axis_mins: |
||
510 |
2 |
*strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char); |
|
511 |
2 |
sprintf(*strP, "%s%s:", prefix, fs); |
|
512 |
✓✓ | 10 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
513 |
3 |
airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].min); |
|
514 |
3 |
strcat(*strP, buff); |
|
515 |
} |
||
516 |
break; |
||
517 |
case nrrdField_axis_maxs: |
||
518 |
2 |
*strP = AIR_CALLOC(fslen + nrrd->dim*(doubleStrlen + 1), char); |
|
519 |
2 |
sprintf(*strP, "%s%s:", prefix, fs); |
|
520 |
✓✓ | 10 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
521 |
3 |
airSinglePrintf(NULL, buff, " %.17g", nrrd->axis[ii].max); |
|
522 |
3 |
strcat(*strP, buff); |
|
523 |
} |
||
524 |
break; |
||
525 |
case nrrdField_space_directions: |
||
526 |
9 |
*strP = AIR_CALLOC(fslen |
|
527 |
+ nrrd->dim*nrrd->spaceDim*(doubleStrlen |
||
528 |
+ strlen("(,) ")), char); |
||
529 |
9 |
sprintf(*strP, "%s%s: ", prefix, fs); |
|
530 |
✓✓ | 88 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
531 |
70 |
_nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, |
|
532 |
35 |
nrrd->axis[ii].spaceDirection); |
|
533 |
✓✓ | 35 |
if (ii < nrrd->dim-1) { |
534 |
26 |
strcat(*strP, " "); |
|
535 |
26 |
} |
|
536 |
} |
||
537 |
break; |
||
538 |
case nrrdField_centers: |
||
539 |
fdlen = 0; |
||
540 |
✓✓ | 98 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
541 |
✓✓ | 106 |
fdlen += 1 + airStrlen(nrrd->axis[ii].center |
542 |
30 |
? airEnumStr(nrrdCenter, nrrd->axis[ii].center) |
|
543 |
: NRRD_UNKNOWN); |
||
544 |
} |
||
545 |
11 |
*strP = AIR_CALLOC(fslen + fdlen, char); |
|
546 |
11 |
sprintf(*strP, "%s%s:", prefix, fs); |
|
547 |
✓✓ | 98 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
548 |
✓✓ | 106 |
sprintf(buff, " %s", |
549 |
(nrrd->axis[ii].center |
||
550 |
? airEnumStr(nrrdCenter, nrrd->axis[ii].center) |
||
551 |
: NRRD_UNKNOWN)); |
||
552 |
38 |
strcat(*strP, buff); |
|
553 |
} |
||
554 |
break; |
||
555 |
case nrrdField_kinds: |
||
556 |
fdlen = 0; |
||
557 |
✓✓ | 92 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
558 |
✓✗ | 108 |
fdlen += 1 + airStrlen(nrrd->axis[ii].kind |
559 |
36 |
? airEnumStr(nrrdKind, nrrd->axis[ii].kind) |
|
560 |
: NRRD_UNKNOWN); |
||
561 |
} |
||
562 |
10 |
*strP = AIR_CALLOC(fslen + fdlen, char); |
|
563 |
10 |
sprintf(*strP, "%s%s:", prefix, fs); |
|
564 |
✓✓ | 92 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
565 |
✓✗ | 108 |
sprintf(buff, " %s", |
566 |
(nrrd->axis[ii].kind |
||
567 |
? airEnumStr(nrrdKind, nrrd->axis[ii].kind) |
||
568 |
: NRRD_UNKNOWN)); |
||
569 |
36 |
strcat(*strP, buff); |
|
570 |
} |
||
571 |
break; |
||
572 |
case nrrdField_labels: |
||
573 |
case nrrdField_units: |
||
574 |
#define LABEL_OR_UNITS (nrrdField_labels == field \ |
||
575 |
? nrrd->axis[ii].label \ |
||
576 |
: nrrd->axis[ii].units) |
||
577 |
fdlen = 0; |
||
578 |
✓✓ | 18 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
579 |
/* The "2*" is because at worst every character needs escaping. |
||
580 |
The "+ 3" for the |" "| between each part */ |
||
581 |
✓✗ | 18 |
fdlen += 2*airStrlen(LABEL_OR_UNITS) + 3; |
582 |
} |
||
583 |
3 |
fdlen += 1; /* for '\0' */ |
|
584 |
3 |
*strP = AIR_CALLOC(fslen + fdlen, char); |
|
585 |
3 |
sprintf(*strP, "%s%s:", prefix, fs); |
|
586 |
✓✓ | 18 |
for (ii=!!dropAxis0; ii<nrrd->dim; ii++) { |
587 |
6 |
strcat(*strP, " \""); |
|
588 |
✓✗✓✗ ✓✓✗✗ |
18 |
if (nrrdField_labels == field |
589 |
12 |
? airStrlen(nrrd->axis[ii].label) |
|
590 |
: airStrlen(nrrd->axis[ii].units)) { |
||
591 |
✓✗ | 15 |
_nrrdWriteEscaped(NULL, *strP, LABEL_OR_UNITS, |
592 |
"\"", _NRRD_WHITESPACE_NOTAB); |
||
593 |
5 |
} |
|
594 |
6 |
strcat(*strP, "\""); |
|
595 |
} |
||
596 |
#undef LABEL_OR_UNITS |
||
597 |
break; |
||
598 |
/* ---- end per-axis fields ---- */ |
||
599 |
case nrrdField_min: |
||
600 |
case nrrdField_max: |
||
601 |
/* we're basically a no-op, now that these fields became meaningless */ |
||
602 |
*strP = AIR_CALLOC(fslen + doubleStrlen, char); |
||
603 |
sprintf(*strP, "%s%s: 0.0", prefix, fs); |
||
604 |
strcat(*strP, buff); |
||
605 |
break; |
||
606 |
case nrrdField_old_min: |
||
607 |
*strP = AIR_CALLOC(fslen + doubleStrlen, char); |
||
608 |
sprintf(*strP, "%s%s: ", prefix, fs); |
||
609 |
airSinglePrintf(NULL, buff, "%.17g", nrrd->oldMin); |
||
610 |
strcat(*strP, buff); |
||
611 |
break; |
||
612 |
case nrrdField_old_max: |
||
613 |
*strP = AIR_CALLOC(fslen + doubleStrlen, char); |
||
614 |
sprintf(*strP, "%s%s: ", prefix, fs); |
||
615 |
airSinglePrintf(NULL, buff, "%.17g", nrrd->oldMax); |
||
616 |
strcat(*strP, buff); |
||
617 |
break; |
||
618 |
case nrrdField_endian: |
||
619 |
✗✓ | 11 |
if (airEndianUnknown != nio->endian) { |
620 |
/* we know a specific endianness because either it was recorded as |
||
621 |
part of "unu make -h", or it was set (and data was possibly |
||
622 |
altered) as part of "unu save" */ |
||
623 |
endi = nio->endian; |
||
624 |
} else { |
||
625 |
/* we record our current architecture's endian because we're |
||
626 |
going to writing out data */ |
||
627 |
11 |
endi = airMyEndian(); |
|
628 |
} |
||
629 |
11 |
*strP = AIR_CALLOC(fslen + strlen(airEnumStr(airEndian, endi)), char); |
|
630 |
11 |
sprintf(*strP, "%s%s: %s", prefix, fs, airEnumStr(airEndian, endi)); |
|
631 |
11 |
break; |
|
632 |
case nrrdField_encoding: |
||
633 |
11 |
*strP = AIR_CALLOC(fslen + strlen(nio->encoding->name), char); |
|
634 |
11 |
sprintf(*strP, "%s%s: %s", prefix, fs, nio->encoding->name); |
|
635 |
11 |
break; |
|
636 |
case nrrdField_line_skip: |
||
637 |
*strP = AIR_CALLOC(fslen + uintStrlen, char); |
||
638 |
sprintf(*strP, "%s%s: %d", prefix, fs, nio->lineSkip); |
||
639 |
break; |
||
640 |
case nrrdField_byte_skip: |
||
641 |
*strP = AIR_CALLOC(fslen + uintStrlen, char); |
||
642 |
sprintf(*strP, "%s%s: %ld", prefix, fs, nio->byteSkip); |
||
643 |
break; |
||
644 |
case nrrdField_sample_units: |
||
645 |
strtmp = airOneLinify(airStrdup(nrrd->sampleUnits)); |
||
646 |
*strP = AIR_CALLOC(fslen + strlen(strtmp), char); |
||
647 |
sprintf(*strP, "%s%s: \"%s\"", prefix, fs, strtmp); |
||
648 |
airFree(strtmp); strtmp = NULL; |
||
649 |
break; |
||
650 |
case nrrdField_space_units: |
||
651 |
fdlen = 0; |
||
652 |
✓✓ | 8 |
for (ii=0; ii<nrrd->spaceDim; ii++) { |
653 |
/* The "2*" is because at worst every character needs escaping. |
||
654 |
See note in formatNRRD.c about how even though its not part |
||
655 |
of the format, we have worst-case scenario of having to |
||
656 |
escape a space units which is nothing but ". The "+ 3" for |
||
657 |
the |" "| between each part */ |
||
658 |
3 |
fdlen += 2*airStrlen(nrrd->spaceUnits[ii]) + 3; |
|
659 |
} |
||
660 |
1 |
fdlen += 1; /* for '\0' */ |
|
661 |
1 |
*strP = AIR_CALLOC(fslen + fdlen, char); |
|
662 |
1 |
sprintf(*strP, "%s%s:", prefix, fs); |
|
663 |
✓✓ | 8 |
for (ii=0; ii<nrrd->spaceDim; ii++) { |
664 |
3 |
strcat(*strP, " \""); |
|
665 |
✓✗ | 3 |
if (airStrlen(nrrd->spaceUnits[ii])) { |
666 |
3 |
_nrrdWriteEscaped(NULL, *strP, nrrd->spaceUnits[ii], |
|
667 |
"\"", _NRRD_WHITESPACE_NOTAB); |
||
668 |
3 |
} |
|
669 |
3 |
strcat(*strP, "\""); |
|
670 |
} |
||
671 |
break; |
||
672 |
case nrrdField_space_origin: |
||
673 |
9 |
*strP = AIR_CALLOC(fslen + nrrd->spaceDim*(doubleStrlen |
|
674 |
+ strlen("(,) ")), char); |
||
675 |
9 |
sprintf(*strP, "%s%s: ", prefix, fs); |
|
676 |
9 |
_nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, nrrd->spaceOrigin); |
|
677 |
9 |
break; |
|
678 |
case nrrdField_measurement_frame: |
||
679 |
8 |
*strP = AIR_CALLOC(fslen + (nrrd->spaceDim* |
|
680 |
nrrd->spaceDim*(doubleStrlen |
||
681 |
+ strlen("(,) "))), char); |
||
682 |
8 |
sprintf(*strP, "%s%s: ", prefix, fs); |
|
683 |
✓✓ | 64 |
for (dd=0; dd<nrrd->spaceDim; dd++) { |
684 |
✓✓ | 192 |
for (ii=0; ii<nrrd->spaceDim; ii++) { |
685 |
72 |
colvec[ii] = nrrd->measurementFrame[dd][ii]; |
|
686 |
} |
||
687 |
24 |
_nrrdStrcatSpaceVector(*strP, nrrd->spaceDim, colvec); |
|
688 |
✓✓ | 24 |
if (dd < nrrd->spaceDim-1) { |
689 |
16 |
strcat(*strP, " "); |
|
690 |
16 |
} |
|
691 |
} |
||
692 |
break; |
||
693 |
case nrrdField_data_file: |
||
694 |
/* NOTE: this comes last (nrrdField_data_file is the highest-valued |
||
695 |
member of the nrrdField* enum) because the "LIST" form of the |
||
696 |
data file specification requires that the following lines be |
||
697 |
the filenames */ |
||
698 |
/* error checking elsewhere: assumes there is data file info */ |
||
699 |
if (nio->dataFNFormat) { |
||
700 |
*strP = AIR_CALLOC(fslen + strlen(nio->dataFNFormat) + 4*uintStrlen, |
||
701 |
char); |
||
702 |
if (nio->dataFileDim == nrrd->dim-1) { |
||
703 |
sprintf(*strP, "%s%s: %s %d %d %d", prefix, fs, nio->dataFNFormat, |
||
704 |
nio->dataFNMin, nio->dataFNMax, nio->dataFNStep); |
||
705 |
} else { |
||
706 |
sprintf(*strP, "%s%s: %s %d %d %d %u", prefix, fs, nio->dataFNFormat, |
||
707 |
nio->dataFNMin, nio->dataFNMax, nio->dataFNStep, |
||
708 |
nio->dataFileDim); |
||
709 |
} |
||
710 |
} else if (nio->dataFNArr->len > 1) { |
||
711 |
maxl = 0; |
||
712 |
for (ii=0; ii<nio->dataFNArr->len; ii++) { |
||
713 |
maxl = AIR_MAX(maxl, strlen(nio->dataFN[ii])); |
||
714 |
} |
||
715 |
*strP = AIR_CALLOC(fslen + strlen(NRRD_LIST_FLAG) |
||
716 |
+ uintStrlen + nio->dataFNArr->len * (maxl + 1), |
||
717 |
char); |
||
718 |
fnb = AIR_CALLOC(fslen + strlen(NRRD_LIST_FLAG) |
||
719 |
+ uintStrlen + maxl + 1, char); |
||
720 |
if (nio->dataFileDim == nrrd->dim-1) { |
||
721 |
sprintf(*strP, "%s%s: LIST\n", prefix, fs); |
||
722 |
} else { |
||
723 |
sprintf(*strP, "%s%s: LIST %u\n", prefix, fs, nio->dataFileDim); |
||
724 |
} |
||
725 |
for (ii=0; ii<nio->dataFNArr->len; ii++) { |
||
726 |
sprintf(fnb, "%s%s", nio->dataFN[ii], |
||
727 |
ii<nio->dataFNArr->len-1 ? "\n" : ""); |
||
728 |
strcat(*strP, fnb); |
||
729 |
} |
||
730 |
free(fnb); |
||
731 |
} else { |
||
732 |
/* there is some ambiguity between a "LIST" of length one, |
||
733 |
and a single explicit data filename, but that's harmless */ |
||
734 |
*strP = AIR_CALLOC(fslen + strlen("./") |
||
735 |
+ strlen(nio->dataFN[0]) + 1, char); |
||
736 |
sprintf(*strP, "%s%s: %s%s", prefix, fs, |
||
737 |
/* this is a favor to older readers that can deal with |
||
738 |
this NRRD file because its being saved in a NRRD0003 |
||
739 |
(or below) version, so we don't want to confuse them |
||
740 |
by not having the old explicit header-relative flag */ |
||
741 |
(_nrrdFormatNRRD_whichVersion(nrrd, nio) < 4 ? "./" : ""), |
||
742 |
nio->dataFN[0]); |
||
743 |
} |
||
744 |
break; |
||
745 |
default: |
||
746 |
fprintf(stderr, "%s: CONFUSION: field %d unrecognized\n", me, field); |
||
747 |
*strP = NULL; |
||
748 |
break; |
||
749 |
} |
||
750 |
|||
751 |
121 |
return; |
|
752 |
121 |
} |
|
753 |
|||
754 |
/* |
||
755 |
** _nrrdFprintFieldInfo |
||
756 |
** |
||
757 |
** convenience wrapper around _nrrdSprintFieldInfo, for writing into |
||
758 |
** a file. Same caveats here: use _nrrdFieldInteresting |
||
759 |
*/ |
||
760 |
void |
||
761 |
_nrrdFprintFieldInfo(FILE *file, const char *prefix, |
||
762 |
const Nrrd *nrrd, NrrdIoState *nio, int field, |
||
763 |
int dropAxis0) { |
||
764 |
242 |
char *line=NULL; |
|
765 |
|||
766 |
121 |
_nrrdSprintFieldInfo(&line, prefix, nrrd, nio, field, dropAxis0); |
|
767 |
✓✗ | 121 |
if (line) { |
768 |
121 |
fprintf(file, "%s\n", line); |
|
769 |
121 |
free(line); |
|
770 |
121 |
} |
|
771 |
return; |
||
772 |
121 |
} |
|
773 |
|||
774 |
int |
||
775 |
_nrrdEncodingMaybeSet(NrrdIoState *nio) { |
||
776 |
static const char me[]="_nrrdEncodingMaybeSet"; |
||
777 |
|||
778 |
✗✓ | 48 |
if (!nio) { |
779 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
780 |
return 1; |
||
781 |
} |
||
782 |
✗✓ | 24 |
if (!nio->encoding) { |
783 |
biffAddf(NRRD, "%s: invalid (NULL) encoding", me); |
||
784 |
return 1; |
||
785 |
} |
||
786 |
✓✓ | 24 |
if (nrrdEncodingUnknown == nio->encoding) { |
787 |
12 |
nio->encoding = nrrdEncodingArray[nrrdDefaultWriteEncodingType]; |
|
788 |
12 |
} |
|
789 |
✗✓ | 24 |
if (!nio->encoding->available()) { |
790 |
biffAddf(NRRD, "%s: %s encoding not available in this Teem build", |
||
791 |
me, nio->encoding->name); |
||
792 |
return 1; |
||
793 |
} |
||
794 |
24 |
return 0; |
|
795 |
24 |
} |
|
796 |
|||
797 |
/* |
||
798 |
** we can assume (via action of caller nrrdSave) that nio->encoding |
||
799 |
** has been set |
||
800 |
** |
||
801 |
** we must set nio->format to something useful/non-trivial |
||
802 |
*/ |
||
803 |
int |
||
804 |
_nrrdFormatMaybeGuess(const Nrrd *nrrd, NrrdIoState *nio, |
||
805 |
const char *filename) { |
||
806 |
static const char me[]="_nrrdFormatMaybeGuess"; |
||
807 |
24 |
char mesg[AIR_STRLEN_MED]; |
|
808 |
int fi, guessed, available, fits; |
||
809 |
|||
810 |
✗✓ | 12 |
if (!nio->format) { |
811 |
biffAddf(NRRD, "%s: got invalid (NULL) format", me); |
||
812 |
return 1; |
||
813 |
} |
||
814 |
✓✗ | 12 |
if (nrrdFormatUnknown == nio->format) { |
815 |
✓✗ | 26 |
for (fi = nrrdFormatTypeUnknown+1; |
816 |
13 |
fi < nrrdFormatTypeLast; |
|
817 |
1 |
fi++) { |
|
818 |
✓✓ | 13 |
if (nrrdFormatArray[fi]->nameLooksLike(filename)) { |
819 |
12 |
nio->format = nrrdFormatArray[fi]; |
|
820 |
12 |
break; |
|
821 |
} |
||
822 |
} |
||
823 |
✗✓ | 12 |
if (nrrdFormatUnknown == nio->format) { |
824 |
/* no nameLooksLike() returned non-zero, punt */ |
||
825 |
nio->format = nrrdFormatNRRD; |
||
826 |
} |
||
827 |
guessed = AIR_TRUE; |
||
828 |
12 |
} else { |
|
829 |
guessed = AIR_FALSE; |
||
830 |
} |
||
831 |
12 |
available = nio->format->available(); |
|
832 |
12 |
fits = nio->format->fitsInto(nrrd, nio->encoding, AIR_FALSE); |
|
833 |
/* !available ==> !fits, by the nature of fitsInto() */ |
||
834 |
✗✓ | 12 |
if (!( available && fits )) { |
835 |
sprintf(mesg, "can not use %s format: %s", nio->format->name, |
||
836 |
(!available |
||
837 |
? "not available in this Teem build" |
||
838 |
: "array doesn\'t fit")); |
||
839 |
if (guessed) { |
||
840 |
if (1 <= nrrdStateVerboseIO) { |
||
841 |
fprintf(stderr, "(%s: %s --> saving to NRRD format)\n", me, mesg); |
||
842 |
} |
||
843 |
nio->format = nrrdFormatNRRD; |
||
844 |
} else { |
||
845 |
/* problem: this was the format someone explicitly requested */ |
||
846 |
biffAddf(NRRD, "%s: %s", me, mesg); |
||
847 |
return 1; |
||
848 |
} |
||
849 |
} |
||
850 |
|||
851 |
12 |
return 0; |
|
852 |
12 |
} |
|
853 |
|||
854 |
int |
||
855 |
_nrrdFormatMaybeSet(NrrdIoState *nio) { |
||
856 |
static const char me[]="_nrrdFormatMaybeSet"; |
||
857 |
|||
858 |
✗✓ | 24 |
if (!nio->format) { |
859 |
biffAddf(NRRD, "%s: invalid (NULL) format", me); |
||
860 |
return 1; |
||
861 |
} |
||
862 |
✗✓ | 12 |
if (nrrdFormatUnknown == nio->format) { |
863 |
nio->format = nrrdFormatNRRD; |
||
864 |
} |
||
865 |
✗✓ | 12 |
if (!nio->format->available()) { |
866 |
biffAddf(NRRD, "%s: %s format not available in this Teem build", |
||
867 |
me, nio->format->name); |
||
868 |
return 1; |
||
869 |
} |
||
870 |
12 |
return 0; |
|
871 |
12 |
} |
|
872 |
|||
873 |
/* |
||
874 |
** _nrrdWrite |
||
875 |
** |
||
876 |
** Write a nrrd to given file or string (allocated by nrrd), using the |
||
877 |
** format and and encoding indicated in nio. Cleverness should be |
||
878 |
** isolated and collected here: by the time nio->format->write() is |
||
879 |
** called, all writing parameters must be given explicitly, and their |
||
880 |
** appropriateness is explicitly tested |
||
881 |
*/ |
||
882 |
int |
||
883 |
_nrrdWrite(FILE *file, char **stringP, const Nrrd *nrrd, NrrdIoState *_nio) { |
||
884 |
static const char me[]="_nrrdWrite"; |
||
885 |
NrrdIoState *nio; |
||
886 |
airArray *mop; |
||
887 |
|||
888 |
✗✓ | 24 |
if (!((file || stringP) && nrrd)) { |
889 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
890 |
return 1; |
||
891 |
} |
||
892 |
✗✓ | 12 |
if (file && stringP) { |
893 |
biffAddf(NRRD, "%s: can't write to both file and string", me); |
||
894 |
return 1; |
||
895 |
} |
||
896 |
✗✓ | 12 |
if (nrrdCheck(nrrd)) { |
897 |
biffAddf(NRRD, "%s:", me); |
||
898 |
return 1; |
||
899 |
} |
||
900 |
12 |
mop = airMopNew(); |
|
901 |
✓✗ | 12 |
if (_nio) { |
902 |
nio = _nio; |
||
903 |
12 |
} else { |
|
904 |
nio = nrrdIoStateNew(); |
||
905 |
if (!nio) { |
||
906 |
biffAddf(NRRD, "%s: couldn't alloc local NrrdIoState", me); |
||
907 |
airMopError(mop); return 1; |
||
908 |
} |
||
909 |
airMopAdd(mop, nio, (airMopper)nrrdIoStateNix, airMopAlways); |
||
910 |
} |
||
911 |
✗✓ | 24 |
if (_nrrdEncodingMaybeSet(nio) |
912 |
✓✗ | 24 |
|| _nrrdFormatMaybeSet(nio)) { |
913 |
biffAddf(NRRD, "%s: ", me); |
||
914 |
airMopError(mop); return 1; |
||
915 |
} |
||
916 |
✓✗✗✓ |
24 |
if (nio->byteSkip || nio->lineSkip) { |
917 |
/* NOTE: unu make bypasses this by calling nrrdFormatNRRD->write() |
||
918 |
directly */ |
||
919 |
biffAddf(NRRD, "%s: can't generate line or byte skips on data write", me); |
||
920 |
airMopError(mop); return 1; |
||
921 |
} |
||
922 |
|||
923 |
✗✓ | 12 |
if (stringP) { |
924 |
if (nrrdFormatNRRD != nio->format) { |
||
925 |
biffAddf(NRRD, "%s: sorry, can only write %s files to strings (not %s)", |
||
926 |
me, nrrdFormatNRRD->name, nio->format->name); |
||
927 |
airMopError(mop); return 1; |
||
928 |
} |
||
929 |
/* we do this in two passes; first see how much room is needed |
||
930 |
for the header, then allocate, then write the header */ |
||
931 |
nio->learningHeaderStrlen = AIR_TRUE; |
||
932 |
if (nio->format->write(NULL, nrrd, nio)) { |
||
933 |
biffAddf(NRRD, "%s:", me); |
||
934 |
airMopError(mop); return 1; |
||
935 |
} |
||
936 |
*stringP = AIR_MALLOC(nio->headerStrlen + 1, char); |
||
937 |
if (!*stringP) { |
||
938 |
biffAddf(NRRD, "%s: couldn't allocate header string (%u len )", |
||
939 |
me, nio->headerStrlen); |
||
940 |
airMopError(mop); return 1; |
||
941 |
} |
||
942 |
nio->learningHeaderStrlen = AIR_FALSE; |
||
943 |
nio->headerStringWrite = *stringP; |
||
944 |
if (nio->format->write(NULL, nrrd, nio)) { |
||
945 |
biffAddf(NRRD, "%s:", me); |
||
946 |
airMopError(mop); return 1; |
||
947 |
} |
||
948 |
} else { |
||
949 |
/* call the writer appropriate for the format */ |
||
950 |
✗✓ | 12 |
if (nio->format->write(file, nrrd, nio)) { |
951 |
biffAddf(NRRD, "%s:", me); |
||
952 |
airMopError(mop); return 1; |
||
953 |
} |
||
954 |
} |
||
955 |
|||
956 |
12 |
airMopOkay(mop); |
|
957 |
12 |
return 0; |
|
958 |
12 |
} |
|
959 |
|||
960 |
/* |
||
961 |
******** nrrdWrite |
||
962 |
** |
||
963 |
** wrapper around _nrrdWrite; writes to a FILE* |
||
964 |
*/ |
||
965 |
int |
||
966 |
nrrdWrite(FILE *file, const Nrrd *nrrd, NrrdIoState *_nio) { |
||
967 |
static const char me[]="nrrdWrite"; |
||
968 |
|||
969 |
✗✓ | 24 |
if (_nrrdWrite(file, NULL, nrrd, _nio)) { |
970 |
biffAddf(NRRD, "%s: trouble", me); |
||
971 |
return 1; |
||
972 |
} |
||
973 |
12 |
return 0; |
|
974 |
12 |
} |
|
975 |
|||
976 |
/* |
||
977 |
******** nrrdStringWrite |
||
978 |
** |
||
979 |
** wrapper around _nrrdWrite; *allocates* and writes to a string |
||
980 |
*/ |
||
981 |
int |
||
982 |
nrrdStringWrite(char **stringP, const Nrrd *nrrd, NrrdIoState *_nio) { |
||
983 |
static const char me[]="nrrdStringWrite"; |
||
984 |
|||
985 |
if (_nrrdWrite(NULL, stringP, nrrd, _nio)) { |
||
986 |
biffAddf(NRRD, "%s: trouble", me); |
||
987 |
return 1; |
||
988 |
} |
||
989 |
return 0; |
||
990 |
} |
||
991 |
|||
992 |
/* |
||
993 |
******** nrrdSave |
||
994 |
** |
||
995 |
** save a given nrrd to a given filename, with cleverness to guess |
||
996 |
** format if not specified by the caller |
||
997 |
** |
||
998 |
** currently, for NRRD format files, we play the detached header game |
||
999 |
** whenever the filename ends in NRRD_EXT_NHDR, and when we play this |
||
1000 |
** game, the data file is ALWAYS header relative. |
||
1001 |
*/ |
||
1002 |
int |
||
1003 |
nrrdSave(const char *filename, const Nrrd *nrrd, NrrdIoState *nio) { |
||
1004 |
static const char me[]="nrrdSave"; |
||
1005 |
FILE *file; |
||
1006 |
airArray *mop; |
||
1007 |
|||
1008 |
✗✓ | 24 |
if (!(nrrd && filename)) { |
1009 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
1010 |
return 1; |
||
1011 |
} |
||
1012 |
12 |
mop = airMopNew(); |
|
1013 |
✓✗ | 12 |
if (!nio) { |
1014 |
12 |
nio = nrrdIoStateNew(); |
|
1015 |
✗✓ | 12 |
if (!nio) { |
1016 |
biffAddf(NRRD, "%s: couldn't alloc local NrrdIoState", me); |
||
1017 |
return 1; |
||
1018 |
} |
||
1019 |
12 |
airMopAdd(mop, nio, (airMopper)nrrdIoStateNix, airMopAlways); |
|
1020 |
12 |
} |
|
1021 |
✗✓ | 24 |
if (_nrrdEncodingMaybeSet(nio) |
1022 |
✓✗ | 24 |
|| _nrrdFormatMaybeGuess(nrrd, nio, filename)) { |
1023 |
biffAddf(NRRD, "%s: ", me); |
||
1024 |
airMopError(mop); return 1; |
||
1025 |
} |
||
1026 |
|||
1027 |
✗✓ | 23 |
if (nrrdFormatNRRD == nio->format |
1028 |
✓✓ | 23 |
&& airEndsWith(filename, NRRD_EXT_NHDR)) { |
1029 |
nio->detachedHeader = AIR_TRUE; |
||
1030 |
_nrrdSplitName(&(nio->path), &(nio->base), filename); |
||
1031 |
/* nix the ".nhdr" suffix */ |
||
1032 |
nio->base[strlen(nio->base) - strlen(NRRD_EXT_NHDR)] = 0; |
||
1033 |
/* nrrdFormatNRRD->write will do the rest */ |
||
1034 |
} else { |
||
1035 |
12 |
nio->detachedHeader = AIR_FALSE; |
|
1036 |
} |
||
1037 |
|||
1038 |
✗✓ | 12 |
if (!( file = airFopen(filename, stdout, "wb") )) { |
1039 |
biffAddf(NRRD, "%s: couldn't fopen(\"%s\",\"wb\"): %s", |
||
1040 |
me, filename, strerror(errno)); |
||
1041 |
airMopError(mop); return 1; |
||
1042 |
} |
||
1043 |
12 |
airMopAdd(mop, file, (airMopper)airFclose, airMopAlways); |
|
1044 |
|||
1045 |
✗✓ | 12 |
if (nrrdWrite(file, nrrd, nio)) { |
1046 |
biffAddf(NRRD, "%s:", me); |
||
1047 |
airMopError(mop); return 1; |
||
1048 |
} |
||
1049 |
|||
1050 |
12 |
airMopOkay(mop); |
|
1051 |
12 |
return 0; |
|
1052 |
12 |
} |
|
1053 |
|||
1054 |
int |
||
1055 |
nrrdSaveMulti(const char *fnameFormat, const Nrrd *const *nin, |
||
1056 |
unsigned int ninLen, unsigned int numStart, NrrdIoState *nio) { |
||
1057 |
static const char me[]="nrrdSaveMulti"; |
||
1058 |
char *fname; |
||
1059 |
airArray *mop; |
||
1060 |
unsigned int nii; |
||
1061 |
|||
1062 |
if (!( fnameFormat && nin )) { |
||
1063 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
1064 |
return 1; |
||
1065 |
} |
||
1066 |
if (!( _nrrdContainsPercentThisAndMore(fnameFormat, 'u') )) { |
||
1067 |
biffAddf(NRRD, "%s: given format \"%s\" doesn't seem to " |
||
1068 |
"have the \"%%u\" conversion specification to sprintf " |
||
1069 |
"an unsigned int\n", me, fnameFormat); |
||
1070 |
return 1; |
||
1071 |
} |
||
1072 |
|||
1073 |
mop = airMopNew(); |
||
1074 |
/* should be big enough for the number replacing the format sequence */ |
||
1075 |
fname = AIR_CALLOC(strlen(fnameFormat) + 128, char); |
||
1076 |
if (!(fname)) { |
||
1077 |
biffAddf(NRRD, "%s: couldn't allocate local fname buffer", me); |
||
1078 |
airMopError(mop); return 1; |
||
1079 |
} |
||
1080 |
airMopAdd(mop, fname, airFree, airMopAlways); |
||
1081 |
|||
1082 |
for (nii=0; nii<ninLen; nii++) { |
||
1083 |
unsigned int num; |
||
1084 |
num = numStart + nii; |
||
1085 |
sprintf(fname, fnameFormat, num); |
||
1086 |
if (nrrdSave(fname, nin[nii], nio)) { |
||
1087 |
biffAddf(NRRD, "%s: trouble saving nin[%u] to %s", me, nii, fname); |
||
1088 |
airMopError(mop); return 1; |
||
1089 |
} |
||
1090 |
/* HEY: GLK hopes that the nio doesn't have any state that needs |
||
1091 |
resetting, but we can't call nrrdIoStateInit() because that |
||
1092 |
would negate the purpose of sending in the nio for all but the |
||
1093 |
first saved nrrd */ |
||
1094 |
} |
||
1095 |
|||
1096 |
airMopOkay(mop); |
||
1097 |
return 0; |
||
1098 |
} |
Generated by: GCOVR (Version 3.3) |