// Extract slab in specified orientation, if slabThickness is 1, this is identical // to GenerateVtkSlice above, so they should be collapsed at some point. // TODO: Tie into Dicom for slice, will need to adjust thickness at least private vtkImageData GenerateVtkSlab(Matrix resliceAxes, int slabThicknessInVoxels) { VtkHelper.StaticInitializationHack(); // Thickness should be at least 1 if (slabThicknessInVoxels < 1) { slabThicknessInVoxels = 1; } using (vtkImageReslice reslicer = new vtkImageReslice()) { VtkHelper.RegisterVtkErrorEvents(reslicer); // Obtain a pinned VTK volume for the reslicer. We'll release this when // VTK is done reslicing. vtkImageData volumeVtkWrapper = _volume.ObtainPinnedVtkVolume(); reslicer.SetInput(volumeVtkWrapper); reslicer.SetInformationInput(volumeVtkWrapper); if (slabThicknessInVoxels > 1) { reslicer.SetOutputDimensionality(3); } else { reslicer.SetOutputDimensionality(3); } // Use the volume's padding value for all pixels that are outside the volume reslicer.SetBackgroundLevel(_volume.PadValue); // This ensures VTK obeys the real spacing, results in all VTK slices being isotropic. // Effective spacing is the minimum of these three. reslicer.SetOutputSpacing(_volume.Spacing.X, _volume.Spacing.Y, _volume.Spacing.Z); reslicer.SetResliceAxes(VtkHelper.ConvertToVtkMatrix(resliceAxes)); // Clamp the output based on the slice extent int sliceExtentX = GetSliceExtentX(); int sliceExtentY = GetSliceExtentY(); reslicer.SetOutputExtent(0, sliceExtentX - 1, 0, sliceExtentY - 1, 0, slabThicknessInVoxels - 1); // Set the output origin to reflect the slice through point. The slice extent is // centered on the slice through point. // VTK output origin is derived from the center image being 0,0 float originX = -sliceExtentX * EffectiveSpacing / 2; float originY = -sliceExtentY * EffectiveSpacing / 2; reslicer.SetOutputOrigin(originX, originY, 0); switch (_slicing.InterpolationMode) { case InterpolationModes.NearestNeighbor: reslicer.SetInterpolationModeToNearestNeighbor(); break; case InterpolationModes.Linear: reslicer.SetInterpolationModeToLinear(); break; case InterpolationModes.Cubic: reslicer.SetInterpolationModeToCubic(); break; } using (vtkExecutive exec = reslicer.GetExecutive()) { VtkHelper.RegisterVtkErrorEvents(exec); exec.Update(); _volume.ReleasePinnedVtkVolume(); return(reslicer.GetOutput()); } } }
// Extract slice in specified orientation private vtkImageData GenerateVtkSlice(Matrix resliceAxes) { using (vtkImageReslice reslicer = new vtkImageReslice()) { VtkHelper.RegisterVtkErrorEvents(reslicer); // Obtain a pinned VTK volume for the reslicer. We'll release this when // VTK is done reslicing. using (var volume = _volume.Volume.CreateVtkVolumeHandle()) { reslicer.SetInput(volume.vtkImageData); reslicer.SetInformationInput(volume.vtkImageData); // Must instruct reslicer to output 2D images reslicer.SetOutputDimensionality(2); // Use the volume's padding value for all pixels that are outside the volume reslicer.SetBackgroundLevel(_volume.Volume.PaddingValue); // This ensures VTK obeys the real spacing, results in all VTK slices being isotropic. // Effective spacing is the minimum of these three. reslicer.SetOutputSpacing(_volume.Volume.VoxelSpacing.X, _volume.Volume.VoxelSpacing.Y, _volume.Volume.VoxelSpacing.Z); using (vtkMatrix4x4 resliceAxesMatrix = VtkHelper.ConvertToVtkMatrix(resliceAxes)) { reslicer.SetResliceAxes(resliceAxesMatrix); // Clamp the output based on the slice extent int sliceExtentX = GetSliceExtentX(); int sliceExtentY = GetSliceExtentY(); reslicer.SetOutputExtent(0, sliceExtentX - 1, 0, sliceExtentY - 1, 0, 0); // Set the output origin to reflect the slice through point. The slice extent is // centered on the slice through point. // VTK output origin is derived from the center image being 0,0 float originX = -sliceExtentX * EffectiveSpacing / 2; float originY = -sliceExtentY * EffectiveSpacing / 2; reslicer.SetOutputOrigin(originX, originY, 0); switch (_slicerParams.InterpolationMode) { case VolumeSlicerInterpolationMode.NearestNeighbor: reslicer.SetInterpolationModeToNearestNeighbor(); break; case VolumeSlicerInterpolationMode.Linear: reslicer.SetInterpolationModeToLinear(); break; case VolumeSlicerInterpolationMode.Cubic: reslicer.SetInterpolationModeToCubic(); break; } using (vtkExecutive exec = reslicer.GetExecutive()) { VtkHelper.RegisterVtkErrorEvents(exec); exec.Update(); } var output = reslicer.GetOutput(); //Just in case VTK uses the matrix internally. return(output); } } } }