imagedata.h 11.2 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-2013, 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 Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, 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
// 
// ================================================================================================

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

28
#include <tbb/concurrent_vector.h>
29
#include "tgt/logmanager.h"
30
#include "tgt/vector.h"
31
32

#include "core/coreapi.h"
schultezub's avatar
schultezub committed
33
#include "core/datastructures/abstractdata.h"
34
#include "core/datastructures/abstractimagerepresentation.h"
schultezub's avatar
schultezub committed
35
#include "core/datastructures/imagemappinginformation.h"
36

37
38

#include <vector>
schultezub's avatar
schultezub committed
39

schultezub's avatar
schultezub committed
40
namespace campvis {
41
42
    class ImageRepresentationLocal;

schultezub's avatar
schultezub committed
43
44
    /**
     * Stores basic information about one (semantic) image of arbitrary dimension.
45
     * Different representations (e.g. local memory, OpenGL texture) are
schultezub's avatar
schultezub committed
46
47
48
49
     * to be defined by inheritance.
     * 
     * \todo 
     */
50
    class CAMPVIS_CORE_API ImageData : public AbstractData, public IHasWorldBounds {
51
52
53
    // friend so that it can add itself as representation
    friend class AbstractImageRepresentation;

schultezub's avatar
schultezub committed
54
    public:
55
56
57
58
59
60
        /**
         * Creates a new ImageData instance with the given parameters.
         * \param dimensionality    Dimensionality of this image
         * \param size              Size of this image (number of elements per dimension)
         * \param numChannels       Number of channels per element
         */
61
        explicit ImageData(size_t dimensionality, const tgt::svec3& size, size_t numChannels);
schultezub's avatar
schultezub committed
62

63
        /// Destructor
schultezub's avatar
schultezub committed
64
65
        virtual ~ImageData();

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
        /**
         * Prototype - clone method, some people call this virtual constructor...
         * \note    Deep-copies all contained representations!
         * \return  A copy of this object.
         */
        virtual ImageData* clone() const;

        /**
         * Returns the local memory footprint of the data in bytes.
         * \return  Number of bytes occupied in local memory by the data.
         */
        virtual size_t getLocalMemoryFootprint() const;

        /**
         * Returns the video memory footprint of the data in bytes.
         * \return  Number of bytes occupied in video memory by the data.
         */
        virtual size_t getVideoMemoryFootprint() const;

schultezub's avatar
schultezub committed
85
86
87
88
89
90
91
92
93
94
95
96
        /**
         * Dimensionality of this image.
         * \return _dimensionality
         */
        size_t getDimensionality() const;

        /**
         * Size of this image (number of elements per dimension).
         * \return _size
         */
        const tgt::svec3& getSize() const;

97
98
99
100
101
102
        /**
         * Returns the number of channels per element.
         * \return  _numChannels
         */
        size_t getNumChannels() const;

103
104
105
106
107
108
        /**
         * Returns the number of elements (= tgt::hmul(getSize())).
         * \return  _numElements
         */
        size_t getNumElements() const;

schultezub's avatar
schultezub committed
109
110
111
112
113
114
        /**
         * Mapping information of this image
         * \return _mappingInformation
         */
        const ImageMappingInformation& getMappingInformation() const;

115
116
117
118
119
120
        /**
         * Sets the mapping information for this image to \a imi.
         * \param   imi The new ImageMappingInformation for this image.
         */
        void setMappingInformation(const ImageMappingInformation& imi);

schultezub's avatar
schultezub committed
121
        /**
122
123
         * Returns the image extent in world coordinates.
         * \return  The image extent in world coordinates.
schultezub's avatar
schultezub committed
124
         */
125
        virtual tgt::Bounds getWorldBounds() const;
schultezub's avatar
schultezub committed
126

schultezub's avatar
schultezub committed
127
128
129
130
131
132
133
134
        /**
         * Returns the image extent in world coordinates for the given voxel coordinates.
         * \param   llf     Lower-left-front in voxel coordinates.
         * \param   urb     Upper-right-back in voxel coordinates.
         * \return  The image extent in world coordinates for the given voxel coordinates.
         */
        tgt::Bounds getWorldBounds(const tgt::svec3& llf, const tgt::svec3& urb) const;

schultezub's avatar
schultezub committed
135
136
137
        /**
         * Returns the subimage of this image given by \a llf and \a urb.
         * TODO: Check whether it is necessary to adjust image mapping!
138
139
         * 
         * \note    Creates sub-images of all representations.
schultezub's avatar
schultezub committed
140
141
         * \param   llf     Lower-Left-Front coordinates of subimage
         * \param   urb     Upper-Right-Back coordinates of subimage
142
         * \return  An image containing the sub-image of this image with the given coordinates.
schultezub's avatar
schultezub committed
143
         */
144
        virtual ImageData* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const;
schultezub's avatar
schultezub committed
145

146
147
148
149
150
151
152
153
154
        /**
         * Transforms a vector based position to the corresponding array index.
         * \note    Caution, this method might return wrong results for non-continuous storage.
         *          In this case you should provide an appropriate overload.
         * \param   position    Vector based image coordinates
         * \return  Array index when image is stored continuously.
         */
        size_t positionToIndex(const tgt::svec3& position) const;

155
156
157
158
159
160
161
162
        /**
         * Transforms an array index to the corresponding vector based position.
         * \note    Caution, this method might return wrong results for non-continuous storage.
         *          In this case you should provide an appropriate overload.
         * \param   index   Array index when image is stored continuously.
         * \return  Vector based image coordinates.
         */
        tgt::svec3 indexToPosition(size_t index) const;
163
164
165

