diff --git a/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.cpp b/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.cpp index 397fdd10a4..0ef5827bff 100644 --- a/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.cpp +++ b/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.cpp @@ -1,490 +1,491 @@ /*=================================================================== 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 "mitkOverwriteDirectedPlaneImageFilter.h" #include "mitkImageCast.h" #include "mitkImageAccessByItk.h" #include "mitkSegmentationInterpolationController.h" #include "mitkApplyDiffImageOperation.h" #include "mitkOperationEvent.h" #include "mitkInteractionConst.h" #include "mitkUndoController.h" #include "mitkDiffImageApplier.h" #include "mitkImageTimeSelector.h" #include #include mitk::OverwriteDirectedPlaneImageFilter::OverwriteDirectedPlaneImageFilter() :m_PlaneGeometry(0), m_ImageGeometry3D(0), m_TimeStep(0), m_Dimension0(0), m_Dimension1(1), m_CreateUndoInformation(false) { + MITK_WARN << "Class is deprecated! Use mitkVtkImageOverwrite instead."; } mitk::OverwriteDirectedPlaneImageFilter::~OverwriteDirectedPlaneImageFilter() { } void mitk::OverwriteDirectedPlaneImageFilter::GenerateData() { // // this is the place to implement the major part of undo functionality (bug #491) // here we have to create undo/do operations // // WHO is the operation actor? This object may not be destroyed ever (design of undo stack)! // -> some singleton method of this filter? // // neccessary additional objects: // - something that executes the operations // - the operation class (must hold a binary diff or something) // - observer commands to know when the image is deleted (no further action then, perhaps even remove the operations from the undo stack) // //Image::ConstPointer input = ImageToImageFilter::GetInput(0); Image::ConstPointer input3D = ImageToImageFilter::GetInput(0); //Image::ConstPointer slice = m_SliceImage; if ( input3D.IsNull() || m_SliceImage.IsNull() ) return; if ( input3D->GetDimension() == 4 ) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( input3D ); timeSelector->SetTimeNr( m_TimeStep ); timeSelector->UpdateLargestPossibleRegion(); input3D = timeSelector->GetOutput(); } m_ImageGeometry3D = input3D->GetGeometry(); /* if ( m_SliceDifferenceImage.IsNull() || m_SliceDifferenceImage->GetDimension(0) != m_SliceImage->GetDimension(0) || m_SliceDifferenceImage->GetDimension(1) != m_SliceImage->GetDimension(1) ) { m_SliceDifferenceImage = mitk::Image::New(); mitk::PixelType pixelType( typeid(short signed int) ); m_SliceDifferenceImage->Initialize( pixelType, 2, m_SliceImage->GetDimensions() ); } */ //MITK_INFO << "Overwriting slice " << m_SliceIndex << " in dimension " << m_SliceDimension << " at time step " << m_TimeStep << std::endl; // this will do a long long if/else to find out both pixel types /*AccessFixedDimensionByItk( input3D, ItkImageSwitch, 3 );*/ AccessFixedDimensionByItk( input3D, ItkSliceOverwriting, 3 ); //SegmentationInterpolationController* interpolator = SegmentationInterpolationController::InterpolatorForImage( input3D ); //if (interpolator) //{ // interpolator->BlockModified(true); // //interpolator->SetChangedSlice( m_SliceDifferenceImage, m_SliceDimension, m_SliceIndex, m_TimeStep ); //} /* if ( m_CreateUndoInformation ) { // create do/undo operations (we don't execute the doOp here, because it has already been executed during calculation of the diff image ApplyDiffImageOperation* doOp = new ApplyDiffImageOperation( OpTEST, const_cast(input.GetPointer()), m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex ); ApplyDiffImageOperation* undoOp = new ApplyDiffImageOperation( OpTEST, const_cast(input.GetPointer()), m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex ); undoOp->SetFactor( -1.0 ); OperationEvent* undoStackItem = new OperationEvent( DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, this->EventDescription(m_SliceDimension, m_SliceIndex, m_TimeStep) ); UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem ); } */ // this image is modified (good to know for the renderer) input3D->Modified(); /*if (interpolator) { interpolator->BlockModified(false); }*/ } template void mitk::OverwriteDirectedPlaneImageFilter::ItkSliceOverwriting( itk::Image* input3D ) { typedef itk::Image SliceImageType; typedef itk::Image VolumeImageType; typedef itk::ImageSliceIteratorWithIndex< VolumeImageType > OutputSliceIteratorType; typedef itk::ImageRegionConstIterator< SliceImageType > SliceIteratorType; typename SliceImageType::Pointer sliceImage = SliceImageType::New(); CastToItkImage(m_SliceImage,sliceImage); SliceIteratorType sliceIterator( sliceImage, sliceImage->GetLargestPossibleRegion() ); sliceIterator.GoToBegin(); Point3D currentPointIn2D; Point3D worldPointIn3D; //Here we just iterate over the slice which must be written into the 3D volumen and set the corresponding pixel in our 3D volume while ( !sliceIterator.IsAtEnd() ) { currentPointIn2D[0] = sliceIterator.GetIndex()[0]+0.5; currentPointIn2D[1] = sliceIterator.GetIndex()[1]+0.5; currentPointIn2D[2] = 0; m_PlaneGeometry->IndexToWorld( currentPointIn2D, worldPointIn3D ); typename itk::Image::IndexType outputIndex; m_ImageGeometry3D->WorldToIndex( worldPointIn3D, outputIndex ); // Only access ITK image if it's inside if ( m_ImageGeometry3D->IsIndexInside( outputIndex ) ) { input3D->SetPixel( outputIndex, (TPixel)sliceIterator.Get() ); } ++sliceIterator; } } /****TEST***/ //Maybe a bit more efficient but doesn`t already work. See also ExtractCirectedPlaneImageFilter //typename itk::Image::IndexType outputIndex; //if ( columns == extent[0] ) //{ ////If we are at the end of a row, then we have to go to the beginning of the next row //currentImagePointIn3D = origin; //currentImagePointIn3D += spacing[1]*bottom*currentPointIn2D[1]; //columns = 0; //m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); //} //else //{ //if ( columns != 0 ) //{ //currentImagePointIn3D += spacing[0]*right; //} //m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); //} //if ( m_ImageGeometry3D->IsIndexInside( outputIndex )) //{ //outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() ); //} //else if (currentImagePointIn3D == origin) //{ //Point3D temp; //temp[0] = bottom[0]*spacing[0]*0.5; //temp[1] = bottom[1]*spacing[1]*0.5; //temp[2] = bottom[2]*spacing[2]*0.5; //origin[0] += temp[0]; //origin[1] += temp[1]; //origin[2] += temp[2]; //currentImagePointIn3D = origin; //m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); //if ( m_ImageGeometry3D->IsIndexInside( outputIndex )) //{ //outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() ); //} //} //columns++; /****TEST ENDE****/ //* // // Offset the world coordinate by one pixel to compensate for // // index/world origin differences. // Point3D offsetIndex; // offsetIndex.Fill( 1 ); // Point3D offsetWorld; // offsetWorld.Fill( 0 ); // m_PlaneGeometry->IndexToWorld( offsetIndex, offsetWorld ); // // remove origin shift // const Point3D origin = m_PlaneGeometry->GetOrigin(); // offsetWorld[0] -= origin[0]; // offsetWorld[1] -= origin[1]; // offsetWorld[2] -= origin[2]; // // offset world coordinate // worldPointIn3D[ 0 ] += offsetWorld[0]; // worldPointIn3D[ 1 ] += offsetWorld[1]; // worldPointIn3D[ 2 ] += offsetWorld[2]; //*/ // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h /*#define myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \ // if ( typeId == typeid(pixeltype) ) \ //{ \ // typedef itk::Image ImageType; \ // typedef mitk::ImageToItk ImageToItkType; \ // itk::SmartPointer imagetoitk = ImageToItkType::New(); \ // imagetoitk->SetInput(mitkImage); \ // imagetoitk->Update(); \ // itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \ //} // //#define myMITKOverwriteDirectedPlaneImageFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \ //{ \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, float, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned int, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, char, dimension, itkimage2) else \ // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned char, dimension, itkimage2) \ //}*/ // // //template //void mitk::OverwriteDirectedPlaneImageFilter::ItkImageSwitch( itk::Image* itkImage ) //{ // const std::type_info& typeId=*(m_SliceImage->GetPixelType().GetTypeId()); // // myMITKOverwriteDirectedPlaneImageFilterAccessAllTypesByItk( m_SliceImage, ItkImageProcessing, 2, itkImage ); //} //template //void mitk::OverwriteDirectedPlaneImageFilter::ItkImageProcessing( itk::Image* inputImage, itk::Image* outputImage ) //{ // typedef itk::Image SliceImageType; // typedef itk::Image DiffImageType; // typedef itk::Image VolumeImageType; // // typedef itk::ImageSliceIteratorWithIndex< VolumeImageType > OutputSliceIteratorType; // typedef itk::ImageRegionConstIterator< SliceImageType > InputSliceIteratorType; // //typedef itk::ImageRegionIterator< DiffImageType > DiffSliceIteratorType; // // InputSliceIteratorType inputIterator( inputImage, inputImage->GetLargestPossibleRegion() ); // // //typename DiffImageType::Pointer diffImage; // //CastToItkImage( m_SliceDifferenceImage, diffImage ); // //DiffSliceIteratorType diffIterator( diffImage, diffImage->GetLargestPossibleRegion() ); // // inputIterator.GoToBegin(); // //diffIterator.GoToBegin(); // // //TEST // Point3D origin = m_PlaneGeometry->GetOrigin(); // Vector3D right = m_PlaneGeometry->GetAxisVector(0); // Vector3D bottom = m_PlaneGeometry->GetAxisVector(1); // right.Normalize(); // bottom.Normalize(); // // Vector2D spacing = inputImage->GetSpacing(); // // Vector2D extentInMM; // extentInMM[0] = m_PlaneGeometry->GetExtentInMM(0); // extentInMM[1] = m_PlaneGeometry->GetExtentInMM(1); // // Vector2D extent; // extent[0] = m_PlaneGeometry->GetExtent(0); // extent[1] = m_PlaneGeometry->GetExtent(1); // //TEST ENDE // // Point3D currentPointIn2D, worldPointIn3D; // TPixel2 outputPixel = 0; // // int debugCounter( 0 ); // // std::ofstream geometryFile; // geometryFile.precision(30); // geometryFile.open("C:/Users/fetzer/Desktop/TEST/geometryFileOv.txt"); // // geometryFile<<"Offset: [ "<GetIndexToWorldTransform()->GetOffset()[0]<<", "<GetIndexToWorldTransform()->GetOffset()[1]<<", "<GetIndexToWorldTransform()->GetOffset()[2]<<" ]"<GetIndexToWorldTransform()->GetMatrix()<IndexToWorld( currentPointIn2D, worldPointIn3D ); // //typename itk::Image::IndexType outputIndex; // m_ImageGeometry3D->WorldToIndex( worldPointIn3D, outputIndex ); // // // Only access ITK image if it's inside // if ( m_ImageGeometry3D->IsIndexInside( outputIndex ) ) // { // //outputPixel = outputImage->GetPixel( outputIndex ); // outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() ); // /*if( inputIterator.Get() == mitk::paint::addPixelValue ) // { // outputImage->SetPixel( outputIndex, (TPixel2)( 1 ) ); // } // else if( inputIterator.Get() == mitk::paint::subPixelValue ) // { // outputImage->SetPixel( outputIndex, (TPixel2)( 0 ) ); // }*/ // } // ///****TEST***/ // ////typename itk::Image::IndexType outputIndex; // ////if ( columns == extent[0] ) ////{ //////If we are at the end of a row, then we have to go to the beginning of the next row ////currentImagePointIn3D = origin; ////currentImagePointIn3D += spacing[1]*bottom*currentPointIn2D[1]; //columns = 0; ////m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); ////} ////else ////{ ////if ( columns != 0 ) ////{ ////currentImagePointIn3D += spacing[0]*right; ////} ////m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); ////} // ////if ( m_ImageGeometry3D->IsIndexInside( outputIndex )) ////{ ////outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() ); ////} ////else if (currentImagePointIn3D == origin) ////{ ////Point3D temp; ////temp[0] = bottom[0]*spacing[0]*0.5; ////temp[1] = bottom[1]*spacing[1]*0.5; ////temp[2] = bottom[2]*spacing[2]*0.5; ////origin[0] += temp[0]; ////origin[1] += temp[1]; ////origin[2] += temp[2]; ////currentImagePointIn3D = origin; ////m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex); ////if ( m_ImageGeometry3D->IsIndexInside( outputIndex )) ////{ ////outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() ); ////} ////} ////columns++; // ///****TEST ENDE****/ // ////* //// // Offset the world coordinate by one pixel to compensate for //// // index/world origin differences. //// Point3D offsetIndex; //// offsetIndex.Fill( 1 ); //// Point3D offsetWorld; //// offsetWorld.Fill( 0 ); //// m_PlaneGeometry->IndexToWorld( offsetIndex, offsetWorld ); //// // remove origin shift //// const Point3D origin = m_PlaneGeometry->GetOrigin(); //// offsetWorld[0] -= origin[0]; //// offsetWorld[1] -= origin[1]; //// offsetWorld[2] -= origin[2]; //// // offset world coordinate //// worldPointIn3D[ 0 ] += offsetWorld[0]; //// worldPointIn3D[ 1 ] += offsetWorld[1]; //// worldPointIn3D[ 2 ] += offsetWorld[2]; ////*/ // // Output index // // ////For the purpose of debug ////if( debugCounter%100 == 0) //////{ ////Point3D contIndex; ////m_ImageGeometry3D->WorldToIndex(worldPointIn3D,contIndex); ////overriderFile.precision(10); ////overriderFile<<"2D-Index: [ "<(inputIterator.Get() - outputPixel ) ); // oh oh, not good for bigger values // ++inputIterator; ////++debugCounter; // //++diffIterator; // } // /*overriderFile.close(); // overriderFileIndex.close();*/ // geometryFile.close(); // ///* // typename VolumeImageType::RegionType sliceInVolumeRegion; // // sliceInVolumeRegion = outputImage->GetLargestPossibleRegion(); // sliceInVolumeRegion.SetSize( m_SliceDimension, 1 ); // just one slice // sliceInVolumeRegion.SetIndex( m_SliceDimension, m_SliceIndex ); // exactly this slice, please // // OutputSliceIteratorType outputIterator( outputImage, sliceInVolumeRegion ); // outputIterator.SetFirstDirection(m_Dimension0); // outputIterator.SetSecondDirection(m_Dimension1); // // // iterate over output slice (and over input slice simultaneously) // outputIterator.GoToBegin(); // while ( !outputIterator.IsAtEnd() ) // { // while ( !outputIterator.IsAtEndOfSlice() ) // { // while ( !outputIterator.IsAtEndOfLine() ) // { // diffIterator.Set( static_cast(inputIterator.Get() - outputIterator.Get()) ); // oh oh, not good for bigger values // outputIterator.Set( (TPixel2) inputIterator.Get() ); // ++outputIterator; // ++inputIterator; // ++diffIterator; // } // outputIterator.NextLine(); // } // outputIterator.NextSlice(); // } // */ //} /* std::string mitk::OverwriteDirectedPlaneImageFilter::EventDescription( unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep ) { std::stringstream s; s << "Changed slice ("; switch (sliceDimension) { default: case 2: s << "T"; break; case 1: s << "C"; break; case 0: s << "S"; break; } s << " " << sliceIndex << " " << timeStep << ")"; return s.str(); } */ diff --git a/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.h b/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.h index 32db491432..5e8aaeefaf 100644 --- a/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.h +++ b/Modules/Segmentation/Algorithms/mitkOverwriteDirectedPlaneImageFilter.h @@ -1,118 +1,121 @@ /*=================================================================== 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 mitkOverwriteDirectedPlaneImageFilter_h_Included #define mitkOverwriteDirectedPlaneImageFilter_h_Included #include "mitkCommon.h" #include "SegmentationExports.h" #include "mitkImageToImageFilter.h" #include namespace mitk { /** + \deprecated This class is deprecated. Use mitkVtkImageOverwrite instead. + \sa mitkVtkImageOverwrite + \brief Writes a 2D slice into a 3D image. \sa SegTool2D \sa ContourTool \sa ExtractImageFilter \ingroup Process \ingroup Reliver There is a separate page describing the general design of QmitkInteractiveSegmentation: \ref QmitkInteractiveSegmentationTechnicalPage This class takes a 3D mitk::Image as input and tries to replace one slice in it with the second input image, which is specified by calling SetSliceImage with a 2D mitk::Image. Two parameters determine which slice is replaced: the "slice dimension" is that one, which is constant for all points in the plane, e.g. transversal would mean 2. The "slice index" is the slice index in the image direction you specified with "affected dimension". Indices count from zero. This class works with all kind of image types, the only restrictions being that the input is 3D, and the slice image is 2D. If requested by SetCreateUndoInformation(true), this class will create instances of ApplyDiffImageOperation for the undo stack. These operations will (on user request) be executed by DiffImageApplier to perform undo. Last contributor: $Author: maleike $ */ class Segmentation_EXPORT OverwriteDirectedPlaneImageFilter : public ImageToImageFilter { public: mitkClassMacro(OverwriteDirectedPlaneImageFilter, ImageToImageFilter); itkNewMacro(OverwriteDirectedPlaneImageFilter); /** \brief Which plane to overwrite */ const Geometry3D* GetPlaneGeometry3D() const { return m_PlaneGeometry; } void SetPlaneGeometry3D( const Geometry3D *geometry ) { m_PlaneGeometry = geometry; } /** \brief Time step of the slice to overwrite */ itkSetMacro(TimeStep, unsigned int); itkGetConstMacro(TimeStep, unsigned int); /** \brief Whether to create undo operation in the MITK undo stack */ itkSetMacro(CreateUndoInformation, bool); itkGetConstMacro(CreateUndoInformation, bool); itkSetObjectMacro(SliceImage, Image); const Image* GetSliceImage() { return m_SliceImage.GetPointer(); } const Image* GetLastDifferenceImage() { return m_SliceDifferenceImage.GetPointer(); } protected: OverwriteDirectedPlaneImageFilter(); // purposely hidden virtual ~OverwriteDirectedPlaneImageFilter(); virtual void GenerateData(); template void ItkSliceOverwriting (itk::Image* input3D); template void ItkImageSwitch( itk::Image* image ); template void ItkImageProcessing( itk::Image* itkImage1, itk::Image* itkImage2 ); //std::string EventDescription( unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep ); Image::ConstPointer m_SliceImage; Image::Pointer m_SliceDifferenceImage; const Geometry3D *m_PlaneGeometry; const Geometry3D *m_ImageGeometry3D; unsigned int m_TimeStep; unsigned int m_Dimension0; unsigned int m_Dimension1; bool m_CreateUndoInformation; }; } // namespace #endif diff --git a/Modules/Segmentation/Algorithms/mitkOverwriteSliceImageFilter.cpp b/Modules/Segmentation/Algorithms/mitkOverwriteSliceImageFilter.cpp index 8024b01963..da25152a48 100644 --- a/Modules/Segmentation/Algorithms/mitkOverwriteSliceImageFilter.cpp +++ b/Modules/Segmentation/Algorithms/mitkOverwriteSliceImageFilter.cpp @@ -1,246 +1,247 @@ /*=================================================================== 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 "mitkOverwriteSliceImageFilter.h" #include "mitkImageCast.h" #include "mitkImageAccessByItk.h" #include "mitkSegmentationInterpolationController.h" #include "mitkApplyDiffImageOperation.h" #include "mitkOperationEvent.h" #include "mitkInteractionConst.h" #include "mitkUndoController.h" #include "mitkDiffImageApplier.h" #include "mitkImageTimeSelector.h" #include #include mitk::OverwriteSliceImageFilter::OverwriteSliceImageFilter() :m_SliceIndex(0), m_SliceDimension(0), m_TimeStep(0), m_Dimension0(0), m_Dimension1(1), m_CreateUndoInformation(false) { + MITK_WARN << "Class is deprecated! Use mitkVtkImageOverwrite instead."; } mitk::OverwriteSliceImageFilter::~OverwriteSliceImageFilter() { } void mitk::OverwriteSliceImageFilter::GenerateData() { // // this is the place to implement the major part of undo functionality (bug #491) // here we have to create undo/do operations // // WHO is the operation actor? This object may not be destroyed ever (design of undo stack)! // -> some singleton method of this filter? // // neccessary additional objects: // - something that executes the operations // - the operation class (must hold a binary diff or something) // - observer commands to know when the image is deleted (no further action then, perhaps even remove the operations from the undo stack) // Image::ConstPointer input = ImageToImageFilter::GetInput(0); Image::ConstPointer input3D = input; Image::ConstPointer slice = m_SliceImage; if ( input.IsNull() || slice.IsNull() ) return; switch (m_SliceDimension) { default: case 2: m_Dimension0 = 0; m_Dimension1 = 1; break; case 1: m_Dimension0 = 0; m_Dimension1 = 2; break; case 0: m_Dimension0 = 1; m_Dimension1 = 2; break; } if ( slice->GetDimension() < 2 || input->GetDimension() > 4 || slice->GetDimension(0) != input->GetDimension(m_Dimension0) || slice->GetDimension(1) != input->GetDimension(m_Dimension1) || m_SliceIndex >= input->GetDimension(m_SliceDimension) ) { itkExceptionMacro("Slice and image dimensions differ or slice index is too large. Sorry, cannot work like this."); return; } if ( input->GetDimension() == 4 ) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( input ); timeSelector->SetTimeNr( m_TimeStep ); timeSelector->UpdateLargestPossibleRegion(); input3D = timeSelector->GetOutput(); } if ( m_SliceDifferenceImage.IsNull() || m_SliceDifferenceImage->GetDimension(0) != m_SliceImage->GetDimension(0) || m_SliceDifferenceImage->GetDimension(1) != m_SliceImage->GetDimension(1) ) { m_SliceDifferenceImage = mitk::Image::New(); mitk::PixelType pixelType( mitk::MakeScalarPixelType() ); m_SliceDifferenceImage->Initialize( pixelType, 2, m_SliceImage->GetDimensions() ); } //MITK_INFO << "Overwriting slice " << m_SliceIndex << " in dimension " << m_SliceDimension << " at time step " << m_TimeStep << std::endl; // this will do a long long if/else to find out both pixel types AccessFixedDimensionByItk( input3D, ItkImageSwitch, 3 ); SegmentationInterpolationController* interpolator = SegmentationInterpolationController::InterpolatorForImage( input ); if (interpolator) { interpolator->BlockModified(true); interpolator->SetChangedSlice( m_SliceDifferenceImage, m_SliceDimension, m_SliceIndex, m_TimeStep ); } if ( m_CreateUndoInformation ) { // create do/undo operations (we don't execute the doOp here, because it has already been executed during calculation of the diff image ApplyDiffImageOperation* doOp = new ApplyDiffImageOperation( OpTEST, const_cast(input.GetPointer()), m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex ); ApplyDiffImageOperation* undoOp = new ApplyDiffImageOperation( OpTEST, const_cast(input.GetPointer()), m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex ); undoOp->SetFactor( -1.0 ); OperationEvent* undoStackItem = new OperationEvent( DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, this->EventDescription(m_SliceDimension, m_SliceIndex, m_TimeStep) ); UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem ); } // this image is modified (good to know for the renderer) input->Modified(); if (interpolator) { interpolator->BlockModified(false); } } // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h #define myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \ if ( typeId == typeid(pixeltype) ) \ { \ typedef itk::Image ImageType; \ typedef mitk::ImageToItk ImageToItkType; \ itk::SmartPointer imagetoitk = ImageToItkType::New(); \ imagetoitk->SetInput(mitkImage); \ imagetoitk->Update(); \ itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \ } #define myMITKOverwriteSliceImageFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \ { \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, float, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned int, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, char, dimension, itkimage2) else \ myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned char, dimension, itkimage2) \ } template void mitk::OverwriteSliceImageFilter::ItkImageSwitch( itk::Image* itkImage ) { const std::type_info& typeId=m_SliceImage->GetPixelType().GetTypeId(); myMITKOverwriteSliceImageFilterAccessAllTypesByItk( m_SliceImage, ItkImageProcessing, 2, itkImage ); } template void mitk::OverwriteSliceImageFilter::ItkImageProcessing( itk::Image* inputImage, itk::Image* outputImage ) { typedef itk::Image SliceImageType; typedef itk::Image DiffImageType; typedef itk::Image VolumeImageType; typedef itk::ImageSliceIteratorWithIndex< VolumeImageType > OutputSliceIteratorType; typedef itk::ImageRegionConstIterator< SliceImageType > InputSliceIteratorType; typedef itk::ImageRegionIterator< DiffImageType > DiffSliceIteratorType; typename VolumeImageType::RegionType sliceInVolumeRegion; sliceInVolumeRegion = outputImage->GetLargestPossibleRegion(); sliceInVolumeRegion.SetSize( m_SliceDimension, 1 ); // just one slice sliceInVolumeRegion.SetIndex( m_SliceDimension, m_SliceIndex ); // exactly this slice, please OutputSliceIteratorType outputIterator( outputImage, sliceInVolumeRegion ); outputIterator.SetFirstDirection(m_Dimension0); outputIterator.SetSecondDirection(m_Dimension1); InputSliceIteratorType inputIterator( inputImage, inputImage->GetLargestPossibleRegion() ); typename DiffImageType::Pointer diffImage; CastToItkImage( m_SliceDifferenceImage, diffImage ); DiffSliceIteratorType diffIterator( diffImage, diffImage->GetLargestPossibleRegion() ); // iterate over output slice (and over input slice simultaneously) outputIterator.GoToBegin(); inputIterator.GoToBegin(); diffIterator.GoToBegin(); while ( !outputIterator.IsAtEnd() ) { while ( !outputIterator.IsAtEndOfSlice() ) { while ( !outputIterator.IsAtEndOfLine() ) { diffIterator.Set( static_cast(inputIterator.Get() - outputIterator.Get()) ); // oh oh, not good for bigger values outputIterator.Set( (TPixel2) inputIterator.Get() ); ++outputIterator; ++inputIterator; ++diffIterator; } outputIterator.NextLine(); } outputIterator.NextSlice(); } } std::string mitk::OverwriteSliceImageFilter::EventDescription( unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep ) { std::stringstream s; s << "Changed slice ("; switch (sliceDimension) { default: case 2: s << "T"; break; case 1: s << "C"; break; case 0: s << "S"; break; } s << " " << sliceIndex << " " << timeStep << ")"; return s.str(); } diff --git a/Modules/Segmentation/Algorithms/mitkOverwriteSliceImageFilter.h b/Modules/Segmentation/Algorithms/mitkOverwriteSliceImageFilter.h index bb165108ae..1c0e2d9624 100644 --- a/Modules/Segmentation/Algorithms/mitkOverwriteSliceImageFilter.h +++ b/Modules/Segmentation/Algorithms/mitkOverwriteSliceImageFilter.h @@ -1,123 +1,126 @@ /*=================================================================== 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 mitkOverwriteSliceImageFilter_h_Included #define mitkOverwriteSliceImageFilter_h_Included #include "mitkCommon.h" #include "SegmentationExports.h" #include "mitkImageToImageFilter.h" #include namespace mitk { /** + \deprecated This class is deprecated. Use mitkVtkImageOverwrite instead. + \sa mitkVtkImageOverwrite + \brief Writes a 2D slice into a 3D image. \sa SegTool2D \sa ContourTool \sa ExtractImageFilter \ingroup Process \ingroup ToolManagerEtAl There is a separate page describing the general design of QmitkInteractiveSegmentation: \ref QmitkInteractiveSegmentationTechnicalPage This class takes a 3D mitk::Image as input and tries to replace one slice in it with the second input image, which is specified by calling SetSliceImage with a 2D mitk::Image. Two parameters determine which slice is replaced: the "slice dimension" is that one, which is constant for all points in the plane, e.g. transversal would mean 2. The "slice index" is the slice index in the image direction you specified with "affected dimension". Indices count from zero. This class works with all kind of image types, the only restrictions being that the input is 3D, and the slice image is 2D. If requested by SetCreateUndoInformation(true), this class will create instances of ApplyDiffImageOperation for the undo stack. These operations will (on user request) be executed by DiffImageApplier to perform undo. Last contributor: $Author$ */ class Segmentation_EXPORT OverwriteSliceImageFilter : public ImageToImageFilter { public: mitkClassMacro(OverwriteSliceImageFilter, ImageToImageFilter); itkNewMacro(OverwriteSliceImageFilter); /** \brief Which slice to overwrite (first one has index 0). */ itkSetMacro(SliceIndex, unsigned int); itkGetConstMacro(SliceIndex, unsigned int); /** \brief The orientation of the slice to overwrite. \a Parameter \a SliceDimension Number of the dimension which is constant for all pixels of the desired slices (e.g. 0 for transversal) */ itkSetMacro(SliceDimension, unsigned int); itkGetConstMacro(SliceDimension, unsigned int); /** \brief Time step of the slice to overwrite */ itkSetMacro(TimeStep, unsigned int); itkGetConstMacro(TimeStep, unsigned int); /** \brief Whether to create undo operation in the MITK undo stack */ itkSetMacro(CreateUndoInformation, bool); itkGetConstMacro(CreateUndoInformation, bool); itkSetObjectMacro(SliceImage, Image); const Image* GetSliceImage() { return m_SliceImage.GetPointer(); } const Image* GetLastDifferenceImage() { return m_SliceDifferenceImage.GetPointer(); } protected: OverwriteSliceImageFilter(); // purposely hidden virtual ~OverwriteSliceImageFilter(); virtual void GenerateData(); template void ItkImageSwitch( itk::Image* image ); template void ItkImageProcessing( itk::Image* itkImage1, itk::Image* itkImage2 ); std::string EventDescription( unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep ); Image::ConstPointer m_SliceImage; Image::Pointer m_SliceDifferenceImage; unsigned int m_SliceIndex; unsigned int m_SliceDimension; unsigned int m_TimeStep; unsigned int m_Dimension0; unsigned int m_Dimension1; bool m_CreateUndoInformation; }; } // namespace #endif