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

* added AbstractTransferFunction::s_imageHandleChanged signal

 * fixed bug in AbstractTransferFunction::createTexture
 * added button to fit intensity domain to image to TransferFunctionPropertyWidget
 * improved compatability of MhdImageReader

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@360 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent db11a8a7
......@@ -31,6 +31,8 @@
#include "application/gui/properties/abstracttransferfunctioneditor.h"
#include "application/gui/properties/transferfunctioneditorfactory.h"
#include "core/datastructures/imagedatalocal.h"
#include <QDockWidget>
#include <QDoubleSpinBox>
#include <QGridLayout>
......@@ -71,20 +73,40 @@ namespace campvis {
updateWidgetFromProperty();
_btnFitDomainToImage = new QPushButton("Fit Intensity Domain to Image", _widget);
_gridLayout->addWidget(_btnFitDomainToImage, 1, 0, 1, 3);
_btnEditTF = new QPushButton("Edit Transfer Function", _widget);
_gridLayout->addWidget(_btnEditTF, 1, 0, 1, 3);
_gridLayout->addWidget(_btnEditTF, 2, 0, 1, 3);
addWidget(_widget);
onTransferFunctionImageHandleChanged();
property->getTF()->s_imageHandleChanged.connect(this, &TransferFunctionPropertyWidget::onTransferFunctionImageHandleChanged);
connect(_spinDomainLeft, SIGNAL(valueChanged(double)), this, SLOT(onDomainChanged(double)));
connect(_spinDomainRight, SIGNAL(valueChanged(double)), this, SLOT(onDomainChanged(double)));
connect(_btnEditTF, SIGNAL(clicked(bool)), this, SLOT(onEditClicked(bool)));
connect(_btnFitDomainToImage, SIGNAL(clicked(bool)), this, SLOT(onFitClicked(bool)));
}
TransferFunctionPropertyWidget::~TransferFunctionPropertyWidget() {
static_cast<TransferFunctionProperty*>(_property)->getTF()->s_imageHandleChanged.disconnect(this);
delete _dockWidget;
}
void TransferFunctionPropertyWidget::onTransferFunctionImageHandleChanged() {
DataHandle dh = static_cast<TransferFunctionProperty*>(_property)->getTF()->getImageHandle();
if (dh.getData() != 0) {
const ImageDataLocal* idl = dynamic_cast<const ImageDataLocal*>(dh.getData());
if (idl != 0) {
Interval<float> intensityInterval = idl->getNormalizedIntensityRange();
_spinDomainLeft->setMinimum(intensityInterval.getLeft());
_spinDomainRight->setMaximum(intensityInterval.getRight());
}
}
}
void TransferFunctionPropertyWidget::updateWidgetFromProperty() {
TransferFunctionProperty* prop = static_cast<TransferFunctionProperty*>(_property);
AbstractTransferFunction* tf = prop->getTF();
......@@ -123,5 +145,19 @@ namespace campvis {
_dockWidget->setVisible(true);
}
void TransferFunctionPropertyWidget::onFitClicked(bool checked) {
TransferFunctionProperty* prop = static_cast<TransferFunctionProperty*>(_property);
AbstractTransferFunction* tf = prop->getTF();
DataHandle dh = tf->getImageHandle();
if (dh.getData() != 0) {
const ImageDataLocal* idl = dynamic_cast<const ImageDataLocal*>(dh.getData());
if (idl != 0) {
Interval<float> intensityInterval = idl->getNormalizedIntensityRange();
tf->setIntensityDomain(tgt::vec2(intensityInterval.getLeft(), intensityInterval.getRight()));
}
}
}
}
\ No newline at end of file
......@@ -61,6 +61,12 @@ namespace campvis {
*/
virtual ~TransferFunctionPropertyWidget();
/**
* Slot to be called when the propertie's TF changed its image DataHandle.
* Resets the intensity domain borders.
*/
void onTransferFunctionImageHandleChanged();
protected:
/**
* Gets called when the property has changed, so that widget can update its state.
......@@ -72,6 +78,8 @@ namespace campvis {
void onDomainChanged(double value);
/// slot called when edit TF button clicked
void onEditClicked(bool checked);
/// slot called when _btnFitDomainToImage clicked
void onFitClicked(bool checked);
private:
QWidget* _widget; ///< Widget grouping the widgets together
......@@ -80,6 +88,7 @@ namespace campvis {
QLabel* _lblDomain; ///< intensity domain label
QDoubleSpinBox* _spinDomainLeft; ///< spin edit for intensity domain lower bound
QDoubleSpinBox* _spinDomainRight; ///< spin edit for intensity domain upper bound
QPushButton* _btnFitDomainToImage; ///< button for fitting the intensity domain to the image
QPushButton* _btnEditTF; ///< button for showing the TF editor widget
QDockWidget* _dockWidget; ///< DockWidget for transfer function editor
......
......@@ -86,11 +86,15 @@ namespace campvis {
}
void AbstractTransferFunction::bind(tgt::Shader* shader, const tgt::TextureUnit& texUnit, const std::string& transFuncUniform /*= "_transferFunction"*/) {
// TODO: lock here or in createTexture?
tgtAssert(shader != 0, "Shader must not be 0.");
{
// TODO: lock here or in createTexture?
tbb::mutex::scoped_lock lock(_localMutex);
if (_texture == 0 || _dirtyTexture) {
shader->deactivate();
createTexture();
shader->activate();
}
}
......@@ -157,6 +161,7 @@ namespace campvis {
void AbstractTransferFunction::setImageHandle(const DataHandle& imageHandle) {
_imageHandle = imageHandle;
_dirtyHistogram = true;
s_imageHandleChanged();
}
void AbstractTransferFunction::computeIntensityHistogram() const {
......
......@@ -147,6 +147,9 @@ namespace campvis {
/// Signal emitted when transfer function has changed.
sigslot::signal0<> s_changed;
/// Signal emitted when the image DataHandle for this TF has changed.
sigslot::signal0<> s_imageHandleChanged;
protected:
/**
* Computes the intensity histogram;
......
......@@ -97,7 +97,6 @@ namespace campvis {
}
glPushAttrib(GL_ALL_ATTRIB_BITS);
p_transferFunction.getTF()->uploadTexture();
glEnable(GL_DEPTH_TEST);
_shader->activate();
......
......@@ -71,9 +71,14 @@ namespace campvis {
EndianHelper::Endianness e = EndianHelper::LITTLE_ENDIAN;
// image type
if (tfp.getString("ObjectType") != "Image") {
LERROR("Error while parsing MHD header: ObjectType = Image expected");
return;
if (tfp.hasKey("ObjectType")) {
if (tfp.getString("ObjectType") != "Image") {
LERROR("Error while parsing MHD header: ObjectType = Image expected");
return;
}
}
else {
LWARNING("No Key 'ObjectType' found - assuming Image.");
}
// dimensionality and size
......
......@@ -31,6 +31,8 @@
#include "tgt/event/keyevent.h"
#include "core/datastructures/imagedataconverter.h"
#include "core/classification/geometry1dtransferfunction.h"
#include "core/classification/tfgeometry1d.h"
namespace campvis {
......@@ -67,8 +69,11 @@ namespace campvis {
_sliceExtractor.p_sourceImageID.setValue("se.input");
_sliceExtractor.p_sliceNumber.setValue(0);
// TODO: replace this hardcoded domain by automatically determined from image min/max values
_sliceExtractor.p_transferFunction.getTF()->setIntensityDomain(tgt::vec2(0, 0.05f));
Geometry1DTransferFunction* tf = new Geometry1DTransferFunction(128, tgt::vec2(0.f, .08f));
tf->addGeometry(TFGeometry1D::createQuad(tgt::vec2(0.f, 1.f), tgt::col4(0, 0, 0, 0), tgt::col4(255, 255, 255, 255)));
_sliceExtractor.p_transferFunction.replaceTF(tf);
_renderTargetID.setValue("renderTarget");
_renderTargetID.addSharedProperty(&(_sliceExtractor.p_targetImageID));
......@@ -91,7 +96,8 @@ namespace campvis {
DataContainer::ScopedTypedData<ImageData> img(_data, "reader.output");
ImageDataLocal* local = ImageDataConverter::tryConvert<ImageDataLocal>(img);
if (local != 0) {
_data.addData("se.input", local);
DataHandle dh = _data.addData("se.input", local);
_sliceExtractor.p_transferFunction.getTF()->setImageHandle(dh);
}
}
// if (! _gvg.getInvalidationLevel().isValid()) {
......
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