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;
-}
-
-// -------------------------------------------------------------------------
-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 )
-{
- 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( );
-}
// -------------------------------------------------------------------------
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 );
}
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 )
+ this->m_Ranges.clear( );
+ for( int i = 0; i < this->GetNumberOfInputPorts( ); ++i )
{
- vtkErrorMacro(
- "ThreadedRequestData: Input has " << numComp
- << " components, but just 1 is supported"
- );
- return;
-
- } // fi
-
- for( int i = 1; i < numInputs; ++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<vtkDoubleArray *>(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;
}
else
{
- inIts = new vtkImageIterator< unsigned char >[ numInputs ];
- inSI = new unsigned char*[ numInputs ];
+ inIts = new vtkImageIterator< T >[ numInputs ];
+ inSI = new T*[ numInputs ];
} // fi
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;
} // 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$