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,10 +71,15 @@ namespace campvis {
EndianHelper::Endianness e = EndianHelper::LITTLE_ENDIAN;
// image type
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
dimensionality = tfp.getSizeT("NDims");
......
......@@ -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