]> Creatis software - cpPlugins.git/blobdiff - lib/cpExtensions/Visualization/ImageBlender.cxx
Some bugs...
[cpPlugins.git] / lib / cpExtensions / Visualization / ImageBlender.cxx
index 3d90d5823dd1558934f7fa64856ab22e842745fe..44a08abc90c9f169d7dd89661b3c82c6dfda4ded 100644 (file)
@@ -16,140 +16,20 @@ New( )
 }
 
 // -------------------------------------------------------------------------
-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 )
+unsigned int cpExtensions::Visualization::ImageBlender::
+GetNumberOfInputs( )
 {
-  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( );
+  unsigned int np = this->GetNumberOfInputPorts( );
+  unsigned int ni = 0;
+  for( unsigned int p = 0; p < np; ++p )
+    ni += this->GetNumberOfInputConnections( p );
+  return( ni );
 }
 
 // -------------------------------------------------------------------------
 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 );
 }
@@ -168,119 +48,73 @@ RequestInformation(
   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 )
-  {
-    vtkErrorMacro(
-      "ThreadedRequestData: Input has " << numComp
-      << " components, but just 1 is supported"
-      );
-    return;
-
-  } // fi
-
-  for( int i = 1; i < numInputs; ++i )
+  this->m_Ranges.clear( );
+  for( int i = 0; i < this->GetNumberOfInputPorts( ); ++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;
@@ -288,8 +122,8 @@ _GenerateData(
   }
   else
   {
-    inIts = new vtkImageIterator< unsigned char >[ numInputs ];
-    inSI = new unsigned char*[ numInputs ];
+    inIts = new vtkImageIterator< T >[ numInputs ];
+    inSI = new T*[ numInputs ];
 
   } // fi
 
@@ -298,64 +132,41 @@ _GenerateData(
     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;
@@ -363,4 +174,66 @@ _GenerateData(
   } // 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$