From: Leonardo Florez-Valencia Date: Mon, 8 Dec 2014 21:23:50 +0000 (+0100) Subject: Basic IO architecture within itk-based pipelines X-Git-Tag: v0.1~449 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=cf8ebcdb1e31f332e74569b2be5dfb5f5100df07;p=cpPlugins.git Basic IO architecture within itk-based pipelines --- diff --git a/appli/examples/example_ReadWriteImage.cxx b/appli/examples/example_ReadWriteImage.cxx index 4d5987b..e07761c 100644 --- a/appli/examples/example_ReadWriteImage.cxx +++ b/appli/examples/example_ReadWriteImage.cxx @@ -67,6 +67,19 @@ int main( int argc, char* argv[] ) reader_params[ "IsColorImage" ].second = ( is_color )? "1": "0"; reader->SetParameters( reader_params ); + // Configure reader + TParameters writer_params = writer->GetDefaultParameters( ); + writer_params[ "FileName" ].second = output_image_file; + writer->SetParameters( writer_params ); + + // Connect pipeline + writer->SetInput( 0, reader->GetOutput( 0 ) ); + + std::string msg = writer->Update( ); + + if( msg != "" ) + std::cerr << "ERROR: " << msg << std::endl; + // Free memory delete writer; delete reader; diff --git a/lib/cpPlugins/Interface/DataObject.cxx b/lib/cpPlugins/Interface/DataObject.cxx index 0b64bec..9c15346 100644 --- a/lib/cpPlugins/Interface/DataObject.cxx +++ b/lib/cpPlugins/Interface/DataObject.cxx @@ -21,9 +21,23 @@ GetClassName( ) const return( "cpPlugins::Interface::DataObject" ); } +// ------------------------------------------------------------------------- +itk::DataObject* cpPlugins::Interface::DataObject:: +GetDataObject( ) const +{ + return( this->m_DataObject ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::DataObject:: +SetDataObject( itk::DataObject* src ) +{ + this->m_DataObject = src; +} + // ------------------------------------------------------------------------- cpPlugins::Interface::ProcessObject* cpPlugins::Interface::DataObject:: -GetSource( ProcessObject* src ) const +GetSource( ) const { return( this->m_Source ); } @@ -35,6 +49,4 @@ SetSource( cpPlugins::Interface::ProcessObject* src ) this->m_Source = src; } -#endif // __CPPLUGINS__INTERFACE__DATAOBJECT__H__ - // eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/DataObject.h b/lib/cpPlugins/Interface/DataObject.h index 359b2b4..9a8901e 100644 --- a/lib/cpPlugins/Interface/DataObject.h +++ b/lib/cpPlugins/Interface/DataObject.h @@ -28,7 +28,7 @@ namespace cpPlugins virtual std::string GetClassName( ) const; itk::DataObject* GetDataObject( ) const; - void SetDataObject( itk::DataObject* src ); + virtual void SetDataObject( itk::DataObject* src ); ProcessObject* GetSource( ) const; void SetSource( ProcessObject* src ); diff --git a/lib/cpPlugins/Interface/Image.h b/lib/cpPlugins/Interface/Image.h index e69de29..360da01 100644 --- a/lib/cpPlugins/Interface/Image.h +++ b/lib/cpPlugins/Interface/Image.h @@ -0,0 +1,35 @@ +#ifndef __CPPLUGINS__INTERFACE__IMAGE__H__ +#define __CPPLUGINS__INTERFACE__IMAGE__H__ + +#include +#include +#include +#include + +namespace cpPlugins +{ + namespace Interface + { + /** + */ + class Image + : public DataObject + { + public: + typedef Image Self; + typedef DataObject Superclass; + + public: + Image( ); + virtual ~Image( ); + + virtual std::string GetClassName( ) const; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPPLUGINS__INTERFACE__IMAGE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/ProcessObject.cxx b/lib/cpPlugins/Interface/ProcessObject.cxx index cd88ea6..79fc2ab 100644 --- a/lib/cpPlugins/Interface/ProcessObject.cxx +++ b/lib/cpPlugins/Interface/ProcessObject.cxx @@ -1,4 +1,5 @@ #include +#include // ------------------------------------------------------------------------- cpPlugins::Interface::ProcessObject:: @@ -49,6 +50,26 @@ GetNumberOfOutputs( ) const return( this->m_Outputs.size( ) ); } +// ------------------------------------------------------------------------- +void cpPlugins::Interface::ProcessObject:: +SetNumberOfInputs( unsigned int n ) +{ + this->m_Inputs.clear( ); + this->m_Inputs.resize( n, NULL ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::ProcessObject:: +SetNumberOfOutputs( unsigned int n ) +{ + this->m_Outputs.clear( ); + this->m_Outputs.resize( n ); + + // Sync outputs with this source + for( unsigned int odx = 0; odx < this->m_Outputs.size( ); ++odx ) + this->m_Outputs[ odx ].SetSource( this ); +} + // ------------------------------------------------------------------------- void cpPlugins::Interface::ProcessObject:: SetInput( @@ -61,10 +82,10 @@ SetInput( // ------------------------------------------------------------------------- cpPlugins::Interface::DataObject* cpPlugins::Interface::ProcessObject:: -GetOutput( unsigned int idx ) const +GetOutput( unsigned int idx ) { if( idx < this->m_Outputs.size( ) ) - return( this->m_Outputs[ idx ] ); + return( &( this->m_Outputs[ idx ] ) ); else return( NULL ); } @@ -75,17 +96,31 @@ Update( ) { // Force upstream updates for( unsigned int idx = 0; idx < this->m_Inputs.size( ); ++idx ) - this->m_Inputs->GetSource( )->Update( ); + this->m_Inputs[ idx ]->GetSource( )->Update( ); // Current update std::string ret = this->_GenerateData( ); - // Sync outputs - for( unsigned int odx = 0; odx < this->m_Outputs.size( ); ++odx ) - this->m_Outputs->SetSource( this ); - + // Return error description, if any return( ret ); } +// ------------------------------------------------------------------------- +itk::DataObject* cpPlugins::Interface::ProcessObject:: +_GetInput( unsigned int idx ) +{ + if( idx < this->m_Inputs.size( ) ) + return( this->m_Inputs[ idx ]->GetDataObject( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface::ProcessObject:: +_SetOutput( unsigned int idx, itk::DataObject* dobj ) +{ + if( idx < this->m_Outputs.size( ) ) + this->m_Outputs[ idx ].SetDataObject( dobj ); +} // eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/ProcessObject.h b/lib/cpPlugins/Interface/ProcessObject.h index 3137913..362cd76 100644 --- a/lib/cpPlugins/Interface/ProcessObject.h +++ b/lib/cpPlugins/Interface/ProcessObject.h @@ -3,6 +3,7 @@ #include #include +#include #include namespace cpPlugins @@ -34,12 +35,17 @@ namespace cpPlugins virtual unsigned int GetNumberOfInputs( ) const; virtual unsigned int GetNumberOfOutputs( ) const; + virtual void SetNumberOfInputs( unsigned int n ); + virtual void SetNumberOfOutputs( unsigned int n ); + virtual void SetInput( unsigned int idx, const DataObject* dobj ); - virtual DataObject* GetOutput( unsigned int idx ) const; + virtual DataObject* GetOutput( unsigned int idx ); virtual std::string Update( ); protected: + virtual itk::DataObject* _GetInput( unsigned int idx ); + virtual void _SetOutput( unsigned int idx, itk::DataObject* dobj ); virtual std::string _GenerateData( ) = 0; protected: @@ -47,7 +53,7 @@ namespace cpPlugins TParameters m_Parameters; std::vector< const DataObject* > m_Inputs; - std::vector< DataObject* > m_Outputs; + std::vector< DataObject > m_Outputs; }; } // ecapseman diff --git a/lib/cpPlugins/Interface/SinkObject.h b/lib/cpPlugins/Interface/SinkObject.h index e69de29..38801df 100644 --- a/lib/cpPlugins/Interface/SinkObject.h +++ b/lib/cpPlugins/Interface/SinkObject.h @@ -0,0 +1,35 @@ +#ifndef __CPPLUGINS__INTERFACE__SINKOBJECT__H__ +#define __CPPLUGINS__INTERFACE__SINKOBJECT__H__ + +#include + +namespace cpPlugins +{ + namespace Interface + { + /** + */ + class SinkObject + : public ProcessObject + { + public: + typedef SinkObject Self; + typedef ProcessObject Superclass; + + typedef Superclass::TParameter TParameter; + typedef Superclass::TParameters TParameters; + + public: + SinkObject( ); + virtual ~SinkObject( ); + + virtual std::string GetClassName( ) const; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPPLUGINS__INTERFACE__SINKOBJECT__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface/SourceObject.cxx b/lib/cpPlugins/Interface/SourceObject.cxx index b798def..b4499db 100644 --- a/lib/cpPlugins/Interface/SourceObject.cxx +++ b/lib/cpPlugins/Interface/SourceObject.cxx @@ -5,6 +5,7 @@ cpPlugins::Interface::SourceObject:: SourceObject( ) : Superclass( ) { + this->SetNumberOfInputs( 0 ); } // ------------------------------------------------------------------------- diff --git a/lib/cpPlugins/Plugins/ImageReader.cxx b/lib/cpPlugins/Plugins/ImageReader.cxx index 5bc182e..feca19b 100644 --- a/lib/cpPlugins/Plugins/ImageReader.cxx +++ b/lib/cpPlugins/Plugins/ImageReader.cxx @@ -10,6 +10,8 @@ cpPlugins::Plugins::ImageReader:: ImageReader( ) : Superclass( ) { + this->SetNumberOfOutputs( 1 ); + this->m_DefaultParameters[ "FileName" ] = TParameter( "string", "no_file_name" ); this->m_DefaultParameters[ "PixelType" ] = TParameter( "type", "uchar" ); @@ -31,8 +33,8 @@ GetClassName( ) const } // ------------------------------------------------------------------------- -bool cpPlugins::Plugins::ImageReader:: -Update( ) +std::string cpPlugins::Plugins::ImageReader:: +_GenerateData( ) { TParameters::const_iterator dIt; @@ -41,19 +43,19 @@ Update( ) if( dIt == this->m_Parameters.end( ) ) dIt = this->m_DefaultParameters.find( "ImageDimension" ); - bool ret = false; - if ( dIt->second.second == "1" ) ret = this->_Update0< 1 >( ); - else if( dIt->second.second == "2" ) ret = this->_Update0< 2 >( ); - else if( dIt->second.second == "3" ) ret = this->_Update0< 3 >( ); - else if( dIt->second.second == "4" ) ret = this->_Update0< 4 >( ); + std::string ret = "itk::Image dimension not supported."; + if ( dIt->second.second == "1" ) ret = this->_GenerateData0< 1 >( ); + else if( dIt->second.second == "2" ) ret = this->_GenerateData0< 2 >( ); + else if( dIt->second.second == "3" ) ret = this->_GenerateData0< 3 >( ); + else if( dIt->second.second == "4" ) ret = this->_GenerateData0< 4 >( ); return( ret ); } // ------------------------------------------------------------------------- template< unsigned int D > -bool cpPlugins::Plugins::ImageReader:: -_Update0( ) +std::string cpPlugins::Plugins::ImageReader:: +_GenerateData0( ) { TParameters::const_iterator tIt, cIt; @@ -65,60 +67,60 @@ _Update0( ) if( cIt == this->m_Parameters.end( ) ) cIt = this->m_DefaultParameters.find( "IsColorImage" ); - bool ret = false; + std::string ret = "itk::Image pixel type not supported"; if( cIt->second.second == "0" ) { if( tIt->second.second == "char" ) - ret = this->_Update1< char, D >( ); + ret = this->_GenerateData1< char, D >( ); else if( tIt->second.second == "short" ) - ret = this->_Update1< short, D >( ); + ret = this->_GenerateData1< short, D >( ); else if( tIt->second.second == "int" ) - ret = this->_Update1< int, D >( ); + ret = this->_GenerateData1< int, D >( ); else if( tIt->second.second == "long" ) - ret = this->_Update1< long, D >( ); + ret = this->_GenerateData1< long, D >( ); else if( tIt->second.second == "uchar" ) - ret = this->_Update1< unsigned char, D >( ); + ret = this->_GenerateData1< unsigned char, D >( ); else if( tIt->second.second == "ushort" ) - ret = this->_Update1< unsigned short, D >( ); + ret = this->_GenerateData1< unsigned short, D >( ); else if( tIt->second.second == "uint" ) - ret = this->_Update1< unsigned int, D >( ); + ret = this->_GenerateData1< unsigned int, D >( ); else if( tIt->second.second == "ulong" ) - ret = this->_Update1< unsigned long, D >( ); + ret = this->_GenerateData1< unsigned long, D >( ); else if( tIt->second.second == "float" ) - ret = this->_Update1< float, D >( ); + ret = this->_GenerateData1< float, D >( ); else if( tIt->second.second == "double" ) - ret = this->_Update1< double, D >( ); + ret = this->_GenerateData1< double, D >( ); } else if( cIt->second.second == "1" ) { if( tIt->second.second == "char" ) - ret = this->_Update1< itk::RGBPixel< char >, D >( ); + ret = this->_GenerateData1< itk::RGBPixel< char >, D >( ); else if( tIt->second.second == "short" ) - ret = this->_Update1< itk::RGBPixel< short >, D >( ); + ret = this->_GenerateData1< itk::RGBPixel< short >, D >( ); else if( tIt->second.second == "int" ) - ret = this->_Update1< itk::RGBPixel< int >, D >( ); + ret = this->_GenerateData1< itk::RGBPixel< int >, D >( ); else if( tIt->second.second == "long" ) - ret = this->_Update1< itk::RGBPixel< long >, D >( ); + ret = this->_GenerateData1< itk::RGBPixel< long >, D >( ); else if( tIt->second.second == "uchar" ) - ret = this->_Update1< itk::RGBPixel< unsigned char >, D >( ); + ret = this->_GenerateData1< itk::RGBPixel< unsigned char >, D >( ); else if( tIt->second.second == "ushort" ) - ret = this->_Update1< itk::RGBPixel< unsigned short >, D >( ); + ret = this->_GenerateData1< itk::RGBPixel< unsigned short >, D >( ); else if( tIt->second.second == "uint" ) - ret = this->_Update1< itk::RGBPixel< unsigned int >, D >( ); + ret = this->_GenerateData1< itk::RGBPixel< unsigned int >, D >( ); else if( tIt->second.second == "ulong" ) - ret = this->_Update1< itk::RGBPixel< unsigned long >, D >( ); + ret = this->_GenerateData1< itk::RGBPixel< unsigned long >, D >( ); else if( tIt->second.second == "float" ) - ret = this->_Update1< itk::RGBPixel< float >, D >( ); + ret = this->_GenerateData1< itk::RGBPixel< float >, D >( ); else if( tIt->second.second == "double" ) - ret = this->_Update1< itk::RGBPixel< double >, D >( ); + ret = this->_GenerateData1< itk::RGBPixel< double >, D >( ); } // fi return( ret ); } // ------------------------------------------------------------------------- template< class P, unsigned int D > -bool cpPlugins::Plugins::ImageReader:: -_Update1( ) +std::string cpPlugins::Plugins::ImageReader:: +_GenerateData1( ) { TParameters::const_iterator fIt; @@ -145,10 +147,11 @@ _Update1( ) } catch( itk::ExceptionObject& err ) { - return( false ); + return( err.GetDescription( ) ); } // yrt - return( true ); + this->_SetOutput( 0, reader->GetOutput( ) ); + return( "" ); } // eof - $RCSfile$ diff --git a/lib/cpPlugins/Plugins/ImageReader.h b/lib/cpPlugins/Plugins/ImageReader.h index 6110c92..4ecdfab 100644 --- a/lib/cpPlugins/Plugins/ImageReader.h +++ b/lib/cpPlugins/Plugins/ImageReader.h @@ -28,13 +28,13 @@ namespace cpPlugins protected: - virtual bool _GenerateData( ); + virtual std::string _GenerateData( ); template< unsigned int D > - bool _GenerateData0( ); + std::string _GenerateData0( ); template< class P, unsigned int D > - bool _GenerateData1( ); + std::string _GenerateData1( ); protected: itk::ProcessObject::Pointer m_Reader; diff --git a/lib/cpPlugins/Plugins/ImageWriter.cxx b/lib/cpPlugins/Plugins/ImageWriter.cxx index 3dd319a..e4af224 100644 --- a/lib/cpPlugins/Plugins/ImageWriter.cxx +++ b/lib/cpPlugins/Plugins/ImageWriter.cxx @@ -1,10 +1,34 @@ #include +// TODO: interesting... #define ITK_MANUAL_INSTANTIATION +#include +#include +#include + +// ------------------------------------------------------------------------- +#define cpPlugins_Plugins_ImageWriter_Dimension( ret, d, dobj, func ) \ + if( dynamic_cast< itk::ImageBase< d >* >( dobj ) != NULL ) \ + ret = this->func< d >( ) + +// ------------------------------------------------------------------------- +#define cpPlugins_Plugins_ImageWriter_Pixel( ret, p, d, dobj, func ) \ + if( dynamic_cast< itk::Image< p, d >* >( dobj ) != NULL ) \ + ret = this->func< p, d >( ) + +// ------------------------------------------------------------------------- +#define cpPlugins_Plugins_ImageWriter_RGB( ret, p, d, dobj, func ) \ + if( dynamic_cast< itk::Image< itk::RGBPixel< p >, d >* >( dobj ) != NULL ) \ + ret = this->func< itk::RGBPixel< p >, d >( ) + // ------------------------------------------------------------------------- cpPlugins::Plugins::ImageWriter:: ImageWriter( ) : Superclass( ) { + this->SetNumberOfInputs( 1 ); + + this->m_DefaultParameters[ "FileName" ] = + TParameter( "string", "no_file_name" ); } // ------------------------------------------------------------------------- @@ -21,10 +45,88 @@ GetClassName( ) const } // ------------------------------------------------------------------------- -bool cpPlugins::Plugins::ImageWriter:: -Update( ) +std::string cpPlugins::Plugins::ImageWriter:: +_GenerateData( ) +{ + itk::DataObject* dobj = this->_GetInput( 0 ); + + std::string ret = "itk::Image dimension not supported."; + cpPlugins_Plugins_ImageWriter_Dimension( ret, 1, dobj, _GenerateData0 ); + else cpPlugins_Plugins_ImageWriter_Dimension( ret, 2, dobj, _GenerateData0 ); + else cpPlugins_Plugins_ImageWriter_Dimension( ret, 3, dobj, _GenerateData0 ); + else cpPlugins_Plugins_ImageWriter_Dimension( ret, 4, dobj, _GenerateData0 ); + + return( ret ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +std::string cpPlugins::Plugins::ImageWriter:: +_GenerateData0( ) +{ + itk::ImageBase< D >* img = + dynamic_cast< itk::ImageBase< D >* >( this->_GetInput( 0 ) ); + + std::string ret = "itk::Image pixel type not supported"; + cpPlugins_Plugins_ImageWriter_Pixel( ret, char, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_Pixel( ret, short, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_Pixel( ret, int, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_Pixel( ret, long, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_Pixel( ret, unsigned char, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_Pixel( ret, unsigned short, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_Pixel( ret, unsigned int, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_Pixel( ret, unsigned long, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_Pixel( ret, float, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_Pixel( ret, double, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_RGB( ret, char, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_RGB( ret, short, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_RGB( ret, int, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_RGB( ret, long, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_RGB( ret, unsigned char, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_RGB( ret, unsigned short, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_RGB( ret, unsigned int, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_RGB( ret, unsigned long, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_RGB( ret, float, D, img, _GenerateData1 ); + else cpPlugins_Plugins_ImageWriter_RGB( ret, double, D, img, _GenerateData1 ); + + return( ret ); +} + +// ------------------------------------------------------------------------- +template< class P, unsigned int D > +std::string cpPlugins::Plugins::ImageWriter:: +_GenerateData1( ) { - return( false ); + typedef itk::Image< P, D > _TImage; + typedef itk::ImageFileWriter< _TImage > _TImageWriter; + + TParameters::const_iterator fIt; + + // Get image pixelType + fIt = this->m_Parameters.find( "FileName" ); + if( fIt == this->m_Parameters.end( ) ) + fIt = this->m_DefaultParameters.find( "FileName" ); + + _TImageWriter* writer = + dynamic_cast< _TImageWriter* >( this->m_Writer.GetPointer( ) ); + if( writer == NULL ) + { + this->m_Writer = _TImageWriter::New( ); + writer = dynamic_cast< _TImageWriter* >( this->m_Writer.GetPointer( ) ); + + } // fi + writer->SetFileName( fIt->second.second ); + writer->SetInput( dynamic_cast< _TImage* >( this->_GetInput( 0 ) ) ); + try + { + writer->Update( ); + } + catch( itk::ExceptionObject& err ) + { + return( err.GetDescription( ) ); + + } // yrt + return( "" ); } // eof - $RCSfile$ diff --git a/lib/cpPlugins/Plugins/ImageWriter.h b/lib/cpPlugins/Plugins/ImageWriter.h index af80058..78f00ef 100644 --- a/lib/cpPlugins/Plugins/ImageWriter.h +++ b/lib/cpPlugins/Plugins/ImageWriter.h @@ -1,7 +1,8 @@ #ifndef __CPPLUGINS__PLUGINS__IMAGEWRITER__H__ #define __CPPLUGINS__PLUGINS__IMAGEWRITER__H__ -#include +#include +#include namespace cpPlugins { @@ -10,11 +11,11 @@ namespace cpPlugins /** */ class ImageWriter - : public cpPlugins::Interface::SourceObject + : public cpPlugins::Interface::SinkObject { public: - typedef ImageWriter Self; - typedef cpPlugins::Interface::SourceObject Superclass; + typedef ImageWriter Self; + typedef cpPlugins::Interface::SinkObject Superclass; typedef Superclass::TParameter TParameter; typedef Superclass::TParameters TParameters; @@ -24,7 +25,18 @@ namespace cpPlugins virtual ~ImageWriter( ); virtual std::string GetClassName( ) const; - virtual bool Update( ); + + protected: + virtual std::string _GenerateData( ); + + template< unsigned int D > + std::string _GenerateData0( ); + + template< class P, unsigned int D > + std::string _GenerateData1( ); + + protected: + itk::ProcessObject::Pointer m_Writer; }; // ---------------------------------------------------------------------