X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;ds=sidebyside;f=lib%2FcpExtensions%2FVisualization%2FImageBlender.cxx;h=d5cbbd4b872326263d88ba1abaf9845b2dd7084f;hb=106a56bfe6a48067380089ffd61a518e40d77933;hp=3d90d5823dd1558934f7fa64856ab22e842745fe;hpb=700a810d574b8ed4c0227a1c3fd4862f01254d03;p=cpPlugins.git diff --git a/lib/cpExtensions/Visualization/ImageBlender.cxx b/lib/cpExtensions/Visualization/ImageBlender.cxx index 3d90d58..d5cbbd4 100644 --- a/lib/cpExtensions/Visualization/ImageBlender.cxx +++ b/lib/cpExtensions/Visualization/ImageBlender.cxx @@ -1,5 +1,7 @@ #include +#include + #include #include #include @@ -33,6 +35,13 @@ PrintSelf( std::ostream& os, vtkIndent indent ) << std::endl; } +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::ImageBlender:: +GetNumberOfImages( ) const +{ + return( ( const_cast< Self* >( this ) )->GetNumberOfInputConnections( 0 ) ); +} + // ------------------------------------------------------------------------- const double& cpExtensions::Visualization::ImageBlender:: GetMaxWindow( ) const @@ -124,7 +133,13 @@ GetColor( b = c->second.B; } else - r = g = b = double( 1 ); + { + TColor c; + r = c.R; + g = c.G; + b = c.B; + + } // fi } // ------------------------------------------------------------------------- @@ -168,10 +183,49 @@ RequestInformation( vtkInformationVector* outputVector ) { + // Check number of inputs int numInputs = this->GetNumberOfInputConnections( 0 ); if( numInputs == 0 ) return( 0 ); + // 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 ); + + // 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; + + // 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 ); + + // Configure output type vtkDataObject::SetPointDataActiveScalarInfo( outputVector->GetInformationObject( 0 ), VTK_UNSIGNED_CHAR, 4 @@ -227,25 +281,6 @@ ThreadedRequestData( } // 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 ); } @@ -258,6 +293,44 @@ FillInputPortInformation( int i, vtkInformation* info ) 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( @@ -268,99 +341,78 @@ _GenerateData( 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 + 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 ) { - 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 ) + int dk = ( k - this->m_Extent[ 4 ] ) * e13; + for( int j = outExt[ 2 ]; j <= outExt[ 3 ]; ++j ) { - // 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( ); + 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; - } // elihw + // Prepare color + r = g = b = v; + a = _1; - // Free auxiliary buffers - if( numInputs >= 256 ) - { - delete [] inIts; - delete [] inSI; + // 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 - } // fi + } // rof } // eof - $RCSfile$