        /**
         * Returns a representation of this image of type \a T.
166
         * Looks, whether such a representations already exists, if not and \a performConversion is 
167
         * set, the method tries to create it via T::tryConvertFrom(). Returns 0 on failure.
168
169
         * \note    You do \b NOT have ownership of the returned pointer!
         *          The returned pointer is valid as long as this ImageData object exists.
170
         * \note    If \a T is OpenGL related, make sure to call this method from a valid and locked OpenGL context.
171
172
173
         * \param   performConversion   Flag whether to perform representation conversion if necessary.
         * \return  A pointer to a representation of type \a T, you do NOT have ownership, valid as long 
         *          as this ImageData object exists. 0 if no such representation could be created.
174
175
         */
        template<typename T>
176
        const T* getRepresentation(bool performConversion = true) const;
177

178
    protected:
179
180
181
        template<typename T>
        const T* tryPerformConversion() const;

182
183
184
185
186
187
188
189
190
191
192
193
194
195
        /**
         * Adds the given representation to the list of representations.
         * \note    Since this is non-publich method, no sanity checks are performed!
         * \param   representation  representation to add, must not be 0.
         */
        void addRepresentation(const AbstractImageRepresentation* representation);

        /**
         * Sets the initial representation of this ImageData.
         * \note    Removes and deletes all existing representations.
         * \param   representation  Initial representation of this image.
         */
        void setInitialRepresentation(const AbstractImageRepresentation* representation);

196
197
198
        /**
         * Clears all representations from the vector and frees the memory.
         * \note    Make sure to call this method only when nobody else holds pointers to the
199
         *          representations as they will be invalidated. This method is \b not thread-safe!
200
201
202
203
         */
        void clearRepresentations();

        /// List of all representations of this image. Mutable to allow lazy instantiation of new representations.
204
        mutable tbb::concurrent_vector<const AbstractImageRepresentation*> _representations;
205

206
207
208
209
        const size_t _dimensionality;                   ///< Dimensionality of this image
        const tgt::svec3 _size;                         ///< Size of this image (number of elements per dimension)
        const size_t _numChannels;                      ///< Number of channels per element
        const size_t _numElements;                      ///< number of elements (= tgt::hmul(size))
schultezub's avatar
schultezub committed
210
211
212
213
214
        ImageMappingInformation _mappingInformation;    ///< Mapping information of this image

        static const std::string loggerCat_;
    };

215
216
217
218

// = Template definition ==========================================================================

    template<typename T>
219
    const T* campvis::ImageData::getRepresentation(bool performConversion) const {
220
        // look, whether we already have a suitable representation
221
        for (tbb::concurrent_vector<const AbstractImageRepresentation*>::const_iterator it = _representations.begin(); it != _representations.end(); ++it) {
222
223
224
            if (typeid(T) == typeid(**it)) {
                return static_cast<const T*>(*it);
            }
225
226
        }

227
        // no representation found, create a new one
228
        if (performConversion) {
229
230
            return tryPerformConversion<T>();
        }
231

232
233
234
235
        return 0;
    }

    template<>
236
    CAMPVIS_CORE_API const campvis::ImageRepresentationLocal* campvis::ImageData::getRepresentation<ImageRepresentationLocal>(bool performConversion) const;
237
238

#ifdef CAMPVIS_HAS_MODULE_ITK
239
240
    class AbstractImageRepresentationItk;

241
    template<>
242
    CAMPVIS_CORE_API const campvis::AbstractImageRepresentationItk* campvis::ImageData::getRepresentation<AbstractImageRepresentationItk>(bool performConversion) const;
243
244
245
246
#endif

    template<typename T>
    const T* campvis::ImageData::tryPerformConversion() const {
247
248
249
        // TODO: Currently, we do not check, for multiple parallel conversions into the same
        //       target type. This does not harm thread-safety but may lead to multiple 
        //       representations of the same type for a single image.
250
251
252
253
254
        for (tbb::concurrent_vector<const AbstractImageRepresentation*>::const_iterator it = _representations.begin(); it != _representations.end(); ++it) {
            const T* tester = T::tryConvertFrom(*it);
            if (tester != 0) {
                return tester;
            }
255
256
        }

257
        // could not create a suitable representation
258
        LWARNING("Could not create a " + std::string(typeid(T*).name()) + " representation.");
259
260
        return 0;
    }
261

schultezub's avatar
schultezub committed
262
263
}

schultezub's avatar
schultezub committed
264
#endif // IMAGEDATA_H__