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 666fb04d authored by schultezub's avatar schultezub
Browse files

Implemented image representation conversion GL -> Local


git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@461 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 207a1354
......@@ -284,6 +284,6 @@ namespace campvis {
tgtAssert(_treeModel != 0, "Failed creating TreeViewWidget model.");
setModel(_treeModel);
}
}
}
\ No newline at end of file
......@@ -37,6 +37,7 @@
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationdisk.h"
#include "core/datastructures/imagerepresentationlocal.h"
#include "core/datastructures/imagerepresentationrendertarget.h"
#ifdef CAMPVIS_HAS_MODULE_ITK
#include "modules/itk/core/genericimagerepresentationitk.h"
#endif
......@@ -238,5 +239,12 @@ namespace campvis {
return _texture->getSizeOnGPU();
}
const WeaklyTypedPointer ImageRepresentationGL::getWeaklyTypedPointer() const {
if (_texture->getPixelData() == 0) {
_texture->downloadTexture();
}
return WeaklyTypedPointer(WeaklyTypedPointer::baseType(_texture->getDataType()), _texture->getNumChannels(), _texture->getPixelData());
}
}
\ No newline at end of file
......@@ -134,6 +134,15 @@ namespace campvis {
const tgt::Texture* getTexture() const;
/**
* Returns a WeaklyTypedPointer to the data of this representation.
* You do \b not own the pointer - do \b not modify its content!
* \note Make sure to call this method from a valid OpenGL context.
* \return A WeaklyTypedPointer to the data of this representation. Neither you own nor you may modify its data!
*/
const WeaklyTypedPointer getWeaklyTypedPointer() const;
protected:
/**
* Creates a new ImageRepresentationGL representation from a tgt::Texture.
......
......@@ -29,10 +29,14 @@
#include "imagerepresentationlocal.h"
#include "tgt/qt/qtcontextmanager.h"
#include "tbb/tbb.h"
#include "tbb/spin_mutex.h"
#include "core/datastructures/imagerepresentationdisk.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
#include "core/tools/opengljobprocessor.h"
#include "core/tools/job.h"
#ifdef CAMPVIS_HAS_MODULE_ITK
#include "modules/itk/core/genericimagerepresentationitk.h"
......@@ -118,7 +122,24 @@ namespace campvis {
// test source image type via dynamic cast
if (const ImageRepresentationDisk* tester = dynamic_cast<const ImageRepresentationDisk*>(source)) {
return convertToGenericLocal(tester);
return convertToGenericLocal(tester, tester->getImageData());
}
else if (const ImageRepresentationGL* tester = dynamic_cast<const ImageRepresentationGL*>(source)) {
tgt::GLCanvas* context = GLJobProc.iKnowWhatImDoingGetArbitraryContext();
ImageRepresentationLocal* toReturn = 0;
GLJobProc.pause();
try {
tbb::mutex::scoped_lock lock(CtxtMgr.getGlMutex());
context->getContext()->acquire();
WeaklyTypedPointer wtp = tester->getWeaklyTypedPointer();
toReturn = convertToGenericLocal(source, wtp);
CtxtMgr.releaseCurrentContext();
}
catch (...) {
LERROR("An unknown error occured during conversion...");
}
GLJobProc.resume();
return toReturn;
}
#ifdef CAMPVIS_HAS_MODULE_ITK
......@@ -197,9 +218,7 @@ namespace campvis {
tbb::parallel_for(tbb::blocked_range<size_t>(0, getNumElements()), IntensityHistogramGenerator(this, _intensityHistogram));
}
ImageRepresentationLocal* ImageRepresentationLocal::convertToGenericLocal(const ImageRepresentationDisk* source) {
WeaklyTypedPointer wtp = source->getImageData();
ImageRepresentationLocal* ImageRepresentationLocal::convertToGenericLocal(const AbstractImageRepresentation* source, const WeaklyTypedPointer& wtp) {
#define CONVERT_DISK_TO_GENERIC_LOCAL(baseType,numChannels) \
return GenericImageRepresentationLocal<baseType, numChannels>::create( \
const_cast<ImageData*>(source->getParent()), \
......@@ -207,7 +226,7 @@ namespace campvis {
#define DISPATCH_DISK_TO_GENERIC_LOCAL_CONVERSION(numChannels) \
if (source->getParent()->getNumChannels() == (numChannels)) { \
switch (source->getBaseType()) { \
switch (wtp._baseType) { \
case WeaklyTypedPointer::UINT8: \
CONVERT_DISK_TO_GENERIC_LOCAL(uint8_t, (numChannels)) \
case WeaklyTypedPointer::INT8: \
......@@ -238,6 +257,5 @@ namespace campvis {
}
}
}
\ No newline at end of file
......@@ -210,7 +210,8 @@ namespace campvis {
private:
static ImageRepresentationLocal* convertToGenericLocal(const ImageRepresentationDisk* source);
static ImageRepresentationLocal* convertToGenericLocal(const AbstractImageRepresentation* source, const WeaklyTypedPointer& wtp);
// 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)
......
......@@ -38,6 +38,7 @@ namespace campvis {
OpenGLJobProcessor::OpenGLJobProcessor()
: _currentContext(0)
{
_pause = 0;
}
OpenGLJobProcessor::~OpenGLJobProcessor() {
......@@ -123,6 +124,13 @@ namespace campvis {
delete jobToDo;
}
}
while (_pause > 0) {
CtxtMgr.releaseCurrentContext();
_evaluationCondition.wait(lock);
_currentContext->getContext()->acquire();
hadWork = true;
}
if (! hadWork) {
CtxtMgr.releaseCurrentContext();
......@@ -135,6 +143,21 @@ namespace campvis {
CtxtMgr.releaseCurrentContext();
}
void OpenGLJobProcessor::pause() {
++_pause;
}
void OpenGLJobProcessor::resume() {
if (_pause == 0) {
tgtAssert(false, "Called resume on non-paused job processor!");
return;
}
--_pause;
if (_pause == 0)
_evaluationCondition.notify_all();
}
void OpenGLJobProcessor::enqueueJob(tgt::GLCanvas* canvas, AbstractJob* job, JobType priority) {
tbb::concurrent_hash_map<tgt::GLCanvas*, PerContextJobQueue*>::const_accessor a;
if (_contextQueueMap.find(a, canvas)) {
......@@ -184,5 +207,16 @@ namespace campvis {
}
}
tgt::GLCanvas* OpenGLJobProcessor::iKnowWhatImDoingGetArbitraryContext() {
if (_currentContext != 0)
return _currentContext;
else if (!_contexts.empty())
return _contexts.front();
else {
tgtAssert(false, "No Contexts registered!");
return 0;
}
}
}
......@@ -107,6 +107,16 @@ namespace campvis {
*/
void run();
/**
* Pauses the job processor as at the next possible moment.
*/
void pause();
/**
* Resume the execution of the job processor.
*/
void resume();
/**
* Enqueues the given Job with the given priority.
*
......@@ -118,6 +128,14 @@ namespace campvis {
void enqueueJob(tgt::GLCanvas* canvas, AbstractJob* job, JobType priority);
/**
* Returns an arbitrary registered OpenGL context.
* \note You can do really messy things with this. Do not use this method unless
* you know what you're doing and know that there is no other way...
*/
tgt::GLCanvas* iKnowWhatImDoingGetArbitraryContext();
protected:
/**
* Struct encapsulating the job queue for a single OpenGL context.
......@@ -162,6 +180,7 @@ namespace campvis {
tbb::concurrent_hash_map<tgt::GLCanvas*, PerContextJobQueue*> _contextQueueMap;
tbb::concurrent_vector<tgt::GLCanvas*> _contexts;
tbb::atomic<int> _pause;
std::condition_variable _evaluationCondition; ///< conditional wait to be used when there are currently no jobs to process
tgt::GLCanvas* _currentContext; ///< current active OpenGL context
......
......@@ -41,8 +41,8 @@ namespace campvis {
AdvancedUsVis::AdvancedUsVis()
: DigraphVisualizationPipeline()
, _camera("camera", "Camera")
, _usReader()
, _confidenceReader()
, _usReader(_effectiveRenderTargetSize)
, _confidenceReader(_effectiveRenderTargetSize)
, _confidenceGenerator()
, _gvg()
, _lhh()
......@@ -96,7 +96,8 @@ namespace campvis {
_camera.addSharedProperty(&_usDVR.p_camera);
//_usReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\01\\BMode_01.mhd");
_usReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\UltrasoundBoneData\\SynthesEvaluationUnterschenkel\\Athanasios\\US.csvd");
//_usReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\UltrasoundBoneData\\SynthesEvaluationUnterschenkel\\Athanasios\\US.csvd");
_usReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\transcranial\\us.png");
_usReader.p_targetImageID.setValue("us.image");
_usReader.p_targetImageID.connect(&_confidenceGenerator.p_sourceImageID);
_usReader.p_targetImageID.connect(&_usFusion1.p_usImageId);
......@@ -109,14 +110,19 @@ namespace campvis {
_usReader.p_targetImageID.connect(&_usDenoiseilter.p_sourceImageID);
//_confidenceReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\01\\Confidence_01.mhd");
_confidenceReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\UltrasoundBoneData\\SynthesEvaluationUnterschenkel\\Athanasios\\Map.csvd");
//_confidenceReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\UltrasoundBoneData\\SynthesEvaluationUnterschenkel\\Athanasios\\Map.csvd");
_confidenceReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\transcranial\\cm.png");
_confidenceReader.p_targetImageID.setValue("confidence.image.read");
_confidenceReader.p_targetImageID.connect(&_usFusion1.p_confidenceImageID);
_confidenceReader.p_targetImageID.connect(&_usFusion2.p_confidenceImageID);
_confidenceReader.p_targetImageID.connect(&_usFusion3.p_confidenceImageID);
_confidenceReader.p_targetImageID.connect(&_usFusion4.p_confidenceImageID);
_confidenceGenerator.p_targetImageID.setValue("confidence.image.generated");
_confidenceGenerator.p_targetImageID.connect(&_usFusion1.p_confidenceImageID);
_confidenceGenerator.p_targetImageID.connect(&_usFusion2.p_confidenceImageID);
_confidenceGenerator.p_targetImageID.connect(&_usFusion3.p_confidenceImageID);
_confidenceGenerator.p_targetImageID.connect(&_usFusion4.p_confidenceImageID);
//_confidenceGenerator.p_targetImageID.connect(&_usFusion1.p_confidenceImageID);
//_confidenceGenerator.p_targetImageID.connect(&_usFusion2.p_confidenceImageID);
//_confidenceGenerator.p_targetImageID.connect(&_usFusion3.p_confidenceImageID);
//_confidenceGenerator.p_targetImageID.connect(&_usFusion4.p_confidenceImageID);
_gvg.p_targetImageID.connect(&_lhh.p_gradientsId);
_gvg.p_targetImageID.connect(&_usFusion1.p_gradientImageID);
......
......@@ -35,6 +35,7 @@
#include "core/eventhandlers/transfuncwindowingeventhandler.h"
#include "core/eventhandlers/trackballnavigationeventhandler.h"
#include "core/pipeline/digraphvisualizationpipeline.h"
#include "modules/devil/processors/devilimagereader.h"
#include "modules/io/processors/mhdimagereader.h"
#include "modules/io/processors/csvdimagereader.h"
#include "modules/advancedusvis/processors/advancedusfusion.h"
......@@ -88,8 +89,8 @@ namespace campvis {
CameraProperty _camera;
CsvdImageReader _usReader;
CsvdImageReader _confidenceReader;
DevilImageReader _usReader;
DevilImageReader _confidenceReader;
ConfidenceMapGenerator _confidenceGenerator;
GradientVolumeGenerator _gvg;
......
......@@ -103,7 +103,7 @@ namespace campvis {
ImageRepresentationGL::ScopedRepresentation gradients(data, p_gradientImageID.getValue());
if (img != 0 && blurred != 0 && gradients != 0 && confidence != 0) {
if (img->getDimensionality() == 3) {
if (img->getDimensionality() >= 2) {
if (img.getDataHandle().getTimestamp() != _sourceImageTimestamp) {
// source DataHandle has changed
updateProperties(img.getDataHandle());
......
......@@ -52,10 +52,12 @@ namespace campvis {
: VisualizationProcessor(canvasSize)
, p_url("url", "Image URL", "")
, p_targetImageID("targetImageName", "Target Image ID", "DevilImageReader.output", DataNameProperty::WRITE)
, p_useRenderTarget("UseRenderTarget", "Read Into RenderTarget", false)
, _devilTextureReader(0)
{
addProperty(&p_url);
addProperty(&p_targetImageID);
addProperty(&p_useRenderTarget);
_devilTextureReader = new tgt::TextureReaderDevil();
}
......@@ -79,36 +81,44 @@ 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(), tex->getNumChannels());
ImageRepresentationGL* image = ImageRepresentationGL::create(&id, tex);
std::pair<ImageData*, ImageRepresentationRenderTarget*> rt = ImageRepresentationRenderTarget::createWithImageData(_renderTargetSize.getValue());
glPushAttrib(GL_ALL_ATTRIB_BITS);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
_shader->activate();
_shader->setIgnoreUniformLocationError(true);
_shader->setUniform("_viewportSize", _renderTargetSize.getValue());
_shader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(_renderTargetSize.getValue()));
_shader->setIgnoreUniformLocationError(false);
tgt::TextureUnit texUnit;
image->bind(_shader, texUnit, "_colorTexture");
rt.second->activate();
LGL_ERROR;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QuadRdr.renderQuad();
rt.second->deactivate();
_shader->deactivate();
tgt::TextureUnit::setZeroUnit();
glPopAttrib();
LGL_ERROR;
data.addData(p_targetImageID.getValue(), rt.first);
p_targetImageID.issueWrite();
if (p_useRenderTarget.getValue()) {
ImageData id (2, tex->getDimensions(), tex->getNumChannels());
ImageRepresentationGL* image = ImageRepresentationGL::create(&id, tex);
std::pair<ImageData*, ImageRepresentationRenderTarget*> rt = ImageRepresentationRenderTarget::createWithImageData(_renderTargetSize.getValue());
glPushAttrib(GL_ALL_ATTRIB_BITS);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
_shader->activate();
_shader->setIgnoreUniformLocationError(true);
_shader->setUniform("_viewportSize", _renderTargetSize.getValue());
_shader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(_renderTargetSize.getValue()));
_shader->setIgnoreUniformLocationError(false);
tgt::TextureUnit texUnit;
image->bind(_shader, texUnit, "_colorTexture");
rt.second->activate();
LGL_ERROR;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QuadRdr.renderQuad();
rt.second->deactivate();
_shader->deactivate();
tgt::TextureUnit::setZeroUnit();
glPopAttrib();
LGL_ERROR;
data.addData(p_targetImageID.getValue(), rt.first);
p_targetImageID.issueWrite();
}
else {
ImageData* id = new ImageData(2, tex->getDimensions(), tex->getNumChannels());
ImageRepresentationGL::create(id, tex);
data.addData(p_targetImageID.getValue(), id);
p_targetImageID.issueWrite();
}
}
else {
LERROR("Could not load image.");
......
......@@ -80,6 +80,7 @@ namespace campvis {
StringProperty p_url; ///< URL for file to read
DataNameProperty p_targetImageID; ///< image ID for read image
BoolProperty p_useRenderTarget; ///< Flag whether to read into a render target
protected:
tgt::Shader* _shader;
......
......@@ -140,7 +140,7 @@ namespace campvis {
void ConfidenceMapGenerator::process(DataContainer& data) {
ImageRepresentationLocal::ScopedRepresentation input(data, p_sourceImageID.getValue());
if (input != 0 && input->getDimensionality() >= 2 && input->getParent()->getNumChannels() == 1) {
if (input != 0 && input->getDimensionality() >= 2 && input->getParent()->getNumChannels() >= 1) {
const tgt::svec3& imageSize = input->getSize();
size_t numElements = input->getNumElements();
float* outputValues = new float[numElements];
......
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