#include <cpExtensions/Visualization/ImageBlender.h>
-#include <cstring>
-
#include <vtkDataObject.h>
#include <vtkImageData.h>
#include <vtkImageIterator.h>
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->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;
-}
-
// -------------------------------------------------------------------------
unsigned int cpExtensions::Visualization::ImageBlender::
-GetNumberOfImages( ) const
-{
- return( ( const_cast< Self* >( this ) )->GetNumberOfInputConnections( 0 ) );
-}
-
-// -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetMaxWindow( ) const
+GetNumberOfInputs( )
{
- return( this->m_MaxWindow );
+ unsigned int np = this->GetNumberOfInputPorts( );
+ unsigned int ni = 0;
+ for( unsigned int p = 0; p < np; ++p )
+ ni += this->GetNumberOfInputConnections( p );
+ return( ni );
}
// -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetMaxLevel( ) const
-{
- return( this->m_MaxLevel );
-}
-
-// -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetMinWindow( ) const
+cpExtensions::Visualization::ImageBlender::
+ImageBlender( )
+ : Superclass( )
{
- return( this->m_MinWindow );
+ this->SetNumberOfInputPorts( 1 );
}
// -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetMinLevel( ) const
+cpExtensions::Visualization::ImageBlender::
+~ImageBlender( )
{
- return( this->m_MinLevel );
}
// -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetWindow( ) const
+int cpExtensions::Visualization::ImageBlender::
+RequestInformation(
+ vtkInformation* request,
+ vtkInformationVector** inputVector,
+ vtkInformationVector* outputVector
+ )
{
- return( this->m_Window );
-}
+ if( this->GetNumberOfInputConnections( 0 ) == 0 )
+ return( 0 );
-// -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetLevel( ) const
-{
- return( this->m_Level );
+ vtkDataObject::SetPointDataActiveScalarInfo(
+ outputVector->GetInformationObject( 0 ),
+ VTK_UNSIGNED_CHAR,
+ 1
+ );
+ return( 1 );
}
// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageBlender::
-SetWindow( const double& w )
+int cpExtensions::Visualization::ImageBlender::
+RequestData(
+ vtkInformation* request,
+ vtkInformationVector** inputVector,
+ vtkInformationVector* outputVector
+ )
{
- if( this->m_Window != w )
+ this->m_Ranges.clear( );
+ for( int i = 0; i < this->GetNumberOfInputPorts( ); ++i )
{
- this->m_Window = w;
- this->Modified( );
-
- } // fi
-}
+ vtkInformationVector* portInfo = inputVector[ i ];
+ for( int j = 0; j < portInfo->GetNumberOfInformationObjects( ); ++j )
+ {
+ 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 ) );
-// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageBlender::
-SetLevel( const double& l )
-{
- if( this->m_Level != l )
- {
- this->m_Level = l;
- this->Modified( );
+ } // fi
- } // fi
-}
+ } // rof
-// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageBlender::
-SetWindowLevel( const double& w, const double& l )
-{
- this->SetWindow( w );
- this->SetLevel( l );
+ } // rof
+ return(
+ this->Superclass::RequestData( request, inputVector, outputVector )
+ );
}
// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageBlender::
-GetColor(
- const unsigned int& i,
- double& r,
- double& g,
- double& b
- ) const
+// 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
+ )
{
- auto c = this->m_Colors.find( i );
- if( c != this->m_Colors.end( ) )
+ vtkImageIterator< T > inItsFast[ 256 ];
+ T* inSIFast[ 256 ];
+ vtkImageProgressIterator< T > outIt( outData, outExt, self, id );
+ vtkImageIterator< T >* inIts;
+ T** inSI;
+ if( numInputs < 256 )
{
- r = c->second.R;
- g = c->second.G;
- b = c->second.B;
+ inIts = inItsFast;
+ inSI = inSIFast;
}
else
{
- TColor c;
- r = c.R;
- g = c.G;
- b = c.B;
+ inIts = new vtkImageIterator< T >[ numInputs ];
+ inSI = new T*[ numInputs ];
} // fi
-}
-// -------------------------------------------------------------------------
-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( );
-}
+ // Loop through all input ImageData to initialize iterators
+ for( int i = 0; i < numInputs; ++i )
+ inIts[ i ].Initialize( inDatas[ i ], outExt );
-// -------------------------------------------------------------------------
-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 ) )
-{
- this->SetNumberOfInputPorts( 1 );
-}
+ // Loop through output pixels
+ while( !outIt.IsAtEnd( ) )
+ {
+ for( int j = 0; j < numInputs; ++j )
+ inSI[ j ] = inIts[ j ].BeginSpan( );
-// -------------------------------------------------------------------------
-cpExtensions::Visualization::ImageBlender::
-~ImageBlender( )
-{
-}
+ T* outSI = outIt.BeginSpan( );
+ T* outSIEnd = outIt.EndSpan( );
-// -------------------------------------------------------------------------
-int cpExtensions::Visualization::ImageBlender::
-RequestInformation(
- vtkInformation* request,
- vtkInformationVector** inputVector,
- vtkInformationVector* outputVector
- )
-{
- // Check number of inputs
- int numInputs = this->GetNumberOfInputConnections( 0 );
- if( numInputs == 0 )
- return( 0 );
+ // Pixel operation
+ while( outSI != outSIEnd )
+ {
+ // 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;
- // 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 )
- return( 0 );
+ } // rof
+ *outSI = static_cast< T >( vmax );
+ outSI++;
+ for( int l = 0; l < numInputs; ++l )
+ inSI[ l ]++;
- // 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;
+ } // elihw
+ for( int j = 0; j < numInputs; ++j )
+ inIts[ j ].NextSpan( );
+ outIt.NextSpan( );
- // Configure window/level
- double range[ 2 ];
- inData->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 ];
- 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;
- this->m_WLSlope = double( 1 ) / this->m_Window;
- this->m_WLOffset = double( 0.5 ) - ( this->m_Level / this->m_Window );
+ } // elihw
- // Configure output type
- vtkDataObject::SetPointDataActiveScalarInfo(
- outputVector->GetInformationObject( 0 ),
- VTK_UNSIGNED_CHAR, 4
- );
- return( 1 );
+ if( numInputs >= 256)
+ {
+ delete [] inIts;
+ delete [] inSI;
+
+ } // fi
}
// -------------------------------------------------------------------------
vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector,
- vtkImageData*** inData,
- vtkImageData** outData,
+ vtkImageData*** inData, vtkImageData** outData,
int outExt[ 6 ], int id
)
{
} // 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;
} // rof
- // Real update
- this->_GenerateData( inData[ 0 ], numInputs, outData[ 0 ], outExt, id );
+ 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
}
// -------------------------------------------------------------------------
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, a;
- 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;
- a = _1;
-
- // 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->m_Colors[ i ];
- r *= rgb.R * rgb.N;
- g *= rgb.G * rgb.N;
- b *= rgb.B * rgb.N;
- a = _1;
-
- } // fi
-
- } // rof
-
- // Update color
- int di4 = di << 2;
- oBuffer[ di4 + 0 ] = static_cast< unsigned char >( r * _255 );
- oBuffer[ di4 + 1 ] = static_cast< unsigned char >( g * _255 );
- oBuffer[ di4 + 2 ] = static_cast< unsigned char >( b * _255 );
- oBuffer[ di4 + 3 ] = static_cast< unsigned char >( a * _255 );
-
- } // rof
-
- } // rof
-
- } // rof
+ return( this->Superclass::FillInputPortInformation( i,info ) );
}
// eof - $RCSfile$