]> Creatis software - cpPlugins.git/blobdiff - lib/cpExtensions/Visualization/ImageBlender.cxx
Some bugs...
[cpPlugins.git] / lib / cpExtensions / Visualization / ImageBlender.cxx
index d5cbbd4b872326263d88ba1abaf9845b2dd7084f..44a08abc90c9f169d7dd89661b3c82c6dfda4ded 100644 (file)
@@ -1,7 +1,5 @@
 #include <cpExtensions/Visualization/ImageBlender.h>
 
-#include <cstring>
-
 #include <vtkDataObject.h>
 #include <vtkImageData.h>
 #include <vtkImageIterator.h>
@@ -17,220 +15,163 @@ 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;
-}
-
 // -------------------------------------------------------------------------
 unsigned int cpExtensions::Visualization::ImageBlender::
-GetNumberOfImages( ) const
-{
-  return( ( const_cast< Self* >( this ) )->GetNumberOfInputConnections( 0 ) );
-}
-
-// -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetMaxWindow( ) const
+GetNumberOfInputs( )
 {
-  return( this->m_MaxWindow );
+  unsigned int np = this->GetNumberOfInputPorts( );
+  unsigned int ni = 0;
+  for( unsigned int p = 0; p < np; ++p )
+    ni += this->GetNumberOfInputConnections( p );
+  return( ni );
 }
 
 // -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetMaxLevel( ) const
-{
-  return( this->m_MaxLevel );
-}
-
-// -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetMinWindow( ) const
+cpExtensions::Visualization::ImageBlender::
+ImageBlender( )
+  : Superclass( )
 {
-  return( this->m_MinWindow );
+  this->SetNumberOfInputPorts( 1 );
 }
 
 // -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetMinLevel( ) const
+cpExtensions::Visualization::ImageBlender::
+~ImageBlender( )
 {
-  return( this->m_MinLevel );
 }
 
 // -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetWindow( ) const
+int cpExtensions::Visualization::ImageBlender::
+RequestInformation(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector
+  )
 {
-  return( this->m_Window );
-}
+  if( this->GetNumberOfInputConnections( 0 ) == 0 )
+    return( 0 );
 
-// -------------------------------------------------------------------------
-const double& cpExtensions::Visualization::ImageBlender::
-GetLevel( ) const
-{
-  return( this->m_Level );
+  vtkDataObject::SetPointDataActiveScalarInfo(
+    outputVector->GetInformationObject( 0 ),
+    VTK_UNSIGNED_CHAR,
+    1
+    );
+  return( 1 );
 }
 
 // -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageBlender::
-SetWindow( const double& w )
+int cpExtensions::Visualization::ImageBlender::
+RequestData(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector
+  )
 {
-  if( this->m_Window != w )
+  this->m_Ranges.clear( );
+  for( int i = 0; i < this->GetNumberOfInputPorts( ); ++i )
   {
-    this->m_Window = w;
-    this->Modified( );
-
-  } // fi
-}
+    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 ) );
 
-// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageBlender::
-SetLevel( const double& l )
-{
-  if( this->m_Level != l )
-  {
-    this->m_Level = l;
-    this->Modified( );
+      } // fi
 
-  } // fi
-}
+    } // rof
 
-// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageBlender::
-SetWindowLevel( const double& w, const double& l )
-{
-  this->SetWindow( w );
-  this->SetLevel( l );
+  } // rof
+  return(
+    this->Superclass::RequestData( request, inputVector, outputVector )
+    );
 }
 
 // -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageBlender::
-GetColor(
-  const unsigned int& i,
-  double& r,
-  double& g,
-  double& b
-  ) const
+// 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
+  )
 {
-  auto c = this->m_Colors.find( i );
-  if( c != this->m_Colors.end( ) )
+  vtkImageIterator< T > inItsFast[ 256 ];
+  T* inSIFast[ 256 ];
+  vtkImageProgressIterator< T > outIt( outData, outExt, self, id );
+  vtkImageIterator< T >* inIts;
+  T** inSI;
+  if( numInputs < 256 )
   {
-    r = c->second.R;
-    g = c->second.G;
-    b = c->second.B;
+    inIts = inItsFast;
+    inSI = inSIFast;
   }
   else
   {
-    TColor c;
-    r = c.R;
-    g = c.G;
-    b = c.B;
+    inIts = new vtkImageIterator< T >[ numInputs ];
+    inSI = new T*[ numInputs ];
 
   } // fi
-}
 
-// -------------------------------------------------------------------------
-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( );
-}
+  // Loop through all input ImageData to initialize iterators
+  for( int i = 0; i < numInputs; ++i )
+    inIts[ i ].Initialize( inDatas[ i ], outExt );
 
-// -------------------------------------------------------------------------
-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 );
-}
+  // Loop through output pixels
+  while( !outIt.IsAtEnd( ) )
+  {
+    for( int j = 0; j < numInputs; ++j )
+      inSI[ j ] = inIts[ j ].BeginSpan( );
 
-// -------------------------------------------------------------------------
-cpExtensions::Visualization::ImageBlender::
-~ImageBlender( )
-{
-}
+    T* outSI = outIt.BeginSpan( );
+    T* outSIEnd = outIt.EndSpan( );
 
-// -------------------------------------------------------------------------
-int cpExtensions::Visualization::ImageBlender::
-RequestInformation(
-  vtkInformation* request,
-  vtkInformationVector** inputVector,
-  vtkInformationVector* outputVector
-  )
-{
-  // Check number of inputs
-  int numInputs = this->GetNumberOfInputConnections( 0 );
-  if( numInputs == 0 )
-    return( 0 );
+    // 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;
 
-  // 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 );
+      } // rof
+      *outSI = static_cast< T >( vmax );
+      outSI++;
+      for( int l = 0; l < numInputs; ++l )
+        inSI[ l ]++;
 
-  // 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;
+    } // elihw
+    for( int j = 0; j < numInputs; ++j )
+      inIts[ j ].NextSpan( );
+    outIt.NextSpan( );
 
-  // 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 );
+  } // elihw
 
-  // Configure output type
-  vtkDataObject::SetPointDataActiveScalarInfo(
-    outputVector->GetInformationObject( 0 ),
-    VTK_UNSIGNED_CHAR, 4
-    );
-  return( 1 );
+  if( numInputs >= 256)
+  {
+    delete [] inIts;
+    delete [] inSI;
+
+  } // fi
 }
 
 // -------------------------------------------------------------------------
@@ -239,8 +180,7 @@ ThreadedRequestData(
   vtkInformation* request,
   vtkInformationVector** inputVector,
   vtkInformationVector* outputVector,
-  vtkImageData*** inData,
-  vtkImageData** outData,
+  vtkImageData*** inData, vtkImageData** outData,
   int outExt[ 6 ], int id
   )
 {
@@ -252,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;
 
@@ -281,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
 }
 
 // -------------------------------------------------------------------------
@@ -290,129 +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, a;
-  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;
-        a = _1;
-
-        // 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
-
-  } // rof
+  return( this->Superclass::FillInputPortInformation( i,info ) );
 }
 
 // eof - $RCSfile$