diff --git a/GUI/Model/JoinModel.cxx b/GUI/Model/JoinModel.cxx index 61413500..0f834fc0 100644 --- a/GUI/Model/JoinModel.cxx +++ b/GUI/Model/JoinModel.cxx @@ -94,75 +94,9 @@ bool JoinModel::processCnJ(bool reverse_mode){ // Get the global objects IRISApplication *driver = m_Parent->GetDriver(); - GlobalState *gs = driver->GetGlobalState(); - - // Get Join source image - JsrcImageWrapper *jsrc = driver->GetJOINImageData()->GetJsrc(); - - // Get Join destination image - JdstImageWrapper *jdst = driver->GetJOINImageData()->GetJdst(); - - // Get the segmentation image - //LabelImageWrapper *imgLabel = driver->GetCurrentImageData()->GetSegmentation(); - - // Get the paint properties - LabelType drawing_color = gs->GetDrawingColorLabel(); - DrawOverFilter drawover = gs->GetDrawOverFilter(); - - // Define a region of interest - //LabelImageWrapper::ImageType::RegionType xTestRegion= jsrc->GetImage()->GetBufferedRegion(); - JsrcImageWrapper::ImageType::RegionType xTestRegion= jsrc->GetImage()->GetLargestPossibleRegion(); // Flag to see if anything was changed - bool flagUpdate = false; - - JsrcImageWrapper::ImageType::ValueType JsrcClickPV= jsrc->GetImage()->GetPixel(to_itkIndex(m_MousePosition)); - // JdstImageWrapper::ImageType::ValueType JdstClickPV= jdst->GetImage()->GetPixel(to_itkIndex(m_MousePosition)); - - - // Iterate over the region - JsrcImageWrapper::Iterator sit(jsrc->GetImage(), xTestRegion); - LabelImageWrapper::Iterator dit(jdst->GetImage(), xTestRegion); - for(; !sit.IsAtEnd(); ++sit, ++dit){ - - if(sit.Get() != JsrcClickPV) - continue; - - LabelType pxLabel = dit.Get(); - - // Standard paint mode - if(!reverse_mode) - { - if(drawover.CoverageMode == PAINT_OVER_ALL || - (drawover.CoverageMode == PAINT_OVER_ONE && pxLabel == drawover.DrawOverLabel) || - (drawover.CoverageMode == PAINT_OVER_VISIBLE && pxLabel != 0)) - { - dit.Set(drawing_color); - if(pxLabel != drawing_color) flagUpdate = true; - } - } - // Background paint mode (clear label over current label) - else - { - if(drawing_color != 0 && pxLabel == drawing_color) - { - dit.Set(0); - if(pxLabel != 0) flagUpdate = true; - } - else if(drawing_color == 0 && drawover.CoverageMode == PAINT_OVER_ONE) - { - dit.Set(drawover.DrawOverLabel); - if(pxLabel != drawover.DrawOverLabel) flagUpdate = true; - } - } - } - - // Image has been updated - if(flagUpdate) - { - jdst->GetImage()->Modified(); - //imgLabel->GetImage()->Modified(); - } + bool flagUpdate= driver->ExecuteCnJCopy(to_itkIndex(m_MousePosition)); return flagUpdate; } diff --git a/Logic/Common/itkJoinCopyFilter.cxx b/Logic/Common/itkJoinCopyFilter.cxx new file mode 100644 index 00000000..20b7daf2 --- /dev/null +++ b/Logic/Common/itkJoinCopyFilter.cxx @@ -0,0 +1,76 @@ +////image filter to set DrawingColor in output image if input pixel equals SeedValue + +#ifndef __itkJoinCopyFilter_cxx +#define __itkJoinCopyFilter_cxx + +#include "itkJoinCopyFilter.h" +#include +#include +#include + +namespace itk{ + + template + JoinCopyFilter + ::JoinCopyFilter(){ + m_SeedActive= false; + m_SeedIndex.Fill(0); + m_SeedValue= NumericTraits::Zero; + } + + template + void JoinCopyFilter + ::SetJsrc(const TInputImage1 *image1){ + this->SetNthInput( 0, const_cast< TInputImage1 * >( image1 ) ); + } + + template + void JoinCopyFilter + ::SetJdst(const TInputImage2 *image2){ + this->SetNthInput( 1, const_cast< TInputImage2 * >( image2 ) ); + } + + + template + void JoinCopyFilter + ::BeforeThreadedGenerateData(){ + + if(m_SeedActive){ + typename TInputImage1::ConstPointer input = dynamic_cast( ProcessObject::GetInput(0) ); + m_SeedValue= input->GetPixel(m_SeedIndex); + } + m_UpdateFlag= false; + } + + + template + void JoinCopyFilter + ::ThreadedGenerateData(const typename Superclass::OutputImageRegionType& outputRegionForThread, ThreadIdType threadId){ + + if(m_SeedActive){ + typename TInputImage1::ConstPointer input = dynamic_cast( ProcessObject::GetInput(0) ); + typename TOutputImage::Pointer output = this->GetOutput(); + + itk::ImageRegionConstIterator iti(input, outputRegionForThread); + itk::ImageRegionIterator ito(output, outputRegionForThread); + + // support progress methods/callbacks with 1000 updates + ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels(), 1000); + + while(!iti.IsAtEnd()){ + if(iti.Get() == m_SeedValue){ + ito.Set(m_DrawingColor); + } + ++iti; + ++ito; + progress.CompletedPixel(); + } + + m_UpdateFlag= true; + m_SeedActive= false; + //output->Modified(); + } + } + }// end namespace + +#endif //__itkJoinCopyFilter_cxx diff --git a/Logic/Common/itkJoinCopyFilter.h b/Logic/Common/itkJoinCopyFilter.h new file mode 100644 index 00000000..5b0a4150 --- /dev/null +++ b/Logic/Common/itkJoinCopyFilter.h @@ -0,0 +1,73 @@ +#ifndef __itkJoinCopyFilter_h +#define __itkJoinCopyFilter_h + +#include + +namespace itk{ + /** \class JoinCopyFilter + * \brief: sets DrawingColor in output image if input pixel equals SeedValue + * + * \ingroup ImageFilters + */ + template + class JoinCopyFilter: + public InPlaceImageFilter{ + public: + /** Standard class typedefs. */ + typedef JoinCopyFilter Self; + typedef InPlaceImageFilter Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(JoinCopyFilter, InPlaceImageFilter); + + void SetJsrc(const TInputImage1 *image1); + void SetJdst(const TInputImage2 *image2); + + /** Set/Get SeedIndex value */ + itkSetMacro(SeedIndex, typename TInputImage1::IndexType); + itkGetConstMacro(SeedIndex, typename TInputImage1::IndexType); + + /** Set/Get DrawingColor value */ + itkSetMacro(DrawingColor, typename TOutputImage::ValueType); + itkGetConstMacro(DrawingColor, typename TOutputImage::ValueType); + + /** Get UpdateFlag value */ + itkGetConstMacro(UpdateFlag, bool); + + /** Get/Set SeedActive value */ + itkSetMacro(SeedActive, bool); + itkGetConstMacro(SeedActive, bool); + + protected: + JoinCopyFilter(); + ~JoinCopyFilter(){} + + bool m_SeedActive; + typename TInputImage1::IndexType m_SeedIndex; + typename TInputImage1::ValueType m_SeedValue; + typename TOutputImage::ValueType m_DrawingColor; + bool m_UpdateFlag; + + + virtual void BeforeThreadedGenerateData(); + virtual void ThreadedGenerateData(const typename Superclass::OutputImageRegionType& outputRegionForThread, ThreadIdType threadId); + + private: + JoinCopyFilter(const Self &); //purposely not implemented + void operator=(const Self &); //purposely not implemented + + }; + } //namespace ITK + + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkJoinCopyFilter.cxx" +#endif + +#endif // __itkJoinCopyFilter_h + diff --git a/Logic/Framework/IRISApplication.cxx b/Logic/Framework/IRISApplication.cxx index 5cf09dc2..ce8f2ce4 100644 --- a/Logic/Framework/IRISApplication.cxx +++ b/Logic/Framework/IRISApplication.cxx @@ -289,10 +289,34 @@ ::InitializeJOINImageData(const SNAPSegmentationROISettings &roi, int CnJMode, c // Remember the ROI object m_GlobalState->SetSegmentationROISettings(roi); + // Initialize JoinCopyFilter + m_JOINImageData->InitializeJoinCF(); + // The set of layers has changed InvokeEvent(LayerChangeEvent()); } +bool +IRISApplication +::ExecuteCnJCopy(JsrcImageWrapper::ImageType::IndexType SeedIndex) +{ + assert(m_JOINImageData->IsJsrcLoaded()); + + GlobalState *gs = GetGlobalState(); + + // Get the paint properties + LabelType drawing_color = gs->GetDrawingColorLabel(); + DrawOverFilter drawover = gs->GetDrawOverFilter(); + + m_JOINImageData->GetJoinCF()->SetSeedIndex(SeedIndex); + m_JOINImageData->GetJoinCF()->SetDrawingColor(drawing_color); + m_JOINImageData->GetJoinCF()->SetSeedActive(true); + m_JOINImageData->GetJoinCF()->Update(); + + InvokeEvent(LayerChangeEvent()); + return m_JOINImageData->GetJoinCF()->GetUpdateFlag(); +} + void IRISApplication ::CopySegementationToJsrc(const SNAPSegmentationROISettings &roi, diff --git a/Logic/Framework/IRISApplication.h b/Logic/Framework/IRISApplication.h index 1accd45b..3f55fd29 100644 --- a/Logic/Framework/IRISApplication.h +++ b/Logic/Framework/IRISApplication.h @@ -46,6 +46,7 @@ #include "SystemInterface.h" #include "UndoDataManager.h" #include "SNAPEvents.h" +#include "JOINImageData.h" //for JsrcImageWrapper::ImageType::IndexType // #include "itkImage.h" @@ -320,6 +321,11 @@ class IRISApplication : public itk::Object void InitializeJOINImageData(const SNAPSegmentationROISettings &roi, int CnJMode, const char* FileName, CommandType *progressCommand = NULL); + /** + * Execute CnJ CopyFilter + */ + bool ExecuteCnJCopy(JsrcImageWrapper::ImageType::IndexType SeedIndex); + /** * Copy Segmentation to Jsrc for JOIN-mode 0 */ diff --git a/Logic/Framework/JOINImageData.cxx b/Logic/Framework/JOINImageData.cxx index 4da628ac..694958b9 100644 --- a/Logic/Framework/JOINImageData.cxx +++ b/Logic/Framework/JOINImageData.cxx @@ -301,4 +301,26 @@ void JOINImageData::UnloadAll(){ InvokeEvent(LayerChangeEvent()); } + +void +JOINImageData +::InitializeJoinCF(){ + ////make sure Jsrc and Jdst exist + assert(IsJsrcLoaded()); + assert(IsJdstLoaded()); + + ////Initialize JoinCopyFilter + m_JoinCF= JoinCopyFilterType::New(); + m_JoinCF->SetJsrc(m_JsrcWrapper->GetImage()); + m_JoinCF->SetJdst(m_JdstWrapper->GetImage()); + m_JdstWrapper->SetImage(m_JoinCF->GetOutput()); + m_JdstWrapper->GetImage()->Modified(); + m_JoinCF->InPlaceOn(); //adjust Jdst directly + } + +JOINImageData::JoinCopyFilterPointer +JOINImageData::GetJoinCF(){ + ////todo: introduce check if m_JoinCF was initialized + return m_JoinCF; + } diff --git a/Logic/Framework/JOINImageData.h b/Logic/Framework/JOINImageData.h index cf430a63..5dfbac21 100644 --- a/Logic/Framework/JOINImageData.h +++ b/Logic/Framework/JOINImageData.h @@ -39,6 +39,7 @@ #include "GenericImageData.h" #include "itkImageAdaptor.h" +#include "itkJoinCopyFilter.h" /** * \class JOINImageData @@ -57,6 +58,9 @@ class JOINImageData : public GenericImageData typedef JdstImageWrapper::ImageType JdstImageType; typedef WsrcImageWrapper::ImageType WsrcImageType; + typedef itk::JoinCopyFilter JoinCopyFilterType; + typedef JoinCopyFilterType::Pointer JoinCopyFilterPointer; + /** Initialize to a ROI from another image data object */ void InitializeToROI(GenericImageData *source, const SNAPSegmentationROISettings &roi, @@ -88,6 +92,8 @@ class JOINImageData : public GenericImageData bool IsWsrcLoaded(); void SetWsrcSticky(bool sticky); + void InitializeJoinCF(); + JoinCopyFilterType::Pointer GetJoinCF(); protected: @@ -102,6 +108,9 @@ class JOINImageData : public GenericImageData // GWS source image SmartPtr m_WsrcWrapper; + + JoinCopyFilterPointer m_JoinCF; + }; diff --git a/todo b/todo index 06b7f56c..8516173d 100644 --- a/todo +++ b/todo @@ -1,5 +1,12 @@ TODOs for GWS: +- implement JoinCopyFilter (templated over dimension) +-- multi-threaded ImageRegionIterator +-- multi-threaded ImageScanlineIterator +-- FloodFilledImageFunctionConditionalIterator (Modules/Segmentation/RegionGrowing/include/itkConnectedThresholdImageFilter.hxx) +--- add 2D/3D option to GUI + implementation +- optimize CopySegementationToJdst and CopySegementationToJsrc + - combine mode 2 with mode 0 and add extra button for "LoadImageToJsrc" -- restructure JoinDataPanel to have two main buttons: CnJ from Seg. or File OR CnJ from gWS - add 'n' for next smallest unused label see eg m_Wrapper->GetHistogram(nBins) in ./Logic/ImageWrapper/DisplayMappingPolicy.cxx