@@ -488,80 +488,108 @@ void vtkSlicerVolumeRenderingLogic::SetThresholdToVolumeProp(
488488
489489// ----------------------------------------------------------------------------
490490void vtkSlicerVolumeRenderingLogic::SetWindowLevelToVolumeProp (
491- double scalarRange[2 ], double windowLevel[2 ], vtkLookupTable* lut , vtkVolumeProperty* volumeProp)
491+ double scalarRange[2 ], double windowLevel[2 ], vtkScalarsToColors* colors , vtkVolumeProperty* volumeProp)
492492{
493493 if (!volumeProp || !scalarRange || !windowLevel)
494- {
494+ {
495495 vtkWarningMacro (" SetWindowLevelToVolumeProp: Inputs do not exist." );
496496 return ;
497- }
498-
499- double windowLevelMinMax[2 ];
500- windowLevelMinMax[0 ] = windowLevel[1 ] - 0.5 * windowLevel[0 ];
501- windowLevelMinMax[1 ] = windowLevel[1 ] + 0.5 * windowLevel[0 ];
497+ }
502498
503- double previous = VTK_DOUBLE_MIN;
499+ double windowLevelMinMax[2 ] =
500+ {
501+ windowLevel[1 ] - 0.5 * windowLevel[0 ],
502+ windowLevel[1 ] + 0.5 * windowLevel[0 ],
503+ };
504504
505505 vtkNew<vtkColorTransferFunction> colorTransfer;
506506
507- const int size = lut ? lut->GetNumberOfTableValues () : 0 ;
508- if (size == 0 )
509- {
510- const double black[3 ] = {0 ., 0 ., 0 .};
511- const double white[3 ] = {1 ., 1 ., 1 .};
512- colorTransfer->AddRGBPoint (scalarRange[0 ], black[0 ], black[1 ], black[2 ]);
513- colorTransfer->AddRGBPoint (windowLevelMinMax[0 ], black[0 ], black[1 ], black[2 ]);
514- colorTransfer->AddRGBPoint (windowLevelMinMax[1 ], white[0 ], white[1 ], white[2 ]);
515- colorTransfer->AddRGBPoint (scalarRange[1 ], white[0 ], white[1 ], white[2 ]);
516- }
517- else if (size == 1 )
518- {
519- double color[4 ];
520- lut->GetTableValue (0 , color);
521-
522- colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (scalarRange[0 ], previous),
523- color[0 ], color[1 ], color[2 ]);
524- colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (windowLevelMinMax[0 ], previous),
525- color[0 ], color[1 ], color[2 ]);
526- colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (windowLevelMinMax[1 ], previous),
527- color[0 ], color[1 ], color[2 ]);
528- colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (scalarRange[1 ], previous),
529- color[0 ], color[1 ], color[2 ]);
530- }
531- else // if (size > 1)
532- {
533- previous = VTK_DOUBLE_MIN;
534-
535- double color[4 ];
536- lut->GetTableValue (0 , color);
537- colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (scalarRange[0 ], previous),
538- color[0 ], color[1 ], color[2 ]);
507+ vtkColorTransferFunction* inputColorTransfer = vtkColorTransferFunction::SafeDownCast (colors);
508+ if (inputColorTransfer)
509+ {
510+ // Colors are defined by transfer function
511+ // We cannot simply copy but we need to scale and offset as specified by window/level
512+ double inputColorTransferRange[2 ] = { 0.0 , 1.0 };
513+ inputColorTransfer->GetRange (inputColorTransferRange);
514+ const double scale = (windowLevelMinMax[1 ] - windowLevelMinMax[0 ]) / (inputColorTransferRange[1 ] - inputColorTransferRange[0 ]);
515+ const double offset = windowLevelMinMax[0 ] - scale * inputColorTransferRange[0 ];
516+ const vtkIdType colorCount = inputColorTransfer->GetSize ();
517+ double color_X_RGB_MS[6 ] = { 0 ., 0 ., 0 ., 0 ., 0.5 , 1.0 }; // x, RGB, midpoint, sharpness
518+ for (vtkIdType i = 0 ; i < colorCount; ++i)
519+ {
520+ inputColorTransfer->GetNodeValue (i, color_X_RGB_MS);
521+ colorTransfer->AddRGBPoint (offset + color_X_RGB_MS[0 ] * scale,
522+ color_X_RGB_MS[1 ], color_X_RGB_MS[2 ], color_X_RGB_MS[3 ], color_X_RGB_MS[4 ], color_X_RGB_MS[5 ]);
523+ }
524+ }
525+ else
526+ {
527+ // Colors are defined by lookup table
528+ vtkLookupTable* lut = vtkLookupTable::SafeDownCast (colors);
529+ double previous = VTK_DOUBLE_MIN;
530+ const vtkIdType numberOfColors = lut ? lut->GetNumberOfTableValues () : 0 ;
531+ if (numberOfColors == 0 )
532+ {
533+ const double black[3 ] = { 0 ., 0 ., 0 . };
534+ const double white[3 ] = { 1 ., 1 ., 1 . };
535+ colorTransfer->AddRGBPoint (scalarRange[0 ], black[0 ], black[1 ], black[2 ]);
536+ colorTransfer->AddRGBPoint (windowLevelMinMax[0 ], black[0 ], black[1 ], black[2 ]);
537+ colorTransfer->AddRGBPoint (windowLevelMinMax[1 ], white[0 ], white[1 ], white[2 ]);
538+ colorTransfer->AddRGBPoint (scalarRange[1 ], white[0 ], white[1 ], white[2 ]);
539+ }
540+ else if (numberOfColors == 1 )
541+ {
542+ double color[4 ];
543+ lut->GetTableValue (0 , color);
539544
540- double value = windowLevelMinMax[0 ];
545+ colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (scalarRange[0 ], previous),
546+ color[0 ], color[1 ], color[2 ]);
547+ colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (windowLevelMinMax[0 ], previous),
548+ color[0 ], color[1 ], color[2 ]);
549+ colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (windowLevelMinMax[1 ], previous),
550+ color[0 ], color[1 ], color[2 ]);
551+ colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (scalarRange[1 ], previous),
552+ color[0 ], color[1 ], color[2 ]);
553+ }
554+ else // if (numberOfColors > 1)
555+ {
556+ double color[4 ] = { 0.0 , 0.0 , 0.0 , 1.0 };
557+ lut->GetTableValue (0 , color);
558+ colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (scalarRange[0 ], previous),
559+ color[0 ], color[1 ], color[2 ]);
541560
542- double step = windowLevel[0 ] / (size - 1 );
561+ // We place up to maxNumberOfPoints points in the color transfer function.
562+ // The number is high enough to accurately describe most color tables,
563+ // but not too high so that the user can still edit the function manually.
564+ const vtkIdType maxNumberOfPoints = 24 ;
565+
566+ const vtkIdType numberOfPoints = std::min (numberOfColors, maxNumberOfPoints);
567+ // convert from point index to color index
568+ double pointIndexScale = static_cast <double >(numberOfColors - 1 ) / (numberOfPoints - 1 );
569+ double offset = windowLevelMinMax[0 ];
570+ double scale = windowLevel[0 ] / (numberOfColors - 1 );
571+ for (vtkIdType pointIndex = 0 ; pointIndex < numberOfPoints; ++pointIndex)
572+ {
573+ vtkIdType colorIndex = pointIndex * pointIndexScale;
574+ lut->GetTableValue (colorIndex, color);
575+ const double value = offset + colorIndex * scale;
576+ colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (value, previous),
577+ color[0 ], color[1 ], color[2 ]);
578+ }
543579
544- int downSamplingFactor = 64 ;
545- for (int i = 0 ; i < size; i += downSamplingFactor,
546- value += downSamplingFactor*step)
547- {
548- lut->GetTableValue (i, color);
549- colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (value, previous),
580+ lut->GetTableValue (numberOfColors - 1 , color);
581+ colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (windowLevelMinMax[1 ], previous),
582+ color[0 ], color[1 ], color[2 ]);
583+ colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (scalarRange[1 ], previous),
550584 color[0 ], color[1 ], color[2 ]);
585+ }
551586 }
552587
553- lut->GetTableValue (size - 1 , color);
554- colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (windowLevelMinMax[1 ], previous),
555- color[0 ], color[1 ], color[2 ]);
556- colorTransfer->AddRGBPoint (vtkMRMLVolumePropertyNode::HigherAndUnique (scalarRange[1 ], previous),
557- color[0 ], color[1 ], color[2 ]);
558- }
559-
560588 vtkColorTransferFunction *volumePropColorTransfer = volumeProp->GetRGBTransferFunction ();
561589 if (this ->IsDifferentFunction (colorTransfer.GetPointer (), volumePropColorTransfer))
562- {
590+ {
563591 volumePropColorTransfer->DeepCopy (colorTransfer.GetPointer ());
564- }
592+ }
565593
566594 volumeProp->SetInterpolationTypeToLinear ();
567595 volumeProp->ShadeOn ();
@@ -727,7 +755,7 @@ void vtkSlicerVolumeRenderingLogic::CopyScalarDisplayToVolumeRenderingDisplayNod
727755 threshold[1 ] = vpNode->GetWindowLevelMax ();
728756 }
729757
730- vtkLookupTable * lut = vpNode->GetColorNode () ? vpNode->GetColorNode ()->GetLookupTable () : nullptr ;
758+ vtkScalarsToColors * lut = vpNode->GetColorNode () ? vpNode->GetColorNode ()->GetScalarsToColors () : nullptr ;
731759 vtkVolumeProperty *prop = vspNode->GetVolumePropertyNode ()->GetVolumeProperty ();
732760
733761 int disabledModify = vspNode->StartModify ();
0 commit comments