#include #include #include #include #include #include #include // ------------------------------------------------------------------------- cpExtensions::Visualization::ImageBlender:: Self* cpExtensions::Visualization::ImageBlender:: 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->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 ) ) { this->SetNumberOfInputPorts( 1 ); } // ------------------------------------------------------------------------- cpExtensions::Visualization::ImageBlender:: ~ImageBlender( ) { } // ------------------------------------------------------------------------- int cpExtensions::Visualization::ImageBlender:: RequestInformation( vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector ) { int numInputs = this->GetNumberOfInputConnections( 0 ); if( numInputs == 0 ) return( 0 ); vtkDataObject::SetPointDataActiveScalarInfo( outputVector->GetInformationObject( 0 ), VTK_UNSIGNED_CHAR, 4 ); return( 1 ); } // ------------------------------------------------------------------------- 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 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 otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( ); if( otherComp != numComp ) { if( id == 0 ) vtkErrorMacro( "ThreadedRequestData: Input " << i << " has " << otherComp << " components, but input 0 has " << numComp << " components" ); return; } // fi } // 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 ) ); } // ------------------------------------------------------------------------- void cpExtensions::Visualization::ImageBlender:: _GenerateData( vtkImageData** inDatas, int numInputs, vtkImageData* outData, int outExt[6], int id ) { 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; if( numInputs < 256 ) { inIts = inItsFast; inSI = inSIFast; } else { inIts = new vtkImageIterator< unsigned char >[ numInputs ]; inSI = new unsigned char*[ 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 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( ); // 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 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 ) { delete [] inIts; delete [] inSI; } // fi } // eof - $RCSfile$