GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/nrrd/convertNrrd.c Lines: 2 23 8.7 %
Date: 2017-05-26 Branches: 21 1234 1.7 %

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
** making these typedefs here allows us to use one token for both
29
** constructing function names, and for specifying argument types
30
*/
31
typedef signed char CH;
32
typedef unsigned char UC;
33
typedef signed short SH;
34
typedef unsigned short US;
35
/* Microsoft apparently uses 'IN' as a keyword, so we changed 'IN' to 'JN'. */
36
typedef signed int JN;
37
typedef unsigned int UI;
38
typedef airLLong LL;
39
/* ui64 to double conversion is not implemented, sorry */
40
#if _MSC_VER < 1300
41
typedef airLLong UL;
42
#else
43
typedef airULLong UL;
44
#endif
45
typedef float FL;
46
typedef double DB;
47
typedef size_t IT;
48
/* typedef long double LD; */
49
50
/*
51
** I don't think that I can get out of defining this macro twice,
52
** because of the rules of C preprocessor macro expansion.  If
53
** you can figure out a way to not use two identical macros, then
54
** email me (glk@uchicago.edu) and I'll send you money for dinner.
55
**
56
** >>> MAP1 and MAP2 need to be identical <<<
57
*/
58
59
#define MAP1(F, A) \
60
F(A, CH) \
61
F(A, UC) \
62
F(A, SH) \
63
F(A, US) \
64
F(A, JN) \
65
F(A, UI) \
66
F(A, LL) \
67
F(A, UL) \
68
F(A, FL) \
69
F(A, DB)
70
/* F(A, LD) */
71
72
#define MAP2(F, A) \
73
F(A, CH) \
74
F(A, UC) \
75
F(A, SH) \
76
F(A, US) \
77
F(A, JN) \
78
F(A, UI) \
79
F(A, LL) \
80
F(A, UL) \
81
F(A, FL) \
82
F(A, DB)
83
/* F(A, LD) */
84
85
/*
86
** _nrrdConv<Ta><Tb>()
87
**
88
** given two arrays, a and b, of different types (Ta and Tb) but equal
89
** size N, _nrrdConvTaTb(a, b, N) will copy all the values from b into
90
** a, thereby effecting the same type-conversion as one gets with a
91
** cast.  See K+R Appendix A6 (pg. 197) for the details of what that
92
** entails.  There are plenty of situations where the results are
93
** "undefined" (assigning -23 to an unsigned char); the point here is
94
** simply to make available on arrays all the same behavior you can
95
** get from scalars.
96
*/
97
#define CONV_DEF(TA, TB) \
98
static void \
99
_nrrdConv##TA##TB(TA *a, const TB *b, IT N) { \
100
  size_t ii; \
101
  for (ii=0; ii<N; ii++) { \
102
    a[ii] = AIR_CAST(TA, b[ii]); \
103
  } \
104
}
105
106
/*
107
** _nrrdClCv<Ta><Tb>()
108
**
109
** same as _nrrdConv<Ta><Tb>(), but with clamping to the representable
110
** range of values of the output type, using a double as intermediate
111
** storage type HEY WHICH MEANS THAT LONG LONG (BOTH SIGNED AND UNSIGNED)
112
** may suffer loss of data!!!
113
*/
114
#define CLCV_DEF(TA, TB) \
115
static void \
116
_nrrdClCv##TA##TB(TA *a, const TB *b, IT N) { \
117
  size_t ii; \
118
  for (ii=0; ii<N; ii++) { \
119
    a[ii] = AIR_CAST(TA, _nrrdDClamp##TA(AIR_CAST(double, b[ii]))); \
120
  } \
121
}
122
123
/*
124
** _nrrdCcrd<Ta><Tb>()
125
**
126
** like _nrrdClCv<Ta><Tb>() and _nrrdConv<Ta><Tb>(), but with the
127
** ability to control if there is rounding and/or clamping. As above,
128
** there may be loss of precision with long long input.
129
*/
130
#define CCRD_DEF(TA, TB)                                        \
131
static void                                                     \
132
 _nrrdCcrd##TA##TB(TA *a, const TB *b, IT N,                    \
