Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

typetraits.h 19.9 KB
Newer Older
1
2
// ================================================================================================
// 
schultezub's avatar
schultezub committed
3
// This file is part of the CAMPVis Software Framework.
4
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
//      Chair for Computer Aided Medical Procedures
8
9
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
10
// 
schultezub's avatar
schultezub committed
11
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
12
// 
13
14
15
16
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 
// except in compliance with the License. You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
17
// 
18
19
20
21
// Unless required by applicable law or agreed to in writing, software distributed under the 
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
// either express or implied. See the License for the specific language governing permissions 
// and limitations under the License.
22
23
24
// 
// ================================================================================================

25
26
#ifndef TYPETRAITS_H__
#define TYPETRAITS_H__
schultezub's avatar
schultezub committed
27

28
29
30
31
#include "cgt/tgt_gl.h"
#include "cgt/tgt_math.h"
#include "cgt/matrix.h"
#include "cgt/vector.h"
32
#include "core/datastructures/tensor.h"
33
#include "core/tools/weaklytypedpointer.h"
schultezub's avatar
schultezub committed
34
35
#include <limits>

36

schultezub's avatar
schultezub committed
37
namespace campvis {
schultezub's avatar
schultezub committed
38

39
40
41
// anonymous namespace for helper traits
// irrelevant for the outside world...
namespace {
42

43
44
45
46
47
    /**
     * Helper Traits for TypeTraits varying only in the number of channels.
     * Template specializations offer the following constants/methods:
     *  - const GLint glFormat: OpenGL format to use
     */
48
    template<size_t NUMCHANNELS>
49
    struct TypeTraitsHelperPerChannel {};
50
51

    template<>
52
    struct TypeTraitsHelperPerChannel<1> {
53
        static const GLint glFormat = GL_RED;
54
55
56
    };

    template<>
57
    struct TypeTraitsHelperPerChannel<2> {
58
        static const GLint glFormat = GL_RG;
59
60
61
    };

    template<>
62
    struct TypeTraitsHelperPerChannel<3> {
63
64
65
66
        static const GLint glFormat = GL_RGB;
    };

    template<>
67
    struct TypeTraitsHelperPerChannel<4> {
68
69
70
        static const GLint glFormat = GL_RGBA;
    };

71
72
73
74
75
    template<>
    struct TypeTraitsHelperPerChannel<6> {
        static const GLint glFormat = GL_RGB;
    };

76
77
78
79
80
    template<>
    struct TypeTraitsHelperPerChannel<9> {
        static const GLint glFormat = GL_RGB;
    };

81
82
// ================================================================================================
// ================================================================================================
83

84
85
86
87
88
    /**
     * Helper Traits for TypeTraits varying in the base type and in the number of channels.
     * Template specializations offer the following constants/methods:
     *  - const GLint glInternalFormat: OpenGL internal format to use
     */
89
    template<typename BASETYPE, size_t NUMCHANNELS>
90
    struct TypeTraitsHelperPerBasetypePerChannel {};
91

92
// use nifty macros for easier template specialization
93
94
#define SPCIALIZE_TTIF(type,nc,internalFormat) \
    template<> \
95
    struct TypeTraitsHelperPerBasetypePerChannel<type, nc> { \
96
97
98
        static const GLint glInteralFormat = internalFormat; \
    }; \

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    SPCIALIZE_TTIF(uint8_t, 1, GL_R8)
    SPCIALIZE_TTIF(int8_t,  1, GL_R8)
    SPCIALIZE_TTIF(uint16_t,1, GL_R16)
    SPCIALIZE_TTIF(int16_t, 1, GL_R16)
    SPCIALIZE_TTIF(uint32_t,1, GL_R32F)
    SPCIALIZE_TTIF(int32_t, 1, GL_R32F)
    SPCIALIZE_TTIF(float,   1, GL_R32F)

    SPCIALIZE_TTIF(uint8_t, 2, GL_RG8)
    SPCIALIZE_TTIF(int8_t,  2, GL_RG8)
    SPCIALIZE_TTIF(uint16_t,2, GL_RG16)
    SPCIALIZE_TTIF(int16_t, 2, GL_RG16)
    SPCIALIZE_TTIF(uint32_t,2, GL_RG32F)
    SPCIALIZE_TTIF(int32_t, 2, GL_RG32F)
    SPCIALIZE_TTIF(float,   2, GL_RG32F)
114
115
116
117
118

