diff --git a/Modules/Core/files.cmake b/Modules/Core/files.cmake index c02fce90e1..6127764eb7 100644 --- a/Modules/Core/files.cmake +++ b/Modules/Core/files.cmake @@ -1,320 +1,321 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkCoreActivator.cpp mitkCoreObjectFactoryBase.cpp mitkCoreObjectFactory.cpp mitkCoreServices.cpp mitkException.cpp Algorithms/mitkBaseDataSource.cpp Algorithms/mitkClippedSurfaceBoundsCalculator.cpp Algorithms/mitkCompareImageDataFilter.cpp Algorithms/mitkCompositePixelValueToString.cpp Algorithms/mitkConvert2Dto3DImageFilter.cpp Algorithms/mitkDataNodeSource.cpp Algorithms/mitkExtractSliceFilter.cpp + Algorithms/mitkExtractSliceFilter2.cpp Algorithms/mitkHistogramGenerator.cpp Algorithms/mitkImageChannelSelector.cpp Algorithms/mitkImageSliceSelector.cpp Algorithms/mitkImageSource.cpp Algorithms/mitkImageTimeSelector.cpp Algorithms/mitkImageToImageFilter.cpp Algorithms/mitkImageToSurfaceFilter.cpp Algorithms/mitkMultiComponentImageDataComparisonFilter.cpp Algorithms/mitkPlaneGeometryDataToSurfaceFilter.cpp Algorithms/mitkPointSetSource.cpp Algorithms/mitkPointSetToPointSetFilter.cpp Algorithms/mitkRGBToRGBACastImageFilter.cpp Algorithms/mitkSubImageSelector.cpp Algorithms/mitkSurfaceSource.cpp Algorithms/mitkSurfaceToImageFilter.cpp Algorithms/mitkSurfaceToSurfaceFilter.cpp Algorithms/mitkUIDGenerator.cpp Algorithms/mitkVolumeCalculator.cpp Controllers/mitkBaseController.cpp Controllers/mitkCallbackFromGUIThread.cpp Controllers/mitkCameraController.cpp Controllers/mitkCameraRotationController.cpp Controllers/mitkLimitedLinearUndo.cpp Controllers/mitkOperationEvent.cpp Controllers/mitkPlanePositionManager.cpp Controllers/mitkProgressBar.cpp Controllers/mitkRenderingManager.cpp Controllers/mitkSliceNavigationController.cpp Controllers/mitkSlicesCoordinator.cpp Controllers/mitkStatusBar.cpp Controllers/mitkStepper.cpp Controllers/mitkTestManager.cpp Controllers/mitkUndoController.cpp Controllers/mitkVerboseLimitedLinearUndo.cpp Controllers/mitkVtkLayerController.cpp DataManagement/mitkAnatomicalStructureColorPresets.cpp DataManagement/mitkArbitraryTimeGeometry.cpp DataManagement/mitkAbstractTransformGeometry.cpp DataManagement/mitkAnnotationProperty.cpp DataManagement/mitkApplicationCursor.cpp DataManagement/mitkApplyTransformMatrixOperation.cpp DataManagement/mitkBaseData.cpp DataManagement/mitkBaseGeometry.cpp DataManagement/mitkBaseProperty.cpp DataManagement/mitkChannelDescriptor.cpp DataManagement/mitkClippingProperty.cpp DataManagement/mitkColorProperty.cpp DataManagement/mitkDataNode.cpp DataManagement/mitkDataStorage.cpp DataManagement/mitkEnumerationProperty.cpp DataManagement/mitkFloatPropertyExtension.cpp DataManagement/mitkGeometry3D.cpp DataManagement/mitkGeometryData.cpp DataManagement/mitkGeometryTransformHolder.cpp DataManagement/mitkGroupTagProperty.cpp DataManagement/mitkIdentifiable.cpp DataManagement/mitkImageAccessorBase.cpp DataManagement/mitkImageCaster.cpp DataManagement/mitkImageCastPart1.cpp DataManagement/mitkImageCastPart2.cpp DataManagement/mitkImageCastPart3.cpp DataManagement/mitkImageCastPart4.cpp DataManagement/mitkImage.cpp DataManagement/mitkImageDataItem.cpp DataManagement/mitkImageDescriptor.cpp DataManagement/mitkImageReadAccessor.cpp DataManagement/mitkImageStatisticsHolder.cpp DataManagement/mitkImageVtkAccessor.cpp DataManagement/mitkImageVtkReadAccessor.cpp DataManagement/mitkImageVtkWriteAccessor.cpp DataManagement/mitkImageWriteAccessor.cpp DataManagement/mitkIntPropertyExtension.cpp DataManagement/mitkIPersistenceService.cpp DataManagement/mitkIPropertyAliases.cpp DataManagement/mitkIPropertyDescriptions.cpp DataManagement/mitkIPropertyExtensions.cpp DataManagement/mitkIPropertyFilters.cpp DataManagement/mitkIPropertyOwner.cpp DataManagement/mitkIPropertyPersistence.cpp DataManagement/mitkIPropertyProvider.cpp DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjector.cpp DataManagement/mitkLevelWindow.cpp DataManagement/mitkLevelWindowManager.cpp DataManagement/mitkLevelWindowPreset.cpp DataManagement/mitkLevelWindowProperty.cpp DataManagement/mitkLine.cpp DataManagement/mitkLookupTable.cpp DataManagement/mitkLookupTableProperty.cpp DataManagement/mitkLookupTables.cpp # specializations of GenericLookupTable DataManagement/mitkMaterial.cpp DataManagement/mitkMemoryUtilities.cpp DataManagement/mitkModalityProperty.cpp DataManagement/mitkModifiedLock.cpp DataManagement/mitkNodePredicateAnd.cpp DataManagement/mitkNodePredicateBase.cpp DataManagement/mitkNodePredicateCompositeBase.cpp DataManagement/mitkNodePredicateData.cpp DataManagement/mitkNodePredicateDataType.cpp DataManagement/mitkNodePredicateDataUID.cpp DataManagement/mitkNodePredicateDimension.cpp DataManagement/mitkNodePredicateFirstLevel.cpp DataManagement/mitkNodePredicateFunction.cpp DataManagement/mitkNodePredicateGeometry.cpp DataManagement/mitkNodePredicateNot.cpp DataManagement/mitkNodePredicateOr.cpp DataManagement/mitkNodePredicateProperty.cpp DataManagement/mitkNodePredicateDataProperty.cpp DataManagement/mitkNodePredicateSource.cpp DataManagement/mitkNodePredicateUID.cpp DataManagement/mitkNumericConstants.cpp DataManagement/mitkPlaneGeometry.cpp DataManagement/mitkPlaneGeometryData.cpp DataManagement/mitkPlaneOperation.cpp DataManagement/mitkPlaneOrientationProperty.cpp DataManagement/mitkPointOperation.cpp DataManagement/mitkPointSet.cpp DataManagement/mitkPointSetShapeProperty.cpp DataManagement/mitkProperties.cpp DataManagement/mitkPropertyAliases.cpp DataManagement/mitkPropertyDescriptions.cpp DataManagement/mitkPropertyExtension.cpp DataManagement/mitkPropertyExtensions.cpp DataManagement/mitkPropertyFilter.cpp DataManagement/mitkPropertyFilters.cpp DataManagement/mitkPropertyKeyPath.cpp DataManagement/mitkPropertyList.cpp DataManagement/mitkPropertyListReplacedObserver.cpp DataManagement/mitkPropertyNameHelper.cpp DataManagement/mitkPropertyObserver.cpp DataManagement/mitkPropertyPersistence.cpp DataManagement/mitkPropertyPersistenceInfo.cpp DataManagement/mitkProportionalTimeGeometry.cpp DataManagement/mitkRenderingModeProperty.cpp DataManagement/mitkResliceMethodProperty.cpp DataManagement/mitkRestorePlanePositionOperation.cpp DataManagement/mitkRotationOperation.cpp DataManagement/mitkScaleOperation.cpp DataManagement/mitkSlicedData.cpp DataManagement/mitkSlicedGeometry3D.cpp DataManagement/mitkSmartPointerProperty.cpp DataManagement/mitkStandaloneDataStorage.cpp DataManagement/mitkStringProperty.cpp DataManagement/mitkSurface.cpp DataManagement/mitkSurfaceOperation.cpp DataManagement/mitkThinPlateSplineCurvedGeometry.cpp DataManagement/mitkTimeGeometry.cpp DataManagement/mitkTransferFunction.cpp DataManagement/mitkTransferFunctionInitializer.cpp DataManagement/mitkTransferFunctionProperty.cpp DataManagement/mitkTemporoSpatialStringProperty.cpp DataManagement/mitkUIDManipulator.cpp DataManagement/mitkVector.cpp DataManagement/mitkVectorProperty.cpp DataManagement/mitkVtkInterpolationProperty.cpp DataManagement/mitkVtkRepresentationProperty.cpp DataManagement/mitkVtkResliceInterpolationProperty.cpp DataManagement/mitkVtkScalarModeProperty.cpp DataManagement/mitkVtkVolumeRenderingProperty.cpp DataManagement/mitkWeakPointerProperty.cpp Interactions/mitkAction.cpp Interactions/mitkBindDispatcherInteractor.cpp Interactions/mitkCrosshairPositionEvent.cpp Interactions/mitkDataInteractor.cpp Interactions/mitkDispatcher.cpp Interactions/mitkDisplayCoordinateOperation.cpp Interactions/mitkDisplayInteractor.cpp Interactions/mitkEventConfig.cpp Interactions/mitkEventFactory.cpp Interactions/mitkEventRecorder.cpp Interactions/mitkEventStateMachine.cpp Interactions/mitkInteractionEventConst.cpp Interactions/mitkInteractionEvent.cpp Interactions/mitkInteractionEventHandler.cpp Interactions/mitkInteractionEventObserver.cpp Interactions/mitkInteractionKeyEvent.cpp Interactions/mitkInteractionPositionEvent.cpp Interactions/mitkInternalEvent.cpp Interactions/mitkMouseDoubleClickEvent.cpp Interactions/mitkMouseModeSwitcher.cpp Interactions/mitkMouseMoveEvent.cpp Interactions/mitkMousePressEvent.cpp Interactions/mitkMouseReleaseEvent.cpp Interactions/mitkMouseWheelEvent.cpp Interactions/mitkPointSetDataInteractor.cpp Interactions/mitkSinglePointDataInteractor.cpp Interactions/mitkStateMachineAction.cpp Interactions/mitkStateMachineCondition.cpp Interactions/mitkStateMachineContainer.cpp Interactions/mitkStateMachineState.cpp Interactions/mitkStateMachineTransition.cpp Interactions/mitkVtkEventAdapter.cpp Interactions/mitkVtkInteractorStyle.cxx Interactions/mitkXML2EventParser.cpp IO/mitkAbstractFileIO.cpp IO/mitkAbstractFileReader.cpp IO/mitkAbstractFileWriter.cpp IO/mitkCustomMimeType.cpp IO/mitkDicomSeriesReader.cpp IO/mitkDicomSeriesReaderService.cpp IO/mitkDicomSR_GantryTiltInformation.cpp IO/mitkDicomSR_ImageBlockDescriptor.cpp IO/mitkDicomSR_LoadDICOMRGBPixel4D.cpp IO/mitkDicomSR_LoadDICOMRGBPixel.cpp IO/mitkDicomSR_LoadDICOMScalar4D.cpp IO/mitkDicomSR_LoadDICOMScalar.cpp IO/mitkDicomSR_SliceGroupingResult.cpp IO/mitkFileReader.cpp IO/mitkFileReaderRegistry.cpp IO/mitkFileReaderSelector.cpp IO/mitkFileReaderWriterBase.cpp IO/mitkFileWriter.cpp IO/mitkFileWriterRegistry.cpp IO/mitkFileWriterSelector.cpp IO/mitkGeometry3DToXML.cpp IO/mitkIFileIO.cpp IO/mitkIFileReader.cpp IO/mitkIFileWriter.cpp IO/mitkGeometryDataReaderService.cpp IO/mitkGeometryDataWriterService.cpp IO/mitkImageGenerator.cpp IO/mitkImageVtkLegacyIO.cpp IO/mitkImageVtkXmlIO.cpp IO/mitkIMimeTypeProvider.cpp IO/mitkIOConstants.cpp IO/mitkIOMimeTypes.cpp IO/mitkIOUtil.cpp IO/mitkItkImageIO.cpp IO/mitkItkLoggingAdapter.cpp IO/mitkLegacyFileReaderService.cpp IO/mitkLegacyFileWriterService.cpp IO/mitkLocaleSwitch.cpp IO/mitkLog.cpp IO/mitkMimeType.cpp IO/mitkMimeTypeProvider.cpp IO/mitkOperation.cpp IO/mitkPixelType.cpp IO/mitkPointSetReaderService.cpp IO/mitkPointSetWriterService.cpp IO/mitkProportionalTimeGeometryToXML.cpp IO/mitkRawImageFileReader.cpp IO/mitkStandardFileLocations.cpp IO/mitkSurfaceStlIO.cpp IO/mitkSurfaceVtkIO.cpp IO/mitkSurfaceVtkLegacyIO.cpp IO/mitkSurfaceVtkXmlIO.cpp IO/mitkVtkLoggingAdapter.cpp IO/mitkPreferenceListReaderOptionsFunctor.cpp Rendering/mitkAbstractAnnotationRenderer.cpp Rendering/mitkAnnotationUtils.cpp Rendering/mitkBaseRenderer.cpp #Rendering/mitkGLMapper.cpp Moved to deprecated LegacyGL Module Rendering/mitkGradientBackground.cpp Rendering/mitkImageVtkMapper2D.cpp Rendering/mitkMapper.cpp Rendering/mitkAnnotation.cpp Rendering/mitkPlaneGeometryDataMapper2D.cpp Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp Rendering/mitkPointSetVtkMapper2D.cpp Rendering/mitkPointSetVtkMapper3D.cpp Rendering/mitkRenderWindowBase.cpp Rendering/mitkRenderWindow.cpp Rendering/mitkRenderWindowFrame.cpp #Rendering/mitkSurfaceGLMapper2D.cpp Moved to deprecated LegacyGL Module Rendering/mitkSurfaceVtkMapper2D.cpp Rendering/mitkSurfaceVtkMapper3D.cpp Rendering/mitkVtkEventProvider.cpp Rendering/mitkVtkMapper.cpp Rendering/mitkVtkPropRenderer.cpp Rendering/mitkVtkWidgetRendering.cpp Rendering/vtkMitkLevelWindowFilter.cpp Rendering/vtkMitkRectangleProp.cpp Rendering/vtkMitkRenderProp.cpp Rendering/vtkMitkThickSlicesFilter.cpp Rendering/vtkNeverTranslucentTexture.cpp ) set(RESOURCE_FILES Interactions/globalConfig.xml Interactions/DisplayInteraction.xml Interactions/DisplayConfig.xml Interactions/DisplayConfigPACS.xml Interactions/DisplayConfigPACSPan.xml Interactions/DisplayConfigPACSScroll.xml Interactions/DisplayConfigPACSZoom.xml Interactions/DisplayConfigPACSLevelWindow.xml Interactions/DisplayConfigMITK.xml Interactions/DisplayConfigMITKNoCrosshair.xml Interactions/DisplayConfigMITKRotation.xml Interactions/DisplayConfigMITKRotationUnCoupled.xml Interactions/DisplayConfigMITKSwivel.xml Interactions/DisplayConfigMITKLimited.xml Interactions/PointSet.xml Interactions/Legacy/StateMachine.xml Interactions/Legacy/DisplayConfigMITKTools.xml Interactions/PointSetConfig.xml mitkLevelWindowPresets.xml mitkAnatomicalStructureColorPresets.xml ) diff --git a/Modules/Core/include/mitkExtractSliceFilter2.h b/Modules/Core/include/mitkExtractSliceFilter2.h new file mode 100644 index 0000000000..161e8459e5 --- /dev/null +++ b/Modules/Core/include/mitkExtractSliceFilter2.h @@ -0,0 +1,82 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef mitkExtractSliceFilter2_h +#define mitkExtractSliceFilter2_h + +#include +#include +#include + +namespace mitk +{ + /** \brief Extract an arbitrarily oriented 2-d image from a 3-d image. + * + * Use ExtractSliceFilter2::SetOutputGeometry to specify the orientation of + * the 2-d output image. + * + * If a pixel of the 2-d output image isn't located within the bounds of the + * 3-d input image, it is set to the lowest possible pixel value. + * + * Cubic interpolation is considerably slow on the first update for a newly + * set input image. Subsequent filter updates with cubic interpolation are + * faster by several orders of magnitude as long as the input image was + * neither changed nor modified. + * + * This filter is completely based on ITK compared to the VTK-based + * mitk::ExtractSliceFilter. It is more robust, easy to use, and produces + * an mitk::Image with valid geometry. Generally it is not as fast as + * mitk::ExtractSliceFilter, though. + */ + class MITKCORE_EXPORT ExtractSliceFilter2 final : public ImageToImageFilter + { + public: + enum Interpolator + { + NearestNeighbor, + Linear, + Cubic + }; + + mitkClassMacro(ExtractSliceFilter2, ImageToImageFilter) + itkFactorylessNewMacro(Self) + + void SetInput(const InputImageType* image) override; + void SetInput(unsigned int index, const InputImageType* image) override; + + const PlaneGeometry* GetOutputGeometry() const; + void SetOutputGeometry(PlaneGeometry::Pointer outputGeometry); + + Interpolator GetInterpolator() const; + void SetInterpolator(Interpolator interpolator); + + private: + using Superclass::SetInput; + + ExtractSliceFilter2(); + ~ExtractSliceFilter2() override; + + void AllocateOutputs() override; + void BeforeThreadedGenerateData() override; + void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) override; + void VerifyInputInformation() override; + + struct Impl; + Impl* m_Impl; + }; +} + +#endif diff --git a/Modules/Core/include/mitkImageToItk.txx b/Modules/Core/include/mitkImageToItk.txx index c99f9dc6a0..3b2b49d897 100644 --- a/Modules/Core/include/mitkImageToItk.txx +++ b/Modules/Core/include/mitkImageToItk.txx @@ -1,294 +1,294 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef IMAGETOITK_TXX_INCLUDED_C1C2FCD2 #define IMAGETOITK_TXX_INCLUDED_C1C2FCD2 #include "itkImportMitkImageContainer.h" #include "mitkBaseProcess.h" #include "mitkException.h" #include "mitkImageReadAccessor.h" #include "mitkImageToItk.h" #include "mitkImageWriteAccessor.h" +#include + template struct SetLengthHelper { SetLengthHelper(TImageType *in) { m_Image = in; } private: TImageType *m_Image; }; template struct SetLengthHelper> { typedef itk::Image TImageType; SetLengthHelper(TImageType *in) { m_Image = in; } void SetVectorLength(size_t) {} private: TImageType *m_Image; }; template struct SetLengthHelper> { typedef itk::VectorImage TImageType; SetLengthHelper(TImageType *in) { m_Image = in; } void SetVectorLength(size_t len) { m_Image->SetVectorLength(len); } private: TImageType *m_Image; }; template void mitk::ImageToItk::SetInput(mitk::Image *input) { this->SetInput(static_cast(input)); m_ConstInput = false; } template void mitk::ImageToItk::SetInput(const mitk::Image *input) { this->CheckInput(input); // Process object is not const-correct so the const_cast is required here itk::ProcessObject::PushFrontInput(input); m_ConstInput = true; } template mitk::Image *mitk::ImageToItk::GetInput(void) { if (this->GetNumberOfInputs() < 1) { return nullptr; } return static_cast(itk::ProcessObject::GetInput(0)); } template const mitk::Image *mitk::ImageToItk::GetInput() const { if (this->GetNumberOfInputs() < 1) { return nullptr; } return static_cast(itk::ProcessObject::GetInput(0)); } template void mitk::ImageToItk::GenerateData() { // Allocate output mitk::Image::Pointer input = this->GetInput(); typename Superclass::OutputImageType::Pointer output = this->GetOutput(); unsigned long noBytes = input->GetDimension(0); for (unsigned int i = 1; i < TOutputImage::GetImageDimension(); ++i) { noBytes = noBytes * input->GetDimension(i); } const mitk::PixelType pixelType = input->GetPixelType(); if (pixelType.GetPixelType() == itk::ImageIOBase::VECTOR) { noBytes *= pixelType.GetNumberOfComponents(); SetLengthHelper helper(output.GetPointer()); helper.SetVectorLength(pixelType.GetNumberOfComponents()); } - mitk::ImageAccessorBase *imageAccess; + std::unique_ptr imageAccess; if (m_ConstInput) { - imageAccess = new mitk::ImageReadAccessor(input, static_cast(nullptr), m_Options); + imageAccess.reset(new mitk::ImageReadAccessor(input, nullptr, m_Options)); } else { - imageAccess = new mitk::ImageWriteAccessor(input, static_cast(nullptr), m_Options); + imageAccess.reset(new mitk::ImageWriteAccessor(input, nullptr, m_Options)); } // hier wird momentan wohl nur der erste Channel verwendet??!! if (imageAccess->GetData() == nullptr) { itkWarningMacro(<< "no image data to import in ITK image"); RegionType bufferedRegion; output->SetBufferedRegion(bufferedRegion); return; } if (m_CopyMemFlag) { itkDebugMacro("copyMem ..."); output->Allocate(); memcpy(output->GetBufferPointer(), imageAccess->GetData(), sizeof(InternalPixelType) * noBytes); - - delete imageAccess; } else { itkDebugMacro("do not copyMem ..."); typedef itk::ImportMitkImageContainer ImportContainerType; typename ImportContainerType::Pointer import; import = ImportContainerType::New(); import->Initialize(); itkDebugMacro(<< "size of container = " << import->Size()); // import->SetImageDataItem(m_ImageDataItem); - import->SetImageAccessor(imageAccess, sizeof(InternalPixelType) * noBytes); + import->SetImageAccessor(imageAccess.release(), sizeof(InternalPixelType) * noBytes); output->SetPixelContainer(import); itkDebugMacro(<< "size of container = " << import->Size()); } } template void mitk::ImageToItk::UpdateOutputInformation() { mitk::Image::Pointer input = this->GetInput(); if (input.IsNotNull() && (input->GetSource().IsNotNull()) && input->GetSource()->Updating()) { typename Superclass::OutputImageType::Pointer output = this->GetOutput(); unsigned long t1 = input->GetUpdateMTime() + 1; if (t1 > this->m_OutputInformationMTime.GetMTime()) { output->SetPipelineMTime(t1); this->GenerateOutputInformation(); this->m_OutputInformationMTime.Modified(); } return; } Superclass::UpdateOutputInformation(); } template void mitk::ImageToItk::GenerateOutputInformation() { mitk::Image::ConstPointer input = this->GetInput(); typename Superclass::OutputImageType::Pointer output = this->GetOutput(); // allocate size, origin, spacing, direction in types of output image SizeType size; const unsigned int itkDimMin3 = (TOutputImage::ImageDimension > 3 ? TOutputImage::ImageDimension : 3); const unsigned int itkDimMax3 = (TOutputImage::ImageDimension < 3 ? TOutputImage::ImageDimension : 3); typename Superclass::OutputImageType::PointType::ValueType origin[itkDimMin3]; typename Superclass::OutputImageType::SpacingType::ComponentType spacing[itkDimMin3]; typename Superclass::OutputImageType::DirectionType direction; // copy as much information as possible into size and spacing unsigned int i; for (i = 0; i < itkDimMax3; ++i) { size[i] = input->GetDimension(i); spacing[i] = input->GetGeometry()->GetSpacing()[i]; } for (; i < TOutputImage::ImageDimension; ++i) { origin[i] = 0.0; size[i] = input->GetDimension(i); spacing[i] = 1.0; } // build region from size IndexType start; start.Fill(0); RegionType region; region.SetIndex(start); region.SetSize(size); // copy as much information as possible into origin const mitk::Point3D &mitkorigin = input->GetGeometry()->GetOrigin(); itk2vtk(mitkorigin, origin); // copy as much information as possible into direction direction.SetIdentity(); unsigned int j; const AffineTransform3D::MatrixType &matrix = input->GetGeometry()->GetIndexToWorldTransform()->GetMatrix(); /// \warning 2D MITK images could have a 3D rotation, since they have a 3x3 geometry matrix. /// If it is only a rotation around the axial plane normal, it can be express with a 2x2 matrix. /// In this case, the ITK image conservs this information and is identical to the MITK image! /// If the MITK image contains any other rotation, the ITK image will have no rotation at all. /// Spacing is of course conserved in both cases. // the following loop devides by spacing now to normalize columns. // counterpart of InitializeByItk in mitkImage.h line 372 of revision 15092. // Check if information is lost if (TOutputImage::ImageDimension <= 2) { if ((TOutputImage::ImageDimension == 2) && ((matrix[0][2] != 0) || (matrix[1][2] != 0) || (matrix[2][0] != 0) || (matrix[2][1] != 0) || ((matrix[2][2] != 1) && (matrix[2][2] != -1)))) { // The 2D MITK image contains 3D rotation information. // This cannot be expressed in a 2D ITK image, so the ITK image will have no rotation } else { // The 2D MITK image can be converted to an 2D ITK image without information loss! for (i = 0; i < itkDimMax3; ++i) for (j = 0; j < itkDimMax3; ++j) direction[i][j] = matrix[i][j] / spacing[j]; } } else { // Normal 3D image. Conversion possible without problem! for (i = 0; i < itkDimMax3; ++i) for (j = 0; j < itkDimMax3; ++j) direction[i][j] = matrix[i][j] / spacing[j]; } // set information into output image output->SetRegions(region); output->SetOrigin(origin); output->SetSpacing(spacing); output->SetDirection(direction); } template void mitk::ImageToItk::CheckInput(const mitk::Image *input) const { if (input == nullptr) { itkExceptionMacro(<< "image is null"); } if (input->GetDimension() != TOutputImage::GetImageDimension()) { itkExceptionMacro(<< "image has dimension " << input->GetDimension() << " instead of " << TOutputImage::GetImageDimension()); } if (!(input->GetPixelType() == mitk::MakePixelType(input->GetPixelType().GetNumberOfComponents()))) { itkExceptionMacro(<< "image has wrong pixel type "); } } template void mitk::ImageToItk::PrintSelf(std::ostream &os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); } #endif // IMAGETOITK_TXX_INCLUDED_C1C2FCD2 diff --git a/Modules/Core/src/Algorithms/mitkExtractSliceFilter2.cpp b/Modules/Core/src/Algorithms/mitkExtractSliceFilter2.cpp new file mode 100644 index 0000000000..261c5d5e61 --- /dev/null +++ b/Modules/Core/src/Algorithms/mitkExtractSliceFilter2.cpp @@ -0,0 +1,278 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +struct mitk::ExtractSliceFilter2::Impl +{ + Impl(); + ~Impl(); + + mitk::Image* OutputImage; + PlaneGeometry::Pointer OutputGeometry; + mitk::ExtractSliceFilter2::Interpolator Interpolator; + itk::Object::Pointer InterpolateImageFunction; +}; + +mitk::ExtractSliceFilter2::Impl::Impl() + : OutputImage(nullptr), + Interpolator(NearestNeighbor) +{ +} + +mitk::ExtractSliceFilter2::Impl::~Impl() +{ +} + +namespace +{ + template + void CreateInterpolateImageFunction(const TInputImage* inputImage, mitk::ExtractSliceFilter2::Impl* impl) + { + typename itk::InterpolateImageFunction::Pointer interpolateImageFunction; + + switch (impl->Interpolator) + { + case mitk::ExtractSliceFilter2::NearestNeighbor: + interpolateImageFunction = itk::NearestNeighborInterpolateImageFunction::New().GetPointer(); + break; + + case mitk::ExtractSliceFilter2::Linear: + interpolateImageFunction = itk::LinearInterpolateImageFunction::New().GetPointer(); + break; + + case mitk::ExtractSliceFilter2::Cubic: + { + auto bSplineInterpolateImageFunction = itk::BSplineInterpolateImageFunction::New(); + bSplineInterpolateImageFunction->SetSplineOrder(2); + interpolateImageFunction = bSplineInterpolateImageFunction.GetPointer(); + break; + } + + default: + mitkThrow() << "Interplator is unknown."; + } + + interpolateImageFunction->SetInputImage(inputImage); + + impl->InterpolateImageFunction = interpolateImageFunction.GetPointer(); + } + + template + void GenerateData(const itk::Image* inputImage, const mitk::ExtractSliceFilter2::Impl* impl, const mitk::ExtractSliceFilter2::OutputImageRegionType& outputRegion) + { + typedef itk::Image TInputImage; + typedef itk::InterpolateImageFunction TInterpolateImageFunction; + + auto outputImage = impl->OutputImage; + auto outputGeometry = impl->OutputGeometry; + auto interpolateImageFunction = static_cast(impl->InterpolateImageFunction.GetPointer()); + + auto origin = outputGeometry->GetOrigin(); + auto spacing = outputGeometry->GetSpacing(); + auto xDirection = outputGeometry->GetAxisVector(0); + auto yDirection = outputGeometry->GetAxisVector(1); + + xDirection.Normalize(); + yDirection.Normalize(); + + auto spacingAlongXDirection = xDirection * spacing[0]; + auto spacingAlongYDirection = yDirection * spacing[1]; + + origin -= spacingAlongXDirection * 0.5; + origin -= spacingAlongYDirection * 0.5; + + const std::size_t pixelSize = outputImage->GetPixelType().GetSize(); + const std::size_t height = outputGeometry->GetExtent(1); + const std::size_t xBegin = outputRegion.GetIndex(0); + const std::size_t yBegin = outputRegion.GetIndex(1); + const std::size_t xEnd = xBegin + outputRegion.GetSize(0); + const std::size_t yEnd = yBegin + outputRegion.GetSize(1); + + mitk::ImageWriteAccessor writeAccess(outputImage, nullptr, mitk::ImageAccessorBase::IgnoreLock); + auto data = static_cast(writeAccess.GetData());; + + const TPixel backgroundPixel = std::numeric_limits::lowest(); + TPixel pixel; + + itk::ContinuousIndex index; + mitk::Point3D yPoint; + mitk::Point3D point; + + for (std::size_t y = yBegin; y < yEnd; ++y) + { + yPoint = origin + spacingAlongYDirection * y; + + for (std::size_t x = xBegin; x < xEnd; ++x) + { + point = yPoint + spacingAlongXDirection * x; + + if (inputImage->TransformPhysicalPointToContinuousIndex(point, index)) + { + pixel = interpolateImageFunction->EvaluateAtContinuousIndex(index); + memcpy(static_cast(data + pixelSize * (height * y + x)), static_cast(&pixel), pixelSize); + } + else + { + memcpy(static_cast(data + pixelSize * (height * y + x)), static_cast(&backgroundPixel), pixelSize); + } + } + } + } + + void VerifyInputImage(const mitk::Image* inputImage) + { + auto dimension = inputImage->GetDimension(); + + if (3 != dimension) + mitkThrow() << "Input images with " << dimension << " dimensions are not supported."; + + if (!inputImage->IsInitialized()) + mitkThrow() << "Input image is not initialized."; + + if (!inputImage->IsVolumeSet()) + mitkThrow() << "Input image volume is not set."; + + auto geometry = inputImage->GetGeometry(); + + if (nullptr == geometry || !geometry->IsValid()) + mitkThrow() << "Input image has invalid geometry."; + + if (!geometry->GetImageGeometry()) + mitkThrow() << "Geometry of input image is not an image geometry."; + } + + void VerifyOutputGeometry(const mitk::PlaneGeometry* outputGeometry) + { + if (nullptr == outputGeometry) + mitkThrow() << "Output geometry is not set."; + + if (!outputGeometry->GetImageGeometry()) + mitkThrow() << "Output geometry is not an image geometry."; + } +} + +mitk::ExtractSliceFilter2::ExtractSliceFilter2() + : m_Impl(new Impl) +{ +} + +mitk::ExtractSliceFilter2::~ExtractSliceFilter2() +{ + delete m_Impl; +} + +void mitk::ExtractSliceFilter2::AllocateOutputs() +{ + const auto* inputImage = this->GetInput(); + const auto* outputGeometry = this->GetOutputGeometry(); + auto outputImage = this->GetOutput(); + auto pixelType = inputImage->GetPixelType(); + + outputImage->Initialize(pixelType, 1, *outputGeometry); + + auto data = new char[static_cast(pixelType.GetSize() * outputGeometry->GetExtent(0) * outputGeometry->GetExtent(1))]; + + try + { + if (!outputImage->SetImportVolume(data, 0, 0, mitk::Image::ReferenceMemory)) + throw; + } + catch (...) + { + delete[] data; + } +} + +void mitk::ExtractSliceFilter2::BeforeThreadedGenerateData() +{ + if (nullptr != m_Impl->InterpolateImageFunction && this->GetInput()->GetMTime() < this->GetMTime()) + return; + + const auto* inputImage = this->GetInput(); + AccessFixedDimensionByItk_1(inputImage, CreateInterpolateImageFunction, 3, m_Impl); +} + +void mitk::ExtractSliceFilter2::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType) +{ + m_Impl->OutputImage = this->GetOutput(); + + const auto* inputImage = this->GetInput(); + AccessFixedDimensionByItk_2(inputImage, ::GenerateData, 3, m_Impl, outputRegionForThread); +} + +void mitk::ExtractSliceFilter2::SetInput(const InputImageType* image) +{ + if (this->GetInput() == image) + return; + + Superclass::SetInput(image); + m_Impl->InterpolateImageFunction = nullptr; +} + +void mitk::ExtractSliceFilter2::SetInput(unsigned int index, const InputImageType* image) +{ + if (0 != index) + mitkThrow() << "Input index " << index << " is invalid."; + + this->SetInput(image); +} + +const mitk::PlaneGeometry* mitk::ExtractSliceFilter2::GetOutputGeometry() const +{ + return m_Impl->OutputGeometry; +} + +void mitk::ExtractSliceFilter2::SetOutputGeometry(PlaneGeometry::Pointer outputGeometry) +{ + if (m_Impl->OutputGeometry != outputGeometry) + { + m_Impl->OutputGeometry = outputGeometry; + this->Modified(); + } +} + +mitk::ExtractSliceFilter2::Interpolator mitk::ExtractSliceFilter2::GetInterpolator() const +{ + return m_Impl->Interpolator; +} + +void mitk::ExtractSliceFilter2::SetInterpolator(Interpolator interpolator) +{ + if (m_Impl->Interpolator != interpolator) + { + m_Impl->Interpolator = interpolator; + m_Impl->InterpolateImageFunction = nullptr; + this->Modified(); + } +} + +void mitk::ExtractSliceFilter2::VerifyInputInformation() +{ + Superclass::VerifyInputInformation(); + + VerifyInputImage(this->GetInput()); + VerifyOutputGeometry(m_Impl->OutputGeometry.GetPointer()); +} diff --git a/Modules/Core/src/DataManagement/mitkImageWriteAccessor.cpp b/Modules/Core/src/DataManagement/mitkImageWriteAccessor.cpp index dcd2908507..ffc9a0215d 100644 --- a/Modules/Core/src/DataManagement/mitkImageWriteAccessor.cpp +++ b/Modules/Core/src/DataManagement/mitkImageWriteAccessor.cpp @@ -1,151 +1,151 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkImageWriteAccessor.h" mitk::ImageWriteAccessor::ImageWriteAccessor(ImagePointer image, const mitk::ImageDataItem *iDI, int OptionFlags) : ImageAccessorBase(image.GetPointer(), iDI, OptionFlags), m_Image(image) { OrganizeWriteAccess(); } mitk::ImageWriteAccessor::~ImageWriteAccessor() { // In case of non-coherent memory, copied area needs to be written back // TODO m_Image->m_ReadWriteLock.Lock(); // delete self from list of ImageReadAccessors in Image auto it = std::find(m_Image->m_Writers.begin(), m_Image->m_Writers.end(), this); m_Image->m_Writers.erase(it); // delete lock, if there are no waiting ImageAccessors if (m_WaitLock->m_WaiterCount <= 0) { m_WaitLock->m_Mutex.Unlock(); delete m_WaitLock; } else { m_WaitLock->m_Mutex.Unlock(); } m_Image->m_ReadWriteLock.Unlock(); } const mitk::Image *mitk::ImageWriteAccessor::GetImage() const { return m_Image.GetPointer(); } void mitk::ImageWriteAccessor::OrganizeWriteAccess() { m_Image->m_ReadWriteLock.Lock(); bool readOverlap = false; bool writeOverlap = false; ImageAccessorWaitLock *overlapLock = nullptr; // Check, if there is any Read-Access going on if (m_Image->m_Readers.size() > 0) { // Check for every ReadAccessor, if the Region of this ImageAccessors overlaps // make sure this iterator is not used, when m_ReadWriteLock is Unlocked! auto it = m_Image->m_Readers.begin(); for (; it != m_Image->m_Readers.end(); ++it) { ImageAccessorBase *r = *it; if ((r->m_Options & IgnoreLock) == 0 && Overlap(r)) { // An Overlap was detected. PreventRecursiveMutexLock(r); readOverlap = true; overlapLock = r->m_WaitLock; break; } // if } // for } // if // Check, if there is any Write-Access going on if (m_Image->m_Writers.size() > 0) { // Check for every WriteAccessor, if the Region of this ImageAccessors overlaps // make sure this iterator is not used, when m_ReadWriteLock is Unlocked! auto it = m_Image->m_Writers.begin(); for (; it != m_Image->m_Writers.end(); ++it) { ImageAccessorBase *w = *it; - if (Overlap(w)) + if ((w->m_Options & IgnoreLock) == 0 && Overlap(w)) { // An Overlap was detected. PreventRecursiveMutexLock(w); // save overlapping Waitlock writeOverlap = true; overlapLock = w->m_WaitLock; break; } // if } // for } // if if (readOverlap || writeOverlap) { // Throw an exception or wait for the WriteAccessor w until it is released and start again with the request // afterwards. if (!(m_Options & ExceptionIfLocked)) { // WAIT overlapLock->m_WaiterCount += 1; m_Image->m_ReadWriteLock.Unlock(); ImageAccessorBase::WaitForReleaseOf(overlapLock); // after waiting for the ImageAccessor, start this method again OrganizeWriteAccess(); return; } else { // THROW EXCEPTION m_Image->m_ReadWriteLock.Unlock(); mitkThrowException(mitk::MemoryIsLockedException) << "The image part being ordered by the ImageAccessor is already in use and locked"; // MITK_ERROR("Speicherbereich belegt"); return; } } // Now, we know, that there is no conflict with a Read- or Write-Access // Lock the Mutex in ImageAccessorBase, to make sure that every other ImageAccessor has to wait m_WaitLock->m_Mutex.Lock(); // insert self into Writers list in Image m_Image->m_Writers.push_back(this); // printf("WriteAccess %d %d\n",(int) m_Image->m_Readers.size(),(int) m_Image->m_Writers.size()); // fflush(0); m_Image->m_ReadWriteLock.Unlock(); }