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 |
******** nrrdSplice() |
||
29 |
** |
||
30 |
** (opposite of nrrdSlice): replaces one slice of a nrrd with |
||
31 |
** another nrrd. Will allocate memory for output only if nout != nin. |
||
32 |
*/ |
||
33 |
int |
||
34 |
nrrdSplice(Nrrd *nout, const Nrrd *nin, const Nrrd *nslice, |
||
35 |
unsigned int axis, size_t pos) { |
||
36 |
static const char me[]="nrrdSplice", func[]="splice"; |
||
37 |
size_t |
||
38 |
I, |
||
39 |
rowLen, /* length of segment */ |
||
40 |
colStep, /* distance between start of each segment */ |
||
41 |
colLen; /* number of periods */ |
||
42 |
unsigned int ai; |
||
43 |
char *src, *dest, *sliceCont; |
||
44 |
16 |
char stmp[2][AIR_STRLEN_SMALL]; |
|
45 |
|||
46 |
✗✓ | 8 |
if (!(nin && nout && nslice)) { |
47 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
48 |
return 1; |
||
49 |
} |
||
50 |
✗✓ | 8 |
if (nout == nslice) { |
51 |
biffAddf(NRRD, "%s: nout==nslice disallowed", me); |
||
52 |
return 1; |
||
53 |
} |
||
54 |
|||
55 |
/* check that desired slice location is legit */ |
||
56 |
✗✓ | 8 |
if (!( axis < nin->dim )) { |
57 |
biffAddf(NRRD, "%s: slice axis %d out of bounds (0 to %d)", |
||
58 |
me, axis, nin->dim-1); |
||
59 |
return 1; |
||
60 |
} |
||
61 |
✗✓ | 8 |
if (!( pos < nin->axis[axis].size )) { |
62 |
biffAddf(NRRD, "%s: position %s out of bounds (0 to %s)", me, |
||
63 |
airSprintSize_t(stmp[0], pos), |
||
64 |
airSprintSize_t(stmp[1], nin->axis[axis].size-1)); |
||
65 |
return 1; |
||
66 |
} |
||
67 |
|||
68 |
/* check that slice will fit in nin */ |
||
69 |
✓✗✗✓ |
16 |
if (nrrdCheck(nslice) || nrrdCheck(nin)) { |
70 |
biffAddf(NRRD, "%s: input or slice not valid nrrd", me); |
||
71 |
return 1; |
||
72 |
} |
||
73 |
✗✓ | 8 |
if (!( nin->dim-1 == nslice->dim )) { |
74 |
biffAddf(NRRD, "%s: dim of slice (%d) not one less than " |
||
75 |
"dim of input (%d)", me, nslice->dim, nin->dim); |
||
76 |
return 1; |
||
77 |
} |
||
78 |
✗✓ | 8 |
if (!( nin->type == nslice->type )) { |
79 |
biffAddf(NRRD, "%s: type of slice (%s) != type of input (%s)", |
||
80 |
me, airEnumStr(nrrdType, nslice->type), |
||
81 |
airEnumStr(nrrdType, nin->type)); |
||
82 |
return 1; |
||
83 |
} |
||
84 |
✗✓ | 8 |
if (nrrdTypeBlock == nin->type) { |
85 |
if (!( nin->blockSize == nslice->blockSize )) { |
||
86 |
biffAddf(NRRD, "%s: input's blockSize (%s) != subvolume's (%s)", me, |
||
87 |
airSprintSize_t(stmp[0], nin->blockSize), |
||
88 |
airSprintSize_t(stmp[1], nslice->blockSize)); |
||
89 |
return 1; |
||
90 |
} |
||
91 |
} |
||
92 |
✓✓ | 64 |
for (ai=0; ai<nslice->dim; ai++) { |
93 |
24 |
const unsigned int indexOffset = (ai >= axis); |
|
94 |
unsigned int foundExitCondition = 0; |
||
95 |
✓✗ | 24 |
if(indexOffset){ |
96 |
✗✓ | 24 |
if( nin->axis[ai + 1].size != nslice ->axis[ai].size ) foundExitCondition = 1; |
97 |
} |
||
98 |
else if( nin->axis[ai].size != nslice ->axis[ai].size ) foundExitCondition = 1; |
||
99 |
✗✓ | 24 |
if ( foundExitCondition ) { |
100 |
biffAddf(NRRD, "%s: input ax %u size (%s) != slices ax %u size (%s)", |
||
101 |
me, ai + indexOffset, |
||
102 |
airSprintSize_t(stmp[0], nin->axis[ai + indexOffset].size), ai, |
||
103 |
airSprintSize_t(stmp[1], nslice->axis[ai].size)); |
||
104 |
return 1; |
||
105 |
} |
||
106 |
24 |
} |
|
107 |
|||
108 |
✓✗ | 8 |
if (nout != nin) { |
109 |
✗✓ | 8 |
if (nrrdCopy(nout, nin)) { |
110 |
biffAddf(NRRD, "%s:", me); |
||
111 |
return 1; |
||
112 |
} |
||
113 |
} |
||
114 |
/* else we're going to splice in place */ |
||
115 |
|||
116 |
/* the following was copied from nrrdSlice() */ |
||
117 |
/* set up control variables */ |
||
118 |
rowLen = colLen = 1; |
||
119 |
✓✓ | 80 |
for (ai=0; ai<nin->dim; ai++) { |
120 |
✗✓ | 32 |
if (ai < axis) { |
121 |
rowLen *= nin->axis[ai].size; |
||
122 |
✓✓ | 32 |
} else if (ai > axis) { |
123 |
24 |
colLen *= nin->axis[ai].size; |
|
124 |
24 |
} |
|
125 |
} |
||
126 |
8 |
rowLen *= nrrdElementSize(nin); |
|
127 |
8 |
colStep = rowLen*nin->axis[axis].size; |
|
128 |
|||
129 |
/* the skinny */ |
||
130 |
8 |
src = (char *)nout->data; /* switched src,dest from nrrdSlice() */ |
|
131 |
8 |
dest = (char *)nslice->data; |
|
132 |
8 |
src += rowLen*pos; |
|
133 |
✓✓ | 1556656 |
for (I=0; I<colLen; I++) { |
134 |
/* HEY: replace with AIR_MEMCPY() or similar, when applicable */ |
||
135 |
778320 |
memcpy(src, dest, rowLen); /* switched src,dest from nrrdSlice() */ |
|
136 |
778320 |
src += colStep; |
|
137 |
778320 |
dest += rowLen; |
|
138 |
} |
||
139 |
|||
140 |
8 |
sliceCont = _nrrdContentGet(nslice); |
|
141 |
✗✓ | 8 |
if (nrrdContentSet_va(nout, func, nin, "%s,%d,%s", sliceCont, axis, |
142 |
8 |
airSprintSize_t(stmp[0], pos))) { |
|
143 |
biffAddf(NRRD, "%s:", me); |
||
144 |
free(sliceCont); return 1; |
||
145 |
} |
||
146 |
8 |
free(sliceCont); |
|
147 |
/* basic info copied by nrrdCopy above */ |
||
148 |
|||
149 |
8 |
return 0; |
|
150 |
8 |
} |
|
151 |
|||
152 |
/* |
||
153 |
******** nrrdInset() |
||
154 |
** |
||
155 |
** (opposite of nrrdCrop()) replace some sub-volume inside a nrrd with |
||
156 |
** another given nrrd. |
||
157 |
** |
||
158 |
*/ |
||
159 |
int |
||
160 |
nrrdInset(Nrrd *nout, const Nrrd *nin, const Nrrd *nsub, const size_t *min) { |
||
161 |
static const char me[]="nrrdInset", func[] = "inset"; |
||
162 |
char buff1[NRRD_DIM_MAX*30], buff2[AIR_STRLEN_SMALL]; |
||
163 |
unsigned int ai; |
||
164 |
size_t I, |
||
165 |
lineSize, /* #bytes in one scanline to be copied */ |
||
166 |
typeSize, /* size of data type */ |
||
167 |
cIn[NRRD_DIM_MAX], /* coords for line start, in input */ |
||
168 |
cOut[NRRD_DIM_MAX], /* coords for line start, in output */ |
||
169 |
szIn[NRRD_DIM_MAX], |
||
170 |
szOut[NRRD_DIM_MAX], |
||
171 |
idxIn, idxOut, /* linear indices for input and output */ |
||
172 |
numLines; /* number of scanlines in output nrrd */ |
||
173 |
char *dataIn, *dataOut, *subCont, stmp[3][AIR_STRLEN_SMALL]; |
||
174 |
|||
175 |
/* errors */ |
||
176 |
if (!(nout && nin && nsub && min)) { |
||
177 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
178 |
return 1; |
||
179 |
} |
||
180 |
if (nout == nsub) { |
||
181 |
biffAddf(NRRD, "%s: nout==nsub disallowed", me); |
||
182 |
return 1; |
||
183 |
} |
||
184 |
if (nrrdCheck(nin)) { |
||
185 |
biffAddf(NRRD, "%s: input not valid nrrd", me); |
||
186 |
return 1; |
||
187 |
} |
||
188 |
if (nrrdCheck(nsub)) { |
||
189 |
biffAddf(NRRD, "%s: subvolume not valid nrrd", me); |
||
190 |
return 1; |
||
191 |
} |
||
192 |
if (!( nin->dim == nsub->dim )) { |
||
193 |
biffAddf(NRRD, "%s: input's dim (%d) != subvolume's dim (%d)", |
||
194 |
me, nin->dim, nsub->dim); |
||
195 |
return 1; |
||
196 |
} |
||
197 |
if (!( nin->type == nsub->type )) { |
||
198 |
biffAddf(NRRD, "%s: input's type (%s) != subvolume's type (%s)", me, |
||
199 |
airEnumStr(nrrdType, nin->type), |
||
200 |
airEnumStr(nrrdType, nsub->type)); |
||
201 |
return 1; |
||
202 |
} |
||
203 |
if (nrrdTypeBlock == nin->type) { |
||
204 |
if (!( nin->blockSize == nsub->blockSize )) { |
||
205 |
biffAddf(NRRD, "%s: input's blockSize (%s) != subvolume's (%s)", me, |
||
206 |
airSprintSize_t(stmp[0], nin->blockSize), |
||
207 |
airSprintSize_t(stmp[1], nsub->blockSize)); |
||
208 |
return 1; |
||
209 |
} |
||
210 |
} |
||
211 |
for (ai=0; ai<nin->dim; ai++) { |
||
212 |
if (!( min[ai] + nsub->axis[ai].size - 1 <= nin->axis[ai].size - 1)) { |
||
213 |
biffAddf(NRRD, "%s: axis %d range of inset indices [%s,%s] not within " |
||
214 |
"input indices [0,%s]", me, ai, |
||
215 |
airSprintSize_t(stmp[0], min[ai]), |
||
216 |
airSprintSize_t(stmp[1], min[ai] + nsub->axis[ai].size - 1), |
||
217 |
airSprintSize_t(stmp[2], nin->axis[ai].size - 1)); |
||
218 |
return 1; |
||
219 |
} |
||
220 |
} |
||
221 |
|||
222 |
if (nout != nin) { |
||
223 |
if (nrrdCopy(nout, nin)) { |
||
224 |
biffAddf(NRRD, "%s:", me); |
||
225 |
return 1; |
||
226 |
} |
||
227 |
} |
||
228 |
/* else we're going to inset in place */ |
||
229 |
|||
230 |
/* WARNING: following code copied/modified from nrrdCrop(), |
||
231 |
so the meanings of "in"/"out", "src"/"dest" are all messed up */ |
||
232 |
|||
233 |
nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, szIn); |
||
234 |
nrrdAxisInfoGet_nva(nsub, nrrdAxisInfoSize, szOut); |
||
235 |
numLines = 1; |
||
236 |
for (ai=1; ai<nin->dim; ai++) { |
||
237 |
numLines *= szOut[ai]; |
||
238 |
} |
||
239 |
lineSize = szOut[0]*nrrdElementSize(nin); |
||
240 |
|||
241 |
/* the skinny */ |
||
242 |
typeSize = nrrdElementSize(nin); |
||
243 |
dataIn = (char *)nout->data; |
||
244 |
dataOut = (char *)nsub->data; |
||
245 |
for (ai=0; ai<NRRD_DIM_MAX; ai++) { |
||
246 |
cOut[ai] = 0; |
||
247 |
} |
||
248 |
for (I=0; I<numLines; I++) { |
||
249 |
for (ai=0; ai<nin->dim; ai++) { |
||
250 |
cIn[ai] = cOut[ai] + min[ai]; |
||
251 |
} |
||
252 |
NRRD_INDEX_GEN(idxOut, cOut, szOut, nin->dim); |
||
253 |
NRRD_INDEX_GEN(idxIn, cIn, szIn, nin->dim); |
||
254 |
memcpy(dataIn + idxIn*typeSize, dataOut + idxOut*typeSize, lineSize); |
||
255 |
/* the lowest coordinate in cOut[] will stay zero, since we are |
||
256 |
copying one (1-D) scanline at a time */ |
||
257 |
NRRD_COORD_INCR(cOut, szOut, nin->dim, 1); |
||
258 |
} |
||
259 |
|||
260 |
/* HEY: before Teem version 2.0 figure out nrrdKind stuff here */ |
||
261 |
|||
262 |
strcpy(buff1, "["); |
||
263 |
for (ai=0; ai<nin->dim; ai++) { |
||
264 |
sprintf(buff2, "%s%s", (ai ? "," : ""), |
||
265 |
airSprintSize_t(stmp[0], min[ai])); |
||
266 |
strcat(buff1, buff2); |
||
267 |
} |
||
268 |
strcat(buff1, "]"); |
||
269 |
subCont = _nrrdContentGet(nsub); |
||
270 |
if (nrrdContentSet_va(nout, func, nin, "%s,%s", subCont, buff1)) { |
||
271 |
biffAddf(NRRD, "%s:", me); |
||
272 |
free(subCont); return 1; |
||
273 |
} |
||
274 |
free(subCont); |
||
275 |
/* basic info copied by nrrdCopy above */ |
||
276 |
|||
277 |
return 0; |
||
278 |
} |
||
279 |
|||
280 |
#define MIRROR(N, I, M) \ |
||
281 |
M = (I < 0 ? -I : I); \ |
||
282 |
M = M % (2*N); \ |
||
283 |
M = (M >= N \ |
||
284 |
? 2*N - 1 - M \ |
||
285 |
: M) \ |
||
286 |
|||
287 |
size_t |
||
288 |
_nrrdMirror_64(size_t N, ptrdiff_t I) { |
||
289 |
size_t M; |
||
290 |
|||
291 |
M = (I < 0 ? -I : I); |
||
292 |
M = M % (2*N); |
||
293 |
M = (M >= N |
||
294 |
? 2*N - 1 - M |
||
295 |
: M); |
||
296 |
return M; |
||
297 |
} |
||
298 |
|||
299 |
unsigned int |
||
300 |
_nrrdMirror_32(unsigned int N, int I) { |
||
301 |
unsigned int M; |
||
302 |
|||
303 |
M = (I < 0 ? -I : I); |
||
304 |
M = M % (2*N); |
||
305 |
M = (M >= N |
||
306 |
? 2*N - 1 - M |
||
307 |
: M); |
||
308 |
return M; |
||
309 |
} |
||
310 |
|||
311 |
/* |
||
312 |
******** nrrdPad_va() |
||
313 |
** |
||
314 |
** strictly for padding |
||
315 |
*/ |
||
316 |
int |
||
317 |
nrrdPad_va(Nrrd *nout, const Nrrd *nin, |
||
318 |
const ptrdiff_t *min, const ptrdiff_t *max, int boundary, ...) { |
||
319 |
static const char me[]="nrrdPad_va", func[]="pad"; |
||
320 |
48 |
char buff1[NRRD_DIM_MAX*30], buff2[AIR_STRLEN_MED]; |
|
321 |
24 |
double padValue=AIR_NAN; |
|
322 |
int outside; /* whether current sample in output has any coordinates |
||
323 |
that are outside the input volume (this is per-sample, |
||
324 |
not per-axis) */ |
||
325 |
unsigned int ai; |
||
326 |
24 |
ptrdiff_t |
|
327 |
cIn[NRRD_DIM_MAX]; /* coords for line start, in input */ |
||
328 |
24 |
size_t |
|
329 |
typeSize, |
||
330 |
idxIn, idxOut, /* linear indices for input and output */ |
||
331 |
numOut, /* number of elements in output nrrd */ |
||
332 |
szIn[NRRD_DIM_MAX], |
||
333 |
szOut[NRRD_DIM_MAX], |
||
334 |
cOut[NRRD_DIM_MAX]; /* coords for line start, in output */ |
||
335 |
24 |
va_list ap; |
|
336 |
char *dataIn, *dataOut; |
||
337 |
24 |
char stmp[2][AIR_STRLEN_SMALL]; |
|
338 |
|||
339 |
✗✓ | 24 |
if (!(nout && nin && min && max)) { |
340 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
341 |
return 1; |
||
342 |
} |
||
343 |
✗✓ | 24 |
if (nout == nin) { |
344 |
biffAddf(NRRD, "%s: nout==nin disallowed", me); |
||
345 |
return 1; |
||
346 |
} |
||
347 |
✗✓ | 24 |
if (!AIR_IN_OP(nrrdBoundaryUnknown, boundary, nrrdBoundaryLast)) { |
348 |
biffAddf(NRRD, "%s: boundary behavior %d invalid", me, boundary); |
||
349 |
return 1; |
||
350 |
} |
||
351 |
✗✓ | 24 |
if (nrrdBoundaryWeight == boundary) { |
352 |
biffAddf(NRRD, "%s: boundary strategy %s not applicable here", me, |
||
353 |
airEnumStr(nrrdBoundary, boundary)); |
||
354 |
return 1; |
||
355 |
} |
||
356 |
✗✓ | 24 |
if (nrrdTypeBlock == nin->type && nrrdBoundaryPad == boundary) { |
357 |
biffAddf(NRRD, "%s: with nrrd type %s, boundary %s not valid", me, |
||
358 |
airEnumStr(nrrdType, nrrdTypeBlock), |
||
359 |
airEnumStr(nrrdBoundary, nrrdBoundaryPad)); |
||
360 |
return 1; |
||
361 |
} |
||
362 |
24 |
va_start(ap, boundary); |
|
363 |
✓✓ | 24 |
if (nrrdBoundaryPad == boundary) { |
364 |
✓✗ | 48 |
padValue = va_arg(ap, double); |
365 |
16 |
} |
|
366 |
24 |
va_end(ap); |
|
367 |
✗✗✗✗ ✓ |
24 |
switch(boundary) { |
368 |
case nrrdBoundaryPad: |
||
369 |
case nrrdBoundaryBleed: |
||
370 |
case nrrdBoundaryWrap: |
||
371 |
case nrrdBoundaryMirror: |
||
372 |
break; |
||
373 |
default: |
||
374 |
biffAddf(NRRD, "%s: sorry boundary %s (%d) unimplemented\n", |
||
375 |
me, airEnumStr(nrrdBoundary, boundary), boundary); |
||
376 |
return 1; |
||
377 |
} |
||
378 |
/* |
||
379 |
printf("!%s: boundary = %d, padValue = %g\n", me, boundary, padValue); |
||
380 |
*/ |
||
381 |
|||
382 |
24 |
nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, szIn); |
|
383 |
✓✓ | 208 |
for (ai=0; ai<nin->dim; ai++) { |
384 |
✗✓ | 80 |
if (!( min[ai] <= 0 )) { |
385 |
biffAddf(NRRD, "%s: axis %d min (%s) not <= 0", me, ai, |
||
386 |
airSprintPtrdiff_t(stmp[0], min[ai])); |
||
387 |
return 1; |
||
388 |
} |
||
389 |
✗✓ | 80 |
if (!( (size_t)max[ai] >= szIn[ai]-1)) { |
390 |
biffAddf(NRRD, "%s: axis %d max (%s) not >= size-1 (%s)", me, ai, |
||
391 |
airSprintPtrdiff_t(stmp[0], max[ai]), |
||
392 |
airSprintSize_t(stmp[1], szIn[ai]-1)); |
||
393 |
return 1; |
||
394 |
} |
||
395 |
} |
||
396 |
/* this shouldn't actually be necessary .. */ |
||
397 |
✗✓ | 24 |
if (!nrrdElementSize(nin)) { |
398 |
biffAddf(NRRD, "%s: nrrd reports zero element size!", me); |
||
399 |
return 1; |
||
400 |
} |
||
401 |
|||
402 |
/* allocate */ |
||
403 |
numOut = 1; |
||
404 |
✓✓ | 208 |
for (ai=0; ai<nin->dim; ai++) { |
405 |
80 |
numOut *= (szOut[ai] = -min[ai] + max[ai] + 1); |
|
406 |
} |
||
407 |
24 |
nout->blockSize = nin->blockSize; |
|
408 |
✗✓ | 24 |
if (nrrdMaybeAlloc_nva(nout, nin->type, nin->dim, szOut)) { |
409 |
biffAddf(NRRD, "%s:", me); |
||
410 |
return 1; |
||
411 |
} |
||
412 |
|||
413 |
/* the skinny */ |
||
414 |
24 |
typeSize = nrrdElementSize(nin); |
|
415 |
24 |
dataIn = (char *)nin->data; |
|
416 |
24 |
dataOut = (char *)nout->data; |
|
417 |
✓✓ | 816 |
for (ai=0; ai<NRRD_DIM_MAX; ai++) { |
418 |
384 |
cOut[ai] = 0; |
|
419 |
} |
||
420 |
✓✓ | 7783456 |
for (idxOut=0; idxOut<numOut; idxOut++) { |
421 |
outside = 0; |
||
422 |
✓✓ | 38916624 |
for (ai=0; ai<nin->dim; ai++) { |
423 |
31133216 |
cIn[ai] = cOut[ai] + min[ai]; |
|
424 |
✗✓✗✗ ✓ |
31133216 |
switch(boundary) { |
425 |
case nrrdBoundaryPad: /* HEY, this shouldn't result in any |
||
426 |
input coordinate being set */ |
||
427 |
case nrrdBoundaryBleed: |
||
428 |
✓✓✓✓ |
30354872 |
if (!AIR_IN_CL(0, cIn[ai], (ptrdiff_t)szIn[ai]-1)) { |
429 |
✓✓✓✗ |
7783248 |
cIn[ai] = AIR_CLAMP(0, cIn[ai], (ptrdiff_t)szIn[ai]-1); |
430 |
outside = 1; |
||
431 |
2334984 |
} |
|
432 |
break; |
||
433 |
case nrrdBoundaryWrap: |
||
434 |
if (!AIR_IN_CL(0, cIn[ai], (ptrdiff_t)szIn[ai]-1)) { |
||
435 |
/* HEY: shouldn't have to cast szIn[ai] to ptrdiff_t */ |
||
436 |
cIn[ai] = AIR_MOD(cIn[ai], (ptrdiff_t)szIn[ai]); |
||
437 |
outside = 1; |
||
438 |
} |
||
439 |
break; |
||
440 |
case nrrdBoundaryMirror: |
||
441 |
if (!AIR_IN_CL(0, cIn[ai], (ptrdiff_t)szIn[ai]-1)) { |
||
442 |
cIn[ai] = _nrrdMirror_64(szIn[ai], cIn[ai]); |
||
443 |
outside = 1; |
||
444 |
} |
||
445 |
break; |
||
446 |
} |
||
447 |
} |
||
448 |
✓✓ | 38916624 |
NRRD_INDEX_GEN(idxIn, cIn, szIn, nin->dim); |
449 |
✓✓ | 3891704 |
if (!outside) { |
450 |
/* the cIn coords are within the input nrrd: do memcpy() of whole |
||
451 |
1-D scanline, then artificially bump for-loop to the end of |
||
452 |
the scanline */ |
||
453 |
1556720 |
memcpy(dataOut + idxOut*typeSize, dataIn + idxIn*typeSize, |
|
454 |
szIn[0]*typeSize); |
||
455 |
1556720 |
idxOut += nin->axis[0].size-1; |
|
456 |
1556720 |
cOut[0] += nin->axis[0].size-1; |
|
457 |
1556720 |
} else { |
|
458 |
/* we copy only a single value */ |
||
459 |
✓✓ | 2334984 |
if (nrrdBoundaryPad == boundary) { |
460 |
1556664 |
nrrdDInsert[nout->type](dataOut, idxOut, padValue); |
|
461 |
1556664 |
} else { |
|
462 |
778320 |
memcpy(dataOut + idxOut*typeSize, dataIn + idxIn*typeSize, typeSize); |
|
463 |
} |
||
464 |
} |
||
465 |
✓✗✓✓ ✓✓✓✗ ✓✓ |
39800712 |
NRRD_COORD_INCR(cOut, szOut, nin->dim, 0); |
466 |
} |
||
467 |
✗✓ | 24 |
if (nrrdAxisInfoCopy(nout, nin, NULL, (NRRD_AXIS_INFO_SIZE_BIT | |
468 |
NRRD_AXIS_INFO_MIN_BIT | |
||
469 |
NRRD_AXIS_INFO_MAX_BIT ))) { |
||
470 |
biffAddf(NRRD, "%s:", me); |
||
471 |
return 1; |
||
472 |
} |
||
473 |
✓✓ | 208 |
for (ai=0; ai<nin->dim; ai++) { |
474 |
160 |
nrrdAxisInfoPosRange(&(nout->axis[ai].min), &(nout->axis[ai].max), |
|
475 |
80 |
nin, ai, AIR_CAST(double, min[ai]), |
|
476 |
80 |
AIR_CAST(double, max[ai])); |
|
477 |
✓✗✓✓ |
160 |
if (!nrrdStateKindNoop && nout->axis[ai].size == nin->axis[ai].size) { |
478 |
/* nothing changed along this axis; the kind should be preserved */ |
||
479 |
56 |
nout->axis[ai].kind = nin->axis[ai].kind; |
|
480 |
56 |
} else { |
|
481 |
24 |
nout->axis[ai].kind = _nrrdKindAltered(nin->axis[ai].kind, AIR_FALSE); |
|
482 |
} |
||
483 |
} |
||
484 |
24 |
strcpy(buff1, ""); |
|
485 |
✓✓ | 208 |
for (ai=0; ai<nin->dim; ai++) { |
486 |
80 |
sprintf(buff2, "%s[%s,%s]", (ai ? "x" : ""), |
|
487 |
airSprintPtrdiff_t(stmp[0], min[ai]), |
||
488 |
airSprintPtrdiff_t(stmp[1], max[ai])); |
||
489 |
80 |
strcat(buff1, buff2); |
|
490 |
} |
||
491 |
✓✓ | 24 |
if (nrrdBoundaryPad == boundary) { |
492 |
40 |
sprintf(buff2, "%s(%g)", airEnumStr(nrrdBoundary, nrrdBoundaryPad), |
|
493 |
padValue); |
||
494 |
16 |
} else { |
|
495 |
8 |
strcpy(buff2, airEnumStr(nrrdBoundary, boundary)); |
|
496 |
} |
||
497 |
✗✓ | 24 |
if (nrrdContentSet_va(nout, func, nin, "%s,%s", buff1, buff2)) { |
498 |
biffAddf(NRRD, "%s:", me); |
||
499 |
return 1; |
||
500 |
} |
||
501 |
✗✓ | 24 |
if (nrrdBasicInfoCopy(nout, nin, |
502 |
NRRD_BASIC_INFO_DATA_BIT |
||
503 |
| NRRD_BASIC_INFO_TYPE_BIT |
||
504 |
| NRRD_BASIC_INFO_BLOCKSIZE_BIT |
||
505 |
| NRRD_BASIC_INFO_DIMENSION_BIT |
||
506 |
| NRRD_BASIC_INFO_CONTENT_BIT |
||
507 |
| NRRD_BASIC_INFO_COMMENTS_BIT |
||
508 |
24 |
| (nrrdStateKeyValuePairsPropagate |
|
509 |
? 0 |
||
510 |
: NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) { |
||
511 |
biffAddf(NRRD, "%s:", me); |
||
512 |
return 1; |
||
513 |
} |
||
514 |
/* copy origin, then shift it along the spatial axes */ |
||
515 |
24 |
nrrdSpaceVecCopy(nout->spaceOrigin, nin->spaceOrigin); |
|
516 |
✓✓ | 208 |
for (ai=0; ai<nin->dim; ai++) { |
517 |
✓✓ | 80 |
if (AIR_EXISTS(nin->axis[ai].spaceDirection[0])) { |
518 |
48 |
nrrdSpaceVecScaleAdd2(nout->spaceOrigin, |
|
519 |
1.0, nout->spaceOrigin, |
||
520 |
48 |
AIR_CAST(double, min[ai]), |
|
521 |
48 |
nin->axis[ai].spaceDirection); |
|
522 |
48 |
} |
|
523 |
} |
||
524 |
|||
525 |
24 |
return 0; |
|
526 |
24 |
} |
|
527 |
|||
528 |
/* |
||
529 |
******** nrrdPad_nva() |
||
530 |
** |
||
531 |
** unlike other {X_va,X_nva} pairs, nrrdPad_nva() is a wrapper around |
||
532 |
** nrrdPad_va() instead of the other way around. |
||
533 |
*/ |
||
534 |
int |
||
535 |
nrrdPad_nva(Nrrd *nout, const Nrrd *nin, |
||
536 |
const ptrdiff_t *min, const ptrdiff_t *max, |
||
537 |
int boundary, double padValue) { |
||
538 |
static const char me[]="nrrdPad_nva"; |
||
539 |
int E; |
||
540 |
|||
541 |
✗✓ | 48 |
if (!AIR_IN_OP(nrrdBoundaryUnknown, boundary, nrrdBoundaryLast)) { |
542 |
biffAddf(NRRD, "%s: boundary behavior %d invalid", me, boundary); |
||
543 |
return 1; |
||
544 |
} |
||
545 |
✓✓ | 24 |
if (nrrdBoundaryPad == boundary) { |
546 |
16 |
E = nrrdPad_va(nout, nin, min, max, boundary, padValue); |
|
547 |
16 |
} else { |
|
548 |
8 |
E = nrrdPad_va(nout, nin, min, max, boundary); |
|
549 |
} |
||
550 |
✗✓ | 24 |
if (E) { |
551 |
biffAddf(NRRD, "%s:", me); |
||
552 |
return 1; |
||
553 |
} |
||
554 |
|||
555 |
24 |
return 0; |
|
556 |
24 |
} |
|
557 |
|||
558 |
/* |
||
559 |
******** nrrdSimplePad_va() |
||
560 |
** |
||
561 |
** pads by a given amount on top and bottom of EVERY axis |
||
562 |
*/ |
||
563 |
int |
||
564 |
nrrdSimplePad_va(Nrrd *nout, const Nrrd *nin, unsigned int pad, |
||
565 |
int boundary, ...) { |
||
566 |
static const char me[]="nrrdSimplePad_va"; |
||
567 |
unsigned ai; |
||
568 |
int ret; |
||
569 |
ptrdiff_t min[NRRD_DIM_MAX], max[NRRD_DIM_MAX]; |
||
570 |
double padValue; |
||
571 |
va_list ap; |
||
572 |
|||
573 |
if (!(nout && nin)) { |
||
574 |
biffAddf(NRRD, "%s: got NULL pointer", me); |
||
575 |
return 1; |
||
576 |
} |
||
577 |
for (ai=0; ai<nin->dim; ai++) { |
||
578 |
min[ai] = -AIR_CAST(ptrdiff_t, pad); |
||
579 |
max[ai] = nin->axis[ai].size-1 + pad; |
||
580 |
} |
||
581 |
va_start(ap, boundary); |
||
582 |
if (nrrdBoundaryPad == boundary) { |
||
583 |
padValue = va_arg(ap, double); |
||
584 |
ret = nrrdPad_va(nout, nin, min, max, boundary, padValue); |
||
585 |
} else { |
||
586 |
ret = nrrdPad_va(nout, nin, min, max, boundary); |
||
587 |
} |
||
588 |
va_end(ap); |
||
589 |
if (ret) { |
||
590 |
biffAddf(NRRD, "%s:", me); |
||
591 |
return 1; |
||
592 |
} |
||
593 |
return 0; |
||
594 |
} |
||
595 |
|||
596 |
/* |
||
597 |
******** nrrdSimplePad_nva() |
||
598 |
** |
||
599 |
** unlike other {X_va,X_nva} pairs, nrrdSimplePad_nva() is a wrapper |
||
600 |
** around nrrdSimplePad_va() instead of the other way around. |
||
601 |
*/ |
||
602 |
int |
||
603 |
nrrdSimplePad_nva(Nrrd *nout, const Nrrd *nin, unsigned int pad, |
||
604 |
int boundary, double padValue) { |
||
605 |
static const char me[]="nrrdSimplePad_nva"; |
||
606 |
int E; |
||
607 |
|||
608 |
if (!AIR_IN_OP(nrrdBoundaryUnknown, boundary, nrrdBoundaryLast)) { |
||
609 |
biffAddf(NRRD, "%s: boundary behavior %d invalid", me, boundary); |
||
610 |
return 1; |
||
611 |
} |
||
612 |
if (nrrdBoundaryPad == boundary) { |
||
613 |
E = nrrdSimplePad_va(nout, nin, pad, boundary, padValue); |
||
614 |
} else { |
||
615 |
E = nrrdSimplePad_va(nout, nin, pad, boundary); |
||
616 |
} |
||
617 |
if (E) { |
||
618 |
biffAddf(NRRD, "%s:", me); |
||
619 |
return 1; |
||
620 |
} |
||
621 |
|||
622 |
return 0; |
||
623 |
} |
Generated by: GCOVR (Version 3.3) |