    SPCIALIZE_TTIF(uint8_t, 3, GL_RGB8)
    SPCIALIZE_TTIF(int8_t,  3, GL_RGB8)
    SPCIALIZE_TTIF(uint16_t,3, GL_RGB16)
    SPCIALIZE_TTIF(int16_t, 3, GL_RGB16)
119
120
121
    SPCIALIZE_TTIF(uint32_t,3, GL_RGB32F)
    SPCIALIZE_TTIF(int32_t, 3, GL_RGB32F)
    SPCIALIZE_TTIF(float,   3, GL_RGB32F)
122
123
124
125
126

    SPCIALIZE_TTIF(uint8_t, 4, GL_RGBA8)
    SPCIALIZE_TTIF(int8_t,  4, GL_RGBA8)
    SPCIALIZE_TTIF(uint16_t,4, GL_RGBA16)
    SPCIALIZE_TTIF(int16_t, 4, GL_RGBA16)
127
128
129
130
131
132
133
134
135
136
137
    SPCIALIZE_TTIF(uint32_t,4, GL_RGBA32F)
    SPCIALIZE_TTIF(int32_t, 4, GL_RGBA32F)
    SPCIALIZE_TTIF(float,   4, GL_RGBA32F)

    SPCIALIZE_TTIF(uint8_t, 6, GL_RGB8)
    SPCIALIZE_TTIF(int8_t,  6, GL_RGB8)
    SPCIALIZE_TTIF(uint16_t,6, GL_RGB16)
    SPCIALIZE_TTIF(int16_t, 6, GL_RGB16)
    SPCIALIZE_TTIF(uint32_t,6, GL_RGB32F)
    SPCIALIZE_TTIF(int32_t, 6, GL_RGB32F)
    SPCIALIZE_TTIF(float,   6, GL_RGB32F)
138

139
140
141
142
143
144
145
146
    SPCIALIZE_TTIF(uint8_t, 9, GL_RGB8)
    SPCIALIZE_TTIF(int8_t,  9, GL_RGB8)
    SPCIALIZE_TTIF(uint16_t,9, GL_RGB16)
    SPCIALIZE_TTIF(int16_t, 9, GL_RGB16)
    SPCIALIZE_TTIF(uint32_t,9, GL_RGB32F)
    SPCIALIZE_TTIF(int32_t, 9, GL_RGB32F)
    SPCIALIZE_TTIF(float,   9, GL_RGB32F)

147
148
// ================================================================================================
// ================================================================================================
149

schultezub's avatar
schultezub committed
150
    /**
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
     * Helper Traits for TypeTraits varying only in the base type.
     * Template specializations offer the following constants/methods:
     *  - const GLenum glInternalFormat: OpenGL data type
     *  - const WeaklyTypedPointer::BaseType: WeaklyTypedPointer base type to use
     *  - const bool isSigned: flag whether this base type is signed
     *  - const bool isFloat: flag wheter this base type is floating point or integer
     */
    template<typename BASETYPE>
    struct TypeTraitsHelperPerBasetype {};

    template<>
    struct TypeTraitsHelperPerBasetype<uint8_t> {
        static const GLenum glDataType = GL_UNSIGNED_BYTE;
        static const WeaklyTypedPointer::BaseType weaklyTypedPointerBaseType = WeaklyTypedPointer::UINT8;
        static const bool isSigned = false;
        static const bool isFloat = false;
    };

    template<>
    struct TypeTraitsHelperPerBasetype<int8_t> {
        static const GLenum glDataType = GL_BYTE;
        static const WeaklyTypedPointer::BaseType weaklyTypedPointerBaseType = WeaklyTypedPointer::INT8;
        static const bool isSigned = true;
        static const bool isFloat = false;
    };

    template<>
    struct TypeTraitsHelperPerBasetype<uint16_t> {
        static const GLenum glDataType = GL_UNSIGNED_SHORT;
        static const WeaklyTypedPointer::BaseType weaklyTypedPointerBaseType = WeaklyTypedPointer::UINT16;
        static const bool isSigned = false;
        static const bool isFloat = false;
    };

    template<>
    struct TypeTraitsHelperPerBasetype<int16_t> {
        static const GLenum glDataType = GL_SHORT;
        static const WeaklyTypedPointer::BaseType weaklyTypedPointerBaseType = WeaklyTypedPointer::INT16;
        static const bool isSigned = true;
        static const bool isFloat = false;
    };

