36 #include <QDomDocument>
38 #include <vtkImageAccumulate.h>
39 #include <vtkImageReslice.h>
40 #include <vtkImageData.h>
41 #include <vtkMatrix4x4.h>
43 #include <vtkPlanes.h>
44 #include <vtkImageResample.h>
45 #include <vtkImageChangeInformation.h>
46 #include <vtkImageClip.h>
47 #include <vtkImageIterator.h>
48 #include <vtkImageShiftScale.h>
49 #include <vtkPiecewiseFunction.h>
50 #include <vtkColorTransferFunction.h>
81 double Image::ShadingStruct::loadAttribute(QDomNode dataNode, QString name,
double defVal)
83 QString text = dataNode.toElement().attribute(name);
85 double val = text.toDouble(&ok);
93 QDomElement elem = dataNode.toElement();
94 elem.setAttribute(
"on", on);
95 elem.setAttribute(
"ambient", ambient);
96 elem.setAttribute(
"diffuse", diffuse);
97 elem.setAttribute(
"specular", specular);
98 elem.setAttribute(
"specularPower", specularPower);
103 if (dataNode.isNull())
106 on = dataNode.toElement().attribute(
"on").toInt();
108 ambient = loadAttribute(dataNode,
"ambient", ambient);
109 diffuse = loadAttribute(dataNode,
"diffuse", diffuse);
110 specular = loadAttribute(dataNode,
"specular", specular);
111 specularPower = loadAttribute(dataNode,
"specularPower", specularPower);
130 mInitialWindowWidth = -1;
131 mInitialWindowLevel = -1;
138 mImageLookupTable2D.reset();
139 mImageTransferFunctions3D.reset();
149 baseImageDataCopy = vtkImageDataPtr::New();
160 retval->mImageLookupTable2D = mImageLookupTable2D;
161 retval->mImageTransferFunctions3D = mImageTransferFunctions3D;
162 retval->mInitialWindowWidth = mInitialWindowWidth;
163 retval->mInitialWindowLevel = mInitialWindowLevel;
176 ImageTF3DPtr transferFunctions = parentImage->getUnmodifiedTransferFunctions3D()->createCopy();
177 ImageLUT2DPtr LUT2D = parentImage->getUnmodifiedLookupTable2D()->createCopy();
183 mInitialWindowWidth = parentImage->getInitialWindowWidth();
184 mInitialWindowLevel = parentImage->getInitialWindowLevel();
233 this->blockSignals(
true);
235 this->resetTransferFunction(imageTransferFunctions3D);
236 this->resetTransferFunction(imageLookupTable2D);
238 this->blockSignals(
false);
242 void Image::resetTransferFunction(
ImageLUT2DPtr imageLookupTable2D)
244 if (mImageLookupTable2D)
249 mImageLookupTable2D = imageLookupTable2D;
251 if (mImageLookupTable2D)
259 void Image::resetTransferFunction(
ImageTF3DPtr imageTransferFunctions3D)
261 if (mImageTransferFunctions3D)
266 mImageTransferFunctions3D = imageTransferFunctions3D;
268 if (mImageTransferFunctions3D)
283 this->moveToThread(thread);
284 this->getUnmodifiedTransferFunctions3D()->moveToThread(thread);
285 this->getUnmodifiedLookupTable2D()->moveToThread(thread);
294 if (resetTransferFunctions)
301 double windowWidth = mImageLookupTable2D->getWindow();
302 double windowLevel = mImageLookupTable2D->getLevel();
319 if(mThresholdPreview)
320 return mTresholdPreviewTransferfunctions3D;
321 return getUnmodifiedTransferFunctions3D();
326 if(!this->mImageTransferFunctions3D)
328 return mImageTransferFunctions3D;
333 this->resetTransferFunction(transferFuntion);
338 if(mThresholdPreview)
339 return mTresholdPreviewLookupTable2D;
340 return getUnmodifiedLookupTable2D();
345 if(!mImageLookupTable2D)
347 return mImageLookupTable2D;
352 this->resetTransferFunction(imageLookupTable2D);
388 template<
typename scalartype>
static int getRGBMax(
vtkImageDataPtr image)
391 vtkImageIterator<scalartype> iter(image, image->GetExtent());
392 while (!iter.IsAtEnd())
394 typename vtkImageIterator<scalartype>::SpanIterator siter = iter.BeginSpan();
395 while (siter != iter.EndSpan())
426 QDateTime before = QDateTime::currentDateTime();
430 case VTK_UNSIGNED_CHAR:
433 case VTK_UNSIGNED_SHORT:
472 QDomNode imageNode = dataNode;
473 QDomDocument doc = dataNode.ownerDocument();
475 QDomElement tf3DNode = doc.createElement(
"transferfunctions");
476 this->getUnmodifiedTransferFunctions3D()->addXml(tf3DNode);
477 imageNode.appendChild(tf3DNode);
479 QDomElement lut2DNode = doc.createElement(
"lookuptable2D");
480 this->getUnmodifiedLookupTable2D()->addXml(lut2DNode);
481 imageNode.appendChild(lut2DNode);
483 QDomElement shadingNode = doc.createElement(
"shading");
485 imageNode.appendChild(shadingNode);
491 QDomElement cropNode = doc.createElement(
"crop");
494 imageNode.appendChild(cropNode);
496 QDomElement clipNode = doc.createElement(
"clip");
499 QDomElement planeNode = doc.createElement(
"plane");
504 clipNode.appendChild(planeNode);
506 imageNode.appendChild(clipNode);
508 QDomElement modalityNode = doc.createElement(
"modality");
509 modalityNode.appendChild(doc.createTextNode(
mModality));
510 imageNode.appendChild(modalityNode);
512 QDomElement imageTypeNode = doc.createElement(
"imageType");
513 imageTypeNode.appendChild(doc.createTextNode(
mImageType));
514 imageNode.appendChild(imageTypeNode);
516 QDomElement interpolationNode = doc.createElement(
"vtk_interpolation");
518 imageNode.appendChild(interpolationNode);
520 QDomElement initialWindowNode = doc.createElement(
"initialWindow");
521 initialWindowNode.setAttribute(
"width", mInitialWindowWidth);
522 initialWindowNode.setAttribute(
"level", mInitialWindowLevel);
525 double Image::loadAttribute(QDomNode dataNode, QString name,
double defVal)
527 QString text = dataNode.toElement().attribute(name);
529 double val = text.toDouble(&ok);
549 if (dataNode.isNull())
553 QDomNode transferfunctionsNode = dataNode.namedItem(
"transferfunctions");
554 if (!transferfunctionsNode.isNull())
555 this->getUnmodifiedTransferFunctions3D()->parseXml(transferfunctionsNode);
558 std::cout <<
"Warning: Image::parseXml() found no transferfunctions";
559 std::cout << std::endl;
562 mInitialWindowWidth = this->loadAttribute(dataNode.namedItem(
"initialWindow"),
"width", -1);
563 mInitialWindowLevel = this->loadAttribute(dataNode.namedItem(
"initialWindow"),
"level", -1);
565 this->getUnmodifiedLookupTable2D()->parseXml(dataNode.namedItem(
"lookuptable2D"));
568 mShading.
on = dataNode.namedItem(
"shading").toElement().text().toInt();
570 if (!dataNode.namedItem(
"shadingAmbient").isNull())
571 mShading.
ambient = dataNode.namedItem(
"shadingAmbient").toElement().text().toDouble();
572 if (!dataNode.namedItem(
"shadingDiffuse").isNull())
573 mShading.
diffuse = dataNode.namedItem(
"shadingDiffuse").toElement().text().toDouble();
574 if (!dataNode.namedItem(
"shadingSpecular").isNull())
575 mShading.
specular = dataNode.namedItem(
"shadingSpecular").toElement().text().toDouble();
576 if (!dataNode.namedItem(
"shadingSpecularPower").isNull())
584 QDomElement cropNode = dataNode.namedItem(
"crop").toElement();
585 if (!cropNode.isNull())
591 QDomElement clipNode = dataNode.namedItem(
"clip").toElement();
592 QDomElement clipPlaneNode = clipNode.firstChildElement(
"plane");
593 for (; !clipPlaneNode.isNull(); clipPlaneNode = clipPlaneNode.nextSiblingElement(
"plane"))
595 Vector3D normal = Vector3D::fromString(clipPlaneNode.attribute(
"normal"));
596 Vector3D origin = Vector3D::fromString(clipPlaneNode.attribute(
"origin"));
598 plane->SetNormal(normal.begin());
599 plane->SetOrigin(origin.begin());
603 mModality = dataNode.namedItem(
"modality").toElement().text();
604 mImageType = dataNode.namedItem(
"imageType").toElement().text();
606 QDomElement interpoationNode = dataNode.namedItem(
"vtk_interpolation").toElement();
607 if (!interpoationNode.isNull())
616 mInitialWindowWidth = width;
617 mInitialWindowLevel = level;
628 if (mThresholdPreview)
772 info->SetOutputExtentStart(0, 0, 0);
773 info->SetOutputOrigin(0, 0, 0);
775 info->UpdateInformation();
813 int size = axisSize - 1;
815 dummyImageData->SetExtent(0, size, 0, size, 0, size);
816 dummyImageData->SetSpacing(1, 1, 1);
821 dummyImageData->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
822 unsigned char* dataPtr =
static_cast<unsigned char*
> (dummyImageData->GetScalarPointer());
825 int minVoxelValue = 0;
826 int numVoxels = axisSize*axisSize*axisSize;
827 for (
int i = 0; i < numVoxels; ++i)
829 int voxelValue = minVoxelValue + i;
831 dataPtr[i] = maxVoxelValue;
832 else if (voxelValue < maxVoxelValue)
833 dataPtr[i] = voxelValue;
835 dataPtr[i] = maxVoxelValue;
838 return dummyImageData;
851 if (mThresholdPreview)
858 if (mThresholdPreview)
859 return VTK_NEAREST_INTERPOLATION;
868 double factor = computeResampleFactor(maxVoxels);
870 if (fabs(1.0-factor)>0.01)
873 resampler->SetInterpolationModeToLinear();
874 resampler->SetAxisMagnificationFactor(0, factor);
875 resampler->SetAxisMagnificationFactor(1, factor);
876 resampler->SetAxisMagnificationFactor(2, factor);
877 resampler->SetInputData(retval);
880 resampler->GetOutput()->GetScalarRange();
881 retval = resampler->GetOutput();
883 long voxelsDown = retval->GetNumberOfPoints();
894 double Image::computeResampleFactor(
long maxVoxels)
900 double factor = (double)maxVoxels/(
double)voxels;
901 factor = pow(factor, 1.0/3.0);
913 QString filename = basePath +
"/Images/" + this->
getUid() +
".mhd";
914 this->
setFilename(QDir(basePath).relativeFilePath(filename));
922 mThresholdPreview =
true;
924 this->createThresholdPreviewTransferFunctions3D(threshold);
925 this->createThresholdPreviewLookupTable2D(threshold);
930 void Image::createThresholdPreviewTransferFunctions3D(
const Eigen::Vector2d &threshold)
934 ColorMap colors = this->createPreviewColorMap(threshold);
935 IntIntMap opacity = this->createPreviewOpacityMap(threshold);
937 mTresholdPreviewTransferfunctions3D = tfGenerator.generate3DTFPreset();
938 mTresholdPreviewTransferfunctions3D->resetColor(colors);
939 mTresholdPreviewTransferfunctions3D->resetAlpha(opacity);
942 void Image::createThresholdPreviewLookupTable2D(
const Eigen::Vector2d &threshold)
944 ImageDefaultTFGenerator tfGenerator(
ImagePtr(
this, null_deleter()));
946 ColorMap colors = this->createPreviewColorMap(threshold);
948 mTresholdPreviewLookupTable2D = tfGenerator.generate2DTFPreset();
949 mTresholdPreviewLookupTable2D->resetColor(colors);
950 mTresholdPreviewLookupTable2D->setLLR(threshold[0]);
953 ColorMap Image::createPreviewColorMap(
const Eigen::Vector2d &threshold)
955 double lower = threshold[0];
957 colors[lower] = Qt::green;
958 colors[this->
getMax()] = Qt::green;
962 IntIntMap Image::createPreviewOpacityMap(
const Eigen::Vector2d &threshold)
964 double lower = threshold[0];
965 double upper = threshold[1];
967 opacity[lower - 1] = 0;
970 opacity[upper + 1] = 0;
976 mThresholdPreview =
false;
977 mTresholdPreviewTransferfunctions3D.reset();
978 mTresholdPreviewLookupTable2D.reset();
virtual void parseXml(QDomNode &dataNode)
Use a XML node to load data.
QString qstring_cast(const T &val)
void transferFunctionsChanged()
static vtkImageDataPtr createDummyImageData(int axisSize, int maxVoxelValue)
Create a moc object of vtkImageData.
Image(const QString &uid, const vtkImageDataPtr &data, const QString &name="")
virtual bool getCropping() const
virtual void setModality(const QString &val)
virtual Transform3D get_rMd() const
bool mUseCropping
image should be cropped using mCroppingBox
virtual vtkImageDataPtr getGrayScaleVtkImageData()
as getBaseVtkImageData(), but constrained to 1 component if multicolor.
int getInterpolationType() const
virtual Eigen::Array3d getSpacing() const
QString mImageType
type of the image, defined as DICOM tag (0008,0008) (mainly value 3, but might be a merge of value 4)...
void parseXml(QDomNode dataNode)
virtual void setTransferFunctions3D(ImageTF3DPtr transferFuntion)
PlainObject normal() const
virtual double getShadingDiffuse()
Get shading diffuse parmeter.
virtual vtkImageAccumulatePtr getHistogram()
void mergevtkSettingsIntosscTransform()
static ImagePtr create(const QString &uid, const QString &name)
void addXml(QDomNode dataNode)
#define CX_ASSERT(statement)
virtual void setShadingDiffuse(double diffuse)
Set shading diffuse parmeter.
virtual QString getModality() const
virtual std::vector< vtkPlanePtr > getAllClipPlanes()
virtual void addPersistentClipPlane(vtkPlanePtr plane)
virtual void setVtkImageData(const vtkImageDataPtr &data, bool resetTransferFunctions=true)
vtkSmartPointer< class vtkImageAccumulate > vtkImageAccumulatePtr
void propertiesChanged()
emitted when one of the metadata properties (uid, name etc) changes
virtual void setLookupTable2D(ImageLUT2DPtr imageLookupTable2D)
boost::shared_ptr< class Image > ImagePtr
virtual void setInitialWindowLevel(double width, double level)
vtkSmartPointer< vtkImageChangeInformation > vtkImageChangeInformationPtr
static DoubleBoundingBox3D fromString(const QString &text)
construct a bb from a string containing 6 whitespace-separated numbers
virtual void setCropping(bool on)
virtual Image::ShadingStruct getShading()
virtual void setShadingOn(bool on)
DoubleBoundingBox3D mCroppingBox_d
box defining the cropping size.
virtual void setShadingAmbient(double ambient)
Set shading ambient parmeter.
virtual vtkImageDataPtr getBaseVtkImageData()
static ImagePtr create(ImagePtr base)
virtual void addXml(QDomNode &dataNode)
adds xml information about the data and its variabels
virtual double getShadingSpecular()
Get shading specular parmeter.
virtual void setShadingSpecular(double specular)
Set shading specular parmeter.
virtual void setImageType(const QString &val)
ImagePtr mUnsigned
version of this containing unsigned data.
virtual ImagePtr getUnsigned(ImagePtr self)
virtual void intitializeFromParentImage(ImagePtr parentImage)
virtual QString getUid() const
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
virtual ImageTF3DPtr getTransferFunctions3D()
void addXml(QDomNode &dataNode)
adds xml information about the image and its variabels
virtual RegistrationHistoryPtr get_rMd_History()
vtkSmartPointer< class vtkImageChangeInformation > vtkImageChangeInformationPtr
std::map< int, QColor > ColorMap
boost::shared_ptr< class ImageLUT2D > ImageLUT2DPtr
ImageLUT2DPtr generate2DTFPreset()
void startThresholdPreview(const Eigen::Vector2d &threshold)
vtkPlanePtr mInteractiveClipPlane
QString mModality
modality of the image, defined as DICOM tag (0008,0060), Section 3, C.7.3.1.1.1
void reportWarning(QString msg)
virtual int getMaxAlphaValue()
Max alpha value (probably 255)
vtkImageDataPtr convertImageDataTo8Bit(vtkImageDataPtr image, double windowWidth, double windowLevel)
Have never been used or tested. Create a test for it.
virtual void parseXml(QDomNode &dataNode)
Use a XML node to load data.
virtual void setShadingSpecularPower(double specularPower)
Set shading specular power parmeter.
void moveThisAndChildrenToThread(QThread *thread)
Move this and all children to thread. Use the thread is generated in a worker thread and the result i...
virtual int getRange()
For convenience: getMax() - getMin()
virtual void save(const QString &basePath)
void setAcquisitionTime(QDateTime time)
void transferFunctionsChanged()
emitted when image transfer functions in 2D or 3D are changed.
Transform3D createTransformTranslate(const Vector3D &translation)
Representation of an integer bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
Representation of a floating-point bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
vtkSmartPointer< class vtkImageResample > vtkImageResamplePtr
vtkImageAccumulatePtr mHistogramPtr
Histogram.
vtkImageDataPtr resample(long maxVoxels)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Vector3D multiply_elems(const Vector3D &a, const Vector3D &b)
perform element-wise multiplication of a and b.
virtual void setInteractiveClipPlane(vtkPlanePtr plane)
set a plane that is not saved
virtual void setShading(Image::ShadingStruct shading)
vtkImageDataPtr convertImageDataToGrayScale(vtkImageDataPtr image)
RegistrationHistoryPtr m_rMd_History
Superclass for all data objects.
std::map< int, int > IntIntMap
void setDeepModified(vtkImageDataPtr image)
void readInto(DataPtr data, QString path)
virtual DoubleBoundingBox3D getCroppingBox() const
std::vector< vtkPlanePtr > mPersistentClipPlanes
virtual void setCroppingBox(const DoubleBoundingBox3D &bb_d)
ImageTF3DPtr generate3DTFPreset()
void vtkImageDataChanged()
emitted when the vktimagedata are invalidated and must be retrieved anew.
virtual vtkImageDataPtr get8bitGrayScaleVtkImageData()
Have never been used or tested. Create a test for it.
REGISTRATION_STATUS mRegistrationStatus
virtual double getShadingAmbient()
Get shading ambient parmeter.
virtual bool load(QString path)
void stopThresholdPreview()
void setInterpolationType(int val)
virtual QString getImageType() const
void setInterpolationTypeToNearest()
virtual double getShadingSpecularPower()
Get shading specular power parmeter.
vtkImageDataPtr mBaseImageData
image data in data space
int mInterpolationType
mirror the interpolationType in vtkVolumeProperty
vtkSmartPointer< class vtkPlane > vtkPlanePtr
void setInterpolationTypeToLinear()
virtual void clearPersistentClipPlanes()
boost::shared_ptr< class ImageTF3D > ImageTF3DPtr
virtual void setFilename(QString val)
virtual void transformChangedSlot()
virtual ImageLUT2DPtr getLookupTable2D()
virtual bool getShadingOn() const
void resetTransferFunctions(bool _2D=true, bool _3D=true)
Resets the transfer functions and creates new defaut values.
virtual DoubleBoundingBox3D boundingBox() const
bounding box in image space
vtkImageDataPtr mBaseGrayScaleImageData
image data in data space