15 #include <QDomDocument>
17 #include <vtkImageAccumulate.h>
18 #include <vtkImageReslice.h>
19 #include <vtkImageData.h>
20 #include <vtkMatrix4x4.h>
22 #include <vtkPlanes.h>
23 #include <vtkImageResample.h>
24 #include <vtkImageChangeInformation.h>
25 #include <vtkImageClip.h>
26 #include <vtkImageIterator.h>
27 #include <vtkPiecewiseFunction.h>
28 #include <vtkColorTransferFunction.h>
60 double Image::ShadingStruct::loadAttribute(QDomNode dataNode, QString name,
double defVal)
62 QString text = dataNode.toElement().attribute(name);
64 double val = text.toDouble(&ok);
72 QDomElement elem = dataNode.toElement();
73 elem.setAttribute(
"on", on);
74 elem.setAttribute(
"ambient", ambient);
75 elem.setAttribute(
"diffuse", diffuse);
76 elem.setAttribute(
"specular", specular);
77 elem.setAttribute(
"specularPower", specularPower);
82 if (dataNode.isNull())
85 on = dataNode.toElement().attribute(
"on").toInt();
87 ambient = loadAttribute(dataNode,
"ambient", ambient);
88 diffuse = loadAttribute(dataNode,
"diffuse", diffuse);
89 specular = loadAttribute(dataNode,
"specular", specular);
90 specularPower = loadAttribute(dataNode,
"specularPower", specularPower);
109 mInitialWindowWidth = -1;
110 mInitialWindowLevel = -1;
117 mImageLookupTable2D.reset();
118 mImageTransferFunctions3D.reset();
128 baseImageDataCopy = vtkImageDataPtr::New();
139 retval->mImageLookupTable2D = mImageLookupTable2D;
140 retval->mImageTransferFunctions3D = mImageTransferFunctions3D;
141 retval->mInitialWindowWidth = mInitialWindowWidth;
142 retval->mInitialWindowLevel = mInitialWindowLevel;
155 ImageTF3DPtr transferFunctions = parentImage->getUnmodifiedTransferFunctions3D()->createCopy();
156 ImageLUT2DPtr LUT2D = parentImage->getUnmodifiedLookupTable2D()->createCopy();
162 mInitialWindowWidth = parentImage->getInitialWindowWidth();
163 mInitialWindowLevel = parentImage->getInitialWindowLevel();
212 this->blockSignals(
true);
214 this->resetTransferFunction(imageTransferFunctions3D);
215 this->resetTransferFunction(imageLookupTable2D);
217 this->blockSignals(
false);
221 void Image::resetTransferFunction(
ImageLUT2DPtr imageLookupTable2D)
223 if (mImageLookupTable2D)
228 mImageLookupTable2D = imageLookupTable2D;
230 if (mImageLookupTable2D)
238 void Image::resetTransferFunction(
ImageTF3DPtr imageTransferFunctions3D)
240 if (mImageTransferFunctions3D)
245 mImageTransferFunctions3D = imageTransferFunctions3D;
247 if (mImageTransferFunctions3D)
262 this->moveToThread(thread);
263 this->getUnmodifiedTransferFunctions3D()->moveToThread(thread);
264 this->getUnmodifiedLookupTable2D()->moveToThread(thread);
281 double windowWidth = this->getUnmodifiedLookupTable2D()->getWindow();
282 double windowLevel = this->getUnmodifiedLookupTable2D()->getLevel();
299 if(mThresholdPreview)
300 return mTresholdPreviewTransferfunctions3D;
301 return getUnmodifiedTransferFunctions3D();
306 if(!this->mImageTransferFunctions3D)
308 return mImageTransferFunctions3D;
313 this->resetTransferFunction(transferFuntion);
318 if(mThresholdPreview)
319 return mTresholdPreviewLookupTable2D;
320 return getUnmodifiedLookupTable2D();
325 if(!mImageLookupTable2D)
327 return mImageLookupTable2D;
332 this->resetTransferFunction(imageLookupTable2D);
368 template<
typename scalartype>
static int getRGBMax(
vtkImageDataPtr image)
371 vtkImageIterator<scalartype> iter(image, image->GetExtent());
372 while (!iter.IsAtEnd())
374 typename vtkImageIterator<scalartype>::SpanIterator siter = iter.BeginSpan();
375 while (siter != iter.EndSpan())
409 case VTK_UNSIGNED_CHAR:
412 case VTK_UNSIGNED_SHORT:
452 if (vtkScalarType==VTK_CHAR)
454 else if (vtkScalarType==VTK_UNSIGNED_CHAR)
455 return VTK_UNSIGNED_CHAR_MIN;
456 else if (vtkScalarType==VTK_SIGNED_CHAR)
457 return VTK_SIGNED_CHAR_MIN;
458 else if (vtkScalarType==VTK_UNSIGNED_SHORT)
459 return VTK_UNSIGNED_SHORT_MIN;
460 else if (vtkScalarType==VTK_SHORT)
461 return VTK_SHORT_MIN;
462 else if (vtkScalarType==VTK_UNSIGNED_INT)
463 return VTK_UNSIGNED_INT_MIN;
464 else if (vtkScalarType==VTK_INT)
466 else if (vtkScalarType==VTK_FLOAT)
467 return VTK_FLOAT_MIN;
469 reportError(QString(
"Unknown VTK ScalarType: %1").arg(vtkScalarType));
477 if (vtkScalarType==VTK_CHAR)
479 else if (vtkScalarType==VTK_UNSIGNED_CHAR)
480 return VTK_UNSIGNED_CHAR_MAX;
481 else if (vtkScalarType==VTK_SIGNED_CHAR)
482 return VTK_SIGNED_CHAR_MAX;
483 else if (vtkScalarType==VTK_UNSIGNED_SHORT)
484 return VTK_UNSIGNED_SHORT_MAX;
485 else if (vtkScalarType==VTK_SHORT)
486 return VTK_SHORT_MAX;
487 else if (vtkScalarType==VTK_UNSIGNED_INT)
488 return VTK_UNSIGNED_INT_MAX;
489 else if (vtkScalarType==VTK_INT)
491 else if (vtkScalarType==VTK_FLOAT)
492 return VTK_FLOAT_MAX;
494 reportError(QString(
"Unknown VTK ScalarType: %1").arg(vtkScalarType));
506 QDomNode imageNode = dataNode;
507 QDomDocument doc = dataNode.ownerDocument();
509 QDomElement tf3DNode = doc.createElement(
"transferfunctions");
510 this->getUnmodifiedTransferFunctions3D()->addXml(tf3DNode);
511 imageNode.appendChild(tf3DNode);
513 QDomElement lut2DNode = doc.createElement(
"lookuptable2D");
514 this->getUnmodifiedLookupTable2D()->addXml(lut2DNode);
515 imageNode.appendChild(lut2DNode);
517 QDomElement shadingNode = doc.createElement(
"shading");
519 imageNode.appendChild(shadingNode);
525 QDomElement cropNode = doc.createElement(
"crop");
528 imageNode.appendChild(cropNode);
530 QDomElement clipNode = doc.createElement(
"clip");
533 QDomElement planeNode = doc.createElement(
"plane");
538 clipNode.appendChild(planeNode);
540 imageNode.appendChild(clipNode);
542 QDomElement modalityNode = doc.createElement(
"modality");
544 imageNode.appendChild(modalityNode);
546 QDomElement imageTypeNode = doc.createElement(
"imageType");
548 imageNode.appendChild(imageTypeNode);
550 QDomElement interpolationNode = doc.createElement(
"vtk_interpolation");
552 imageNode.appendChild(interpolationNode);
554 QDomElement initialWindowNode = doc.createElement(
"initialWindow");
555 initialWindowNode.setAttribute(
"width", mInitialWindowWidth);
556 initialWindowNode.setAttribute(
"level", mInitialWindowLevel);
557 imageNode.appendChild(initialWindowNode);
560 double Image::loadAttribute(QDomNode dataNode, QString name,
double defVal)
562 QString text = dataNode.toElement().attribute(name);
564 double val = text.toDouble(&ok);
573 filemanager->readInto(
self, path);
584 if (dataNode.isNull())
588 QDomNode transferfunctionsNode = dataNode.namedItem(
"transferfunctions");
589 if (!transferfunctionsNode.isNull())
590 this->getUnmodifiedTransferFunctions3D()->parseXml(transferfunctionsNode);
593 std::cout <<
"Warning: Image::parseXml() found no transferfunctions";
594 std::cout << std::endl;
597 mInitialWindowWidth = this->loadAttribute(dataNode.namedItem(
"initialWindow"),
"width", mInitialWindowWidth);
598 mInitialWindowLevel = this->loadAttribute(dataNode.namedItem(
"initialWindow"),
"level", mInitialWindowLevel);
600 this->getUnmodifiedLookupTable2D()->parseXml(dataNode.namedItem(
"lookuptable2D"));
603 mShading.
on = dataNode.namedItem(
"shading").toElement().text().toInt();
605 if (!dataNode.namedItem(
"shadingAmbient").isNull())
606 mShading.
ambient = dataNode.namedItem(
"shadingAmbient").toElement().text().toDouble();
607 if (!dataNode.namedItem(
"shadingDiffuse").isNull())
608 mShading.
diffuse = dataNode.namedItem(
"shadingDiffuse").toElement().text().toDouble();
609 if (!dataNode.namedItem(
"shadingSpecular").isNull())
610 mShading.
specular = dataNode.namedItem(
"shadingSpecular").toElement().text().toDouble();
611 if (!dataNode.namedItem(
"shadingSpecularPower").isNull())
619 QDomElement cropNode = dataNode.namedItem(
"crop").toElement();
620 if (!cropNode.isNull())
626 QDomElement clipNode = dataNode.namedItem(
"clip").toElement();
627 QDomElement clipPlaneNode = clipNode.firstChildElement(
"plane");
628 for (; !clipPlaneNode.isNull(); clipPlaneNode = clipPlaneNode.nextSiblingElement(
"plane"))
630 Vector3D normal = Vector3D::fromString(clipPlaneNode.attribute(
"normal"));
631 Vector3D origin = Vector3D::fromString(clipPlaneNode.attribute(
"origin"));
633 plane->SetNormal(
normal.begin());
634 plane->SetOrigin(origin.begin());
641 QDomElement interpoationNode = dataNode.namedItem(
"vtk_interpolation").toElement();
642 if (!interpoationNode.isNull())
651 mInitialWindowWidth = width;
652 mInitialWindowLevel = level;
663 if (mThresholdPreview)
778 info->SetOutputExtentStart(0, 0, 0);
779 info->SetOutputOrigin(0, 0, 0);
781 info->UpdateInformation();
819 int size = axisSize - 1;
821 dummyImageData->SetExtent(0, size, 0, size, 0, size);
822 dummyImageData->SetSpacing(1, 1, 1);
827 dummyImageData->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
828 unsigned char* dataPtr =
static_cast<unsigned char*
> (dummyImageData->GetScalarPointer());
831 int minVoxelValue = 0;
832 int numVoxels = axisSize*axisSize*axisSize;
833 for (
int i = 0; i < numVoxels; ++i)
835 int voxelValue = minVoxelValue + i;
837 dataPtr[i] = maxVoxelValue;
838 else if (voxelValue < maxVoxelValue)
839 dataPtr[i] = voxelValue;
841 dataPtr[i] = maxVoxelValue;
844 return dummyImageData;
860 if (mThresholdPreview)
867 if (mThresholdPreview)
868 return VTK_NEAREST_INTERPOLATION;
877 double factor = computeResampleFactor(maxVoxels);
879 if (fabs(1.0-factor)>0.01)
882 resampler->SetInterpolationModeToLinear();
883 resampler->SetAxisMagnificationFactor(0, factor);
884 resampler->SetAxisMagnificationFactor(1, factor);
885 resampler->SetAxisMagnificationFactor(2, factor);
886 resampler->SetInputData(retval);
889 resampler->GetOutput()->GetScalarRange();
890 retval = resampler->GetOutput();
903 double Image::computeResampleFactor(
long maxVoxels)
909 double factor = (double)maxVoxels/(
double)voxels;
910 factor = pow(factor, 1.0/3.0);
922 QString filename = basePath +
"/Images/" + this->
getUid() +
".mhd";
923 this->
setFilename(QDir(basePath).relativeFilePath(filename));
926 filemanager->save(
self, filename);
931 mThresholdPreview =
true;
933 this->createThresholdPreviewTransferFunctions3D(threshold);
934 this->createThresholdPreviewLookupTable2D(threshold);
939 void Image::createThresholdPreviewTransferFunctions3D(
const Eigen::Vector2d &threshold)
943 ColorMap colors = this->createPreviewColorMap(threshold);
944 IntIntMap opacity = this->createPreviewOpacityMap(threshold);
946 mTresholdPreviewTransferfunctions3D = tfGenerator.generate3DTFPreset();
947 mTresholdPreviewTransferfunctions3D->resetColor(colors);
948 mTresholdPreviewTransferfunctions3D->resetAlpha(opacity);
951 void Image::createThresholdPreviewLookupTable2D(
const Eigen::Vector2d &threshold)
953 ImageDefaultTFGenerator tfGenerator(
ImagePtr(
this, null_deleter()));
955 ColorMap colors = this->createPreviewColorMap(threshold);
957 mTresholdPreviewLookupTable2D = tfGenerator.generate2DTFPreset();
958 mTresholdPreviewLookupTable2D->resetColor(colors);
959 mTresholdPreviewLookupTable2D->setLLR(threshold[0]);
962 ColorMap Image::createPreviewColorMap(
const Eigen::Vector2d &threshold)
964 double lower = threshold[0];
966 colors[lower] = Qt::green;
967 colors[this->
getMax()] = Qt::green;
971 IntIntMap Image::createPreviewOpacityMap(
const Eigen::Vector2d &threshold)
973 double lower = threshold[0];
974 double upper = threshold[1];
976 opacity[lower - 1] = 0;
979 opacity[upper + 1] = 0;
985 mThresholdPreview =
false;
986 mTresholdPreviewTransferfunctions3D.reset();
987 mTresholdPreviewLookupTable2D.reset();