    template<>
    struct TypeTraitsHelperPerBasetype<uint32_t> {
        static const GLenum glDataType = GL_UNSIGNED_INT;
        static const WeaklyTypedPointer::BaseType weaklyTypedPointerBaseType = WeaklyTypedPointer::UINT32;
        static const bool isSigned = false;
        static const bool isFloat = false;
    };

    template<>
    struct TypeTraitsHelperPerBasetype<int32_t> {
        static const GLenum glDataType = GL_INT;
        static const WeaklyTypedPointer::BaseType weaklyTypedPointerBaseType = WeaklyTypedPointer::INT32;
        static const bool isSigned = true;
        static const bool isFloat = false;
    };

    template<>
    struct TypeTraitsHelperPerBasetype<float> {
        static const GLenum glDataType = GL_FLOAT;
        static const WeaklyTypedPointer::BaseType weaklyTypedPointerBaseType = WeaklyTypedPointer::FLOAT;
        static const bool isSigned = true;
        static const bool isFloat = true;
    };

// ================================================================================================
// ================================================================================================

    /**
     * Helper Traits for TypeTraits of generic base type varying only in the base type.
     * Template specializations offer the following constants/methods:
     *  - typedef ElementType: Typedef for the type of a single image element
     *  - static BASETYPE getChannel(element, channel): Method for accessing a specific channel of the given image element
     *  - static void getChannel(element, channel, value): Method setting a specific channel of the given image element to \a value
     */
    template<typename BASETYPE, size_t NUMCHANNELS>
    struct TypeTraitsHelperOfBasetypePerChannel {};

    template<typename BASETYPE>
    struct TypeTraitsHelperOfBasetypePerChannel<BASETYPE, 1> {
        typedef BASETYPE ElementType;

        static inline BASETYPE getChannel(const ElementType& element, size_t channel) {
            tgtAssert(channel == 0, "Channel out of bounds!");
            return element;
        }

        static inline void setChannel(ElementType& element, size_t channel, BASETYPE value) {
            tgtAssert(channel == 0, "Channel out of bounds!");
            element = value;
        }
    };

    template<typename BASETYPE>
    struct TypeTraitsHelperOfBasetypePerChannel<BASETYPE, 2> {
        typedef tgt::Vector2< BASETYPE > ElementType;

        static inline BASETYPE getChannel(const ElementType& element, size_t channel) {
            tgtAssert(channel >= 0 && channel <= 1, "Channel out of bounds!");
            return element[channel];
        }

        static inline void setChannel(ElementType& element, size_t channel, BASETYPE value) {
            tgtAssert(channel >= 0 && channel <= 1, "Channel out of bounds!");
            element[channel] = value;
        }
    };

    template<typename BASETYPE>
    struct TypeTraitsHelperOfBasetypePerChannel<BASETYPE, 3> {
        typedef tgt::Vector3< BASETYPE > ElementType;

        static inline BASETYPE getChannel(const ElementType& element, size_t channel) {
            tgtAssert(channel >= 0 && channel <= 2, "Channel out of bounds!");
            return element[channel];
        }

        static inline void setChannel(ElementType& element, size_t channel, BASETYPE value) {
            tgtAssert(channel >= 0 && channel <= 2, "Channel out of bounds!");
            element[channel] = value;
        }
    };

    template<typename BASETYPE>
    struct TypeTraitsHelperOfBasetypePerChannel<BASETYPE, 4> {
        typedef tgt::Vector4< BASETYPE > ElementType;

        static inline BASETYPE getChannel(const ElementType& element, size_t channel) {
            tgtAssert(channel >= 0 && channel <= 3, "Channel out of bounds!");
            return element[channel];
        }

        static inline void setChannel(ElementType& element, size_t channel, BASETYPE value) {
            tgtAssert(channel >= 0 && channel <= 3, "Channel out of bounds!");
            element[channel] = value;
        }
    };

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
    template<typename BASETYPE>
    struct TypeTraitsHelperOfBasetypePerChannel<BASETYPE, 6> {
        typedef Tensor2< BASETYPE > ElementType;

        static inline BASETYPE getChannel(const ElementType& element, size_t channel) {
            tgtAssert(channel >= 0 && channel <= 5, "Channel out of bounds!");
            return element[channel];
        }

