]> Creatis software - cpPlugins.git/blobdiff - lib/cpExtensions/Visualization/ImageBlender.cxx
Some bugs...
[cpPlugins.git] / lib / cpExtensions / Visualization / ImageBlender.cxx
index 49292c8dfaa61bc230ce2d1a8581ecd59b02652e..44a08abc90c9f169d7dd89661b3c82c6dfda4ded 100644 (file)
@@ -1,7 +1,5 @@
 #include <cpExtensions/Visualization/ImageBlender.h>
 
-#include <cstring>
-
 #include <vtkDataObject.h>
 #include <vtkImageData.h>
 #include <vtkImageIterator.h>
@@ -17,90 +15,21 @@ 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->Colors.begin( );
-  for( ; i != this->Colors.end( ); ++i )
-    os
-      << indent << indent << i->first << " : ["
-      << i->second.R << ", "
-      << i->second.G << ", "
-      << i->second.B << "]"
-      << std::endl;
-}
-
 // -------------------------------------------------------------------------
 unsigned int cpExtensions::Visualization::ImageBlender::
-GetNumberOfImages( ) const
-{
-  return(
-    ( const_cast< Self* >( this ) )->GetNumberOfInputConnections( 0 )
-    );
-}
-
-// -------------------------------------------------------------------------
-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->Colors.find( i );
-  if( c != this->Colors.end( ) )
-  {
-    r = c->second.R;
-    g = c->second.G;
-    b = c->second.B;
-  }
-  else
-  {
-    TColor c;
-    r = c.R;
-    g = c.G;
-    b = c.B;
-
-  } // fi
-}
-
-// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageBlender::
-SetColor(
-  const unsigned int& i,
-  const double& r,
-  const double& g,
-  const double& b
-  )
+GetNumberOfInputs( )
 {
-  this->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( ),
-    MaxWindow( double( 1 ) ),
-    MaxLevel( double( 1 ) ),
-    MinWindow( double( 0 ) ),
-    MinLevel( double( 0 ) ),
-    Window( double( 1 ) ),
-    Level( double( 0.5 ) )
+  : Superclass( )
 {
   this->SetNumberOfInputPorts( 1 );
 }
@@ -119,40 +48,130 @@ RequestInformation(
   vtkInformationVector* outputVector
   )
 {
-  // Check number of inputs
-  int numInputs = this->GetNumberOfInputConnections( 0 );
-  if( numInputs == 0 )
+  if( this->GetNumberOfInputConnections( 0 ) == 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( ) )
+  vtkDataObject::SetPointDataActiveScalarInfo(
+    outputVector->GetInformationObject( 0 ),
+    VTK_UNSIGNED_CHAR,
+    1
     );
-  if( inData == NULL )
-    return( 0 );
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::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 ) );
 
-  // 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;
+      } // fi
 
-  // Configure window/level
-  this->m_WLSlope = double( 1 ) / this->Window;
-  this->m_WLOffset = double( 0.5 ) - ( this->Level / this->Window );
+    } // rof
 
-  // Configure output type
-  vtkDataObject::SetPointDataActiveScalarInfo(
-    outputVector->GetInformationObject( 0 ),
-    VTK_UNSIGNED_CHAR, 3
+  } // rof
+  return(
+    this->Superclass::RequestData( request, inputVector, outputVector )
     );
-  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+// 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< 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
+      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
+    for( int j = 0; j < numInputs; ++j )
+      inIts[ j ].NextSpan( );
+    outIt.NextSpan( );
+
+  } // elihw
+
+  if( numInputs >= 256)
+  {
+    delete [] inIts;
+    delete [] inSI;
+
+  } // fi
 }
 
 // -------------------------------------------------------------------------
@@ -161,8 +180,7 @@ ThreadedRequestData(
   vtkInformation* request,
   vtkInformationVector** inputVector,
   vtkInformationVector* outputVector,
-  vtkImageData*** inData,
-  vtkImageData** outData,
+  vtkImageData*** inData, vtkImageData** outData,
   int outExt[ 6 ], int id
   )
 {
@@ -174,28 +192,20 @@ ThreadedRequestData(
   } // fi
 
   int numInputs = this->GetNumberOfInputConnections( 0 );
+  int scalarType = inData[ 0 ][ 0 ]->GetScalarType( );
   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 otherType = inData[ 0 ][ i ]->GetScalarType( );
     int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( );
-    if( otherComp != numComp )
+    if( otherType != scalarType || otherComp != numComp )
     {
       if( id == 0 )
         vtkErrorMacro(
           "ThreadedRequestData: Input " << i
-          << " has " << otherComp
-          << " components, but input 0 has " << numComp
-          << " components"
+          << " has " << otherComp << " components of type "
+          << otherType << ", but input 0 has " << numComp
+          << " components of type " << scalarType
           );
       return;
 
@@ -203,8 +213,19 @@ ThreadedRequestData(
 
   } // rof
 
-  // Real update
-  this->_GenerateData( inData[ 0 ], numInputs, outData[ 0 ], outExt, id );
+  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
 }
 
 // -------------------------------------------------------------------------
@@ -212,126 +233,7 @@ int cpExtensions::Visualization::ImageBlender::
 FillInputPortInformation( int i, vtkInformation* info )
 {
   info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 );
-  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(
-  vtkImageData** inDatas,
-  int numInputs,
-  vtkImageData* outData,
-  int outExt[ 6 ],
-  int id
-  )
-{
-  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;
-  int e13 = this->m_Extent[ 1 ] * this->m_Extent[ 3 ];
-  for( int k = outExt[ 4 ]; k <= outExt[ 5 ]; ++k )
-  {
-    int dk = ( k - this->m_Extent[ 4 ] ) * e13;
-    for( int j = outExt[ 2 ]; j <= outExt[ 3 ]; ++j )
-    {
-      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;
-
-        // Prepare color
-        r = g = b = v;
-
-        // 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->Colors[ i ];
-            r *= rgb.R * rgb.N;
-            g *= rgb.G * rgb.N;
-            b *= rgb.B * rgb.N;
-
-          } // fi
-
-        } // rof
-
-        // Update color
-        int di3 = di * 3;
-        oBuffer[ di3 + 0 ] = static_cast< unsigned char >( r * _255 );
-        oBuffer[ di3 + 1 ] = static_cast< unsigned char >( g * _255 );
-        oBuffer[ di3 + 2 ] = static_cast< unsigned char >( b * _255 );
-
-      } // rof
-
-    } // rof
-
-  } // rof
+  return( this->Superclass::FillInputPortInformation( i,info ) );
 }
 
 // eof - $RCSfile$