imagedata.h 11.7 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, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
8
9
//      Chair for Computer Aided Medical Procedures
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
schultezub's avatar
schultezub committed
10
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
// 
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// 
// ================================================================================================

schultezub's avatar
schultezub committed
30
31
#ifndef IMAGEDATA_H__
#define IMAGEDATA_H__
schultezub's avatar
schultezub committed
32

33
#include <tbb/concurrent_vector.h>
34
#include "tgt/logmanager.h"
35
#include "tgt/vector.h"
schultezub's avatar
schultezub committed
36
#include "core/datastructures/abstractdata.h"
37
#include "core/datastructures/abstractimagerepresentation.h"
schultezub's avatar
schultezub committed
38
#include "core/datastructures/imagemappinginformation.h"
39

40
41

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

schultezub's avatar
schultezub committed
43
namespace campvis {
44
45
    class ImageRepresentationLocal;

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

schultezub's avatar
schultezub committed
57
    public:
58
59
60
61
62
63
        /**
         * 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
         */
64
        explicit ImageData(size_t dimensionality, const tgt::svec3& size, size_t numChannels);
schultezub's avatar
schultezub committed
65

66
        /// Destructor
schultezub's avatar
schultezub committed
67
68
        virtual ~ImageData();

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
        /**
         * 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
88
89
90
91
92
93
94
95
96
97
98
99
        /**
         * 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;

100
101
102
103
104
105
        /**
         * Returns the number of channels per element.
         * \return  _numChannels
         */
        size_t getNumChannels() const;

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

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

118
119
120
121
122
123
        /**
         * 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
124
        /**
125
126
         * Returns the image extent in world coordinates.
         * \return  The image extent in world coordinates.
schultezub's avatar
schultezub committed
127
         */
128
        virtual tgt::Bounds getWorldBounds() const;
schultezub's avatar
schultezub committed
129

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

149
150
151
152
153
154
155
156
157
        /**
         * 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;

158
159
160
161
162
163
164
165
        /**
         * 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;
166
167
168

        /**
         * Returns a representation of this image of type \a T.
169
         * Looks, whether such a representations already exists, if not and \a performConversion is 
170
         * set, the method tries to create it via T::tryConvertFrom(). Returns 0 on failure.
171
172
         * \note    You do \b NOT have ownership of the returned pointer!
         *          The returned pointer is valid as long as this ImageData object exists.
173
         * \note    If \a T is OpenGL related, make sure to call this method from a valid and locked OpenGL context.
174
175
176
         * \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.
177
178
         */
        template<typename T>
179
        const T* getRepresentation(bool performConversion = true) const;
180

181
    protected:
182
183
184
        template<typename T>
        const T* tryPerformConversion() const;

185
186
187
188
189
190
191
192
193
194
195
196
197
198
        /**
         * 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);

199
200
201
        /**
         * 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
202
         *          representations as they will be invalidated. This method is \b not thread-safe!
203
204
205
206
         */
        void clearRepresentations();

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

209
210
211
212
        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
213
214
215
216
217
        ImageMappingInformation _mappingInformation;    ///< Mapping information of this image

        static const std::string loggerCat_;
    };

218
219
220
221

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

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

230
        // no representation found, create a new one
231
        if (performConversion) {
232
233
            return tryPerformConversion<T>();
        }
234

235
236
237
238
239
240
241
        return 0;
    }

    template<>
    const campvis::ImageRepresentationLocal* campvis::ImageData::getRepresentation<ImageRepresentationLocal>(bool performConversion) const;

#ifdef CAMPVIS_HAS_MODULE_ITK
242
243
    class AbstractImageRepresentationItk;

244
245
246
247
248
249
    template<>
    const campvis::AbstractImageRepresentationItk* campvis::ImageData::getRepresentation<AbstractImageRepresentationItk>(bool performConversion) const;
#endif

    template<typename T>
    const T* campvis::ImageData::tryPerformConversion() const {
250
251
252
        // 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.
253
254
255
256
257
        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;
            }
258
259
        }

260
261
        // could not create a suitable representation
        LDEBUG("Could not create a " + std::string(typeid(T*).name()) + " representation.");
262
263
        return 0;
    }
264

schultezub's avatar
schultezub committed
265
266
}

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