        static inline void setChannel(ElementType& element, size_t channel, BASETYPE value) {
            tgtAssert(channel >= 0 && channel <= 5, "Channel out of bounds!");
            element[channel] = value;
        }
    };

305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
    template<typename BASETYPE>
    struct TypeTraitsHelperOfBasetypePerChannel<BASETYPE, 9> {
        typedef tgt::Matrix3< BASETYPE > ElementType;

        static inline BASETYPE getChannel(const ElementType& element, size_t channel) {
            tgtAssert(channel >= 0 && channel <= 8, "Channel out of bounds!");
            return element.elem[channel];
        }

        static inline void setChannel(ElementType& element, size_t channel, BASETYPE value) {
            tgtAssert(channel >= 0 && channel <= 8, "Channel out of bounds!");
            element.elem[channel] = value;
        }
    };

320
321
322
323
324
325
326
327
328
329
330
331
332
333
// ================================================================================================
// ================================================================================================
    
    /**
     * Helper Traits for TypeNormalizer.
     * Template specializations offer the following methods:
     *  - static float normalizeToFloat<T>(T value): Normalize the given value to float
     *  - static T denormalizeFromFloat<T>(float value): Denormalize the given float to T
     *
     * \note    Template parameter T of trait functions have to match trait template parameter flags!
     *
     * \tparam  ISFLOAT     Flag whether base type is floating point or integer
     * \tparam  ISSIGNED    Flag whether base type is signed or not (ignored when ISFLOAT == true)
     */
schultezub's avatar
schultezub committed
334
    template<typename T, bool ISFLOAT, bool ISSIGNED>
335
336
337
338
339
    struct TypeNormalizerHelper {};

    /**
     * Template specialization for floating point types - no normalization needed.
     */
schultezub's avatar
schultezub committed
340
341
    template<typename T, bool ISSIGNED>
    struct TypeNormalizerHelper<T, true, ISSIGNED> {
342
343
344
345
346
347
348
349
350
351
352
353
        static float normalizeToFloat(T value) {
            return static_cast<float>(value);
        }

        static T denormalizeFromFloat(float value) {
            return static_cast<T>(value);
        };
    };

    /**
     * Template specialization for unsigned integer types, map from [0, max] to [0.0, 1.0]
     */
schultezub's avatar
schultezub committed
354
355
    template<typename T>
    struct TypeNormalizerHelper<T, false, false> {
356
357
358
359
360
361
362
363
364
365
366
        static float normalizeToFloat(T value) {
            return static_cast<float>(value) / std::numeric_limits<T>::max();
        }

        static T denormalizeFromFloat(float value) {
            value = tgt::clamp(value, 0.0f, 1.0f);
            return static_cast<T>(value * std::numeric_limits<T>::max());
        };
    };

    /**
367
     * Template specialization for signed integer types, map from [min, max] to [0.0, 1.0]
368
     */
schultezub's avatar
schultezub committed
369
370
    template<typename T>
    struct TypeNormalizerHelper<T, false, true> {
371
372
        static float normalizeToFloat(T value) {
            if (value >= 0)
373
                return (static_cast<float>(value) / std::numeric_limits<T>::max()) * .5f + .5f;
374
            else
375
                return (static_cast<float>(value) / -std::numeric_limits<T>::min()) * .5f + .5f;
376
377
378
        }

        static T denormalizeFromFloat(float value) {
379
            value = (tgt::clamp(value, 0.0f, 1.0f) - .5f) * 2.f;
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
            if(value >= 0.0f)
                return static_cast<T>(value * std::numeric_limits<T>::max());
            else
                return static_cast<T>(value * -std::numeric_limits<T>::min());
        };
    };
}

// ================================================================================================
// = Starting with the actual stuff to use ======================================================== 
// ================================================================================================
    /**
     * Type traits for image data depending on base type and number of channels.
     *
     * \tparam  BASETYPE    Base type of the image data (type of a single channel of an image element)
     * \tparam  NUMCHANNELS Number of channels of the image data.
schultezub's avatar
schultezub committed
396
     **/
397
    template<typename BASETYPE, size_t NUMCHANNELS>
schultezub's avatar
schultezub committed
398
    struct TypeTraits {
399
400
        /// C++ type of one single image element.
        typedef typename TypeTraitsHelperOfBasetypePerChannel<BASETYPE, NUMCHANNELS>::ElementType ElementType;
schultezub's avatar
schultezub committed
401

402
        /// Size of the element base type in bytes.
403
404
        static const size_t basetypeSize = sizeof(BASETYPE);

405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
        /// Number of channels of one single image element.
        static const size_t numChannels = NUMCHANNELS;

