X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=lib%2FcpExtensions%2FVisualization%2FImageBlender.cxx;h=44a08abc90c9f169d7dd89661b3c82c6dfda4ded;hb=dbc5b32e13cf4a299ce29a5666a8e0a2ff5e62a8;hp=3d90d5823dd1558934f7fa64856ab22e842745fe;hpb=8e5fd31fd4d280781d8bc27a799361bf9c30b1d4;p=cpPlugins.git diff --git a/lib/cpExtensions/Visualization/ImageBlender.cxx b/lib/cpExtensions/Visualization/ImageBlender.cxx index 3d90d58..44a08ab 100644 --- a/lib/cpExtensions/Visualization/ImageBlender.cxx +++ b/lib/cpExtensions/Visualization/ImageBlender.cxx @@ -16,140 +16,20 @@ New( ) } // ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -PrintSelf( std::ostream& os, vtkIndent indent ) -{ - this->Superclass::PrintSelf( os, indent ); - - // Objects - os << indent << "Colors: " << std::endl; - auto i = this->m_Colors.begin( ); - for( ; i != this->m_Colors.end( ); ++i ) - os - << indent << indent << i->first << " : [" - << i->second.R << ", " - << i->second.G << ", " - << i->second.B << "]" - << std::endl; -} - -// ------------------------------------------------------------------------- -const double& cpExtensions::Visualization::ImageBlender:: -GetMaxWindow( ) const -{ - return( this->m_MaxWindow ); -} - -// ------------------------------------------------------------------------- -const double& cpExtensions::Visualization::ImageBlender:: -GetMaxLevel( ) const -{ - return( this->m_MaxLevel ); -} - -// ------------------------------------------------------------------------- -const double& cpExtensions::Visualization::ImageBlender:: -GetMinWindow( ) const -{ - return( this->m_MinWindow ); -} - -// ------------------------------------------------------------------------- -const double& cpExtensions::Visualization::ImageBlender:: -GetMinLevel( ) const -{ - return( this->m_MinLevel ); -} - -// ------------------------------------------------------------------------- -const double& cpExtensions::Visualization::ImageBlender:: -GetWindow( ) const -{ - return( this->m_Window ); -} - -// ------------------------------------------------------------------------- -const double& cpExtensions::Visualization::ImageBlender:: -GetLevel( ) const -{ - return( this->m_Level ); -} - -// ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -SetWindow( const double& w ) -{ - if( this->m_Window != w ) - { - this->m_Window = w; - this->Modified( ); - - } // fi -} - -// ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -SetLevel( const double& l ) +unsigned int cpExtensions::Visualization::ImageBlender:: +GetNumberOfInputs( ) { - if( this->m_Level != l ) - { - this->m_Level = l; - this->Modified( ); - - } // fi -} - -// ------------------------------------------------------------------------- -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->m_Colors.find( i ); - if( c != this->m_Colors.end( ) ) - { - r = c->second.R; - g = c->second.G; - b = c->second.B; - } - else - r = g = b = double( 1 ); -} - -// ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -SetColor( - const unsigned int& i, - const double& r, - const double& g, - const double& b - ) -{ - this->m_Colors[ i ] = TColor( r, g, b ); - this->Modified( ); + unsigned int np = this->GetNumberOfInputPorts( ); + unsigned int ni = 0; + for( unsigned int p = 0; p < np; ++p ) + ni += this->GetNumberOfInputConnections( p ); + return( ni ); } // ------------------------------------------------------------------------- cpExtensions::Visualization::ImageBlender:: ImageBlender( ) - : Superclass( ), - m_MaxWindow( double( 0 ) ), - m_MaxLevel( double( 0 ) ), - m_MinWindow( double( 0 ) ), - m_MinLevel( double( 0 ) ), - m_Window( double( 0 ) ), - m_Level( double( 0 ) ) + : Superclass( ) { this->SetNumberOfInputPorts( 1 ); } @@ -168,119 +48,73 @@ RequestInformation( vtkInformationVector* outputVector ) { - int numInputs = this->GetNumberOfInputConnections( 0 ); - if( numInputs == 0 ) + if( this->GetNumberOfInputConnections( 0 ) == 0 ) return( 0 ); vtkDataObject::SetPointDataActiveScalarInfo( outputVector->GetInformationObject( 0 ), - VTK_UNSIGNED_CHAR, 4 + VTK_UNSIGNED_CHAR, + 1 ); return( 1 ); } // ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -ThreadedRequestData( +int cpExtensions::Visualization::ImageBlender:: +RequestData( vtkInformation* request, vtkInformationVector** inputVector, - vtkInformationVector* outputVector, - vtkImageData*** inData, - vtkImageData** outData, - int outExt[ 6 ], int id + vtkInformationVector* outputVector ) { - if( inData[ 0 ][ 0 ] == NULL ) - { - vtkErrorMacro( << "Input " << 0 << " must be specified." ); - return; - - } // fi - - int numInputs = this->GetNumberOfInputConnections( 0 ); - 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 ) + this->m_Ranges.clear( ); + for( int i = 0; i < this->GetNumberOfInputPorts( ); ++i ) { - int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( ); - if( otherComp != numComp ) + vtkInformationVector* portInfo = inputVector[ i ]; + for( int j = 0; j < portInfo->GetNumberOfInformationObjects( ); ++j ) { - if( id == 0 ) - vtkErrorMacro( - "ThreadedRequestData: Input " << i - << " has " << otherComp - << " components, but input 0 has " << numComp - << " components" - ); - return; - - } // fi + vtkInformation* info = portInfo->GetInformationObject( j ); + vtkImageData* image = vtkImageData::SafeDownCast( + info->Get( vtkDataObject::DATA_OBJECT( ) ) + ); + if( image != NULL ) + { + double r[ 2 ]; + image->GetScalarRange( r ); + this->m_Ranges.push_back( r[ 0 ] ); + this->m_Ranges.push_back( r[ 1 ] ); + } + else + { + this->m_Ranges.push_back( double( 0 ) ); + this->m_Ranges.push_back( double( 0 ) ); + + } // fi + + } // rof } // rof - - // Initialize window/level - vtkImageData* main_image = inData[ 0 ][ 0 ]; - double range[ 2 ]; - main_image->GetScalarRange( range ); - this->m_MaxWindow = range[ 1 ] - range[ 0 ]; - this->m_MinWindow = this->m_MaxWindow * double( 1e-2 ); - this->m_MinLevel = range[ 0 ]; - this->m_MaxLevel = range[ 1 ]; - - // Update window/level - if( this->m_Window < this->m_MinWindow ) - this->m_Window = this->m_MinWindow; - if( this->m_Window > this->m_MaxWindow ) - this->m_Window = this->m_MaxWindow; - if( this->m_Level < this->m_MinLevel ) - this->m_Level = this->m_MinLevel; - if( this->m_Level > this->m_MaxLevel ) - this->m_Level = this->m_MaxLevel; - - // Real update - this->_GenerateData( inData[ 0 ], numInputs, outData[ 0 ], outExt, id ); -} - -// ------------------------------------------------------------------------- -int cpExtensions::Visualization::ImageBlender:: -FillInputPortInformation( int i, vtkInformation* info ) -{ - info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 ); - return( this->Superclass::FillInputPortInformation( i, info ) ); + return( + this->Superclass::RequestData( request, inputVector, outputVector ) + ); } // ------------------------------------------------------------------------- -void cpExtensions::Visualization::ImageBlender:: -_GenerateData( - vtkImageData** inDatas, - int numInputs, - vtkImageData* outData, - int outExt[6], - int id +// 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, + const std::vector< double >& ranges, vtkImageData* outData, + int outExt[ 6 ], int id, T* really_not_used ) { - vtkImageIterator< unsigned char > inItsFast[ 256 ]; - unsigned char* inSIFast[ 256 ]; - vtkImageProgressIterator< unsigned char > outIt( outData, outExt, this, id ); - - /* - double *weights = - static_cast(this->GetWeights())->GetPointer(0); - double totalWeight = this->CalculateTotalWeight(); - int normalize = this->GetNormalizeByWeight(); - */ - - vtkImageIterator< unsigned char > *inIts; - unsigned char** inSI; + vtkImageIterator< T > inItsFast[ 256 ]; + T* inSIFast[ 256 ]; + vtkImageProgressIterator< T > outIt( outData, outExt, self, id ); + vtkImageIterator< T >* inIts; + T** inSI; if( numInputs < 256 ) { inIts = inItsFast; @@ -288,8 +122,8 @@ _GenerateData( } else { - inIts = new vtkImageIterator< unsigned char >[ numInputs ]; - inSI = new unsigned char*[ numInputs ]; + inIts = new vtkImageIterator< T >[ numInputs ]; + inSI = new T*[ numInputs ]; } // fi @@ -298,64 +132,41 @@ _GenerateData( inIts[ i ].Initialize( inDatas[ i ], outExt ); // Loop through output pixels - double m = double( 1 ) / this->m_Window; - double c = double( 0.5 ) - ( this->m_Level / this->m_Window ); while( !outIt.IsAtEnd( ) ) { - // Prepare all iterators for( int j = 0; j < numInputs; ++j ) inSI[ j ] = inIts[ j ].BeginSpan( ); - unsigned char* outSI = outIt.BeginSpan( ); - unsigned char* outSIEnd = outIt.EndSpan( ); + + T* outSI = outIt.BeginSpan( ); + T* outSIEnd = outIt.EndSpan( ); // Pixel operation while( outSI != outSIEnd ) { - // Window/Level value from main image - double wl = ( *inSI[ 0 ] * m ) + c; - if( wl < double( 0 ) ) wl = double( 0 ); - if( wl > double( 1 ) ) wl = double( 1 ); - - // Prepare color values - double r = wl; - double g = wl; - double b = wl; - double a = double( 1 ); - - /* - double sum = 0.; - for(int k=0; k < numInputs; ++k) - { - sum += weights[k] * *inSI[k]; - } - */ - - r *= double( 255 ); - g *= double( 255 ); - b *= double( 255 ); - a *= double( 255 ); - - // Assign RGBA value - *outSI = static_cast< unsigned char >( r ); outSI++; - *outSI = static_cast< unsigned char >( g ); outSI++; - *outSI = static_cast< unsigned char >( b ); outSI++; - *outSI = static_cast< unsigned char >( a ); outSI++; - - // Advance inputs + // Input 0 is ignored: it is just used to guarantee sizes all over + // the result + double vmax = double( 0 ); + for( int k = 1; k < numInputs; ++k ) + { + double v = + ( ( double( k ) * double( *inSI[ k ] ) ) - ranges[ k << 1 ] ) / + ( ranges[ ( k << 1 ) + 1 ] - ranges[ k << 1 ] ); + vmax = ( vmax < v )? v: vmax; + + } // rof + *outSI = static_cast< T >( vmax ); + outSI++; for( int l = 0; l < numInputs; ++l ) inSI[ l ]++; } // elihw - - // Advance all iterators for( int j = 0; j < numInputs; ++j ) inIts[ j ].NextSpan( ); outIt.NextSpan( ); } // elihw - // Free auxiliary buffers - if( numInputs >= 256 ) + if( numInputs >= 256) { delete [] inIts; delete [] inSI; @@ -363,4 +174,66 @@ _GenerateData( } // fi } +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageBlender:: +ThreadedRequestData( + vtkInformation* request, + vtkInformationVector** inputVector, + vtkInformationVector* outputVector, + vtkImageData*** inData, vtkImageData** outData, + int outExt[ 6 ], int id + ) +{ + if( inData[ 0 ][ 0 ] == NULL ) + { + vtkErrorMacro( << "Input " << 0 << " must be specified." ); + return; + + } // fi + + int numInputs = this->GetNumberOfInputConnections( 0 ); + int scalarType = inData[ 0 ][ 0 ]->GetScalarType( ); + int numComp = inData[ 0 ][ 0 ]->GetNumberOfScalarComponents( ); + for( int i = 1; i < numInputs; ++i ) + { + int otherType = inData[ 0 ][ i ]->GetScalarType( ); + int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( ); + if( otherType != scalarType || otherComp != numComp ) + { + if( id == 0 ) + vtkErrorMacro( + "ThreadedRequestData: Input " << i + << " has " << otherComp << " components of type " + << otherType << ", but input 0 has " << numComp + << " components of type " << scalarType + ); + return; + + } // fi + + } // rof + + switch( scalarType ) + { + vtkTemplateMacro( + cpExtensions_Visualization_ImageBlender_Execute( + this, inData[ 0 ], numInputs, this->m_Ranges, + outData[ 0 ], outExt, id, static_cast< VTK_TT* >( 0 ) + ) + ); + default: + if( id == 0 ) + vtkErrorMacro( << "Execute: Unknown ScalarType" ); + return; + } // hctiws +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageBlender:: +FillInputPortInformation( int i, vtkInformation* info ) +{ + info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 ); + return( this->Superclass::FillInputPortInformation( i,info ) ); +} + // eof - $RCSfile$