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 |
|
|
#define MAGIC1 "# vtk DataFile Version 1.0" |
28 |
|
|
#define MAGIC2 "# vtk DataFile Version 2.0" |
29 |
|
|
#define MAGIC3 "# vtk DataFile Version 3.0" |
30 |
|
|
|
31 |
|
|
int |
32 |
|
|
_nrrdFormatVTK_available(void) { |
33 |
|
|
|
34 |
|
4 |
return AIR_TRUE; |
35 |
|
|
} |
36 |
|
|
|
37 |
|
|
int |
38 |
|
|
_nrrdFormatVTK_nameLooksLike(const char *fname) { |
39 |
|
|
|
40 |
|
|
return airEndsWith(fname, NRRD_EXT_VTK); |
41 |
|
|
} |
42 |
|
|
|
43 |
|
|
int |
44 |
|
|
_nrrdFormatVTK_fitsInto(const Nrrd *nrrd, const NrrdEncoding *encoding, |
45 |
|
|
int useBiff) { |
46 |
|
|
static const char me[]="_nrrdFormatVTK_fitsInto"; |
47 |
|
|
|
48 |
|
|
if (!( nrrd && encoding )) { |
49 |
|
|
biffMaybeAddf(useBiff, NRRD, "%s: got NULL nrrd (%p) or encoding (%p)", |
50 |
|
|
me, AIR_CVOIDP(nrrd), AIR_CVOIDP(encoding)); |
51 |
|
|
return AIR_FALSE; |
52 |
|
|
} |
53 |
|
|
if (!( nrrdEncodingRaw == encoding || nrrdEncodingAscii == encoding)) { |
54 |
|
|
biffMaybeAddf(useBiff, NRRD, "%s: encoding can only be %s or %s", me, |
55 |
|
|
nrrdEncodingRaw->name, nrrdEncodingAscii->name); |
56 |
|
|
return AIR_FALSE; |
57 |
|
|
} |
58 |
|
|
if (!( nrrdTypeUChar == nrrd->type |
59 |
|
|
|| nrrdTypeChar == nrrd->type |
60 |
|
|
|| nrrdTypeUShort == nrrd->type |
61 |
|
|
|| nrrdTypeShort == nrrd->type |
62 |
|
|
|| nrrdTypeUInt == nrrd->type |
63 |
|
|
|| nrrdTypeInt == nrrd->type |
64 |
|
|
|| nrrdTypeFloat == nrrd->type |
65 |
|
|
|| nrrdTypeDouble == nrrd->type )) { |
66 |
|
|
biffMaybeAddf(useBiff, NRRD, |
67 |
|
|
"%s: type %s doesn't fit in VTK (as currently implemented)", |
68 |
|
|
me, airEnumStr(nrrdType, nrrd->type)); |
69 |
|
|
return AIR_FALSE; |
70 |
|
|
} |
71 |
|
|
if (!( 3 == nrrd->dim |
72 |
|
|
|| (4 == nrrd->dim && 3 == nrrd->axis[0].size) |
73 |
|
|
|| (4 == nrrd->dim && 9 == nrrd->axis[0].size) )) { |
74 |
|
|
biffMaybeAddf(useBiff, NRRD, "%s: nrrd didn't look like a volume of " |
75 |
|
|
"scalars, vectors, or matrices", me); |
76 |
|
|
return AIR_FALSE; |
77 |
|
|
} |
78 |
|
|
return AIR_TRUE; |
79 |
|
|
} |
80 |
|
|
|
81 |
|
|
int |
82 |
|
|
_nrrdFormatVTK_contentStartsLike(NrrdIoState *nio) { |
83 |
|
|
|
84 |
|
|
return (!strcmp(MAGIC1, nio->line) |
85 |
|
|
|| !strcmp(MAGIC2, nio->line) |
86 |
|
|
|| !strcmp(MAGIC3, nio->line)); |
87 |
|
|
} |
88 |
|
|
|
89 |
|
|
int |
90 |
|
|
_nrrdFormatVTK_read(FILE *file, Nrrd *nrrd, NrrdIoState *nio) { |
91 |
|
|
static const char me[]="_nrrdReadVTK"; |
92 |
|
|
char *three[3]; |
93 |
|
|
int sx, sy, sz, ret, N; |
94 |
|
|
double xm=0.0, ym=0.0, zm=0.0, xs=1.0, ys=1.0, zs=1.0; |
95 |
|
|
airArray *mop; |
96 |
|
|
unsigned int llen; |
97 |
|
|
|
98 |
|
|
if (!_nrrdFormatVTK_contentStartsLike(nio)) { |
99 |
|
|
biffAddf(NRRD, "%s: this doesn't look like a %s file", me, |
100 |
|
|
nrrdFormatVTK->name); |
101 |
|
|
return 1; |
102 |
|
|
} |
103 |
|
|
|
104 |
|
|
#define GETLINE(what) \ |
105 |
|
|
do { \ |
106 |
|
|
ret = _nrrdOneLine(&llen, nio, file); \ |
107 |
|
|
} while (!ret && (1 == llen)); \ |
108 |
|
|
if (ret || !llen) { \ |
109 |
|
|
biffAddf(NRRD, "%s: couldn't get " #what " line", me); \ |
110 |
|
|
return 1; \ |
111 |
|
|
} |
112 |
|
|
|
113 |
|
|
/* read in content */ |
114 |
|
|
GETLINE(content); |
115 |
|
|
if (strcmp(NRRD_UNKNOWN, nio->line)) { |
116 |
|
|
if (!(nrrd->content = airStrdup(nio->line))) { |
117 |
|
|
biffAddf(NRRD, "%s: couldn't read or copy content string", me); |
118 |
|
|
return 1; |
119 |
|
|
} |
120 |
|
|
} |
121 |
|
|
GETLINE(encoding); airToUpper(nio->line); |
122 |
|
|
if (!strcmp("ASCII", nio->line)) { |
123 |
|
|
nio->encoding = nrrdEncodingAscii; |
124 |
|
|
} else if (!strcmp("BINARY", nio->line)) { |
125 |
|
|
nio->encoding = nrrdEncodingRaw; |
126 |
|
|
} else { |
127 |
|
|
biffAddf(NRRD, "%s: encoding \"%s\" wasn't \"ASCII\" or \"BINARY\"", |
128 |
|
|
me, nio->line); |
129 |
|
|
return 1; |
130 |
|
|
} |
131 |
|
|
GETLINE(DATASET); airToUpper(nio->line); |
132 |
|
|
if (!strstr(nio->line, "STRUCTURED_POINTS")) { |
133 |
|
|
biffAddf(NRRD, |
134 |
|
|
"%s: sorry, only STRUCTURED_POINTS data is nrrd-ready", me); |
135 |
|
|
return 1; |
136 |
|
|
} |
137 |
|
|
GETLINE(DIMENSIONS); airToUpper(nio->line); |
138 |
|
|
if (!strstr(nio->line, "DIMENSIONS") |
139 |
|
|
|| 3 != sscanf(nio->line, "DIMENSIONS %d %d %d", &sx, &sy, &sz)) { |
140 |
|
|
biffAddf(NRRD, "%s: couldn't parse DIMENSIONS line (\"%s\")", |
141 |
|
|
me, nio->line); |
142 |
|
|
return 1; |
143 |
|
|
} |
144 |
|
|
GETLINE(next); airToUpper(nio->line); |
145 |
|
|
while (!strstr(nio->line, "POINT_DATA")) { |
146 |
|
|
if (strstr(nio->line, "ORIGIN")) { |
147 |
|
|
if (3 != sscanf(nio->line, "ORIGIN %lf %lf %lf", &xm, &ym, &zm)) { |
148 |
|
|
biffAddf(NRRD, "%s: couldn't parse ORIGIN line (\"%s\")", |
149 |
|
|
me, nio->line); |
150 |
|
|
return 1; |
151 |
|
|
} |
152 |
|
|
} else if (strstr(nio->line, "SPACING")) { |
153 |
|
|
if (3 != sscanf(nio->line, "SPACING %lf %lf %lf", |
154 |
|
|
&xs, &ys, &zs)) { |
155 |
|
|
biffAddf(NRRD, "%s: couldn't parse SPACING line (\"%s\")", |
156 |
|
|
me, nio->line); |
157 |
|
|
return 1; |
158 |
|
|
} |
159 |
|
|
} else if (strstr(nio->line, "ASPECT_RATIO")) { |
160 |
|
|
if (3 != sscanf(nio->line, "ASPECT_RATIO %lf %lf %lf", |
161 |
|
|
&xs, &ys, &zs)) { |
162 |
|
|
biffAddf(NRRD, "%s: couldn't parse ASPECT_RATIO line (\"%s\")", |
163 |
|
|
me, nio->line); |
164 |
|
|
return 1; |
165 |
|
|
} |
166 |
|
|
} |
167 |
|
|
GETLINE(next); airToUpper(nio->line); |
168 |
|
|
} |
169 |
|
|
if (1 != sscanf(nio->line, "POINT_DATA %d", &N)) { |
170 |
|
|
biffAddf(NRRD, "%s: couldn't parse POINT_DATA line (\"%s\")", |
171 |
|
|
me, nio->line); |
172 |
|
|
return 1; |
173 |
|
|
} |
174 |
|
|
if (N != sx*sy*sz) { |
175 |
|
|
biffAddf(NRRD, |
176 |
|
|
"%s: product of sizes (%d*%d*%d == %d) != # elements (%d)", |
177 |
|
|
me, sx, sy, sz, sx*sy*sz, N); |
178 |
|
|
return 1; |
179 |
|
|
} |
180 |
|
|
GETLINE(attribute declaration); |
181 |
|
|
mop = airMopNew(); |
182 |
|
|
if (3 != airParseStrS(three, nio->line, AIR_WHITESPACE, 3, AIR_FALSE)) { |
183 |
|
|
biffAddf(NRRD, |
184 |
|
|
"%s: didn't see three words in attribute declaration \"%s\"", |
185 |
|
|
me, nio->line); |
186 |
|
|
return 1; |
187 |
|
|
} |
188 |
|
|
airMopAdd(mop, three[0], airFree, airMopAlways); |
189 |
|
|
airMopAdd(mop, three[1], airFree, airMopAlways); |
190 |
|
|
airMopAdd(mop, three[2], airFree, airMopAlways); |
191 |
|
|
airToLower(three[2]); |
192 |
|
|
if (!strcmp(three[2], "bit")) { |
193 |
|
|
if (nrrdEncodingAscii == nio->encoding) { |
194 |
|
|
fprintf(stderr, "%s: WARNING: \"bit\"-type data will be read in as " |
195 |
|
|
"unsigned char\n", me); |
196 |
|
|
nrrd->type = nrrdTypeUChar; |
197 |
|
|
} else { |
198 |
|
|
biffAddf(NRRD, "%s: can't read in \"bit\"-type data as BINARY", me); |
199 |
|
|
return 1; |
200 |
|
|
} |
201 |
|
|
} else if (!strcmp(three[2], "unsigned_char")) { |
202 |
|
|
nrrd->type = nrrdTypeUChar; |
203 |
|
|
} else if (!strcmp(three[2], "char")) { |
204 |
|
|
nrrd->type = nrrdTypeChar; |
205 |
|
|
} else if (!strcmp(three[2], "unsigned_short")) { |
206 |
|
|
nrrd->type = nrrdTypeUShort; |
207 |
|
|
} else if (!strcmp(three[2], "short")) { |
208 |
|
|
nrrd->type = nrrdTypeShort; |
209 |
|
|
} else if (!strcmp(three[2], "unsigned_int")) { |
210 |
|
|
nrrd->type = nrrdTypeUInt; |
211 |
|
|
} else if (!strcmp(three[2], "int")) { |
212 |
|
|
nrrd->type = nrrdTypeInt; |
213 |
|
|
} else if (!strcmp(three[2], "float")) { |
214 |
|
|
nrrd->type = nrrdTypeFloat; |
215 |
|
|
} else if (!strcmp(three[2], "double")) { |
216 |
|
|
nrrd->type = nrrdTypeDouble; |
217 |
|
|
} else { |
218 |
|
|
/* "unsigned_long" and "long" fall in here- I don't know what |
219 |
|
|
the VTK people mean by these types, since always mean different |
220 |
|
|
things on 32-bit versus 64-bit architectures */ |
221 |
|
|
biffAddf(NRRD, "%s: type \"%s\" not recognized", me, three[2]); |
222 |
|
|
airMopError(mop); return 1; |
223 |
|
|
} |
224 |
|
|
airToUpper(three[0]); |
225 |
|
|
if (!strncmp("SCALARS", three[0], strlen("SCALARS"))) { |
226 |
|
|
GETLINE(LOOKUP_TABLE); airToUpper(nio->line); |
227 |
|
|
if (strcmp(nio->line, "LOOKUP_TABLE DEFAULT")) { |
228 |
|
|
biffAddf(NRRD, |
229 |
|
|
"%s: sorry, can only deal with default LOOKUP_TABLE", me); |
230 |
|
|
airMopError(mop); return 1; |
231 |
|
|
} |
232 |
|
|
nrrd->dim = 3; |
233 |
|
|
nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize, |
234 |
|
|
AIR_CAST(size_t, sx), |
235 |
|
|
AIR_CAST(size_t, sy), |
236 |
|
|
AIR_CAST(size_t, sz)); |
237 |
|
|
nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, xs, ys, zs); |
238 |
|
|
nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, xm, ym, zm); |
239 |
|
|
} else if (!strncmp("VECTORS", three[0], strlen("VECTORS"))) { |
240 |
|
|
nrrd->dim = 4; |
241 |
|
|
nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize, |
242 |
|
|
AIR_CAST(size_t, 3), |
243 |
|
|
AIR_CAST(size_t, sx), |
244 |
|
|
AIR_CAST(size_t, sy), |
245 |
|
|
AIR_CAST(size_t, sz)); |
246 |
|
|
nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, AIR_NAN, xs, ys, zs); |
247 |
|
|
nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, AIR_NAN, xm, ym, zm); |
248 |
|
|
nrrd->axis[0].kind = nrrdKind3Vector; |
249 |
|
|
} else if (!strncmp("TENSORS", three[0], strlen("TENSORS"))) { |
250 |
|
|
nrrd->dim = 4; |
251 |
|
|
nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize, |
252 |
|
|
AIR_CAST(size_t, 9), |
253 |
|
|
AIR_CAST(size_t, sx), |
254 |
|
|
AIR_CAST(size_t, sy), |
255 |
|
|
AIR_CAST(size_t, sz)); |
256 |
|
|
nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, AIR_NAN, xs, ys, zs); |
257 |
|
|
nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, AIR_NAN, xm, ym, zm); |
258 |
|
|
nrrd->axis[0].kind = nrrdKind3DMatrix; |
259 |
|
|
} else { |
260 |
|
|
biffAddf(NRRD, |
261 |
|
|
"%s: sorry, can only deal with SCALARS, VECTORS, and TENSORS " |
262 |
|
|
"currently, so couldn't parse attribute declaration \"%s\"", |
263 |
|
|
me, nio->line); |
264 |
|
|
airMopError(mop); return 1; |
265 |
|
|
} |
266 |
|
|
if (!nio->skipData) { |
267 |
|
|
if (_nrrdCalloc(nrrd, nio, file)) { |
268 |
|
|
biffAddf(NRRD, "%s: couldn't allocate memory for data", me); |
269 |
|
|
return 1; |
270 |
|
|
} |
271 |
|
|
if (nio->encoding->read(file, nrrd->data, nrrdElementNumber(nrrd), |
272 |
|
|
nrrd, nio)) { |
273 |
|
|
biffAddf(NRRD, "%s:", me); |
274 |
|
|
return 1; |
275 |
|
|
} |
276 |
|
|
if (1 < nrrdElementSize(nrrd) |
277 |
|
|
&& nio->encoding->endianMatters |
278 |
|
|
&& airMyEndian() != airEndianBig) { |
279 |
|
|
/* encoding exposes endianness, and its big, but we aren't */ |
280 |
|
|
nrrdSwapEndian(nrrd); |
281 |
|
|
} |
282 |
|
|
} else { |
283 |
|
|
nrrd->data = NULL; |
284 |
|
|
} |
285 |
|
|
|
286 |
|
|
airMopOkay(mop); |
287 |
|
|
return 0; |
288 |
|
|
} |
289 |
|
|
|
290 |
|
|
/* this strongly assumes that nrrdFitsInFormat() was true */ |
291 |
|
|
int |
292 |
|
|
_nrrdFormatVTK_write(FILE *file, const Nrrd *_nrrd, NrrdIoState *nio) { |
293 |
|
|
static const char me[]="_nrrdFormatVTK_write"; |
294 |
|
|
int i, sx, sy, sz, sax; |
295 |
|
|
double xs, ys, zs, xm, ym, zm; |
296 |
|
|
char type[AIR_STRLEN_MED], name[AIR_STRLEN_SMALL]; |
297 |
|
|
Nrrd *nrrd; |
298 |
|
|
airArray *mop; |
299 |
|
|
|
300 |
|
|
/* HEY: should this copy be done more conservatively */ |
301 |
|
|
mop = airMopNew(); |
302 |
|
|
airMopAdd(mop, nrrd=nrrdNew(), (airMopper)nrrdNuke, airMopAlways); |
303 |
|
|
if (nrrdCopy(nrrd, _nrrd)) { |
304 |
|
|
biffAddf(NRRD, "%s: couldn't make private copy", me); |
305 |
|
|
airMopError(mop); return 1; |
306 |
|
|
} |
307 |
|
|
if (!( 3 == nrrd->dim || |
308 |
|
|
(4 == nrrd->dim && (3 == nrrd->axis[0].size || |
309 |
|
|
9 == nrrd->axis[0].size)) )) { |
310 |
|
|
biffAddf(NRRD, "%s: doesn't seem to be scalar, vector, or matrix", me); |
311 |
|
|
airMopError(mop); return 1; |
312 |
|
|
} |
313 |
|
|
sax = nrrd->dim - 3; |
314 |
|
|
xs = nrrd->axis[sax+0].spacing; |
315 |
|
|
ys = nrrd->axis[sax+1].spacing; |
316 |
|
|
zs = nrrd->axis[sax+2].spacing; |
317 |
|
|
if (!( AIR_EXISTS(xs) && AIR_EXISTS(ys) && AIR_EXISTS(zs) )) { |
318 |
|
|
xs = ys = zs = 1.0; |
319 |
|
|
} |
320 |
|
|
xm = nrrd->axis[sax+0].min; |
321 |
|
|
ym = nrrd->axis[sax+1].min; |
322 |
|
|
zm = nrrd->axis[sax+2].min; |
323 |
|
|
if (!( AIR_EXISTS(xm) && AIR_EXISTS(ym) && AIR_EXISTS(zm) )) { |
324 |
|
|
xm = ym = zm = 0.0; |
325 |
|
|
} |
326 |
|
|
sx = AIR_CAST(int, nrrd->axis[sax+0].size); |
327 |
|
|
sy = AIR_CAST(int, nrrd->axis[sax+1].size); |
328 |
|
|
sz = AIR_CAST(int, nrrd->axis[sax+2].size); |
329 |
|
|
|
330 |
|
|
switch(nrrd->type) { |
331 |
|
|
case nrrdTypeUChar: |
332 |
|
|
strcpy(type, "unsigned_char"); |
333 |
|
|
break; |
334 |
|
|
case nrrdTypeChar: |
335 |
|
|
strcpy(type, "char"); |
336 |
|
|
break; |
337 |
|
|
case nrrdTypeUShort: |
338 |
|
|
strcpy(type, "unsigned_short"); |
339 |
|
|
break; |
340 |
|
|
case nrrdTypeShort: |
341 |
|
|
strcpy(type, "short"); |
342 |
|
|
break; |
343 |
|
|
case nrrdTypeUInt: |
344 |
|
|
strcpy(type, "unsigned_int"); |
345 |
|
|
break; |
346 |
|
|
case nrrdTypeInt: |
347 |
|
|
strcpy(type, "int"); |
348 |
|
|
break; |
349 |
|
|
case nrrdTypeFloat: |
350 |
|
|
strcpy(type, "float"); |
351 |
|
|
break; |
352 |
|
|
case nrrdTypeDouble: |
353 |
|
|
strcpy(type, "double"); |
354 |
|
|
break; |
355 |
|
|
default: |
356 |
|
|
biffAddf(NRRD, "%s: can't put %s-type nrrd into VTK", me, |
357 |
|
|
airEnumStr(nrrdType, nrrd->type)); |
358 |
|
|
airMopError(mop); return 1; |
359 |
|
|
} |
360 |
|
|
fprintf(file, "%s\n", MAGIC3); |
361 |
|
|
/* there is a file-format-imposed limit on the length of the "content" */ |
362 |
|
|
if (nrrd->content) { |
363 |
|
|
/* when the "250" below was previously "255", vtk didn't deal */ |
364 |
|
|
for (i=0; i<=250 && nrrd->content[i]; i++) { |
365 |
|
|
fputc(nrrd->content[i], file); |
366 |
|
|
} |
367 |
|
|
fputc('\n', file); |
368 |
|
|
} else { |
369 |
|
|
fprintf(file, NRRD_UNKNOWN "\n"); |
370 |
|
|
} |
371 |
|
|
if (nrrdEncodingRaw == nio->encoding) { |
372 |
|
|
fprintf(file, "BINARY\n"); |
373 |
|
|
} else { |
374 |
|
|
fprintf(file, "ASCII\n"); |
375 |
|
|
} |
376 |
|
|
fprintf(file, "DATASET STRUCTURED_POINTS\n"); |
377 |
|
|
fprintf(file, "DIMENSIONS %d %d %d\n", sx, sy, sz); |
378 |
|
|
fprintf(file, "ORIGIN %g %g %g\n", xm, ym, zm); |
379 |
|
|
fprintf(file, "SPACING %g %g %g\n", xs, ys, zs); |
380 |
|
|
fprintf(file, "POINT_DATA %d\n", sx*sy*sz); |
381 |
|
|
airSrandMT(AIR_CAST(unsigned int, airTime())); |
382 |
|
|
sprintf(name, "nrrd%05d", airRandInt(100000)); |
383 |
|
|
if (3 == nrrd->dim) { |
384 |
|
|
fprintf(file, "SCALARS %s %s\n", name, type); |
385 |
|
|
fprintf(file, "LOOKUP_TABLE default\n"); |
386 |
|
|
} else { |
387 |
|
|
/* 4 == nrrd->dim */ |
388 |
|
|
if (3 == nrrd->axis[0].size) { |
389 |
|
|
fprintf(file, "VECTORS %s %s\n", name, type); |
390 |
|
|
} else { |
391 |
|
|
fprintf(file, "TENSORS %s %s\n", name, type); |
392 |
|
|
} |
393 |
|
|
} |
394 |
|
|
if (1 < nrrdElementSize(nrrd) |
395 |
|
|
&& nio->encoding->endianMatters |
396 |
|
|
&& airMyEndian() != airEndianBig) { |
397 |
|
|
/* encoding exposes endianness, and we're not big, as req.d by VTK */ |
398 |
|
|
nrrdSwapEndian(nrrd); |
399 |
|
|
} |
400 |
|
|
if (nio->encoding->write(file, nrrd->data, nrrdElementNumber(nrrd), |
401 |
|
|
nrrd, nio)) { |
402 |
|
|
biffAddf(NRRD, "%s:", me); |
403 |
|
|
airMopError(mop); return 1; |
404 |
|
|
} |
405 |
|
|
|
406 |
|
|
airMopOkay(mop); |
407 |
|
|
return 0; |
408 |
|
|
} |
409 |
|
|
|
410 |
|
|
const NrrdFormat |
411 |
|
|
_nrrdFormatVTK = { |
412 |
|
|
"VTK", |
413 |
|
|
AIR_FALSE, /* isImage */ |
414 |
|
|
AIR_TRUE, /* readable */ |
415 |
|
|
AIR_FALSE, /* usesDIO */ |
416 |
|
|
_nrrdFormatVTK_available, |
417 |
|
|
_nrrdFormatVTK_nameLooksLike, |
418 |
|
|
_nrrdFormatVTK_fitsInto, |
419 |
|
|
_nrrdFormatVTK_contentStartsLike, |
420 |
|
|
_nrrdFormatVTK_read, |
421 |
|
|
_nrrdFormatVTK_write |
422 |
|
|
}; |
423 |
|
|
|
424 |
|
|
const NrrdFormat *const |
425 |
|
|
nrrdFormatVTK = &_nrrdFormatVTK; |