        /// Size of one single image element in bytes.
        static const size_t elementSize = sizeof(BASETYPE) * NUMCHANNELS;

        /// OpenGL format to apply for this image data.
        static const GLint glFormat = TypeTraitsHelperPerChannel<NUMCHANNELS>::glFormat;

        /// OpenGL data type to apply for this image data.
        static const GLenum glDataType = TypeTraitsHelperPerBasetype<BASETYPE>::glDataType;

        /// OpenGL internal format to apply for this image data.
        static const GLint glInternalFormat = TypeTraitsHelperPerBasetypePerChannel<BASETYPE, NUMCHANNELS>::glInteralFormat;

        /// WeaklyTypedPointer::BaseType for this image data.
        static const WeaklyTypedPointer::BaseType weaklyTypedPointerBaseType = TypeTraitsHelperPerBasetype<BASETYPE>::weaklyTypedPointerBaseType;

423
        /**
424
         * Returns the i-th channel (0-based) of the given image element \a element.
schultezub's avatar
schultezub committed
425
426
         * \param   element Image element to access
         * \param   channel Channel to access, must be within [0, NUMCHANNELS).
427
         * \return  The i-th channel of \a element.
428
         */
429
430
431
        static inline BASETYPE getChannel(const typename TypeTraitsHelperOfBasetypePerChannel<BASETYPE, NUMCHANNELS>::ElementType& element, size_t channel) {
            return TypeTraitsHelperOfBasetypePerChannel<BASETYPE, NUMCHANNELS>::getChannel(element, channel);
        };
schultezub's avatar
schultezub committed
432

433
        /**
434
435
436
437
         * Sets the i-th channel (0-based) of the given image element \a element.
         * \param   element Image Element to set.
         * \param   channel Channel to access, must be within [0, NUMCHANNELS).
         * \param   value   Value to set
438
         */
439
440
441
        static inline void setChannel(typename TypeTraitsHelperOfBasetypePerChannel<BASETYPE, NUMCHANNELS>::ElementType& element, size_t channel, BASETYPE value) {
            TypeTraitsHelperOfBasetypePerChannel<BASETYPE, NUMCHANNELS>::setChannel(element, channel, value);
        }
442
443

    };
schultezub's avatar
schultezub committed
444

445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
    /**
     * Offers methods for (de)normalizing image element base types to/from float.
     * \note    Due to the use of templates and traits, the conversion function is completely
     *          determined at compile-time.
     */
    struct TypeNormalizer {
        /**
         * Normalizes the given value \a value to a float representation.
         *  - for \em unsigned integer types, the value range is mapped linearly to [0.0;1.0]
         *  - for \em signed integer types, the value range is mapped linearly to [-1.0;1.0]
         *  - floating point types are not mapped
         *
         * \tparam  T       Base type of the image element to normalize
         * \param   value   Value to normalize
         * \return  A normalized float representation of \a value.
         */
        template<typename T>
        static float normalizeToFloat(T value) {
schultezub's avatar
schultezub committed
463
            return TypeNormalizerHelper<T, TypeTraitsHelperPerBasetype<T>::isFloat, TypeTraitsHelperPerBasetype<T>::isSigned>::normalizeToFloat(value);
464
        };
schultezub's avatar
schultezub committed
465

466
467
468
469
470
471
472
473
474
475
476
477
        /**
        * Denormalizes the given value \a value from a float representation.
        *  - for \em unsigned integer types, the value range is mapped linearly to [0.0;1.0]
        *  - for \em signed integer types, the value range is mapped linearly to [-1.0;1.0]
        *  - floating point types are not mapped
        *
        * \tparam  T       Base type of the image element to denormalize
        * \param   value   Float representation to denormalize
        * \return  The denormalized value of the float representation \a value.
         */
        template<typename T>
        static T denormalizeFromFloat(float value) {
schultezub's avatar
schultezub committed
478
            return TypeNormalizerHelper<T, TypeTraitsHelperPerBasetype<T>::isFloat, TypeTraitsHelperPerBasetype<T>::isSigned>::denormalizeFromFloat(value);
479
480
        }
    };
schultezub's avatar
schultezub committed
481
482
}

483
#endif // TYPETRAITS_H__