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

Commit 894aa901 authored by schultezub's avatar schultezub
Browse files

moved numChannels field from ImageRepresentationXYZ to ImageData

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@405 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 18997156
......@@ -158,7 +158,11 @@ namespace campvis {
return _imageHandle;
}
void AbstractTransferFunction::setImageHandle(const DataHandle& imageHandle) {
void AbstractTransferFunction::setImageHandle(DataHandle imageHandle) {
tgtAssert(
imageHandle.getData() == 0 || dynamic_cast<const ImageData*>(imageHandle.getData()) != 0,
"The data in the image handle must either be 0 or point to a valid ImageData object!");
_imageHandle = imageHandle;
_dirtyHistogram = true;
s_imageHandleChanged();
......
......@@ -125,17 +125,19 @@ namespace campvis {
const tgt::Texture* getTexture();
/**
* Returns a DataHandle to the image for this transfer function, may be 0.
* \return _imageHandle, may be 0!
* Returns a DataHandle to the image for this transfer function, its pointer may be 0.
* \note If the data in \a imageHandle is not 0, it points to a valid ImageData object.
* \return _imageHandle, its pointer may be 0.
*/
DataHandle getImageHandle() const;
/**
* Sets the DataHandle for this transfer function, may be 0.
* \note This method makes a copy of \a imageHandle, hence does not take ownership.
* \param imageHandle The new DataHandle for this transfer function
* Sets the DataHandle for this transfer function, its pointer may be 0.
* \note If the data in \a imageHandle is not 0, it must point to a valid ImageData object.
* \param imageHandle The new DataHandle for this transfer function, if its pointer is
* not 0 it must point to a valid ImageData object.
*/
void setImageHandle(const DataHandle& imageHandle);
void setImageHandle(DataHandle imageHandle);
/**
* Returns the intensity histogram
......
......@@ -173,9 +173,10 @@ namespace campvis {
template<typename BASETYPE, size_t NUMCHANNELS>
campvis::GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>::GenericImageRepresentationLocal(const ImageData* parent, ElementType* data)
: ImageRepresentationLocal(parent, TypeTraits<BASETYPE, NUMCHANNELS>::weaklyTypedPointerBaseType, NUMCHANNELS)
: ImageRepresentationLocal(parent, TypeTraits<BASETYPE, NUMCHANNELS>::weaklyTypedPointerBaseType)
, _data(data)
{
tgtAssert(_parent->getNumChannels() == NUMCHANNELS, "Number of channels must match parent image's number of channels!");
if (_data == 0) {
size_t numElements = getNumElements();
_data = new ElementType[numElements];
......
......@@ -32,13 +32,15 @@
namespace campvis {
const std::string ImageData::loggerCat_ = "CAMPVis.core.datastructures.ImageData";
ImageData::ImageData(size_t dimensionality, const tgt::svec3& size)
ImageData::ImageData(size_t dimensionality, const tgt::svec3& size, size_t numChannels)
: AbstractData()
, _dimensionality(dimensionality)
, _size(size)
, _numChannels(numChannels)
, _numElements(tgt::hmul(size))
, _mappingInformation(size, tgt::vec3(0.f), tgt::vec3(1.f)) // TODO: get offset/voxel size as parameter or put default values into ImageMappingInformation ctor.
{
tgtAssert(numChannels > 0, "Number of channels must be greater than 0!");
}
ImageData::~ImageData() {
......@@ -46,7 +48,7 @@ namespace campvis {
}
ImageData* ImageData::clone() const {
ImageData* toReturn = new ImageData(_dimensionality, _size);
ImageData* toReturn = new ImageData(_dimensionality, _size, _numChannels);
toReturn->_mappingInformation = _mappingInformation;
toReturn->_representations.assign(_representations.begin(), _representations.end());
return toReturn;
......@@ -76,6 +78,10 @@ namespace campvis {
return _size;
}
size_t ImageData::getNumChannels() const {
return _numChannels;
}
const ImageMappingInformation& ImageData::getMappingInformation() const {
return _mappingInformation;
}
......@@ -111,7 +117,7 @@ namespace campvis {
newDimensionality = 3;
// create new ImageData object and assign mapping information
ImageData* toReturn = new ImageData(newDimensionality, newSize);
ImageData* toReturn = new ImageData(newDimensionality, newSize, _numChannels);
toReturn->_mappingInformation = ImageMappingInformation(newSize, _mappingInformation.getOffset(), _mappingInformation.getVoxelSize(), _mappingInformation.getRealWorldMapping());
// create sub-image of every image representation
......
......@@ -50,8 +50,15 @@ namespace campvis {
*/
class ImageData : public AbstractData {
public:
ImageData(size_t dimensionality, const tgt::svec3& size);
/**
* 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
*/
ImageData(size_t dimensionality, const tgt::svec3& size, size_t numChannels);
/// Destructor
virtual ~ImageData();
/**
......@@ -85,6 +92,12 @@ namespace campvis {
*/
const tgt::svec3& getSize() const;
/**
* Returns the number of channels per element.
* \return _numChannels
*/
size_t getNumChannels() const;
/**
* Returns the number of elements (= tgt::hmul(getSize())).
* \return _numElements
......@@ -181,6 +194,7 @@ namespace campvis {
size_t _dimensionality; ///< Dimensionality of this image
tgt::svec3 _size; ///< Size of this image (number of elements per dimension)
size_t _numChannels; ///< Number of channels per element
size_t _numElements; ///< number of elements (= tgt::hmul(size))
ImageMappingInformation _mappingInformation; ///< Mapping information of this image
......
......@@ -35,12 +35,11 @@
namespace campvis {
const std::string ImageRepresentationDisk::loggerCat_ = "CAMPVis.core.datastructures.ImageRepresentationDisk";
ImageRepresentationDisk::ImageRepresentationDisk(const ImageData* parent, const std::string& url, WeaklyTypedPointer::BaseType type, size_t numChannels, size_t offset /*= 0*/, EndianHelper::Endianness endianness /*= EndianHelper::LITTLE_ENDIAN*/, const tgt::svec3& stride /*= tgt::svec2::zero */)
ImageRepresentationDisk::ImageRepresentationDisk(const ImageData* parent, const std::string& url, WeaklyTypedPointer::BaseType type, size_t offset /*= 0*/, EndianHelper::Endianness endianness /*= EndianHelper::LITTLE_ENDIAN*/, const tgt::svec3& stride /*= tgt::svec2::zero */)
: GenericAbstractImageRepresentation<ImageRepresentationDisk>(parent)
, _url(url)
, _offset(offset)
, _type(type)
, _numChannels(numChannels)
, _endianess(endianness)
, _stride(stride)
{
......@@ -59,16 +58,16 @@ namespace campvis {
return clone();
}
size_t newOffset = _offset + WeaklyTypedPointer::numBytes(_type, _numChannels) * (llf.x + llf.y * size.y + llf.z * size.x * size.y);
size_t newOffset = _offset + WeaklyTypedPointer::numBytes(_type, _parent->getNumChannels()) * (llf.x + llf.y * size.y + llf.z * size.x * size.y);
// the stride doesn't change!
tgt::svec3 newStride = (_stride == tgt::svec3::zero) ? getCanonicStride(getSize()) : _stride;
return new ImageRepresentationDisk(parent, _url, _type, _numChannels, newOffset, _endianess, newStride);
return new ImageRepresentationDisk(parent, _url, _type, newOffset, _endianess, newStride);
}
campvis::WeaklyTypedPointer ImageRepresentationDisk::getImageData() const {
const tgt::svec3& size = getSize();
size_t numElements = tgt::hmul(size);
size_t numBytesPerElement = WeaklyTypedPointer::numBytes(_type, _numChannels);
size_t numBytesPerElement = WeaklyTypedPointer::numBytes(_type, _parent->getNumChannels());
size_t numBytes = numElements * numBytesPerElement;
// open file and prepare for read
......@@ -77,7 +76,7 @@ namespace campvis {
size_t fileSize = static_cast<size_t>(file.tellg());
if (fileSize < numBytes) {
LERROR("File is smaller than expected.");
return WeaklyTypedPointer(_type, _numChannels, 0);
return WeaklyTypedPointer(_type, _parent->getNumChannels(), 0);
}
file.seekg(_offset, std::ios::beg);
......@@ -182,11 +181,11 @@ namespace campvis {
}
return WeaklyTypedPointer(_type, _numChannels, static_cast<void*>(data));
return WeaklyTypedPointer(_type, _parent->getNumChannels(), static_cast<void*>(data));
}
else {
LERROR("Could not open file " << _url << " for reading.");
return WeaklyTypedPointer(_type, _numChannels, 0);
return WeaklyTypedPointer(_type, _parent->getNumChannels(), 0);
}
}
......@@ -196,7 +195,7 @@ namespace campvis {
}
ImageRepresentationDisk* ImageRepresentationDisk::clone() const {
return new ImageRepresentationDisk(_parent, _url, _type, _numChannels, _offset, _endianess, _stride);
return new ImageRepresentationDisk(_parent, _url, _type, _offset, _endianess, _stride);
}
size_t ImageRepresentationDisk::getLocalMemoryFootprint() const {
......@@ -211,10 +210,6 @@ namespace campvis {
return _type;
}
size_t ImageRepresentationDisk::getNumChannels() const {
return _numChannels;
}
ImageRepresentationDisk* ImageRepresentationDisk::tryConvertFrom(const AbstractImageRepresentation* source) {
// no conversion availible for now
return 0;
......
......@@ -50,7 +50,6 @@ namespace campvis {
* \param parent Image this representation represents, must not be 0.
* \param url Path to file with raw data
* \param type Base type of data
* \param numChannels Number of channels per element
* \param offset Offset of first data element in file (in bytes)
* \param endianness Endianess of data
* \param stride Number of _elemments_ _between_ adjacent elements for each dimension (\see ImageRepresentationDisk::_stride).
......@@ -59,7 +58,6 @@ namespace campvis {
const ImageData* parent,
const std::string& url,
WeaklyTypedPointer::BaseType type,
size_t numChannels,
size_t offset = 0,
EndianHelper::Endianness endianness = EndianHelper::LITTLE_ENDIAN,
const tgt::svec3& stride = tgt::svec3::zero
......@@ -106,12 +104,6 @@ namespace campvis {
*/
WeaklyTypedPointer::BaseType getBaseType() const;
/**
* Returns the number of channels per element
* \return _numChannels
*/
size_t getNumChannels() const;
private:
/**
* Calculates the canonical stride for the given image size.
......@@ -123,7 +115,6 @@ namespace campvis {
std::string _url; ///< path to file with raw data
size_t _offset; ///< offset of first data element in file (in bytes)
WeaklyTypedPointer::BaseType _type; ///< base type of data
size_t _numChannels; ///< number of channels per element
EndianHelper::Endianness _endianess; ///< endianess of data
/**
......
......@@ -88,7 +88,7 @@ namespace campvis {
ImageRepresentationGL* ImageRepresentationGL::getSubImage(const ImageData* parent, const tgt::svec3& llf, const tgt::svec3& urb) const {
// TODO: implement
tgtAssert(false, "not yet implemented...");
//LWARNING("ImageRepresentationGL::getSubImage() not implemented!");
return 0;
}
......@@ -177,12 +177,14 @@ namespace campvis {
shader->setUniform(texUniform + "._texture", texUnit.getUnitNumber());
shader->setUniform(texUniform + "._size", tgt::vec2(getSize().xy()));
shader->setUniform(texUniform + "._sizeRCP", tgt::vec2(1.f) / tgt::vec2(getSize().xy()));
shader->setUniform(texUniform + "._numChannels", static_cast<int>(_parent->getNumChannels()));
break;
case 3:
shader->setUniform(texUniform + "._texture", texUnit.getUnitNumber());
shader->setUniform(texUniform + "._size", tgt::vec3(getSize()));
shader->setUniform(texUniform + "._sizeRCP", tgt::vec3(1.f) / tgt::vec3(getSize()));
shader->setUniform(texUniform + "._numChannels", static_cast<int>(_parent->getNumChannels()));
shader->setUniform(texUniform + "._voxelSize", _parent->getMappingInformation().getVoxelSize());
shader->setUniform(texUniform + "._voxelSizeRCP", tgt::vec3(1.f) / _parent->getMappingInformation().getVoxelSize());
shader->setUniform(texUniform + "._textureToWorldMatrix", _parent->getMappingInformation().getTextureToWorldMatrix());
......
......@@ -96,10 +96,9 @@ namespace campvis {
const std::string ImageRepresentationLocal::loggerCat_ = "CAMPVis.core.datastructures.ImageRepresentationLocal";
ImageRepresentationLocal::ImageRepresentationLocal(const ImageData* parent, WeaklyTypedPointer::BaseType baseType, size_t numChannels)
ImageRepresentationLocal::ImageRepresentationLocal(const ImageData* parent, WeaklyTypedPointer::BaseType baseType)
: GenericAbstractImageRepresentation<ImageRepresentationLocal>(parent)
, _baseType(baseType)
, _numChannels(numChannels)
, _intensityHistogram(0)
{
_intensityRangeDirty = true;
......@@ -160,7 +159,7 @@ namespace campvis {
reinterpret_cast< TypeTraits<baseType, numChannels>::ElementType*>(wtp._pointer));
#define DISPATCH_CONVERSION(numChannels) \
if (source->getNumChannels() == (numChannels)) { \
if (source->getParent()->getNumChannels() == (numChannels)) { \
switch (source->getBaseType()) { \
case WeaklyTypedPointer::UINT8: \
CONVERT_TO_GENERIC_LOCAL(uint8_t, (numChannels)) \
......
......@@ -55,9 +55,8 @@ namespace campvis {
* \param dimensionality Dimensionality of data
* \param size Size of this image (number of elements per dimension)
* \param baseType Base type of the image data.
* \param numChannels Number of channels per image element.
*/
ImageRepresentationLocal(const ImageData* parent, WeaklyTypedPointer::BaseType baseType, size_t numChannels);
ImageRepresentationLocal(const ImageData* parent, WeaklyTypedPointer::BaseType baseType);
/**
* Destructor
......@@ -202,7 +201,6 @@ namespace campvis {
void computeIntensityHistogram() const;
WeaklyTypedPointer::BaseType _baseType; ///< Base type of the image data
size_t _numChannels; ///< Number of channels per image element.
mutable tbb::atomic<bool> _intensityRangeDirty; ///< Flag whether _normalizedIntensityRange is dirty and has to be recomputed
mutable Interval<float> _normalizedIntensityRange; ///< Range of the normalized intensities, mutable to allow lazy instantiation
......
......@@ -43,7 +43,7 @@ namespace campvis {
const std::string ImageRepresentationRenderTarget::loggerCat_ = "CAMPVis.core.datastructures.ImageRepresentationRenderTarget";
std::pair<ImageData*, ImageRepresentationRenderTarget*> ImageRepresentationRenderTarget::createWithImageData(const tgt::svec2& size, GLint internalFormatColor /*= GL_RGBA8*/, GLint internalFormatDepth /*= GL_DEPTH_COMPONENT24*/) {
ImageData* id = new ImageData(2, tgt::svec3(size, 1));
ImageData* id = new ImageData(2, tgt::svec3(size, 1), 4);
ImageRepresentationRenderTarget* toReturn = new ImageRepresentationRenderTarget(id, internalFormatColor, internalFormatDepth);
id->setInitialRepresentation(toReturn);
return std::make_pair(id, toReturn);
......
......@@ -33,6 +33,7 @@ struct Texture2D {
sampler2D _texture;
vec2 _size;
vec2 _sizeRCP;
int _numChannels;
};
/**
......
......@@ -37,6 +37,9 @@ struct Texture3D {
vec3 _size;
vec3 _sizeRCP;
// Number of channels
int _numChannels;
// Voxel spacing
vec3 _voxelSize;
vec3 _voxelSizeRCP;
......
......@@ -79,7 +79,7 @@ namespace campvis {
void DevilImageReader::process(DataContainer& data) {
tgt::Texture* tex = _devilTextureReader->loadTexture(p_url.getValue(), tgt::Texture::LINEAR, false, true, true, false);
if (tex != 0) {
ImageData id (2, tex->getDimensions());
ImageData id (2, tex->getDimensions(), tex->getNumChannels());
ImageRepresentationGL image(&id, tex);
std::pair<ImageData*, ImageRepresentationRenderTarget*> rt = ImageRepresentationRenderTarget::createWithImageData(_renderTargetSize.getValue());
......
......@@ -169,8 +169,8 @@ namespace campvis {
// all parsing done - lets create the image:
ImageData* image = new ImageData(dimensionality, size);
image->setInitialRepresentation(new ImageRepresentationDisk(image, url, pt, 1, offset, e));
ImageData* image = new ImageData(dimensionality, size, 1);
image->setInitialRepresentation(new ImageRepresentationDisk(image, url, pt, offset, e));
image->setMappingInformation(ImageMappingInformation(size, imageOffset + p_imageOffset.getValue(), voxelSize + p_voxelSize.getValue()));
data.addData(p_targetImageID.getValue(), image);
p_targetImageID.issueWrite();
......
......@@ -113,7 +113,7 @@ namespace campvis {
float* asFloats = new float[numElements];
for (size_t i = 0; i < numElements; ++i)
asFloats[i] = img->getElementNormalized(i, 0);
ImageData* id = new ImageData(img->getDimensionality(), img->getSize());
ImageData* id = new ImageData(img->getDimensionality(), img->getSize(), img->getParent()->getNumChannels());
GenericImageRepresentationLocal<float, 1>* imageWithFloats = new GenericImageRepresentationLocal<float, 1>(id, asFloats);
id->setInitialRepresentation(imageWithFloats);
......
......@@ -88,11 +88,11 @@ namespace campvis {
GradientVolumeGenerator::GradientVolumeGenerator()
: AbstractProcessor()
, p_inputVolume("InputVolume", "Input Volume ID", "volume", DataNameProperty::READ)
, p_outputGradients("OutputGradients", "Output Gradient Volume ID", "gradients", DataNameProperty::WRITE)
, p_sourceImageID("InputVolume", "Input Volume ID", "volume", DataNameProperty::READ)
, p_targetImageID("OutputGradients", "Output Gradient Volume ID", "gradients", DataNameProperty::WRITE)
{
addProperty(&p_inputVolume);
addProperty(&p_outputGradients);
addProperty(&p_sourceImageID);
addProperty(&p_targetImageID);
}
GradientVolumeGenerator::~GradientVolumeGenerator() {
......@@ -100,16 +100,16 @@ namespace campvis {
}
void GradientVolumeGenerator::process(DataContainer& data) {
ImageRepresentationLocal::ScopedRepresentation input(data, p_inputVolume.getValue());
ImageRepresentationLocal::ScopedRepresentation input(data, p_sourceImageID.getValue());
if (input != 0) {
ImageData* id = new ImageData(input->getDimensionality(), input->getSize());
ImageData* id = new ImageData(input->getDimensionality(), input->getSize(), 4);
GenericImageRepresentationLocal<float, 4>* output = new GenericImageRepresentationLocal<float, 4>(id, 0);
tbb::parallel_for(tbb::blocked_range<size_t>(0, input->getNumElements()), ApplyCentralDifferences(input, output));
id->setInitialRepresentation(output);
data.addData(p_outputGradients.getValue(), id);
p_outputGradients.issueWrite();
data.addData(p_targetImageID.getValue(), id);
p_targetImageID.issueWrite();
}
else {
LDEBUG("No suitable input image found.");
......
......@@ -62,8 +62,8 @@ namespace campvis {
virtual void process(DataContainer& data);
DataNameProperty p_inputVolume; ///< ID for input volume
DataNameProperty p_outputGradients; //< ID for output gradient volume
DataNameProperty p_sourceImageID; ///< ID for input volume
DataNameProperty p_targetImageID; ///< ID for output gradient volume
protected:
......
......@@ -61,7 +61,7 @@ namespace campvis {
_imageReader.p_url.setValue("D:\\Medical Data\\Dentalscan\\dental.mhd");
_imageReader.p_targetImageID.setValue("reader.output");
_imageReader.p_targetImageID.connect(&_gvg.p_inputVolume);
_imageReader.p_targetImageID.connect(&_gvg.p_sourceImageID);
_imageReader.p_targetImageID.connect(&_lhh.p_inputVolume);
_imageReader.p_targetImageID.connect(&_sliceExtractor.p_sourceImageID);
......
......@@ -77,7 +77,12 @@ namespace campvis {
if (img != 0) {
if (img->getDimensionality() == 3) {
updateProperties(img);
if (img.getDataHandle().getTimestamp() != _sourceImageTimestamp) {
// source DataHandle has changed
updateProperties(img.getDataHandle());
_sourceImageTimestamp = img.getDataHandle().getTimestamp();
}
const tgt::svec3& imgSize = img->getSize();
ImageData* slice = img->getSubImage(tgt::svec3(0, 0, p_sliceNumber.getValue()), tgt::svec3(imgSize.x, imgSize.y, p_sliceNumber.getValue()+1));
......@@ -114,8 +119,9 @@ namespace campvis {
_invalidationLevel.setValid();
}
void SliceExtractor::updateProperties(const ImageData* img) {
const tgt::svec3& imgSize = img->getSize();
void SliceExtractor::updateProperties(DataHandle img) {
p_transferFunction.getTF()->setImageHandle(img);
const tgt::svec3& imgSize = static_cast<const ImageData*>(img.getData())->getSize();
if (p_sliceNumber.getMaxValue() != imgSize.z - 1){
p_sliceNumber.setMaxValue(imgSize.z - 1);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment