#include #include #include #include #include #include #include // ------------------------------------------------------------------------- cpExtensions::Algorithms::ImageBlender:: Self* cpExtensions::Algorithms::ImageBlender:: New( ) { return( new Self( ) ); } // ------------------------------------------------------------------------- unsigned int cpExtensions::Algorithms::ImageBlender:: GetNumberOfInputs( ) { unsigned int np = this->GetNumberOfInputPorts( ); unsigned int ni = 0; for( unsigned int p = 0; p < np; ++p ) ni += this->GetNumberOfInputConnections( p ); return( ni ); } // ------------------------------------------------------------------------- cpExtensions::Algorithms::ImageBlender:: ImageBlender( ) : Superclass( ) { this->SetNumberOfInputPorts( 1 ); } // ------------------------------------------------------------------------- cpExtensions::Algorithms::ImageBlender:: ~ImageBlender( ) { } // ------------------------------------------------------------------------- int cpExtensions::Algorithms::ImageBlender:: RequestInformation( vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector ) { if( this->GetNumberOfInputConnections( 0 ) == 0 ) return( 0 ); vtkDataObject::SetPointDataActiveScalarInfo( outputVector->GetInformationObject( 0 ), VTK_UNSIGNED_CHAR, 1 ); return( 1 ); } // ------------------------------------------------------------------------- int cpExtensions::Algorithms::ImageBlender:: RequestData( vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector ) { this->m_Ranges.clear( ); for( int i = 0; i < this->GetNumberOfInputPorts( ); ++i ) { 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 ) ); } // fi } // rof } // rof return( this->Superclass::RequestData( request, inputVector, outputVector ) ); } // ------------------------------------------------------------------------- // Description: // This templated function executes the filter for any type of data. template< class T > void cpExtensions_Algorithms_ImageBlender_Execute( cpExtensions::Algorithms::ImageBlender* self, vtkImageData** inDatas, int numInputs, const std::vector< double >& ranges, 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 ) { // Input 0 is ignored: it is just used to guarantee sizes all over // the result int vmax = 0; for( int k = 0; k < numInputs; ++k ) if( double( *inSI[ k ] ) > ranges[ k << 1 ] && vmax <= k ) vmax = k + 1; *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::Algorithms::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 = 0; 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_Algorithms_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::Algorithms::ImageBlender:: FillInputPortInformation( int i, vtkInformation* info ) { info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 ); return( this->Superclass::FillInputPortInformation( i,info ) ); } // eof - $RCSfile$