Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit 97b1566a authored by schultezub's avatar schultezub
Browse files

finished work started on commit #35:

 * Added ImageDataLocal and GenericImageDataLocal<T> replaceing the crapped ImageDataRAM
 * Rewrote most part of TypeTraits and tidied up the rest.
 * Added TypeNormalizer with its traits
 * added ImageData::_numElements and ImageData::positionToIndex()

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@182 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 827ab818
......@@ -11,7 +11,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0 FATAL_ERROR)
#
OPTION(TUMVIS_SHARED_LIBS "Build shared libraries?" ON )
OPTION(TUMVIS_PRECOMPILED_HEADER "Use pre-compiled headers?" ON )
#OPTION(TUMVIS_PRECOMPILED_HEADER "Use pre-compiled headers?" ON )
OPTION(TUMVIS_DEBUG "Activate debug code?" ON )
OPTION(TUMVIS_BUILD_APPLICATION "Build TUMVis Application" ON )
OPTION(TUMVIS_BUILD_CORE "Build TUMVis Core" ON )
......@@ -21,7 +21,7 @@ OPTION(TUMVIS_BUILD_LIB_TGT "Build TGT Library"
IF(WIN32)
OPTION(TUMVIS_COPY_EXTERNAL_DLLS "Copy external DLLs to bin directory?" ON )
OPTION(TUMVIS_INCREMENTAL_LINKING "Enable incremental linking in Visual Studio debug builds?" ON )
OPTION(TUMVIS_GENERATE_MANIFEST "Generate manifest in Visual Studio debug builds?" OFF)
OPTION(TUMVIS_GENERATE_MANIFEST "Generate manifest in Visual Studio debug builds (switch on when encountering errors using incremental linking)?" OFF)
ENDIF()
#
......
......@@ -3,40 +3,237 @@
#include "tgt/vector.h"
#include "core/datastructures/imagedatalocal.h"
#include "core/tools/endianhelper.h"
#include "core/tools/typetraits.h"
#include "core/tools/weaklytypedpointer.h"
#include <cstring>
#include <fstream>
#include <string>
#include <cstring> // needed for memcpy
namespace TUMVis {
/**
* Templated version of ImageDataLocal, storing image data in the local memory.
*
* \sa TypeTraits
* \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.
*/
template<typename BASETYPE, size_t NUMCHANNELS>
class GenericImageDataLocal : public ImageDataLocal {
public:
typedef typedef TypeTraits<
GenericImageDataLocal(size_t dimensionality, const tgt::svec3& size, T* data);
/// Type of one single image element
typedef typename TypeTraits<BASETYPE, NUMCHANNELS>::ElementType ElementType;
/// Type of this template instantiation
typedef GenericImageDataLocal<BASETYPE, NUMCHANNELS> ThisType;
/**
* Creates a new strongly typed ImageData object storing the image in the local memory.
*
* \param dimensionality Dimensionality of data
* \param size Size of this image (number of elements per dimension)
* \param data Pointer to the image data, must not be 0, GenericImageDataLocal takes ownership of this pointer!
*/
GenericImageDataLocal(size_t dimensionality, const tgt::svec3& size, ElementType* data);
/**
* Destructor
*/
virtual ~GenericImageDataLocal();
/// \see AbstractData::clone()
virtual ImageDataLocal<typename BASETYPE, size_t NUMCHANNELS>* clone() const;
virtual ThisType* clone() const;
/// \see ImageData::getSubImage
virtual ImageDataLocal<typename BASETYPE, size_t NUMCHANNELS>* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const;
virtual ThisType* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const;
/// \see ImageDataLocal::getElementNormalized
virtual float getElementNormalized(const tgt::svec3& position, size_t channel) const;
/// \see ImageDataLocal::setElementNormalized
virtual void setElementNormalized(const tgt::svec3& position, size_t channel, float value);
/**
* Returns the image element at the given index \a index.
* \param index Array index of the image element to return.
* \return Image element at index \a index.
*/
ElementType& getElement(size_t index);
/**
* Returns the image element at the given position in image space.
* \param position Pixel/voxel coordinates of the image element to return.
* \return Image element at the coordinates \a position.
*/
ElementType& getElement(const tgt::svec3& position);
/**
* Returns the image element at the given index \a index.
* \param index Array index of the image element to return.
* \return Image element at index \a index.
*/
const ElementType& getElement(size_t index) const;
/**
* Returns the image element at the given position in image space.
* \param position Pixel/voxel coordinates of the image element to return.
* \return Image element at the coordinates \a position.
*/
const ElementType& getElement(const tgt::svec3& position) const;
/**
* Sets the image element at the given index to the value \a value.
* \param index Array index of the image element to change.
* \param value New value of the specified image element.
*/
void setElement(size_t index, const ElementType& value);
/**
* Sets the image element at the given position in image space to the value \a value.
* \param position Pixel/voxel coordinates of the image element to change.
* \param value New value of the specified image element.
*/
void setElement(const tgt::svec3& position, const ElementType& value);
/**
* Returns a pointer to the image data.
* \return _data
*/
ElementType* getImageData();
/**
* Returns a const pointer to the image data.
* \return _data
*/
const ElementType* getImageData() const;
/**
* Returns the image element at the given coordinates \a position using bi-/trilinear filtering.
* \param position Pixel/voxel coordinates of the image element to return.
* \return Bi-/Trilinear filtered image element at the specified coordinates.
*/
ElementType getElementLinear(const tgt::vec3 position) const;
protected:
ElementType* _data;
};
// - Template implementation ----------------------------------------------------------------------
// = Template implementation ======================================================================
template<typename BASETYPE, size_t NUMCHANNELS>
TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::GenericImageDataLocal(size_t dimensionality, const tgt::svec3& size, ElementType* data)
: ImageDataLocal(dimensionality, size, TypeTraits<BASETYPE, NUMCHANNELS>::weaklyTypedPointerBaseType, NUMCHANNELS)
, _data(data)
{
tgtAssert(data != 0, "Pointer to image data must not be 0!");
}
template<typename BASETYPE, size_t NUMCHANNELS>
TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::~GenericImageDataLocal() {
delete _data;
}
template<typename BASETYPE, size_t NUMCHANNELS>
GenericImageDataLocal<BASETYPE, NUMCHANNELS>* TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::clone() const {
size_t numElements = tgt::hmul(_size);
ElementType* newData = new ElementType[numElements];
memcpy(newData, _data, numElements * sizeof(ElementType));
return new ThisType(_dimensionality, _size, newData);
}
template<typename BASETYPE, size_t NUMCHANNELS>
GenericImageDataLocal<BASETYPE, NUMCHANNELS>* TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const {
tgtAssert(tgt::hand(tgt::lessThan(llf, urb)), "Coordinates in LLF must be component-wise smaller than the ones in URB!");
tgt::svec3 newSize = urb - llf;
if (newSize == _size) {
// nothing has changed, just provide a copy:
return clone();
}
size_t numBytesPerElement = sizeof(ElementType);
size_t numElements = tgt::hmul(_size);
ElementType* newData = new ElementType[numElements];
// slice image data into new array
size_t index = 0;
for (size_t z = llf.z; z < urb.z; ++z) {
for (size_t y = llf.y; y < urb.y; ++y) {
size_t offset = llf.x + (y * _size.x) + (z * _size.y * _size.x);
memcpy(newData + index, _data + offset, newSize.x * numBytesPerElement);
index += newSize.x;
}
}
return new ThisType(_dimensionality, newSize, newData);
}
template<typename BASETYPE, size_t NUMCHANNELS>
float TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getElementNormalized(const tgt::svec3& position, size_t channel) const {
tgtAssert(channel >= 0 && channel < NUMCHANNELS, "Channel out of bounds!");
return TypeNormalizer::normalizeToFloat(TypeTraits<BASETYPE, NUMCHANNELS>::getChannel(getElement(position), channel));
}
template<typename BASETYPE, size_t NUMCHANNELS>
void TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::setElementNormalized(const tgt::svec3& position, size_t channel, float value) {
tgtAssert(channel >= 0 && channel < NUMCHANNELS, "Channel out of bounds!");
TypeTraits<BASETYPE, NUMCHANNELS>::setChannel(getElement(position), channel, TypeNormalizer::denormalizeFromFloat<BASETYPE>(value));
}
template<typename BASETYPE, size_t NUMCHANNELS>
typename TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::ElementType& TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getElement(size_t position) {
tgtAssert(position >= 0 && position < _numElements, "Position out of bounds!");
return _data[position];
}
template<typename BASETYPE, size_t NUMCHANNELS>
typename TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::ElementType& TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getElement(const tgt::svec3& position) {
return getElement(positionToIndex(position));
}
template<typename BASETYPE, size_t NUMCHANNELS>
const typename TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::ElementType& TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getElement(size_t position) const {
tgtAssert(position >= 0 && position < _numElements, "Position out of bounds!");
return _data[position];
}
template<typename BASETYPE, size_t NUMCHANNELS>
const typename TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::ElementType& TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getElement(const tgt::svec3& position) const {
return getElement(positionToIndex(position));
}
template<typename BASETYPE, size_t NUMCHANNELS>
void TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::setElement(size_t position, const ElementType& value) {
tgtAssert(position >= 0 && position < _numElements, "Position out of bounds!");
_data[position] = value;
}
template<typename BASETYPE, size_t NUMCHANNELS>
void TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::setElement(const tgt::svec3& position, const ElementType& value) {
_data[positionToIndex(position)] = value;
}
template<typename BASETYPE, size_t NUMCHANNELS>
typename TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::ElementType* TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getImageData() {
return _data;
}
template<typename BASETYPE, size_t NUMCHANNELS>
const typename TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::ElementType* TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getImageData() const {
return _data;
}
template<typename BASETYPE, size_t NUMCHANNELS>
typename TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::ElementType TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getElementLinear(const tgt::vec3 position) const {
// yet to be implemented
// TODO: Check wether pixel/voxel coordinates lie on the edges or on the center of the pixels/voxels
tgtAssert(false, "Yet to be implemented!");
return ElementType(0);
}
}
#endif // GENERICIMAGEDATALOCAL_H__
......@@ -6,6 +6,7 @@ namespace TUMVis {
ImageData::ImageData(size_t dimensionality, const tgt::svec3& size)
: _dimensionality(dimensionality)
, _size(size)
, _numElements(tgt::hmul(size))
{
}
......@@ -27,4 +28,12 @@ namespace TUMVis {
ImageMappingInformation& ImageData::getMappingInformation() {
return _mappingInformation;
}
size_t ImageData::getNumElements() const {
return _numElements;
}
size_t ImageData::positionToIndex(const tgt::svec3& position) const {
return position.x + (position.y * _size.x) + (position.z * _size.x * _size.y);
}
}
\ No newline at end of file
......@@ -32,6 +32,12 @@ namespace TUMVis {
*/
const tgt::svec3& getSize() const;
/**
* Returns the number of elements (= tgt::hmul(getSize())).
* \return _numElements
*/
size_t getNumElements() const;
/**
* Mapping information of this image
* \return _mappingInformation
......@@ -55,8 +61,18 @@ namespace TUMVis {
virtual ImageData* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const = 0;
protected:
/**
* 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;
size_t _dimensionality; ///< Dimensionality of this image
tgt::svec3 _size; ///< Size of this image (number of elements per dimension)
size_t _numElements; ///< number of elements (= tgt::hmul(size))
ImageMappingInformation _mappingInformation; ///< Mapping information of this image
static const std::string loggerCat_;
......
......@@ -4,7 +4,7 @@
#include "tgt/texture.h"
#include "tgt/vector.h"
#include "core/datastructures/imagedata.h"
#include "core/tools/typetraits.h"
#include "core/datastructures/genericimagedatalocal.h"
#include "core/tools/weaklytypedpointer.h"
namespace TUMVis {
......@@ -25,16 +25,16 @@ namespace TUMVis {
ImageDataGL(size_t dimensionality, const tgt::svec3& size, const WeaklyTypedPointer& wtp);
/**
* Creates a new ImageDataGL representation from ImageDataRAM.
* Creates a new ImageDataGL representation from GenericImageDataLocal.
*
* \param dimensionality Dimensionality of data
* \param size Size of this image (number of elements per dimension)
* \param data Pointer to the ImageDataRAM instance, must not be 0, type has to match the template parameters.
* \param data Pointer to the GenericImageDataLocal instance, must not be 0
* \tparam BASETYPE Base type of image data
* \tparam NUMCHANNELS Number of channels per element
*/
template<typename BASETYPE, size_t NUMCHANNELS>
ImageDataGL(size_t dimensionality, const tgt::svec3& size, typename TypeTraits<BASETYPE, NUMCHANNELS>::ImageRAMType* data);
ImageDataGL(size_t dimensionality, const tgt::svec3& size, const GenericImageDataLocal<BASETYPE, NUMCHANNELS>* data);
/**
* Destructor
......@@ -64,12 +64,12 @@ namespace TUMVis {
/**
* Creates the OpenGL texture from the given ImageDataRAM \a data.
* \param data Pointer to the ImageDataRAM instance, must not be 0, type has to match the template parameters.
* \param data Pointer to the GenericImageDataLocal instance, must not be 0
* \tparam BASETYPE Base type of image data
* \tparam NUMCHANNELS Number of channels per element
*/
template<typename BASETYPE, size_t NUMCHANNELS>
void createTexture(typename TypeTraits<BASETYPE, NUMCHANNELS>::ImageRAMType* data);
void createTexture(const GenericImageDataLocal<BASETYPE, NUMCHANNELS>* data);
tgt::Texture* _texture; //< OpenGL texture
......@@ -79,14 +79,14 @@ namespace TUMVis {
// = Template definition ==========================================================================
template<typename BASETYPE, size_t NUMCHANNELS>
TUMVis::ImageDataGL::ImageDataGL(size_t dimensionality, const tgt::svec3& size, typename TypeTraits<BASETYPE, NUMCHANNELS>::ImageRAMType* imageRAM)
TUMVis::ImageDataGL::ImageDataGL(size_t dimensionality, const tgt::svec3& size, const GenericImageDataLocal<BASETYPE, NUMCHANNELS>* data)
: ImageData(dimensionality, size)
{
createTexture<BASETYPE, NUMCHANNELS>(data);
}
template<typename BASETYPE, size_t NUMCHANNELS>
void TUMVis::ImageDataGL::createTexture(typename TypeTraits<BASETYPE, NUMCHANNELS>::ImageRAMType* data) {
void TUMVis::ImageDataGL::createTexture(const GenericImageDataLocal<BASETYPE, NUMCHANNELS>* data) {
tgtAssert(data != 0, "Pointer to image must not be 0!");
_texture = new tgt::Texture(
......
......@@ -14,7 +14,7 @@
namespace TUMVis {
/**
* Abstract base class for strongly typed (templated) ImageDataRAM
* Abstract base class for storing image data in the local memory
*
* \todo implement padding, add some kind of cool iterators
*/
......@@ -44,20 +44,6 @@ namespace TUMVis {
*/
virtual ImageDataLocal* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const = 0;
/**
* Returns the WeaklyTypedPointer to the image data.
* \return Pointer to the image data.
*/
virtual WeaklyTypedPointer& getImageData() = 0;
/**
* Returns the WeaklyTypedPointer to the image data.
* \return Pointer to the image data.
*/
virtual const WeaklyTypedPointer& getImageData() const = 0;
/**
* Returns the normalized value of the element at the given position and channel.
* - for \em unsigned integer types, the value range is mapped linearly to [0.0;1.0]
......
#include "imagedataram.h"
namespace TUMVis {
/*
const std::string ImageDataRAM::loggerCat_ = "TUMVis.core.datastructures.ImageDataRAM";
ImageDataRAM::ImageDataRAM(size_t dimensionality, const tgt::svec3& size, WeaklyTypedPointer data)
: ImageData(dimensionality, size)
, _data(data)
{
Full<int, 2> f;
f.foo(tgt::ivec2(1, 2));
}
ImageDataRAM::~ImageDataRAM() {
delete _data._pointer;
}
ImageDataRAM* ImageDataRAM::clone() const {
size_t numBytes = tgt::hmul(_size) * _data.numBytes();
char* newData = new char[numBytes];
memcpy(newData, _data._pointer, numBytes);
return new ImageDataRAM(_dimensionality, _size, WeaklyTypedPointer(_data._pointerType, static_cast<void*>(newData)));
}
ImageDataRAM* ImageDataRAM::getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const {
tgtAssert(tgt::hand(tgt::lessThan(llf, urb)), "Coordinates in LLF must be component-wise smaller than the ones in URB!");
tgt::svec3 newSize = urb - llf;
if (newSize == _size) {
// nothing has changed, just provide a copy:
return clone();
}
size_t numBytesPerElement = _data.numBytes();
size_t numBytesTotal = tgt::hmul(newSize) * numBytesPerElement;
char* newData = new char[numBytesTotal];
// slice image data into new array
size_t index = 0;
for (size_t z = llf.z; z < urb.z; ++z) {
for (size_t y = llf.y; y < urb.y; ++y) {
size_t offset = llf.x + (y * _size.x) + (z * _size.y * _size.x);
memcpy(newData + (index * numBytesPerElement), static_cast<char*>(_data._pointer) + (offset * numBytesPerElement), newSize.x * numBytesPerElement);
index += newSize.x;
}
}
return new ImageDataRAM(_dimensionality, newSize, WeaklyTypedPointer(_data._pointerType, static_cast<void*>(newData)));
}
WeaklyTypedPointer& ImageDataRAM::getImageData() {
return _data;
}
const WeaklyTypedPointer& ImageDataRAM::getImageData() const {
return _data;
}*/
}
\ No newline at end of file
#ifndef IMAGEDATARAM_H__
#define IMAGEDATARAM_H__
#include "tgt/vector.h"
#include "core/datastructures/imagedata.h"
#include "core/tools/endianhelper.h"
#include "core/tools/weaklytypedpointer.h"
#include <cstring>
#include <fstream>
#include <string>
namespace TUMVis {
/**
* Templated class storing ImageData in the local memory. Each image element is of type \a T.
*
* \note Although you can use ImageDataRAM directly (which works perfectly well), it is
* encouraged to use ImageDataRAMTraits for a clearer approach and better support
* of the ImageData converters.
* \sa ImageDataRAMTraits
* \todo implement padding, add some kind of cool iterators
* \tparam T base class of elements
*/
template<typename T>
class ImageDataRAM : public ImageData {
public:
/**
* Creates a new ImageData disk representation.
*
* \note ImageDataRam takes ownership of \a data.
* \param dimensionality Dimensionality of data
* \param size Size of this image (number of elements per dimension)
* \param data Pointer to the image data, must not be 0, ImageDataRAM takes ownership of that pointer.
*/
ImageDataRAM(
size_t dimensionality,
const tgt::svec3& size,
T* data = 0
);
/**
* Destructor
*/
virtual ~ImageDataRAM();
/**
* \see AbstractData::clone()
**/
virtual ImageDataRAM<T>* clone() const;
/**
* \see ImageData::getSubImage
*/
virtual ImageDataRAM<T>* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const;
/**
* Returns the WeaklyTypedPointer to the image data.
* \return Pointer to the image data.
*/
T* getImageData();
/**
* Returns the WeaklyTypedPointer to the image data.
* \return Pointer to the image data.
*/
const T* getImageData() const;
protected:
T* _data; ///< pointer to image data
static const std::string loggerCat_;
private:
// We don't want this data to be copied - clone() must be enough
// (read: We are too lazy to implement a correct copy constructor / assignment-operator)
ImageDataRAM(const ImageDataRAM<T>& rhs) {};
ImageDataRAM<T>& operator=(const ImageDataRAM& rhs) {};
};
// - Template implementation ----------------------------------------------------------------------
template<typename T>
TUMVis::ImageDataRAM<T>::ImageDataRAM(size_t dimensionality, const tgt::svec3& size, T* data)
: ImageData(dimensionality, size)
, _data(data)
{
}
template<typename T>
TUMVis::ImageDataRAM<T>::~ImageDataRAM() {
delete _data;
}
template<typename T>
ImageDataRAM<T>* TUMVis::ImageDataRAM<T>::clone() const {
size_t numElements = tgt::hmul(_size);
T* newData = new T[numElements];
memcpy(newData, _data, numElements * sizeof(T));
return new ImageDataRAM<T>(_dimensionality, _size, newData);
}
template<typename T>
ImageDataRAM<T>* TUMVis::ImageDataRAM<T>::getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const {
tgtAssert(tgt::hand(tgt::lessThan(llf, urb)), "Coordinates in LLF must be component-wise smaller than the ones in URB!");
tgt::svec3 newSize = urb - llf;
if (newSize == _size) {
// nothing has changed, just provide a copy:
return clone();
}