From 086f7237fe00e86de56b65492081bf6303bce220 Mon Sep 17 00:00:00 2001 From: Leonardo Florez-Valencia Date: Thu, 12 Nov 2015 18:30:50 -0500 Subject: [PATCH] OpenGL with opaque binary image... Soon to be plural --- appli/examples/CMakeLists.txt | 1 + appli/examples/example_HandleWidget.cxx | 2 +- appli/examples/example_SeedWidget.cxx | 2 +- appli/examples/example_SphereWidget.cxx | 2 +- appli/examples/example_Test_Memento.cxx | 4 +- appli/examples/example_View2DImage.cxx | 2 +- appli/examples/example_ViewImageThreshold.cxx | 141 ++++++++ .../Visualization/ImageBlender.cxx | 341 +++++------------- lib/cpExtensions/Visualization/ImageBlender.h | 75 +--- .../Visualization/ImageSliceActors.cxx | 322 ++++++++++++----- .../Visualization/ImageSliceActors.h | 27 +- lib/cpExtensions/Visualization/MPRActors.cxx | 4 +- 12 files changed, 502 insertions(+), 421 deletions(-) create mode 100644 appli/examples/example_ViewImageThreshold.cxx diff --git a/appli/examples/CMakeLists.txt b/appli/examples/CMakeLists.txt index 023d380..3292dd8 100644 --- a/appli/examples/CMakeLists.txt +++ b/appli/examples/CMakeLists.txt @@ -30,6 +30,7 @@ SET( example_MarchingCubes #example_MPR example_View2DImage + example_ViewImageThreshold example_HandleWidget example_SeedWidget example_SphereWidget diff --git a/appli/examples/example_HandleWidget.cxx b/appli/examples/example_HandleWidget.cxx index 692186a..e2dee09 100644 --- a/appli/examples/example_HandleWidget.cxx +++ b/appli/examples/example_HandleWidget.cxx @@ -94,7 +94,7 @@ int main( int argc, char* argv[] ) // Create slice actors vtkSmartPointer< TSliceActors > image_actors = vtkSmartPointer< TSliceActors >::New( ); - image_actors->AddInputData( image->GetVTK< vtkImageData >( ) ); + image_actors->SetInputImage( image->GetVTK< vtkImageData >( ) ); image_actors->SetAxis( 2 ); image_actors->PushActorsInto( window ); diff --git a/appli/examples/example_SeedWidget.cxx b/appli/examples/example_SeedWidget.cxx index 5c414a0..cb3c7e6 100644 --- a/appli/examples/example_SeedWidget.cxx +++ b/appli/examples/example_SeedWidget.cxx @@ -96,7 +96,7 @@ int main( int argc, char* argv[] ) // Create slice actors vtkSmartPointer< TSliceActors > image_actors = vtkSmartPointer< TSliceActors >::New( ); - image_actors->AddInputData( image->GetVTK< vtkImageData >( ) ); + image_actors->SetInputImage( image->GetVTK< vtkImageData >( ) ); image_actors->SetAxis( 2 ); image_actors->PushActorsInto( window ); diff --git a/appli/examples/example_SphereWidget.cxx b/appli/examples/example_SphereWidget.cxx index 73a800f..9276996 100644 --- a/appli/examples/example_SphereWidget.cxx +++ b/appli/examples/example_SphereWidget.cxx @@ -116,7 +116,7 @@ int main(int argc, char* argv[]) // Create slice actors image_actors = vtkSmartPointer< TSliceActors >::New(); - image_actors->AddInputData(image->GetVTK< vtkImageData >()); + image_actors->SetInputImage(image->GetVTK< vtkImageData >()); image_actors->SetAxis(2); image_actors->PushActorsInto(window); diff --git a/appli/examples/example_Test_Memento.cxx b/appli/examples/example_Test_Memento.cxx index edaf0ab..f5deefd 100644 --- a/appli/examples/example_Test_Memento.cxx +++ b/appli/examples/example_Test_Memento.cxx @@ -139,8 +139,8 @@ int main(int argc, char* argv[]) // Create slice actors vtkSmartPointer< TSliceActors > image_actors = vtkSmartPointer< TSliceActors >::New(); - //image_actors->AddInputData(image->GetVTK< vtkImageData >(), 2); - image_actors->AddInputData(retrievedImage); + //image_actors->SetInputImage(image->GetVTK< vtkImageData >(), 2); + image_actors->SetInputImage(retrievedImage); image_actors->SetAxis(2); image_actors->PushActorsInto(window); diff --git a/appli/examples/example_View2DImage.cxx b/appli/examples/example_View2DImage.cxx index 5e83271..ef6e36f 100644 --- a/appli/examples/example_View2DImage.cxx +++ b/appli/examples/example_View2DImage.cxx @@ -76,7 +76,7 @@ int main( int argc, char* argv[] ) // Create slice actors vtkSmartPointer< TSliceActors > image_actors = vtkSmartPointer< TSliceActors >::New( ); - image_actors->AddInputData( image->GetVTK< vtkImageData >( ) ); + image_actors->SetInputImage( image->GetVTK< vtkImageData >( ) ); image_actors->SetAxis( 2 ); image_actors->PushActorsInto( window ); diff --git a/appli/examples/example_ViewImageThreshold.cxx b/appli/examples/example_ViewImageThreshold.cxx new file mode 100644 index 0000000..9c7ffea --- /dev/null +++ b/appli/examples/example_ViewImageThreshold.cxx @@ -0,0 +1,141 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +// ------------------------------------------------------------------------- +typedef cpPlugins::Interface::Plugins TPlugins; +typedef cpPlugins::Interface::Image TImage; +typedef cpExtensions::Visualization::ImageSliceActors TSliceActors; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + if( argc < 5 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " plugins_file input_image lower upper" + << std::endl; + return( 1 ); + + } // fi + std::string plugins_file = argv[ 1 ]; + double lower = std::atof( argv[ argc - 2 ] ); + double upper = std::atof( argv[ argc - 1 ] ); + + // Load plugins + cpPlugins::Interface::Plugins plugins; + if( !plugins.LoadPluginsPath( plugins_file ) ) + { + std::cerr << "Failed to load plugins." << std::endl; + return( 1 ); + + } // fi + + // Associate filenames + std::vector< std::string > fnames; + for( int i = 2; i < argc - 2; ++i ) + fnames.push_back( argv[ i ] ); + + // Read image + std::string image_name = ""; + try + { + image_name = plugins.ReadImage( fnames, "" ); + } + catch( std::exception& err ) + { + std::cerr << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Apply a two-level threshold + std::string filter_name = + "cpPlugins::BasicFilters::BinaryThresholdImageFilter"; + + if( !( plugins.ActivateFilter( filter_name ) ) ) + { + std::cerr << "No filter found" << std::endl; + return( 1 ); + + } // fi + + // Connect inputs + TPlugins::TStringContainer input_names; + plugins.GetActiveFilterInputsNames( input_names ); + for( auto iIt = input_names.begin( ); iIt != input_names.end( ); ++iIt ) + plugins.ConnectInputInActiveFilter( image_name, *iIt ); + + // Configure + TPlugins::TParameters* filter_params = plugins.GetActiveFilterParameters( ); + filter_params->SetReal( "LowerThresholdValue", lower ); + filter_params->SetReal( "UpperThresholdValue", upper ); + filter_params->SetUint( "InsideValue", 1 ); + filter_params->SetUint( "OutsideValue", 0 ); + + // Execute + TPlugins::TStringContainer output_names; + try + { + if( !( plugins.UpdateActiveFilter( output_names, image_name ) ) ) + { + std::cerr << "Error executing filter." << std::endl; + return( 1 ); + + } // fi + } + catch( std::exception& err ) + { + std::cerr << err.what( ) << std::endl; + return( 1 ); + + } // yrt + std::string threshold_name = *( output_names.begin( ) ); + + // Get both images + TImage* image = plugins.GetData< TImage >( image_name ); + TImage* threshold = plugins.GetData< TImage >( threshold_name ); + + // Configure visualization objects + vtkSmartPointer< vtkRenderer > renderer = + vtkSmartPointer< vtkRenderer >::New( ); + renderer->SetBackground( 0.1, 0.3, 0.5 ); + + vtkSmartPointer< vtkRenderWindow > window = + vtkSmartPointer< vtkRenderWindow >::New( ); + window->AddRenderer( renderer ); + window->SetSize( 600, 600 ); + + // Set up the interaction + vtkSmartPointer< vtkRenderWindowInteractor > interactor = + vtkSmartPointer< vtkRenderWindowInteractor >::New( ); + window->SetInteractor( interactor ); + + // Create slice actors + vtkSmartPointer< TSliceActors > image_actors = + vtkSmartPointer< TSliceActors >::New( ); + image_actors->SetInputImage( image->GetVTK< vtkImageData >( ) ); + image_actors->AddBinaryImage( threshold->GetVTK< vtkImageData >( ), 1, 0, 1 ); + image_actors->SetAxis( 2 ); + image_actors->PushActorsInto( window ); + + // Begin interaction + image_actors->ResetCamera( ); + window->Render( ); + interactor->Start( ); + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageBlender.cxx b/lib/cpExtensions/Visualization/ImageBlender.cxx index 49292c8..ee4f616 100644 --- a/lib/cpExtensions/Visualization/ImageBlender.cxx +++ b/lib/cpExtensions/Visualization/ImageBlender.cxx @@ -1,7 +1,5 @@ #include -#include - #include #include #include @@ -17,90 +15,11 @@ New( ) return( new Self( ) ); } -// ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -PrintSelf( std::ostream& os, vtkIndent indent ) -{ - this->Superclass::PrintSelf( os, indent ); - - // Objects - os << indent << "Colors: " << std::endl; - auto i = this->Colors.begin( ); - for( ; i != this->Colors.end( ); ++i ) - os - << indent << indent << i->first << " : [" - << i->second.R << ", " - << i->second.G << ", " - << i->second.B << "]" - << std::endl; -} - -// ------------------------------------------------------------------------- -unsigned int cpExtensions::Visualization::ImageBlender:: -GetNumberOfImages( ) const -{ - return( - ( const_cast< Self* >( this ) )->GetNumberOfInputConnections( 0 ) - ); -} - -// ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -SetWindowLevel( const double& w, const double& l ) -{ - this->SetWindow( w ); - this->SetLevel( l ); -} - -// ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -GetColor( - const unsigned int& i, - double& r, - double& g, - double& b - ) const -{ - auto c = this->Colors.find( i ); - if( c != this->Colors.end( ) ) - { - r = c->second.R; - g = c->second.G; - b = c->second.B; - } - else - { - TColor c; - r = c.R; - g = c.G; - b = c.B; - - } // fi -} - -// ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -SetColor( - const unsigned int& i, - const double& r, - const double& g, - const double& b - ) -{ - this->Colors[ i ] = TColor( r, g, b ); - this->Modified( ); -} // ------------------------------------------------------------------------- cpExtensions::Visualization::ImageBlender:: ImageBlender( ) - : Superclass( ), - MaxWindow( double( 1 ) ), - MaxLevel( double( 1 ) ), - MinWindow( double( 0 ) ), - MinLevel( double( 0 ) ), - Window( double( 1 ) ), - Level( double( 0.5 ) ) + : Superclass( ) { this->SetNumberOfInputPorts( 1 ); } @@ -119,50 +38,92 @@ RequestInformation( vtkInformationVector* outputVector ) { - // Check number of inputs - int numInputs = this->GetNumberOfInputConnections( 0 ); - if( numInputs == 0 ) - return( 0 ); - - // Get input image - vtkInformation* inInfo = inputVector[ 0 ]->GetInformationObject( 0 ); - if( inInfo == NULL ) - return( 0 ); - vtkImageData* inData = vtkImageData::SafeDownCast( - inInfo->Get( vtkDataObject::DATA_OBJECT( ) ) - ); - if( inData == NULL ) + if( this->GetNumberOfInputConnections( 0 ) == 0 ) return( 0 ); - // Configure buffer extent - inData->GetExtent( this->m_Extent ); - this->m_Extent[ 1 ] -= this->m_Extent[ 0 ]; - this->m_Extent[ 3 ] -= this->m_Extent[ 2 ]; - this->m_Extent[ 5 ] -= this->m_Extent[ 4 ]; - this->m_Extent[ 1 ] += 1; - this->m_Extent[ 3 ] += 1; - this->m_Extent[ 5 ] += 1; - - // Configure window/level - this->m_WLSlope = double( 1 ) / this->Window; - this->m_WLOffset = double( 0.5 ) - ( this->Level / this->Window ); - - // Configure output type vtkDataObject::SetPointDataActiveScalarInfo( outputVector->GetInformationObject( 0 ), - VTK_UNSIGNED_CHAR, 3 + VTK_UNSIGNED_CHAR, + 1 ); return( 1 ); } +// ------------------------------------------------------------------------- +// Description: +// This templated function executes the filter for any type of data. +template< class T > +void cpExtensions_Visualization_ImageBlender_Execute( + cpExtensions::Visualization::ImageBlender* self, + vtkImageData** inDatas, int numInputs, vtkImageData* outData, + int outExt[ 6 ], int id, T* really_not_used + ) +{ + vtkImageIterator< T > inItsFast[ 256 ]; + T* inSIFast[ 256 ]; + vtkImageProgressIterator< T > outIt( outData, outExt, self, id ); + vtkImageIterator< T >* inIts; + T** inSI; + if( numInputs < 256 ) + { + inIts = inItsFast; + inSI = inSIFast; + } + else + { + inIts = new vtkImageIterator< T >[ numInputs ]; + inSI = new T*[ numInputs ]; + + } // fi + + // Loop through all input ImageData to initialize iterators + for( int i = 0; i < numInputs; ++i ) + inIts[ i ].Initialize( inDatas[ i ], outExt ); + + // Loop through output pixels + while( !outIt.IsAtEnd( ) ) + { + for( int j = 0; j < numInputs; ++j ) + inSI[ j ] = inIts[ j ].BeginSpan( ); + + T* outSI = outIt.BeginSpan( ); + T* outSIEnd = outIt.EndSpan( ); + + // Pixel operation + while( outSI != outSIEnd ) + { +#error TENER EN CUENTA EL ORDEN DE LAS IMAGENES PARA PONER COLORES + + double vmax = double( *inSI[ 0 ] ); + for( int k = 1; k < numInputs; ++k ) + vmax = ( vmax < double( *inSI[ k ] ) )? double( *inSI[ k ] ): vmax; + *outSI = static_cast< T >( vmax ); + outSI++; + for( int l = 0; l < numInputs; ++l ) + inSI[ l ]++; + + } // elihw + for( int j = 0; j < numInputs; ++j ) + inIts[ j ].NextSpan( ); + outIt.NextSpan( ); + + } // elihw + + if( numInputs >= 256) + { + delete [] inIts; + delete [] inSI; + + } // fi +} + // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageBlender:: ThreadedRequestData( vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector, - vtkImageData*** inData, - vtkImageData** outData, + vtkImageData*** inData, vtkImageData** outData, int outExt[ 6 ], int id ) { @@ -174,28 +135,20 @@ ThreadedRequestData( } // fi int numInputs = this->GetNumberOfInputConnections( 0 ); + int scalarType = inData[ 0 ][ 0 ]->GetScalarType( ); int numComp = inData[ 0 ][ 0 ]->GetNumberOfScalarComponents( ); - if( numComp > 1 ) - { - vtkErrorMacro( - "ThreadedRequestData: Input has " << numComp - << " components, but just 1 is supported" - ); - return; - - } // fi - for( int i = 1; i < numInputs; ++i ) { + int otherType = inData[ 0 ][ i ]->GetScalarType( ); int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( ); - if( otherComp != numComp ) + if( otherType != scalarType || otherComp != numComp ) { if( id == 0 ) vtkErrorMacro( "ThreadedRequestData: Input " << i - << " has " << otherComp - << " components, but input 0 has " << numComp - << " components" + << " has " << otherComp << " components of type " + << otherType << ", but input 0 has " << numComp + << " components of type " << scalarType ); return; @@ -203,8 +156,19 @@ ThreadedRequestData( } // rof - // Real update - this->_GenerateData( inData[ 0 ], numInputs, outData[ 0 ], outExt, id ); + switch( scalarType ) + { + vtkTemplateMacro( + cpExtensions_Visualization_ImageBlender_Execute( + this, inData[ 0 ], numInputs, + outData[ 0 ], outExt, id, static_cast< VTK_TT* >( 0 ) + ) + ); + default: + if( id == 0 ) + vtkErrorMacro( << "Execute: Unknown ScalarType" ); + return; + } // hctiws } // ------------------------------------------------------------------------- @@ -212,126 +176,7 @@ int cpExtensions::Visualization::ImageBlender:: FillInputPortInformation( int i, vtkInformation* info ) { info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 ); - return( this->Superclass::FillInputPortInformation( i, info ) ); -} - - -// ------------------------------------------------------------------------- -#define cpExtensions_ImageBlender_Type( O, V, T, B ) \ - O V = O( 0 ); \ - switch( T ) \ - { \ - case VTK_CHAR: \ - V = O( *( reinterpret_cast< char* >( B ) ) ); \ - break; \ - case VTK_SHORT: \ - V = O( *( reinterpret_cast< short* >( B ) ) ); \ - break; \ - case VTK_INT: \ - V = O( *( reinterpret_cast< int* >( B ) ) ); \ - break; \ - case VTK_LONG: \ - V = O( *( reinterpret_cast< long* >( B ) ) ); \ - break; \ - case VTK_UNSIGNED_CHAR: \ - V = O( *( reinterpret_cast< unsigned char* >( B ) ) ); \ - break; \ - case VTK_UNSIGNED_SHORT: \ - V = O( *( reinterpret_cast< unsigned short* >( B ) ) ); \ - break; \ - case VTK_UNSIGNED_INT: \ - V = O( *( reinterpret_cast< unsigned int* >( B ) ) ); \ - break; \ - case VTK_UNSIGNED_LONG: \ - V = O( *( reinterpret_cast< unsigned long* >( B ) ) ); \ - break; \ - case VTK_FLOAT: \ - V = O( *( reinterpret_cast< float* >( B ) ) ); \ - break; \ - case VTK_DOUBLE: \ - V = O( *( reinterpret_cast< double* >( B ) ) ); \ - break; \ - } - -// ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -_GenerateData( - vtkImageData** inDatas, - int numInputs, - vtkImageData* outData, - int outExt[ 6 ], - int id - ) -{ - static const double _0 = double( 0 ); - static const double _1 = double( 1 ); - static const double _255 = double( 255 ); - - unsigned char* mBuffer = - reinterpret_cast< unsigned char* >( inDatas[ 0 ]->GetScalarPointer( ) ); - unsigned char* oBuffer = - reinterpret_cast< unsigned char* >( outData->GetScalarPointer( ) ); - int mType = inDatas[ 0 ]->GetScalarType( ); - int mSize = inDatas[ 0 ]->GetScalarSize( ); - - double r, g, b; - int e13 = this->m_Extent[ 1 ] * this->m_Extent[ 3 ]; - for( int k = outExt[ 4 ]; k <= outExt[ 5 ]; ++k ) - { - int dk = ( k - this->m_Extent[ 4 ] ) * e13; - for( int j = outExt[ 2 ]; j <= outExt[ 3 ]; ++j ) - { - int dj = ( ( j - this->m_Extent[ 2 ] ) * this->m_Extent[ 3 ] ) + dk; - for( int i = outExt[ 0 ]; i <= outExt[ 1 ]; ++i ) - { - int di = ( i - this->m_Extent[ 0 ] ) + dj; - - // Get main value - cpExtensions_ImageBlender_Type( - double, v, mType, mBuffer + ( di * mSize ) - ); - v *= this->m_WLSlope; - v += this->m_WLOffset; - if( v < _0 ) v = _0; - if( v > _1 ) v = _1; - - // Prepare color - r = g = b = v; - - // Blend colors - for( int i = 1; i < numInputs; ++i ) - { - unsigned char* cBuffer = - reinterpret_cast< unsigned char* >( - inDatas[ i ]->GetScalarPointer( ) - ); - int cType = inDatas[ i ]->GetScalarType( ); - int cSize = inDatas[ i ]->GetScalarSize( ); - cpExtensions_ImageBlender_Type( - double, c, cType, cBuffer + ( di * cSize ) - ); - if( c > double( 0 ) ) - { - TColor rgb = this->Colors[ i ]; - r *= rgb.R * rgb.N; - g *= rgb.G * rgb.N; - b *= rgb.B * rgb.N; - - } // fi - - } // rof - - // Update color - int di3 = di * 3; - oBuffer[ di3 + 0 ] = static_cast< unsigned char >( r * _255 ); - oBuffer[ di3 + 1 ] = static_cast< unsigned char >( g * _255 ); - oBuffer[ di3 + 2 ] = static_cast< unsigned char >( b * _255 ); - - } // rof - - } // rof - - } // rof + return( this->Superclass::FillInputPortInformation( i,info ) ); } // eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageBlender.h b/lib/cpExtensions/Visualization/ImageBlender.h index 7ccc864..c49c62e 100644 --- a/lib/cpExtensions/Visualization/ImageBlender.h +++ b/lib/cpExtensions/Visualization/ImageBlender.h @@ -3,8 +3,7 @@ #include -#include -#include +#include #include @@ -13,6 +12,7 @@ namespace cpExtensions namespace Visualization { /** + * @note: Based on vtkImageWeightedSum */ class cpExtensions_EXPORT ImageBlender : public vtkThreadedImageAlgorithm @@ -21,39 +21,8 @@ namespace cpExtensions typedef ImageBlender Self; vtkTypeMacro( ImageBlender, vtkThreadedImageAlgorithm ); - vtkGetMacro( MaxWindow, double ); - vtkGetMacro( MaxLevel, double ); - vtkGetMacro( MinWindow, double ); - vtkGetMacro( MinLevel, double ); - vtkGetMacro( Window, double ); - vtkGetMacro( Level, double ); - - vtkSetMacro( MaxWindow, double ); - vtkSetMacro( MaxLevel, double ); - vtkSetMacro( MinWindow, double ); - vtkSetMacro( MinLevel, double ); - vtkSetMacro( Window, double ); - vtkSetMacro( Level, double ); - public: static Self* New( ); - void PrintSelf( std::ostream& os, vtkIndent indent ); - - unsigned int GetNumberOfImages( ) const; - void SetWindowLevel( const double& w, const double& l ); - - void GetColor( - const unsigned int& i, - double& r, - double& g, - double& b - ) const; - void SetColor( - const unsigned int& i, - const double& r, - const double& g, - const double& b - ); protected: ImageBlender( ); @@ -68,53 +37,15 @@ namespace cpExtensions vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector, - vtkImageData*** inData, - vtkImageData** outData, + vtkImageData*** inData, vtkImageData** outData, int outExt[ 6 ], int id ); int FillInputPortInformation( int i, vtkInformation* info ); - void _GenerateData( - vtkImageData** inDatas, - int numInputs, - vtkImageData* outData, - int outExt[ 6 ], - int id - ); - private: // Purposely not implemented. ImageBlender( const Self& other ); void operator=( const Self& other ); - - protected: - struct TColor - { - double R, G, B, N; - TColor( - const double& r = double( 1 ), - const double& g = double( 0 ), - const double& b = double( 0 ) - ) - : R( r ), - G( g ), - B( b ) - { - this->N = std::sqrt( ( r * r ) + ( g * g ) + ( b * b ) ); - } - }; - mutable std::map< unsigned int, TColor > Colors; - - double MaxWindow; - double MaxLevel; - double MinWindow; - double MinLevel; - double Window; - double Level; - - int m_Extent[ 6 ]; - double m_WLSlope; - double m_WLOffset; }; } // ecapseman diff --git a/lib/cpExtensions/Visualization/ImageSliceActors.cxx b/lib/cpExtensions/Visualization/ImageSliceActors.cxx index 374835d..c1f8523 100644 --- a/lib/cpExtensions/Visualization/ImageSliceActors.cxx +++ b/lib/cpExtensions/Visualization/ImageSliceActors.cxx @@ -1,5 +1,6 @@ #include +#include #include #include @@ -28,98 +29,168 @@ void cpExtensions::Visualization::ImageSliceActors:: SetAxis( int axis ) { this->m_ImageMapper->SetOrientation( axis ); + this->m_BlenderMapper->SetOrientation( axis ); this->m_ImageMapper->Update( ); + this->m_BlenderMapper->Update( ); this->SetSliceNumber( this->GetSliceNumberMinValue( ) ); this->m_ImageActor->Modified( ); + this->m_BlenderActor->Modified( ); this->Modified( ); this->ResetCamera( ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageSliceActors:: -AddInputConnection( vtkAlgorithmOutput* aout ) +SetInputConnection( vtkAlgorithmOutput* aout ) { // Get input vtkImageData if( aout == NULL ) return; // Create mapper and actors - this->m_ImageMapper = vtkSmartPointer< vtkImageSliceMapper >::New( ); this->m_ImageMapper->SetInputConnection( aout ); - this->m_ImageMapper->SetOrientation( 0 ); - this->m_ImageMapper->Update( ); - - // Create actor - this->m_ImageActor = vtkSmartPointer< vtkImageActor >::New( ); - this->m_ImageActor->SetMapper( this->m_ImageMapper ); - this->m_ImageActor->SetInterpolate( this->m_Interpolate ); - this->m_ImageActor->Modified( ); - - if( this->m_Style.GetPointer( ) != NULL ) - this->m_Style->AssociateImageActor( this->m_ImageActor ); - this->AddItem( this->m_ImageActor ); - - this->SetSliceNumber( this->GetSliceNumberMinValue( ) ); - this->ResetCursor( ); - this->Modified( ); - - // Update window/level ranges - vtkImageData* data = this->GetInputImage( ); - if( data != NULL ) - { - double r[ 2 ]; - data->GetScalarRange( r ); - this->m_WLRange[ 0 ] = double( 0 ); - this->m_WLRange[ 1 ] = r[ 1 ] - r[ 0 ]; - this->m_WLRange[ 2 ] = r[ 0 ]; - this->m_WLRange[ 3 ] = r[ 1 ]; - this->ResetWindowLevel( ); - - } // fi + this->_ConfigureInputImage( ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageSliceActors:: -AddInputData( vtkImageData* data ) +SetInputImage( vtkImageData* data ) { // Get input vtkImageData if( data == NULL ) return; // Create mapper and actors - this->m_ImageMapper = vtkSmartPointer< vtkImageSliceMapper >::New( ); this->m_ImageMapper->SetInputData( data ); - this->m_ImageMapper->SetOrientation( 0 ); - this->m_ImageMapper->Update( ); + this->_ConfigureInputImage( ); +} - // Create actor - this->m_ImageActor = vtkSmartPointer< vtkImageActor >::New( ); - this->m_ImageActor->SetMapper( this->m_ImageMapper ); - this->m_ImageActor->SetInterpolate( this->m_Interpolate ); - this->m_ImageActor->Modified( ); +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageSliceActors:: +AddBinaryConnection( + vtkAlgorithmOutput* aout, + const double& r, const double& g, const double& b + ) +{ +} - if( this->m_Style.GetPointer( ) != NULL ) - this->m_Style->AssociateImageActor( this->m_ImageActor ); - this->AddItem( this->m_ImageActor ); +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageSliceActors:: +AddBinaryImage( + vtkImageData* data, + const double& r, const double& g, const double& b + ) +{ + if( data == NULL ) + return( -1 ); - this->SetSliceNumber( this->GetSliceNumberMinValue( ) ); - this->ResetCursor( ); - this->Modified( ); + this->m_Blender->AddInputData( data ); - // Update window/level ranges - double r[ 2 ]; - data->GetScalarRange( r ); - this->m_WLRange[ 0 ] = double( 0 ); - this->m_WLRange[ 1 ] = r[ 1 ] - r[ 0 ]; - this->m_WLRange[ 2 ] = r[ 0 ]; - this->m_WLRange[ 3 ] = r[ 1 ]; - this->ResetWindowLevel( ); + unsigned int nValues = this->m_BlenderLUT->GetNumberOfTableValues( ); + this->m_BlenderLUT->SetNumberOfTableValues( nValues + 1 ); + this->m_BlenderLUT->SetTableValue( nValues, r, g, b, 0.5 ); + this->m_BlenderLUT->Build( ); + + this->m_BlenderLUT->Modified( ); + this->m_Blender->Modified( ); + this->m_Blender->Update( ); + + this->m_BlenderMapper->Modified( ); + this->m_BlenderActor->Modified( ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageSliceActors:: Clear( ) { + // Unbind from container + this->RemoveAllItems( ); + + // Filters and mappers + this->m_ImageMapper = vtkSmartPointer< vtkImageSliceMapper >::New( ); + this->m_ImageActor = vtkSmartPointer< vtkImageActor >::New( ); + this->m_Blender = vtkSmartPointer< TBlender >::New( ); + this->m_BlenderMapper = vtkSmartPointer< vtkImageSliceMapper >::New( ); + this->m_BlenderLUT = vtkSmartPointer< vtkLookupTable >::New( ); + this->m_BlenderActor = vtkSmartPointer< vtkImageActor >::New( ); + + this->m_ImageActor->SetMapper( this->m_ImageMapper ); + this->m_BlenderMapper-> + SetInputConnection( this->m_Blender->GetOutputPort( ) ); + + this->m_BlenderLUT->SetNumberOfTableValues( 1 ); + this->m_BlenderLUT->SetTableValue( 0, 0, 0, 0, 0 ); + this->m_BlenderLUT->Build( ); + + this->m_BlenderActor->SetMapper( this->m_BlenderMapper ); + this->m_BlenderActor->GetProperty( )->SetLookupTable( this->m_BlenderLUT ); + this->m_BlenderActor->GetProperty( )->UseLookupTableScalarRangeOn( ); + + // Remove associated objects + this->m_AssociatedSlices.clear( ); + + // White cursor + /* + vtkSmartPointer< vtkPoints > cursor_points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > cursor_lines = + vtkSmartPointer< vtkCellArray >::New( ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_lines->InsertNextCell( 2 ); + cursor_lines->InsertCellPoint( 0 ); + cursor_lines->InsertCellPoint( 1 ); + cursor_lines->InsertNextCell( 2 ); + cursor_lines->InsertCellPoint( 2 ); + cursor_lines->InsertCellPoint( 3 ); + cursor_lines->InsertNextCell( 2 ); + cursor_lines->InsertCellPoint( 4 ); + cursor_lines->InsertCellPoint( 5 ); + cursor_lines->InsertNextCell( 2 ); + cursor_lines->InsertCellPoint( 6 ); + cursor_lines->InsertCellPoint( 7 ); + + this->m_Cursor = vtkSmartPointer< vtkPolyData >::New( ); + this->m_CursorMapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->m_CursorActor = vtkSmartPointer< vtkActor >::New( ); + + this->m_Cursor->SetPoints( cursor_points ); + this->m_Cursor->SetLines( cursor_lines ); + this->m_CursorMapper->SetInputData( this->m_Cursor ); + this->m_CursorActor->SetMapper( this->m_CursorMapper ); + */ + + /* + vtkSmartPointer< vtkPolyDataMapper > m_CursorMapper; + vtkSmartPointer< vtkActor > m_CursorActor; + + vtkSmartPointer< vtkPolyData > m_HorizontalLine; + vtkSmartPointer< vtkPolyDataMapper > m_HorizontalLineMapper; + vtkSmartPointer< vtkActor > m_HorizontalLineActor; + + vtkSmartPointer< vtkPolyData > m_VerticalLine; + vtkSmartPointer< vtkPolyDataMapper > m_VerticalLineMapper; + vtkSmartPointer< vtkActor > m_VerticalLineActor; + + vtkSmartPointer< vtkPolyData > m_Plane; + vtkSmartPointer< vtkPolyDataMapper > m_PlaneMapper; + vtkSmartPointer< vtkActor > m_PlaneActor; + + char m_TextBuffer[ 1024 ]; + vtkSmartPointer< vtkTextActor > m_TextActor; + */ + + + + + + /* // Reset values this->m_VisibleExtent[ 0 ] = this->m_VisibleExtent[ 2 ] = @@ -134,9 +205,6 @@ Clear( ) this->m_VisibleBounds[ 3 ] = this->m_VisibleBounds[ 5 ] = double( 0 ); - // Unbind from container - this->RemoveAllItems( ); - // Delete all images this->m_ImageActor = NULL; this->m_ImageMapper = NULL; @@ -256,6 +324,7 @@ Clear( ) this->AddItem( this->m_VerticalLineActor ); this->AddItem( this->m_TextActor ); this->AddItem( this->m_PlaneActor ); + */ } // ------------------------------------------------------------------------- @@ -285,9 +354,7 @@ vtkImageData* cpExtensions::Visualization::ImageSliceActors:: GetInputImage( ) { if( this->m_ImageMapper.GetPointer( ) != NULL ) - return( - dynamic_cast< vtkImageData* >( this->m_ImageMapper->GetInput( ) ) - ); + return( this->m_ImageMapper->GetInput( ) ); else return( NULL ); } @@ -297,11 +364,7 @@ const vtkImageData* cpExtensions::Visualization::ImageSliceActors:: GetInputImage( ) const { if( this->m_ImageMapper.GetPointer( ) != NULL ) - return( - dynamic_cast< const vtkImageData* >( - this->m_ImageMapper->GetInput( ) - ) - ); + return( this->m_ImageMapper->GetInput( ) ); else return( NULL ); } @@ -323,15 +386,17 @@ PushActorsInto( vtkRenderWindow* window, bool force_style ) rwi->SetInteractorStyle( this->m_Style ); // Update actors - vtkProp* prop; - this->InitTraversal( ); - while( prop = this->GetNextProp( ) ) - renderer->AddViewProp( prop ); - renderer->Modified( ); - if( !force_style ) + renderer->AddViewProp( this->m_ImageActor ); + renderer->AddViewProp( this->m_BlenderActor ); + if( force_style ) { - renderer->RemoveViewProp( this->m_CursorActor ); - renderer->RemoveViewProp( this->m_TextActor ); + /* TODO + renderer->AddViewProp( this->m_CursorActor ); + renderer->AddViewProp( this->m_HorizontalLineActor ); + renderer->AddViewProp( this->m_VerticalLineActor ); + renderer->AddViewProp( this->m_PlaneActor ); + renderer->AddViewProp( this->m_TextActor ); + */ } // fi @@ -369,21 +434,23 @@ PushActorsInto( vtkRenderWindow* window, bool force_style ) void cpExtensions::Visualization::ImageSliceActors:: PopActorsFrom( vtkRenderWindow* window ) { - vtkRenderWindowInteractor* rwi = window->GetInteractor( ); - vtkRenderer* renderer = window->GetRenderers( )->GetFirstRenderer( ); - - if( renderer != NULL ) - { - // Update actors - vtkProp* prop; - this->InitTraversal( ); - while( prop = this->GetNextProp( ) ) - renderer->RemoveViewProp( prop ); - renderer->Modified( ); + /* TODO + vtkRenderWindowInteractor* rwi = window->GetInteractor( ); + vtkRenderer* renderer = window->GetRenderers( )->GetFirstRenderer( ); - } // fi - if( rwi != NULL ) - rwi->Render( ); + if( renderer != NULL ) + { + // Update actors + vtkProp* prop; + this->InitTraversal( ); + while( prop = this->GetNextProp( ) ) + renderer->RemoveViewProp( prop ); + renderer->Modified( ); + + } // fi + if( rwi != NULL ) + rwi->Render( ); + */ } // ------------------------------------------------------------------------- @@ -400,6 +467,20 @@ GetImageActor( ) const return( this->m_ImageActor ); } +// ------------------------------------------------------------------------- +vtkImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetBinaryActor( ) +{ + return( this->m_BlenderActor ); +} + +// ------------------------------------------------------------------------- +const vtkImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetBinaryActor( ) const +{ + return( this->m_BlenderActor ); +} + // ------------------------------------------------------------------------- vtkTextActor* cpExtensions::Visualization::ImageSliceActors:: GetTextActor( ) @@ -455,6 +536,7 @@ SetInterpolate( bool v ) if( this->m_Interpolate != v ) { this->m_ImageActor->SetInterpolate( v ); + this->m_BlenderActor->SetInterpolate( v ); this->m_Interpolate = v; this->Modified( ); @@ -502,6 +584,7 @@ GetDisplayBounds( double bounds[ 6 ] ) const void cpExtensions::Visualization::ImageSliceActors:: ResetCursor( ) { + /* TODO if( this->m_ImageMapper.GetPointer( ) != NULL ) { double bounds[ 6 ]; @@ -530,12 +613,14 @@ ResetCursor( ) this->m_CursorActor->Modified( ); } // fi + */ } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageSliceActors:: SetCursor( double pos[ 3 ] ) { + /* if( this->m_ImageMapper.GetPointer( ) == NULL ) return; @@ -574,6 +659,7 @@ SetCursor( double pos[ 3 ] ) this->m_Cursor->Modified( ); this->m_CursorMapper->Modified( ); this->m_CursorActor->Modified( ); + */ } // ------------------------------------------------------------------------- @@ -722,9 +808,11 @@ SetSliceNumber( const int& slice ) // Update mappers and display bounds this->m_ImageMapper->SetSliceNumber( slice ); + this->m_BlenderMapper->SetSliceNumber( slice ); this->m_ImageMapper->Modified( ); + this->m_BlenderMapper->Modified( ); this->m_ImageActor->Modified( ); - this->m_ImageMapper->Update( ); + this->m_BlenderActor->Modified( ); // Update display extent (this isn't done automatically) this->m_ImageMapper->GetInput( )->GetExtent( this->m_VisibleExtent ); @@ -762,6 +850,7 @@ SetSliceNumber( const int& slice ) double* bnds = this->m_VisibleBounds; // Configure visualization and implicit plane orientation + /* this->m_PlaneActor->GetProperty( )->SetRepresentationToWireframe( ); this->m_PlaneActor->GetProperty( )->SetLineWidth( 3 ); vtkPoints* plane_points = this->m_Plane->GetPoints( ); @@ -789,6 +878,7 @@ SetSliceNumber( const int& slice ) // Update text this->UpdateText( ); + */ // Update lines from associated slices /* TODO @@ -843,6 +933,7 @@ SetSlice( double* pos ) void cpExtensions::Visualization::ImageSliceActors:: UpdateText( ) { + /* TODO if( this->m_ImageMapper.GetPointer( ) != NULL ) { char axis; @@ -861,12 +952,14 @@ UpdateText( ) this->m_TextActor->SetInput( this->m_TextBuffer ); this->m_TextActor->Modified( ); this->Modified( ); + */ } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageSliceActors:: UpdateText( double pos[ 3 ] ) { + /* TODO if( this->m_ImageMapper.GetPointer( ) != NULL ) { char axis; @@ -917,12 +1010,14 @@ UpdateText( double pos[ 3 ] ) this->m_TextActor->SetInput( this->m_TextBuffer ); this->m_TextActor->Modified( ); this->Modified( ); +*/ } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageSliceActors:: UpdateText( const double& w, const double& l ) { + /* TODO if( this->m_ImageMapper.GetPointer( ) != NULL ) { char axis; @@ -941,6 +1036,7 @@ UpdateText( const double& w, const double& l ) this->m_TextActor->SetInput( this->m_TextBuffer ); this->m_TextActor->Modified( ); this->Modified( ); +*/ } // ------------------------------------------------------------------------- @@ -1001,6 +1097,50 @@ _ConfigureStyle( ) this->m_Style->AddLeaveCommand( Self::_LeaveCommand, this ); } +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_ConfigureInputImage( ) +{ + this->m_ImageMapper->SetOrientation( 0 ); + this->m_ImageMapper->Update( ); + + // Create actor + this->m_ImageActor->SetInterpolate( this->m_Interpolate ); + this->m_ImageActor->Modified( ); + + if( this->m_Style.GetPointer( ) != NULL ) + this->m_Style->AssociateImageActor( this->m_ImageActor ); + this->AddItem( this->m_ImageActor ); + + this->SetSliceNumber( this->GetSliceNumberMinValue( ) ); + this->ResetCursor( ); + this->Modified( ); + + // Update window/level ranges + vtkImageData* data = this->GetInputImage( ); + if( data != NULL ) + { + double r[ 2 ]; + data->GetScalarRange( r ); + this->m_WLRange[ 0 ] = double( 0 ); + this->m_WLRange[ 1 ] = r[ 1 ] - r[ 0 ]; + this->m_WLRange[ 2 ] = r[ 0 ]; + this->m_WLRange[ 3 ] = r[ 1 ]; + this->ResetWindowLevel( ); + + // Configure blender + this->m_BlenderBase = vtkSmartPointer< vtkImageData >::New( ); + this->m_BlenderBase->ShallowCopy( data ); + this->m_BlenderBase->AllocateScalars( VTK_UNSIGNED_CHAR, 1 ); + std::memset( + this->m_BlenderBase->GetScalarPointer( ), 0, + this->m_BlenderBase->GetActualMemorySize( ) + ); + this->m_Blender->AddInputData( this->m_BlenderBase ); + + } // fi +} + // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageSliceActors:: _MouseMoveCommand( @@ -1165,7 +1305,7 @@ _EnterCommand( void* data ) return; actors->ResetCursor( ); - actors->m_CursorActor->VisibilityOn( ); + // TODO: actors->m_CursorActor->VisibilityOn( ); actors->Render( 1e-3 ); } @@ -1178,7 +1318,7 @@ _LeaveCommand( void* data ) return; actors->ResetCursor( ); - actors->m_CursorActor->VisibilityOff( ); + // TODO: actors->m_CursorActor->VisibilityOff( ); actors->Render( 1e-3 ); } diff --git a/lib/cpExtensions/Visualization/ImageSliceActors.h b/lib/cpExtensions/Visualization/ImageSliceActors.h index ae5b352..378c7a3 100644 --- a/lib/cpExtensions/Visualization/ImageSliceActors.h +++ b/lib/cpExtensions/Visualization/ImageSliceActors.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include +#include // ------------------------------------------------------------------------- class vtkAlgorithmOutput; @@ -50,6 +52,8 @@ namespace cpExtensions typedef void ( *TWindowLevelCommand )( double, double, void* ); typedef TVoidCommand TRenderCommand; + typedef cpExtensions::Visualization::ImageBlender TBlender; + public: vtkTypeMacro( ImageSliceActors, vtkPropCollection ); @@ -62,8 +66,16 @@ namespace cpExtensions static ImageSliceActors* New( ); void SetAxis( int axis ); - void AddInputConnection( vtkAlgorithmOutput* aout ); - void AddInputData( vtkImageData* data ); + void SetInputConnection( vtkAlgorithmOutput* aout ); + void SetInputImage( vtkImageData* data ); + int AddBinaryConnection( + vtkAlgorithmOutput* aout, + const double& r, const double& g, const double& b + ); + int AddBinaryImage( + vtkImageData* data, + const double& r, const double& g, const double& b + ); void Clear( ); void AssociateSlice( Self* slice ); @@ -77,8 +89,11 @@ namespace cpExtensions void PushActorsInto( vtkRenderWindow* window, bool force_style = true ); void PopActorsFrom( vtkRenderWindow* window ); unsigned int GetNumberOfImages( ) const; + vtkImageActor* GetImageActor( ); const vtkImageActor* GetImageActor( ) const; + vtkImageActor* GetBinaryActor( ); + const vtkImageActor* GetBinaryActor( ) const; vtkTextActor* GetTextActor( ); const vtkTextActor* GetTextActor( ) const; vtkActor* GetPlaneActor( ); @@ -125,6 +140,7 @@ namespace cpExtensions virtual ~ImageSliceActors( ); void _ConfigureStyle( ); + void _ConfigureInputImage( ); // Events static void _MouseMoveCommand( @@ -162,6 +178,13 @@ namespace cpExtensions // Multiple actors vtkSmartPointer< vtkImageSliceMapper > m_ImageMapper; vtkSmartPointer< vtkImageActor > m_ImageActor; + + vtkSmartPointer< vtkImageData > m_BlenderBase; + vtkSmartPointer< TBlender > m_Blender; + vtkSmartPointer< vtkImageSliceMapper > m_BlenderMapper; + vtkSmartPointer< vtkLookupTable > m_BlenderLUT; + vtkSmartPointer< vtkImageActor > m_BlenderActor; + bool m_Interpolate; double m_WLRange[ 4 ]; diff --git a/lib/cpExtensions/Visualization/MPRActors.cxx b/lib/cpExtensions/Visualization/MPRActors.cxx index c0e8333..53b77e1 100644 --- a/lib/cpExtensions/Visualization/MPRActors.cxx +++ b/lib/cpExtensions/Visualization/MPRActors.cxx @@ -35,7 +35,7 @@ AddInputConnection( vtkAlgorithmOutput* aout ) { for( unsigned int j = 0; j < 3; ++j ) { - this->Slices[ i ][ j ]->AddInputConnection( aout ); + this->Slices[ i ][ j ]->SetInputConnection( aout ); this->Slices[ i ][ j ]->SetAxis( j ); } // rof @@ -53,7 +53,7 @@ AddInputData( vtkImageData* new_image ) { for( unsigned int j = 0; j < 3; ++j ) { - this->Slices[ i ][ j ]->AddInputData( new_image ); + this->Slices[ i ][ j ]->SetInputImage( new_image ); this->Slices[ i ][ j ]->SetAxis( j ); } // rof -- 2.47.1