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