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 3d5ed98c authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Merge branch 'refactor-conversion-api' into 'development'

Refactor conversion api
parents 62ee2d05 02dbdd8d
......@@ -92,9 +92,9 @@ namespace campvis {
// create a local OpenGL context and init GL
_localContext = new QtThreadedCanvas("", tgt::ivec2(16, 16));
tgt::GlContextManager::getRef().registerContextAndInitGlew(_localContext);
tgt::GLContextScopedLock lock(_localContext);
tgt::GlContextManager::getRef().registerContextAndInitGlew(_localContext);
tgt::initGL(featureset);
ShdrMgr.setDefaultGlslVersion("330");
......
......@@ -43,6 +43,7 @@
#include "core/datastructures/facegeometry.h"
#include "core/datastructures/geometrydata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/imagerepresentationlocal.h"
#include "core/datastructures/renderdata.h"
#ifdef CAMPVIS_HAS_MODULE_COLUMBIA
......
MACRO(WRITE_CONVERTER_REGISTRATION FileName)
MESSAGE(STATUS "* Generating converter registration header: ${FileName}")
SET(ConverterRegistrationSource "// WARNING: This file is automatically generated by CMake, do not modify!\n\n" )
LIST(APPEND ConverterRegistrationSource "// Include Converter Headers:\n" )
FOREACH(IncludeFile ${ConverterRegistrationIncludeFiles})
LIST(APPEND ConverterRegistrationSource "#include \"${IncludeFile}\"\n" )
ENDFOREACH()
FILE(WRITE ${FileName} ${ConverterRegistrationSource})
ENDMACRO(WRITE_CONVERTER_REGISTRATION)
MACRO(PARSE_HEADER_FOR_CONVERTER FileName)
FILE(READ ${FileName} content)
# Find all class definitions inheriting from a Pipeline
STRING(REGEX MATCHALL "template class ConversionFunctionRegistrar<" matches ${content})
LIST(LENGTH matches NumMatches)
IF(${NumMatches} GREATER 0)
MESSAGE(STATUS "Found ${NumMatches} converters in ${FileName}")
LIST(APPEND ConverterRegistrationIncludeFiles ${FileName})
ENDIF()
ENDMACRO(PARSE_HEADER_FOR_CONVERTER)
MACRO(ADD_PIPELINE_REGISTRATION IncludeFile ClassName)
LIST(APPEND PipelineRegistrationIncludeFiles ${IncludeFile})
LIST(APPEND PipelineRegistrationClassNames ${ClassName})
......
......@@ -4,7 +4,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0 FATAL_ERROR)
MESSAGE(STATUS "Configuring CAMPVis Core")
# glob sources from core directories
FILE(GLOB CampvisCoreSources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
classification/*.cpp
......@@ -44,6 +43,11 @@ FOREACH(CampvisModulesCoreHeader ${CampvisModulesCoreHeaders})
LIST(APPEND CampvisCoreHeaders ${ModHeaderFile})
ENDFOREACH()
FOREACH(HeaderFile ${CampvisCoreHeaders})
PARSE_HEADER_FOR_CONVERTER(${HeaderFile})
ENDFOREACH()
WRITE_CONVERTER_REGISTRATION("gen_converterregistration.h")
ADD_LIBRARY(campvis-core
${CampvisCoreSources} ${CampvisCoreHeaders}
)
......
......@@ -25,7 +25,6 @@
#ifndef GENERICIMAGEREPRESENTATIONLOCAL_H__
#define GENERICIMAGEREPRESENTATIONLOCAL_H__
#include "core/datastructures/imagerepresentationdisk.h"
#include "core/datastructures/imagerepresentationlocal.h"
#include "core/tools/typetraits.h"
......@@ -159,15 +158,6 @@ namespace campvis {
virtual ~GenericImageRepresentationLocal();
/**
* Performs a conversion of \a source to an ImageRepresentationLocal if feasible.
* Returns 0 if conversion was not successful or source representation type is not compatible.
* \note The callee, respectively the callee's parent, has the ownership of the returned pointer.
* \param source Source image representation for conversion.
* \return A pointer to a local representation of \a source or 0 on failure. The caller does \b not have ownership.
*/
static GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>* tryConvertFrom(const AbstractImageRepresentation* source);
/// \see AbstractImageRepresentation::clone()
virtual ThisType* clone(ImageData* newParent) const;
......@@ -307,61 +297,6 @@ namespace campvis {
delete [] _data;
}
template<typename BASETYPE, size_t NUMCHANNELS>
GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>* campvis::GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>::tryConvertFrom(const AbstractImageRepresentation* source) {
if (const ImageRepresentationDisk* tester = dynamic_cast<const ImageRepresentationDisk*>(source)) {
// converting from disk representation
if (tester->getBaseType() == TypeTraits<BASETYPE, NUMCHANNELS>::weaklyTypedPointerBaseType && tester->getParent()->getNumChannels() == NUMCHANNELS) {
WeaklyTypedPointer wtp = tester->getImageData();
return create(tester->getParent(), static_cast<ElementType*>(wtp._pointer));
}
else {
LWARNING("Could not convert since base type or number of channels mismatch.");
}
}
if (const ImageRepresentationDisk* tester = dynamic_cast<const ImageRepresentationDisk*>(source)) {
// converting from disk representation
if (tester->getBaseType() == TypeTraits<BASETYPE, NUMCHANNELS>::weaklyTypedPointerBaseType && tester->getParent()->getNumChannels() == NUMCHANNELS) {
WeaklyTypedPointer wtp = tester->getImageData();
return create(tester->getParent(), static_cast<ElementType*>(wtp._pointer));
}
else {
LWARNING("Could not convert since base type or number of channels mismatch.");
}
}
else if (const ThisType* tester = dynamic_cast<const ThisType*>(source)) {
// just to ensure that the following else if case is really a conversion
LDEBUG("Trying to convert into the same type - this should not happen, since it there is no conversion needed...");
return tester->clone(const_cast<ImageData*>(tester->getParent()));
}
else if (const ImageRepresentationLocal* tester = dynamic_cast<const ImageRepresentationLocal*>(source)) {
// converting from other local representation of different data type
// (we ensured with the else if above that at least one of the template parameters does not match)
if (tester->getParent()->getNumChannels() == NUMCHANNELS) {
LDEBUG("Performing conversion between data types, you may lose information or the resulting data may show other unexpected features.");
size_t numElements = tester->getNumElements();
ElementType* newData = new ElementType[numElements];
// traverse each channel of each element and convert the value
for (size_t i = 0; i < numElements; ++i) {
for (size_t channel = 0; channel < NUMCHANNELS; ++channel) {
// get original value normalized to float
float tmp = tester->getElementNormalized(i, channel);
// save new value denormalized from float
TypeTraits<BASETYPE, NUMCHANNELS>::setChannel(newData[i], channel, TypeNormalizer::denormalizeFromFloat<BASETYPE>(tmp));
}
}
return create(tester->getParent(), newData);
}
else {
LWARNING("Could not convert since number of channels mismatch.");
}
}
return 0;
}
template<typename BASETYPE, size_t NUMCHANNELS>
GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>* campvis::GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>::clone(ImageData* newParent) const {
size_t numElements = getNumElements();
......
......@@ -24,12 +24,6 @@
#include "imagedata.h"
#include "core/datastructures/imagerepresentationlocal.h"
#ifdef CAMPVIS_HAS_MODULE_ITK
#include "modules/itk/core/genericimagerepresentationitk.h"
#endif
namespace campvis {
const std::string ImageData::loggerCat_ = "CAMPVis.core.datastructures.ImageData";
......@@ -136,36 +130,4 @@ namespace campvis {
addRepresentation(representation);
}
template<>
const ImageRepresentationLocal* ImageData::getRepresentation<ImageRepresentationLocal>(bool performConversion /*= true*/) const {
// look, whether we already have a suitable representation
for (tbb::concurrent_vector<const AbstractImageRepresentation*>::const_iterator it = _representations.begin(); it != _representations.end(); ++it) {
if (const ImageRepresentationLocal* tester = dynamic_cast<const ImageRepresentationLocal*>(*it))
return tester;
}
if (performConversion) {
return tryPerformConversion<ImageRepresentationLocal>();
}
return 0;
}
#ifdef CAMPVIS_HAS_MODULE_ITK
template<>
const AbstractImageRepresentationItk* ImageData::getRepresentation<AbstractImageRepresentationItk>(bool performConversion /*= true*/) const {
// look, whether we already have a suitable representation
for (tbb::concurrent_vector<const AbstractImageRepresentation*>::const_iterator it = _representations.begin(); it != _representations.end(); ++it) {
if (const AbstractImageRepresentationItk* tester = dynamic_cast<const AbstractImageRepresentationItk*>(*it))
return tester;
}
if (performConversion) {
tgtAssert(false, "Conversion to AbstractImageRepresentationItk not implemented - is it really needed?");
LWARNING("Could not convert to AbstractImageRepresentationItk");
}
return 0;
}
#endif
}
\ No newline at end of file
......@@ -33,19 +33,16 @@
#include "core/datastructures/abstractdata.h"
#include "core/datastructures/abstractimagerepresentation.h"
#include "core/datastructures/imagemappinginformation.h"
#include "core/datastructures/imagerepresentationconverter.h"
#include <vector>
namespace campvis {
class ImageRepresentationLocal;
/**
* Stores basic information about one (semantic) image of arbitrary dimension.
* Different representations (e.g. local memory, OpenGL texture) are
* to be defined by inheritance.
*
* \todo
*/
class CAMPVIS_CORE_API ImageData : public AbstractData, public IHasWorldBounds {
// friend so that it can add itself as representation
......@@ -208,8 +205,8 @@ namespace campvis {
const T* campvis::ImageData::getRepresentation(bool performConversion) const {
// look, whether we already have a suitable representation
for (tbb::concurrent_vector<const AbstractImageRepresentation*>::const_iterator it = _representations.begin(); it != _representations.end(); ++it) {
if (typeid(T) == typeid(**it)) {
return static_cast<const T*>(*it);
if (const T* tester = dynamic_cast<const T*>(*it)) {
return tester;
}
}
......@@ -221,23 +218,13 @@ namespace campvis {
return 0;
}
template<>
CAMPVIS_CORE_API const campvis::ImageRepresentationLocal* campvis::ImageData::getRepresentation<ImageRepresentationLocal>(bool performConversion) const;
#ifdef CAMPVIS_HAS_MODULE_ITK
class AbstractImageRepresentationItk;
template<>
CAMPVIS_CORE_API const campvis::AbstractImageRepresentationItk* campvis::ImageData::getRepresentation<AbstractImageRepresentationItk>(bool performConversion) const;
#endif
template<typename T>
const T* campvis::ImageData::tryPerformConversion() const {
// 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.
for (tbb::concurrent_vector<const AbstractImageRepresentation*>::const_iterator it = _representations.begin(); it != _representations.end(); ++it) {
const T* tester = T::tryConvertFrom(*it);
const T* tester = ImageRepresentationConverter::getRef().tryConvertFrom<T>(*it);
if (tester != 0) {
return tester;
}
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// 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
//
// 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.
//
// ================================================================================================
#include "imagerepresentationconversioncore.h"
#include "tgt/assert.h"
#include "tgt/logmanager.h"
#include "tgt/glcontextmanager.h"
#include "core/tools/opengljobprocessor.h"
#include "core/tools/job.h"
namespace campvis {
ImageRepresentationGL* GlConversion::tryConvertFrom(const AbstractImageRepresentation* source) {
if (source == nullptr)
return nullptr;
// test source image type via dynamic cast
if (const ImageRepresentationDisk* tester = dynamic_cast<const ImageRepresentationDisk*>(source)) {
WeaklyTypedPointer wtp = tester->getImageData();
if (wtp._pointer == nullptr) {
LERRORC("CAMPVis.core.datastructures.GlConversion", "Could not load image from disk during conversion.");
return nullptr;
}
ImageRepresentationGL* toReturn = ImageRepresentationGL::create(const_cast<ImageData*>(tester->getParent()), wtp);
switch (wtp._baseType) {
case WeaklyTypedPointer::UINT8:
delete [] static_cast<uint8_t*>(wtp._pointer);
break;
case WeaklyTypedPointer::INT8:
delete [] static_cast<int8_t*>(wtp._pointer);
break;
case WeaklyTypedPointer::UINT16:
delete [] static_cast<uint16_t*>(wtp._pointer);
break;
case WeaklyTypedPointer::INT16:
delete [] static_cast<int16_t*>(wtp._pointer);
break;
case WeaklyTypedPointer::UINT32:
delete [] static_cast<uint32_t*>(wtp._pointer);
break;
case WeaklyTypedPointer::INT32:
delete [] static_cast<int32_t*>(wtp._pointer);
break;
case WeaklyTypedPointer::FLOAT:
delete [] static_cast<float*>(wtp._pointer);
break;
default:
tgtAssert(false, "Should not reach this - wrong base data type!");
break;
}
return toReturn;
}
else if (const ImageRepresentationLocal* tester = dynamic_cast<const ImageRepresentationLocal*>(source)) {
ImageRepresentationGL* toReturn = ImageRepresentationGL::create(const_cast<ImageData*>(tester->getParent()), tester->getWeaklyTypedPointer());
return toReturn;
}
return nullptr;
}
ImageRepresentationLocal* LocalConversion::tryConvertFrom(const AbstractImageRepresentation* source) {
if (source == 0)
return 0;
// test source image type via dynamic cast
if (const ImageRepresentationDisk* tester = dynamic_cast<const ImageRepresentationDisk*>(source)) {
return ImageRepresentationLocal::create(tester->getParent(), tester->getImageData());
}
else if (const ImageRepresentationGL* tester = dynamic_cast<const ImageRepresentationGL*>(source)) {
OpenGLJobProcessor::ScopedSynchronousGlJobExecution jobGuard;
WeaklyTypedPointer wtp = tester->getWeaklyTypedPointerCopy();
if (wtp._pointer != nullptr)
return ImageRepresentationLocal::create(source->getParent(), wtp);
return nullptr;
}
return nullptr;
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// 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
//
// 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.
//
// ================================================================================================
#ifndef IMAGEREPRESENTATIONCONVERSIONCORE_H__
#define IMAGEREPRESENTATIONCONVERSIONCORE_H__
#include "core/coreapi.h"
#include "core/tools/opengljobprocessor.h"
#include "core/datastructures/imagerepresentationconverter.h"
#include "core/datastructures/imagerepresentationdisk.h"
#include "core/datastructures/imagerepresentationlocal.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
namespace campvis {
// = Declare converter classes ====================================================================
/// Conversion class to convert to ImageRepresentationGL.
struct CAMPVIS_CORE_API GlConversion {
static ImageRepresentationGL* tryConvertFrom(const AbstractImageRepresentation* source);
};
/// Conversion class to convert to ImageRepresentationLocal.
struct CAMPVIS_CORE_API LocalConversion {
static ImageRepresentationLocal* tryConvertFrom(const AbstractImageRepresentation* source);
};
/// Conversion class to convert to GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>.
template<typename BASETYPE, size_t NUMCHANNELS>
struct GenericLocalConversion {
static GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>* tryConvertFrom(const AbstractImageRepresentation* source);
};
// = Instantiate converter templates to register converters =======================================
// Register converters with corresponding target representations
template class ConversionFunctionRegistrar<ImageRepresentationGL, GlConversion>;
template class ConversionFunctionRegistrar<ImageRepresentationLocal, LocalConversion>;
// for GenericImageRepresentationLocal we use some macro magic to instantiate all necessary converters:
#define INSTANTIATE_TEMPLATE_BN(BASETYPE, NUMCHANNELS) template class ConversionFunctionRegistrar< GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS> , GenericLocalConversion<BASETYPE, NUMCHANNELS> >
#define INSTANTIATE_TEMPLATE_N(NUMCHANNELS) \
INSTANTIATE_TEMPLATE_BN(uint8_t, NUMCHANNELS); INSTANTIATE_TEMPLATE_BN(int8_t, NUMCHANNELS); \
INSTANTIATE_TEMPLATE_BN(uint16_t, NUMCHANNELS); INSTANTIATE_TEMPLATE_BN(int16_t, NUMCHANNELS); \
INSTANTIATE_TEMPLATE_BN(uint32_t, NUMCHANNELS); INSTANTIATE_TEMPLATE_BN(int32_t, NUMCHANNELS); \
INSTANTIATE_TEMPLATE_BN(float, NUMCHANNELS);
INSTANTIATE_TEMPLATE_N(1);
INSTANTIATE_TEMPLATE_N(2);
INSTANTIATE_TEMPLATE_N(3);
INSTANTIATE_TEMPLATE_N(4);
// = Template definition ==========================================================================
template<typename BASETYPE, size_t NUMCHANNELS>
GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>* GenericLocalConversion<BASETYPE, NUMCHANNELS>::tryConvertFrom(const AbstractImageRepresentation* source) {
typedef typename GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>::ElementType ElementType;
typedef typename GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>::ThisType ThisType;
if (const ImageRepresentationDisk* tester = dynamic_cast<const ImageRepresentationDisk*>(source)) {
// converting from disk representation
if (tester->getBaseType() == TypeTraits<BASETYPE, NUMCHANNELS>::weaklyTypedPointerBaseType && tester->getParent()->getNumChannels() == NUMCHANNELS) {
WeaklyTypedPointer wtp = tester->getImageData();
return GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>::create(tester->getParent(), static_cast<ElementType*>(wtp._pointer));
}
else {
LWARNINGC("CAMPVis.core.datastructures.GenericLocalConversion", "Could not convert since base type or number of channels mismatch.");
}
}
else if (const ImageRepresentationGL* tester = dynamic_cast<const ImageRepresentationGL*>(source)) {
// converting from GL representation
OpenGLJobProcessor::ScopedSynchronousGlJobExecution jobGuard;
if (tester->getTexture()->getDataType() != TypeTraits<BASETYPE, NUMCHANNELS>::glDataType)
LDEBUGC("CAMPVis.core.datastructures.GenericLocalConversion", "Performing conversion between data types, you may lose information or the resulting data may show other unexpected features.");
WeaklyTypedPointer wtp = tester->getWeaklyTypedPointerConvert(TypeTraits<BASETYPE, NUMCHANNELS>::glDataType);
if (wtp._pointer != nullptr)
return GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>::create(tester->getParent(), static_cast<ElementType*>(wtp._pointer));
return nullptr;
}
else if (const ThisType* tester = dynamic_cast<const ThisType*>(source)) {
// just to ensure that the following else if case is really a conversion
LDEBUGC("CAMPVis.core.datastructures.GenericLocalConversion", "Trying to convert into the same type - this should not happen, since it there is no conversion needed...");
return tester->clone(const_cast<ImageData*>(tester->getParent()));
}
else if (const ImageRepresentationLocal* tester = dynamic_cast<const ImageRepresentationLocal*>(source)) {
// converting from other local representation of different data type
// (we ensured with the else if above that at least one of the template parameters does not match)
if (tester->getParent()->getNumChannels() == NUMCHANNELS) {
LDEBUGC("CAMPVis.core.datastructures.GenericLocalConversion", "Performing conversion between data types, you may lose information or the resulting data may show other unexpected features.");
size_t numElements = tester->getNumElements();
ElementType* newData = new ElementType[numElements];
// traverse each channel of each element and convert the value
for (size_t i = 0; i < numElements; ++i) {
for (size_t channel = 0; channel < NUMCHANNELS; ++channel) {
// get original value normalized to float
float tmp = tester->getElementNormalized(i, channel);
// save new value denormalized from float
TypeTraits<BASETYPE, NUMCHANNELS>::setChannel(newData[i], channel, TypeNormalizer::denormalizeFromFloat<BASETYPE>(tmp));
}
}
return GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>::create(tester->getParent(), newData);
}
else {
LWARNINGC("CAMPVis.core.datastructures.GenericLocalConversion", "Could not convert since number of channels mismatch.");
}
}
return nullptr;
}
}
#endif // IMAGEREPRESENTATIONCONVERSIONCORE_H__
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// 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
//
// 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.
//
// ================================================================================================
#include "imagerepresentationconverter.h"
#include <functional>
#include "core/properties/abstractproperty.h"
#include "core/gen_converterregistration.h"
namespace campvis {
tbb::atomic<ImageRepresentationConverter*> ImageRepresentationConverter::_singleton;
ImageRepresentationConverter& ImageRepresentationConverter::getRef() {
if (_singleton == 0) {
std::cout << "creating ImageRepresentationConverter...\n";
ImageRepresentationConverter* tmp = new ImageRepresentationConverter();
if (_singleton.compare_and_swap(tmp, 0) != 0) {
delete tmp;
}
}
return *_singleton;
}
void ImageRepresentationConverter::deinit() {
delete _singleton;
_singleton = nullptr;
}
size_t ImageRepresentationConverter::registerConversionFunction(const std::type_info& type, ConversionFunctionPointer funcPtr) {
tbb::spin_mutex::scoped_lock lock(_mutex);
std::type_index typeIndex(type);
if (funcPtr != nullptr) {
_conversionFunctionMap.insert(std::make_pair(typeIndex, funcPtr));
}
return _conversionFunctionMap.size();
}
}
\ No newline at end of file
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.