diff --git a/Modules/LegacyAdaptors/mitkLegacyAdaptors.cpp b/Modules/LegacyAdaptors/mitkLegacyAdaptors.cpp index 419b06f425..d7c4aa7973 100644 --- a/Modules/LegacyAdaptors/mitkLegacyAdaptors.cpp +++ b/Modules/LegacyAdaptors/mitkLegacyAdaptors.cpp @@ -1,124 +1,124 @@ #include "mitkLegacyAdaptors.h" mitkIpPicDescriptor* mitk::CastToIpPicDescriptor(mitk::Image::Pointer refImg, mitkIpPicDescriptor* picDesc) { const mitk::ImageDescriptor::Pointer imDesc = refImg->GetImageDescriptor(); // initialize dimension information for (unsigned int i=0; i<8; i++) { picDesc->n[i] = 1; } // set dimension information picDesc->dim = refImg->GetDimension(); memcpy( picDesc->n, imDesc->GetDimensions(), picDesc->dim * sizeof(unsigned int) ); picDesc->type = CastToIpPicType( refImg->GetPixelType().GetTypeId() ); picDesc->bpe = refImg->GetPixelType().GetBpe(); picDesc->data = refImg->GetData(); return picDesc; } mitkIpPicDescriptor* mitk::CastToIpPicDescriptor(itk::SmartPointer refItem, mitkIpPicDescriptor *picDesc) { // initialize dimension information for (unsigned int i=0; i<8; i++) { picDesc->n[i] = 1; } // get the dimensionality information from image item picDesc->dim = refItem->GetDimension(); for( unsigned int i=0; idim; i++) { picDesc->n[i] = refItem->GetDimension(i); } picDesc->type = CastToIpPicType( refItem->GetPixelType().GetTypeId() ); picDesc->bpe = refItem->GetPixelType().GetBpe(); picDesc->data = refItem->GetData(); return picDesc; } mitk::ImageDescriptor::Pointer mitk::CastToImageDescriptor(mitkIpPicDescriptor *desc) { mitk::ImageDescriptor::Pointer imDescriptor = mitk::ImageDescriptor::New(); imDescriptor->Initialize( desc->n, desc->dim ); mitk::PixelType ptype = CastToPixelType( desc->type, (desc->bpe/8) ); imDescriptor->AddNewChannel(ptype, "imported by pic"); return imDescriptor; } mitkIpPicType_t mitk::CastToIpPicType( const std::type_info& intype ) { //const std::type_info& intype = ptype.GetTypeId(); - MITK_INFO << "Casting to PicType from " << intype.name() << std::endl; + //MITK_INFO << "Casting to PicType from " << intype.name() << std::endl; const bool isSignedIntegralType = ( intype == typeid(int) || intype == typeid(short) || intype == typeid(char) || intype == typeid(long int) ); const bool isUnsignedIntegralType = ( intype == typeid(unsigned int) || intype == typeid(unsigned short) || intype == typeid(unsigned char) || intype == typeid(unsigned long int) ); const bool isFloatingPointType = ( intype == typeid(float) || intype == typeid(double) ); if( isSignedIntegralType ) return mitkIpPicInt; if( isUnsignedIntegralType ) return mitkIpPicUInt; if( isFloatingPointType ) return mitkIpPicFloat; return mitkIpPicUnknown; } mitk::PixelType mitk::CastToPixelType(mitkIpPicType_t pictype, size_t bpe) { const bool isSignedIntegralType = (pictype == mitkIpPicInt ); const bool isUnsignedIntegralType = (pictype == mitkIpPicUInt ); if(isSignedIntegralType) { switch(bpe) { case sizeof(char): return MakeScalarPixelType(); case sizeof(short): return MakeScalarPixelType(); default: return MakeScalarPixelType(); } } else if( isUnsignedIntegralType ) { switch(bpe) { case sizeof(unsigned char): return MakeScalarPixelType(); case sizeof(unsigned short): return MakeScalarPixelType(); default: return MakeScalarPixelType(); } } else // is floating point type { switch(bpe) { case sizeof(float): return MakeScalarPixelType(); default: return MakeScalarPixelType(); } } } diff --git a/Modules/MitkExt/Interactions/mitkPaintbrushTool.cpp b/Modules/MitkExt/Interactions/mitkPaintbrushTool.cpp index 7d026af7f1..dbb9eeb2b1 100644 --- a/Modules/MitkExt/Interactions/mitkPaintbrushTool.cpp +++ b/Modules/MitkExt/Interactions/mitkPaintbrushTool.cpp @@ -1,427 +1,379 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkPaintbrushTool.h" #include "mitkToolManager.h" #include "mitkOverwriteSliceImageFilter.h" #include "mitkBaseRenderer.h" #include "mitkImageDataItem.h" #include "ipSegmentation.h" #include "mitkLevelWindowProperty.h" #define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a))) int mitk::PaintbrushTool::m_Size = 1; mitk::PaintbrushTool::PaintbrushTool(int paintingPixelValue) :FeedbackContourTool("PressMoveReleaseWithCTRLInversionAllMouseMoves"), m_PaintingPixelValue(paintingPixelValue), m_LastContourSize(0) // other than initial mitk::PaintbrushTool::m_Size (around l. 28) { m_MasterContour = Contour::New(); m_MasterContour->Initialize(); m_CurrentPlane = NULL; m_WorkingNode = DataNode::New(); m_WorkingNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) ); m_WorkingNode->SetProperty( "binary", mitk::BoolProperty::New(true) ); } mitk::PaintbrushTool::~PaintbrushTool() { } void mitk::PaintbrushTool::Activated() { Superclass::Activated(); FeedbackContourTool::SetFeedbackContourVisible(true); SizeChanged.Send(m_Size); } void mitk::PaintbrushTool::Deactivated() { FeedbackContourTool::SetFeedbackContourVisible(false); if (m_ToolManager->GetDataStorage()->Exists(m_WorkingNode)) m_ToolManager->GetDataStorage()->Remove(m_WorkingNode); Superclass::Deactivated(); } void mitk::PaintbrushTool::SetSize(int value) { m_Size = value; } void mitk::PaintbrushTool::UpdateContour(const StateEvent* stateEvent) { //MITK_INFO<<"Update..."; // examine stateEvent and create a contour that matches the pixel mask that we are going to draw const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return; // create a copy of this slice (at least match the pixel sizes/spacings), // then draw the desired mask on it and create a contour from it // Convert to ipMITKSegmentationTYPE (because getting pixels relys on that data type) itk::Image< ipMITKSegmentationTYPE, 2 >::Pointer correctPixelTypeImage; CastToItkImage(m_WorkingSlice/*dynamic_cast(m_WorkingNode->GetData())*/, correctPixelTypeImage ); assert (correctPixelTypeImage.IsNotNull() ); itk::Image< ipMITKSegmentationTYPE, 2 >::DirectionType imageDirection; imageDirection.SetIdentity(); correctPixelTypeImage->SetDirection(imageDirection); Image::Pointer temporarySlice = Image::New(); CastToMitkImage( correctPixelTypeImage, temporarySlice ); //mitkIpPicDescriptor* stupidClone = mitkIpPicClone( temporarySlice->GetSliceData()->GetPicDescriptor() ); mitkIpPicDescriptor* stupidClone = mitkIpPicNew(); CastToIpPicDescriptor( temporarySlice->GetSliceData(), stupidClone ); unsigned int pixelWidth = m_Size + 1; unsigned int pixelHeight = m_Size + 1; if ( stupidClone->n[0] <= pixelWidth || stupidClone->n[1] <= pixelHeight ) { MITK_INFO << "Brush size is bigger than your working image. Reconsider this...\n" "(Or tell your progammer until (s)he fixes this message.)" << std::endl; mitkIpPicFree( stupidClone ); return; } unsigned int lineLength( stupidClone->n[0] ); unsigned int oneContourOffset(0); float circleCenterX = (float)m_Size / 2.0; float circleCenterY = (float)m_Size / 2.0; for (unsigned int x = 0; x <= pixelWidth; ++x) { for (unsigned int y = 0; y <= pixelHeight; ++y) { unsigned int offset = lineLength * y + x; ipMITKSegmentationTYPE* current = (ipMITKSegmentationTYPE*)stupidClone->data + offset; float pixelCenterX = x + 0.5; float pixelCenterY = y + 0.5; float xoff = pixelCenterX - circleCenterX; float yoff = pixelCenterY - circleCenterY; bool inside = xoff * xoff + yoff * yoff < (m_Size * m_Size) / 4.0; // no idea, if this would work for ellipses if (inside) { *current = 1; oneContourOffset = offset; } else { *current = 0; } } } int numberOfContourPoints( 0 ); int newBufferSize( 0 ); float* contourPoints = ipMITKSegmentationGetContour8N( stupidClone, oneContourOffset, numberOfContourPoints, newBufferSize ); // memory allocated with malloc if (!contourPoints) { mitkIpPicFree( stupidClone ); return; } // copy point from float* to mitk::Contour Contour::Pointer contourInImageIndexCoordinates = Contour::New(); contourInImageIndexCoordinates->Initialize(); Point3D newPoint; //ipMITKSegmentationGetContour8N returns all points, which causes vtk warnings, since the first and the last points are coincident. //leaving the last point out, the contour is still drawn correctly for (int index = 0; index < numberOfContourPoints-1; ++index) { newPoint[0] = contourPoints[ 2 * index + 0 ] - circleCenterX; // master contour should be centered around (0,0) newPoint[1] = contourPoints[ 2 * index + 1] - circleCenterY; newPoint[2] = 0.0; MITK_DEBUG << "Point [" << index << "] (" << newPoint[0] << ", " << newPoint[1] << ")" << std::endl; contourInImageIndexCoordinates->AddVertex( newPoint ); } free(contourPoints); m_MasterContour = contourInImageIndexCoordinates; // The PicDescriptor is only REFERENCING(!) the data, the temporarySlice takes care of deleting the data also the descriptor is pointing on // because they got allocated by the ImageDataItem, not the descriptor. stupidClone->data = NULL; mitkIpPicFree( stupidClone ); } /** Just show the contour, get one point as the central point and add surrounding points to the contour. */ bool mitk::PaintbrushTool::OnMousePressed (Action* action, const StateEvent* stateEvent) { return this->OnMouseMoved(action, stateEvent); } /** Insert the point to the feedback contour,finish to build the contour and at the same time the painting function */ bool mitk::PaintbrushTool::OnMouseMoved (Action* itkNotUsed(action), const StateEvent* stateEvent) { const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; CheckIfCurrentSliceHasChanged(positionEvent); if ( m_LastContourSize != m_Size ) { UpdateContour( stateEvent ); m_LastContourSize = m_Size; } bool leftMouseButtonPressed( stateEvent->GetId() == 530 || stateEvent->GetId() == 534 || stateEvent->GetId() == 1 || stateEvent->GetId() == 5 ); Point3D worldCoordinates = positionEvent->GetWorldPosition(); Point3D indexCoordinates; m_WorkingSlice->GetGeometry()->WorldToIndex( worldCoordinates, indexCoordinates ); MITK_DEBUG << "Mouse at W " << worldCoordinates << std::endl; MITK_DEBUG << "Mouse at I " << indexCoordinates << std::endl; // round to nearest voxel center (abort if this hasn't changed) if ( m_Size % 2 == 0 ) // even { indexCoordinates[0] = ROUND( indexCoordinates[0] /*+ 0.5*/) + 0.5; indexCoordinates[1] = ROUND( indexCoordinates[1] /*+ 0.5*/ ) + 0.5; } else // odd { indexCoordinates[0] = ROUND( indexCoordinates[0] ) ; indexCoordinates[1] = ROUND( indexCoordinates[1] ) ; } static Point3D lastPos; // uninitialized: if somebody finds out how this can be initialized in a one-liner, tell me static bool lastLeftMouseButtonPressed(false); if ( fabs(indexCoordinates[0] - lastPos[0]) > mitk::eps || fabs(indexCoordinates[1] - lastPos[1]) > mitk::eps || fabs(indexCoordinates[2] - lastPos[2]) > mitk::eps || leftMouseButtonPressed != lastLeftMouseButtonPressed ) { lastPos = indexCoordinates; lastLeftMouseButtonPressed = leftMouseButtonPressed; } else { MITK_DEBUG << "." << std::flush; return false; } MITK_DEBUG << "Mouse at C " << indexCoordinates; Contour::Pointer contour = Contour::New(); contour->Initialize(); for (unsigned int index = 0; index < m_MasterContour->GetNumberOfPoints(); ++index) { Point3D point = m_MasterContour->GetPoints()->ElementAt(index); point[0] += indexCoordinates[ 0 ]; point[1] += indexCoordinates[ 1 ]; MITK_DEBUG << "Contour point [" << index << "] :" << point; contour->AddVertex( point ); } if (leftMouseButtonPressed) { FeedbackContourTool::FillContourInSlice( contour, m_WorkingSlice, m_PaintingPixelValue ); m_WorkingNode->SetData(m_WorkingSlice); m_WorkingNode->Modified(); } // visualize contour Contour::Pointer displayContour = Contour::New(); displayContour->Initialize(); //for (unsigned int index = 0; index < contour->GetNumberOfPoints(); ++index) //{ // Point3D point = contour->GetPoints()->ElementAt(index); // if ( m_Size % 2 == 0 ) // even // { // point[0] += 0.5; // point[1] += 0.5; // } // displayContour->AddVertex( point ); //} displayContour = FeedbackContourTool::BackProjectContourFrom2DSlice( m_WorkingSlice->GetGeometry(), /*displayContour*/contour ); SetFeedbackContour( *displayContour ); assert( positionEvent->GetSender()->GetRenderWindow() ); RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::PaintbrushTool::OnMouseReleased(Action* /*action*/, const StateEvent* stateEvent) { //When mouse is released write segmentationresult back into image const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; this->WriteBackSegmentationResult(positionEvent, m_WorkingSlice); // FeedbackContourTool::SetFeedbackContourVisible(false); return true; } /** Called when the CTRL key is pressed. Will change the painting pixel value from 0 to 1 or from 1 to 0. */ bool mitk::PaintbrushTool::OnInvertLogic(Action* action, const StateEvent* stateEvent) { if (!FeedbackContourTool::OnInvertLogic(action, stateEvent)) return false; // Inversion only for 0 and 1 as painting values if (m_PaintingPixelValue == 1) { m_PaintingPixelValue = 0; FeedbackContourTool::SetFeedbackContourColor( 1.0, 0.0, 0.0 ); } else if (m_PaintingPixelValue == 0) { m_PaintingPixelValue = 1; FeedbackContourTool::SetFeedbackContourColorDefault(); } return true; } -bool mitk::PaintbrushTool::CheckIfCurrentSliceHasChanged(const PositionEvent *event) +void mitk::PaintbrushTool::CheckIfCurrentSliceHasChanged(const PositionEvent *event) { const PlaneGeometry* planeGeometry( dynamic_cast (event->GetSender()->GetCurrentWorldGeometry2D() ) ); DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); - if (!workingNode) return false; + + if (!workingNode) + return; + Image::Pointer image = dynamic_cast(workingNode->GetData()); + if ( !image || !planeGeometry ) - return false; + return; if(m_CurrentPlane.IsNull()) { m_CurrentPlane = const_cast(planeGeometry); m_WorkingSlice = SegTool2D::GetAffectedImageSliceAs2DImage(event, image)->Clone(); -// //Workaround because of bug #7079 -// Point3D origin = m_WorkingSlice->GetGeometry()->GetOrigin(); - -// int affectedDimension(-1); - -// if(event->GetSender()->GetRenderWindow() == mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1")) -// { -// affectedDimension = 2; -// } -// if(event->GetSender()->GetRenderWindow() == mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2")) -// { -// affectedDimension = 0; -// } -// if(event->GetSender()->GetRenderWindow() == mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")) -// { -// affectedDimension = 1; -// } - -// if (affectedDimension != -1) -// { -// origin[affectedDimension] = m_CurrentPlane->GetOrigin()[affectedDimension]; -// m_WorkingSlice->GetGeometry()->SetOrigin(origin); -// } -// //Workaround end - m_WorkingNode->ReplaceProperty( "color", workingNode->GetProperty("color") ); m_WorkingNode->SetData(m_WorkingSlice); } else { bool isSameSlice (false); isSameSlice = mitk::MatrixEqualElementWise(planeGeometry->GetIndexToWorldTransform()->GetMatrix(),m_CurrentPlane->GetIndexToWorldTransform()->GetMatrix()); isSameSlice = mitk::Equal(planeGeometry->GetIndexToWorldTransform()->GetOffset(),m_CurrentPlane->GetIndexToWorldTransform()->GetOffset()); if (!isSameSlice) { m_ToolManager->GetDataStorage()->Remove(m_WorkingNode); m_CurrentPlane = NULL; m_WorkingSlice = NULL; m_WorkingNode = NULL; m_CurrentPlane = const_cast(planeGeometry); m_WorkingSlice = SegTool2D::GetAffectedImageSliceAs2DImage(event, image)->Clone(); - //Workaround because of bug #7079 -// Point3D origin = m_WorkingSlice->GetGeometry()->GetOrigin(); - -// int affectedDimension(-1); - -// if(event->GetSender()->GetRenderWindow() == mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1")) -// { -// affectedDimension = 2; -// } -// if(event->GetSender()->GetRenderWindow() == mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2")) -// { -// affectedDimension = 0; -// } -// if(event->GetSender()->GetRenderWindow() == mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3")) -// { -// affectedDimension = 1; -// } - -// if (affectedDimension != -1) -// { -// origin[affectedDimension] = m_CurrentPlane->GetOrigin()[affectedDimension]; -// m_WorkingSlice->GetGeometry()->SetOrigin(origin); -// } - //Workaround end - - m_WorkingNode = mitk::DataNode::New(); - m_WorkingNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) ); - m_WorkingNode->SetProperty( "binary", mitk::BoolProperty::New(true) ); - - m_WorkingNode->SetData(m_WorkingSlice); + m_WorkingNode = mitk::DataNode::New(); + m_WorkingNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( mitk::LevelWindow(0, 1) ) ); + m_WorkingNode->SetProperty( "binary", mitk::BoolProperty::New(true) ); + + m_WorkingNode->SetData(m_WorkingSlice); } } if(!m_ToolManager->GetDataStorage()->Exists(m_WorkingNode)) { m_WorkingNode->SetProperty( "outline binary", mitk::BoolProperty::New(true) ); m_WorkingNode->SetProperty( "color", workingNode->GetProperty("color") ); m_WorkingNode->SetProperty( "texture interpolation", mitk::BoolProperty::New(true) ); m_WorkingNode->SetProperty( "layer", mitk::IntProperty::New( 100 ) ); m_WorkingNode->SetProperty( "name", mitk::StringProperty::New("Paintbrush_Node") ); m_WorkingNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); m_WorkingNode->SetProperty( "opacity", mitk::FloatProperty::New(0.8) ); m_WorkingNode->SetProperty( "includeInBoundingBox", mitk::BoolProperty::New(false)); - m_ToolManager->GetDataStorage()->Add(m_WorkingNode); } } - diff --git a/Modules/MitkExt/Interactions/mitkPaintbrushTool.h b/Modules/MitkExt/Interactions/mitkPaintbrushTool.h index c533ffe7d9..997f0c97c6 100644 --- a/Modules/MitkExt/Interactions/mitkPaintbrushTool.h +++ b/Modules/MitkExt/Interactions/mitkPaintbrushTool.h @@ -1,97 +1,97 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Language: C++ Date: $Date$ Version: $Revision: 1.12 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef mitkPaintbrushTool_h_Included #define mitkPaintbrushTool_h_Included #include "mitkCommon.h" #include "MitkExtExports.h" #include "mitkFeedbackContourTool.h" #include "mitkPointSet.h" #include "mitkPointOperation.h" #include "mitkLegacyAdaptors.h" namespace mitk { /** \brief Paintbrush tool for InteractiveSegmentation \sa FeedbackContourTool \sa ExtractImageFilter \sa OverwriteSliceImageFilter \ingroup Interaction \ingroup ToolManagerEtAl Simple paintbrush drawing tool. Right now there are only circular pens of varying size. \todo Bug #1727: Should be modified, so that the contour is always visible, i.e.without pressing a mouse button. \warning Only to be instantiated by mitk::ToolManager. $Author: maleike $ */ class MitkExt_EXPORT PaintbrushTool : public FeedbackContourTool { public: // sent when the pen size is changed or should be updated in a GUI. Message1 SizeChanged; mitkClassMacro(PaintbrushTool, FeedbackContourTool); void SetSize(int value); protected: PaintbrushTool(int paintingPixelValue = 1); // purposely hidden virtual ~PaintbrushTool(); virtual void Activated(); virtual void Deactivated(); virtual bool OnMousePressed (Action*, const StateEvent*); virtual bool OnMouseMoved (Action*, const StateEvent*); virtual bool OnMouseReleased(Action*, const StateEvent*); virtual bool OnInvertLogic (Action*, const StateEvent*); /** * \todo This is a possible place where to introduce * different types of pens */ void UpdateContour(const StateEvent* stateEvent); /** - * Check if the current slice has changed + * Checks if the current slice has changed */ - bool CheckIfCurrentSliceHasChanged(const PositionEvent* event); + void CheckIfCurrentSliceHasChanged(const PositionEvent* event); int m_PaintingPixelValue; static int m_Size; Contour::Pointer m_MasterContour; int m_LastContourSize; Image::Pointer m_WorkingSlice; PlaneGeometry::Pointer m_CurrentPlane; DataNode::Pointer m_WorkingNode; }; } // namespace #endif