133
                   int doClamp, int roundd) {                   \
134
   size_t ii;                                                   \
135
  for (ii=0; ii<N; ii++) {                                      \
136
    double ccrdTmp = AIR_CAST(double, b[ii]);                   \
137
    ccrdTmp = (roundd > 0                                       \
138
               ? floor(ccrdTmp + 0.5)                           \
139
               : (roundd < 0                                    \
140
                  ? ceil(ccrdTmp - 0.5)                         \
141
                  : ccrdTmp));                                  \
142
    ccrdTmp = (doClamp ? _nrrdDClamp##TA(ccrdTmp) : ccrdTmp);   \
143
    a[ii] = AIR_CAST(TA, ccrdTmp);                              \
144
  }                                                             \
145
}
146
147
/*
148
** These makes the definition of later arrays shorter
149
*/
150
typedef void (*CF)(void *, const void *, IT);
151
typedef void (*CN)(void *, const void *, IT, int, int);
152
153
/*
154
** the individual converter's appearance in the array initialization,
155
** using the cast to the typedefs above
156
*/
157
#define CONV_LIST(TA, TB) (CF)_nrrdConv##TA##TB,
158
#define CLCV_LIST(TA, TB) (CF)_nrrdClCv##TA##TB,
159
#define CCRD_LIST(TA, TB) (CN)_nrrdCcrd##TA##TB,
160
161
/*
162
** the brace-delimited list of all converters _to_ type TA
163
*/
164
#define CONVTO_LIST(_dummy_, TA) {NULL, MAP2(CONV_LIST, TA) NULL},
165
#define CLCVTO_LIST(_dummy_, TA) {NULL, MAP2(CLCV_LIST, TA) NULL},
166
#define CCRDTO_LIST(_dummy_, TA) {NULL, MAP2(CCRD_LIST, TA) NULL},
167
168
169
170
/*
171
** This is where the actual emitted code starts ...
172
*/
173
174
175
/*
176
** the clamping functions were moved here from accessors.c in order
177
** to create the combined clamp-and-convert functions
178
*/
179
180
/*
181
******** nrrdFClamp
182
**
183
** for integral types, clamps a given float to the range representable
184
** by that type; for floating point types we just return
185
** the given number, since every float must fit in a double.
186
*/
187
static float _nrrdFClampCH(FL v) { return AIR_CLAMP(SCHAR_MIN, v, SCHAR_MAX);}
188
static float _nrrdFClampUC(FL v) { return AIR_CLAMP(0, v, UCHAR_MAX);}
189
static float _nrrdFClampSH(FL v) { return AIR_CLAMP(SHRT_MIN, v, SHRT_MAX);}
190
static float _nrrdFClampUS(FL v) { return AIR_CLAMP(0, v, USHRT_MAX);}
191
static float _nrrdFClampJN(FL v) { return AIR_CLAMP(INT_MIN, v, INT_MAX);}
192
static float _nrrdFClampUI(FL v) { return AIR_CLAMP(0, v, UINT_MAX);}
193
static float _nrrdFClampLL(FL v) { return AIR_CLAMP(NRRD_LLONG_MIN, v,
194
                                                    NRRD_LLONG_MAX);}
195
static float _nrrdFClampUL(FL v) { return AIR_CLAMP(0, v, NRRD_ULLONG_MAX);}
196
static float _nrrdFClampFL(FL v) { return v; }
197
static float _nrrdFClampDB(FL v) { return v; }
198
float (*
199
nrrdFClamp[NRRD_TYPE_MAX+1])(FL) = {
200
  NULL,
201
  _nrrdFClampCH,
202
  _nrrdFClampUC,
203
  _nrrdFClampSH,
204
  _nrrdFClampUS,
205
  _nrrdFClampJN,
206
  _nrrdFClampUI,
207
  _nrrdFClampLL,
208
  _nrrdFClampUL,
209
  _nrrdFClampFL,
210
  _nrrdFClampDB,
211
  NULL};
212
213
/*
214
******** nrrdDClamp
215
**
216
** same as nrrdDClamp, but for doubles.  One change: in the case of
217
** floats, doubles are clamped to the range -FLT_MAX to FLT_MAX.
218
*/
219
static double _nrrdDClampCH(DB v) { return AIR_CLAMP(SCHAR_MIN, v, SCHAR_MAX);}
220
static double _nrrdDClampUC(DB v) { return AIR_CLAMP(0, v, UCHAR_MAX);}
221
static double _nrrdDClampSH(DB v) { return AIR_CLAMP(SHRT_MIN, v, SHRT_MAX);}
222
static double _nrrdDClampUS(DB v) { return AIR_CLAMP(0, v, USHRT_MAX);}
223
160000
static double _nrrdDClampJN(DB v) { return AIR_CLAMP(INT_MIN, v, INT_MAX);}
224
static double _nrrdDClampUI(DB v) { return AIR_CLAMP(0, v, UINT_MAX);}
225
static double _nrrdDClampLL(DB v) { return AIR_CLAMP(NRRD_LLONG_MIN, v,
226
                                                     NRRD_LLONG_MAX);}
227
static double _nrrdDClampUL(DB v) { return AIR_CLAMP(0, v, NRRD_ULLONG_MAX);}
228
static double _nrrdDClampFL(DB v) { return AIR_CLAMP(-FLT_MAX, v, FLT_MAX); }
229
static double _nrrdDClampDB(DB v) { return v; }
230
double (*
231
nrrdDClamp[NRRD_TYPE_MAX+1])(DB) = {
232
  NULL,
233
  _nrrdDClampCH,
234
  _nrrdDClampUC,
235
  _nrrdDClampSH,
236
  _nrrdDClampUS,
237
  _nrrdDClampJN,
238
  _nrrdDClampUI,
239
  _nrrdDClampLL,
240
  _nrrdDClampUL,
241
  _nrrdDClampFL,
242
  _nrrdDClampDB,
243
  NULL};
244
245
246
/*
247
** Define all the converters.
248
*/
249


















































13202380
MAP1(MAP2, CONV_DEF)
250
MAP1(MAP2, CLCV_DEF)
251
MAP1(MAP2, CCRD_DEF)
252
253
254
/*
255
** Initialize the converter arrays.
256
**
257
** Each definition generates one incredibly long line of text, which
258
** hopefully will not break a poor compiler with limitations on
259
** line-length...
260
*/
261
CF
262
_nrrdConv[NRRD_TYPE_MAX+1][NRRD_TYPE_MAX+1] = {
263
{NULL},
264
MAP1(CONVTO_LIST, _dummy_)
265
{NULL}
266
};
267
268
CF
269
_nrrdClampConv[NRRD_TYPE_MAX+1][NRRD_TYPE_MAX+1] = {
270
{NULL},
271
MAP1(CLCVTO_LIST, _dummy_)
272
{NULL}
273
};
274
275
CN
276
_nrrdCastClampRound[NRRD_TYPE_MAX+1][NRRD_TYPE_MAX+1] = {
277
{NULL},
278
MAP1(CCRDTO_LIST, _dummy_)
279
{NULL}
280
};