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));
505 mDicomSeriesNumber = seriesNumber;
510 return mDicomSeriesNumber;
516 QDomNode imageNode = dataNode;
517 QDomDocument doc = dataNode.ownerDocument();
519 QDomElement tf3DNode = doc.createElement(
"transferfunctions");
520 this->getUnmodifiedTransferFunctions3D()->addXml(tf3DNode);
521 imageNode.appendChild(tf3DNode);
523 QDomElement lut2DNode = doc.createElement(
"lookuptable2D");
524 this->getUnmodifiedLookupTable2D()->addXml(lut2DNode);
525 imageNode.appendChild(lut2DNode);
527 QDomElement shadingNode = doc.createElement(
"shading");
529 imageNode.appendChild(shadingNode);
535 QDomElement cropNode = doc.createElement(
"crop");
538 imageNode.appendChild(cropNode);
540 QDomElement clipNode = doc.createElement(
"clip");
543 QDomElement planeNode = doc.createElement(
"plane");
548 clipNode.appendChild(planeNode);
550 imageNode.appendChild(clipNode);
552 QDomElement modalityNode = doc.createElement(
"modality");
554 imageNode.appendChild(modalityNode);
556 QDomElement imageTypeNode = doc.createElement(
"imageType");
558 imageNode.appendChild(imageTypeNode);
560 QDomElement interpolationNode = doc.createElement(
"vtk_interpolation");
562 imageNode.appendChild(interpolationNode);
564 QDomElement initialWindowNode = doc.createElement(
"initialWindow");
565 initialWindowNode.setAttribute(
"width", mInitialWindowWidth);
566 initialWindowNode.setAttribute(
"level", mInitialWindowLevel);
567 imageNode.appendChild(initialWindowNode);
570 double Image::loadAttribute(QDomNode dataNode, QString name,
double defVal)
572 QString text = dataNode.toElement().attribute(name);
574 double val = text.toDouble(&ok);
583 filemanager->readInto(
self, path);
594 if (dataNode.isNull())
598 QDomNode transferfunctionsNode = dataNode.namedItem(
"transferfunctions");
599 if (!transferfunctionsNode.isNull())
600 this->getUnmodifiedTransferFunctions3D()->parseXml(transferfunctionsNode);
603 std::cout <<
"Warning: Image::parseXml() found no transferfunctions";
604 std::cout << std::endl;
607 mInitialWindowWidth = this->loadAttribute(dataNode.namedItem(
"initialWindow"),
"width", mInitialWindowWidth);
608 mInitialWindowLevel = this->loadAttribute(dataNode.namedItem(
"initialWindow"),
"level", mInitialWindowLevel);
610 this->getUnmodifiedLookupTable2D()->parseXml(dataNode.namedItem(
"lookuptable2D"));
613 mShading.
on = dataNode.namedItem(
"shading").toElement().text().toInt();
615 if (!dataNode.namedItem(
"shadingAmbient").isNull())
616 mShading.
ambient = dataNode.namedItem(
"shadingAmbient").toElement().text().toDouble();
617 if (!dataNode.namedItem(
"shadingDiffuse").isNull())
618 mShading.
diffuse = dataNode.namedItem(
"shadingDiffuse").toElement().text().toDouble();
619 if (!dataNode.namedItem(
"shadingSpecular").isNull())
620 mShading.
specular = dataNode.namedItem(
"shadingSpecular").toElement().text().toDouble();
621 if (!dataNode.namedItem(
"shadingSpecularPower").isNull())
629 QDomElement cropNode = dataNode.namedItem(
"crop").toElement();
630 if (!cropNode.isNull())
636 QDomElement clipNode = dataNode.namedItem(
"clip").toElement();
637 QDomElement clipPlaneNode = clipNode.firstChildElement(
"plane");
638 for (; !clipPlaneNode.isNull(); clipPlaneNode = clipPlaneNode.nextSiblingElement(
"plane"))
640 Vector3D normal = Vector3D::fromString(clipPlaneNode.attribute(
"normal"));
641 Vector3D origin = Vector3D::fromString(clipPlaneNode.attribute(
"origin"));
643 plane->SetNormal(
normal.begin());
644 plane->SetOrigin(origin.begin());
651 QDomElement interpoationNode = dataNode.namedItem(
"vtk_interpolation").toElement();
652 if (!interpoationNode.isNull())
661 mInitialWindowWidth = width;
662 mInitialWindowLevel = level;
673 if (mThresholdPreview)
788 info->SetOutputExtentStart(0, 0, 0);
789 info->SetOutputOrigin(0, 0, 0);
791 info->UpdateInformation();
829 int size = axisSize - 1;
831 dummyImageData->SetExtent(0, size, 0, size, 0, size);
832 dummyImageData->SetSpacing(1, 1, 1);
837 dummyImageData->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
838 unsigned char* dataPtr =
static_cast<unsigned char*
> (dummyImageData->GetScalarPointer());
841 int minVoxelValue = 0;
842 int numVoxels = axisSize*axisSize*axisSize;
843 for (
int i = 0; i < numVoxels; ++i)
845 int voxelValue = minVoxelValue + i;
847 dataPtr[i] = maxVoxelValue;
848 else if (voxelValue < maxVoxelValue)
849 dataPtr[i] = voxelValue;
851 dataPtr[i] = maxVoxelValue;
854 return dummyImageData;
870 if (mThresholdPreview)
877 if (mThresholdPreview)
878 return VTK_NEAREST_INTERPOLATION;
887 double factor = computeResampleFactor(maxVoxels);
889 if (fabs(1.0-factor)>0.01)
892 resampler->SetInterpolationModeToLinear();
893 resampler->SetAxisMagnificationFactor(0, factor);
894 resampler->SetAxisMagnificationFactor(1, factor);
895 resampler->SetAxisMagnificationFactor(2, factor);
896 resampler->SetInputData(retval);
899 resampler->GetOutput()->GetScalarRange();
900 retval = resampler->GetOutput();
913 double Image::computeResampleFactor(
long maxVoxels)
919 double factor = (double)maxVoxels/(
double)voxels;
920 factor = pow(factor, 1.0/3.0);
932 QString filename = basePath +
"/Images/" + this->
getUid() +
".mhd";
933 this->
setFilename(QDir(basePath).relativeFilePath(filename));
936 filemanager->save(
self, filename);
941 mThresholdPreview =
true;
943 this->createThresholdPreviewTransferFunctions3D(threshold);
944 this->createThresholdPreviewLookupTable2D(threshold);
949 void Image::createThresholdPreviewTransferFunctions3D(
const Eigen::Vector2d &threshold)
953 ColorMap colors = this->createPreviewColorMap(threshold);
954 IntIntMap opacity = this->createPreviewOpacityMap(threshold);
956 mTresholdPreviewTransferfunctions3D = tfGenerator.generate3DTFPreset();
957 mTresholdPreviewTransferfunctions3D->resetColor(colors);
958 mTresholdPreviewTransferfunctions3D->resetAlpha(opacity);
961 void Image::createThresholdPreviewLookupTable2D(
const Eigen::Vector2d &threshold)
963 ImageDefaultTFGenerator tfGenerator(
ImagePtr(
this, null_deleter()));
965 ColorMap colors = this->createPreviewColorMap(threshold);
967 mTresholdPreviewLookupTable2D = tfGenerator.generate2DTFPreset();
968 mTresholdPreviewLookupTable2D->resetColor(colors);
969 mTresholdPreviewLookupTable2D->setLLR(threshold[0]);
972 ColorMap Image::createPreviewColorMap(
const Eigen::Vector2d &threshold)
974 double lower = threshold[0];
976 colors[lower] = Qt::green;
977 colors[this->
getMax()] = Qt::green;
981 IntIntMap Image::createPreviewOpacityMap(
const Eigen::Vector2d &threshold)
983 double lower = threshold[0];
984 double upper = threshold[1];
986 opacity[lower - 1] = 0;
989 opacity[upper + 1] = 0;
995 mThresholdPreview =
false;
996 mTresholdPreviewTransferfunctions3D.reset();
997 mTresholdPreviewLookupTable2D.reset();