]> Creatis software - cpPlugins.git/commitdiff
Binary image visualization improved.
authorLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Mon, 2 Nov 2015 23:40:30 +0000 (18:40 -0500)
committerLeonardo Florez-Valencia <florez-l@javeriana.edu.co>
Mon, 2 Nov 2015 23:40:30 +0000 (18:40 -0500)
appli/examples/example_HandleWidget.cxx
appli/examples/example_SeedWidget.cxx
appli/examples/example_SphereWidget.cxx
appli/examples/example_Test_Memento.cxx
appli/examples/example_View2DImage.cxx
lib/cpExtensions/Visualization/ImageBlender.cxx
lib/cpExtensions/Visualization/ImageBlender.h
lib/cpExtensions/Visualization/ImageSliceActors.cxx
lib/cpExtensions/Visualization/ImageSliceActors.h
lib/cpExtensions/Visualization/MPRActors.cxx
lib/cpExtensions/Visualization/MPRActors.h

index 2cce131af8e9560ad93dcb52e175a03c6278237b..69bc3090b447cd7ee0170a962cfbbb40e85f41bf 100644 (file)
@@ -94,15 +94,16 @@ int main( int argc, char* argv[] )
   // Create slice actors
   vtkSmartPointer< TSliceActors > image_actors =
     vtkSmartPointer< TSliceActors >::New( );
-  image_actors->AddInputData( image->GetVTK< vtkImageData >( ), 2 );
+  image_actors->AddInputData( image->GetVTK< vtkImageData >( ) );
+  image_actors->SetAxis( 2 );
   image_actors->PushActorsInto( window );
 
   vtkSmartPointer< vtkImageActorPointPlacer > placer =
     vtkSmartPointer< vtkImageActorPointPlacer >::New( );
-  placer->SetImageActor( image_actors->GetImageActor( ) );
+  placer->SetImageActor( image_actors->GetImageActor( ) );
 
   double bnds[ 6 ];
-  image_actors->GetImageActor( )->GetDisplayBounds( bnds );
+  image_actors->GetImageActor( )->GetDisplayBounds( bnds );
   double pos[] = { bnds[ 0 ], bnds[ 2 ], bnds[ 4 ] };
 
   vtkSmartPointer< vtkPointHandleRepresentation3D > rep =
index d1e776e638f459a25d5575c010deef1a1d9fc606..3853f23e18dd14c61a2ec4e21e761484bbd31ae5 100644 (file)
@@ -96,12 +96,13 @@ int main( int argc, char* argv[] )
   // Create slice actors
   vtkSmartPointer< TSliceActors > image_actors =
     vtkSmartPointer< TSliceActors >::New( );
-  image_actors->AddInputData( image->GetVTK< vtkImageData >( ), 2 );
+  image_actors->AddInputData( image->GetVTK< vtkImageData >( ) );
+  image_actors->SetAxis( 2 );
   image_actors->PushActorsInto( window );
 
   vtkSmartPointer< vtkImageActorPointPlacer > placer =
     vtkSmartPointer< vtkImageActorPointPlacer >::New( );
-  placer->SetImageActor( image_actors->GetImageActor( ) );
+  placer->SetImageActor( image_actors->GetImageActor( ) );
 
   // Create the widget and its representation
   vtkSmartPointer< vtkPointHandleRepresentation3D > handle =
index 6ba1e5e40e362bedc56be9917ad05ccc0f457906..4079b3a3edbd8c7f701c81b2e437b61cd43ed0d9 100644 (file)
@@ -94,12 +94,13 @@ int main(int argc, char* argv[])
   // Create slice actors
   vtkSmartPointer< TSliceActors > image_actors =
     vtkSmartPointer< TSliceActors >::New();
-  image_actors->AddInputData(image->GetVTK< vtkImageData >(), 2);
+  image_actors->AddInputData(image->GetVTK< vtkImageData >());
+  image_actors->SetAxis(2);
   image_actors->PushActorsInto(window);
 
   vtkSmartPointer< vtkImageActorPointPlacer > placer =
     vtkSmartPointer< vtkImageActorPointPlacer >::New();
-  placer->SetImageActor(image_actors->GetImageActor(0));
+  placer->SetImageActor(image_actors->GetImageActor());
  
   // Create a sphere widget
   vtkSmartPointer<TSphereWidget> sphereWidget =
@@ -118,4 +119,4 @@ int main(int argc, char* argv[])
   interactor->Start();
 
   return(0);
-}
\ No newline at end of file
+}
index 7cbd37a69ef5a5019d494cbe0ab7b76b26e87e90..7a16d696819ec412f08c78305c957ea89e4f2c10 100644 (file)
@@ -140,7 +140,8 @@ int main(int argc, char* argv[])
   vtkSmartPointer< TSliceActors > image_actors =
     vtkSmartPointer< TSliceActors >::New();
   //image_actors->AddInputData(image->GetVTK< vtkImageData >(), 2);
-  image_actors->AddInputData(retrievedImage, 2);
+  image_actors->AddInputData(retrievedImage);
+  image_actors->SetAxis(2);
   image_actors->PushActorsInto(window);
 
   // Begin interaction
index ea0554da0e5c7a78216565bd1a1851a6228f09ef..fcf13147f275f9674fd0025545314f9cf31a909f 100644 (file)
 
 #include <cpExtensions/Visualization/ImageSliceActors.h>
 
-
-#include <cpExtensions/Visualization/ImageBlender.h>
-#include <vtkPNGWriter.h>
-
-
 // -------------------------------------------------------------------------
 typedef cpPlugins::Interface::Interface     TInterface;
 typedef cpPlugins::Interface::ProcessObject TProcessObject;
@@ -100,35 +95,10 @@ int main( int argc, char* argv[] )
   // Create slice actors
   vtkSmartPointer< TSliceActors > image_actors =
     vtkSmartPointer< TSliceActors >::New( );
-  image_actors->AddInputData( image->GetVTK< vtkImageData >( ), 2 );
+  image_actors->AddInputData( image->GetVTK< vtkImageData >( ) );
+  image_actors->SetAxis( 2 );
   image_actors->PushActorsInto( window );
 
-
-
-
-
-  vtkImageData* vimage = image->GetVTK< vtkImageData >( );
-  double range[ 2 ];
-  vimage->GetScalarRange( range );
-
-  vtkSmartPointer< cpExtensions::Visualization::ImageBlender > blender =
-    vtkSmartPointer< cpExtensions::Visualization::ImageBlender >::New( );
-  blender->AddInputData( vimage );
-  blender->SetWindow( range[ 1 ] - range[ 0 ] );
-  blender->SetLevel( ( range[ 1 ] + range[ 0 ] ) / double( 2 ) );
-  blender->Update( );
-
-  std::cout << blender->GetWindow( ) << " " << blender->GetLevel( ) << std::endl;
-
-  vtkSmartPointer< vtkPNGWriter > writer =
-    vtkSmartPointer< vtkPNGWriter >::New( );
-  writer->SetInputConnection( blender->GetOutputPort( ) );
-  writer->SetFileName( "leo_actor.png" );
-  writer->Write( );
-
-  return( 0 );
-
-
   // Activate seed widget
   if( argc == 4 )
   {
index 3d90d5823dd1558934f7fa64856ab22e842745fe..6714d55d3e246efe0d4356a625b315ae43a13335 100644 (file)
@@ -1,5 +1,8 @@
 #include <cpExtensions/Visualization/ImageBlender.h>
 
+#include <cmath>
+#include <cstring>
+
 #include <vtkDataObject.h>
 #include <vtkImageData.h>
 #include <vtkImageIterator.h>
@@ -33,6 +36,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 +134,11 @@ GetColor(
     b = c->second.B;
   }
   else
-    r = g = b = double( 1 );
+  {
+    r = double( 1 );
+    g = b = double( 0 );
+
+  } // fi
 }
 
 // -------------------------------------------------------------------------
@@ -168,10 +182,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 +280,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 +292,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 +340,80 @@ _GenerateData(
   int id
   )
 {
-  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;
-  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 ) )
+          {
+            double cr, cg, cb;
+            this->GetColor( i, cr, cg, cb );
+            double n = std::sqrt( ( cr * cr ) + ( cg * cg ) + ( cb * cb ) );
+            r *= cr * n;
+            g *= cg * n;
+            b *= cb * 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$
index b74b51a9ce4d7fb706ecda5a299a0919e2f3b209..6ba1a43137a7f52801249c896fb14ce9ffb4c445 100644 (file)
@@ -23,6 +23,8 @@ namespace cpExtensions
       static Self* New( );
       void PrintSelf( std::ostream& os, vtkIndent indent );
 
+      unsigned int GetNumberOfImages( ) const;
+
       const double& GetMaxWindow( ) const;
       const double& GetMaxLevel( ) const;
       const double& GetMinWindow( ) const;
@@ -101,6 +103,10 @@ namespace cpExtensions
       double m_MinLevel;
       double m_Window;
       double m_Level;
+
+      int    m_Extent[ 6 ];
+      double m_WLSlope;
+      double m_WLOffset;
     };
 
   } // ecapseman
index 4d20994be61a7ebb29874cd23229feded8513193..ee4947e834d4394463a547de1e958d4752e66f58 100644 (file)
@@ -1,23 +1,18 @@
 #include <cpExtensions/Visualization/ImageSliceActors.h>
 
-#include <cmath>
 #include <sstream>
 
 #include <vtkAlgorithmOutput.h>
 #include <vtkCamera.h>
 #include <vtkCellArray.h>
 #include <vtkImageData.h>
-#include <vtkInformation.h>
-#include <vtkPlane.h>
 #include <vtkPoints.h>
 #include <vtkProperty.h>
 #include <vtkRenderer.h>
 #include <vtkRendererCollection.h>
 #include <vtkRenderWindow.h>
 #include <vtkRenderWindowInteractor.h>
-#include <vtkStreamingDemandDrivenPipeline.h>
 #include <vtkTextProperty.h>
-#include <vtkWindowLevelLookupTable.h>
 
 // -------------------------------------------------------------------------
 cpExtensions::Visualization::ImageSliceActors*
@@ -27,97 +22,121 @@ New( )
   return( new Self( ) );
 }
 
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::
+ImageBlender* cpExtensions::Visualization::ImageSliceActors::
+GetBlender( )
+{
+  return( this->m_ImageBlender );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::Visualization::
+ImageBlender* cpExtensions::Visualization::ImageSliceActors::
+GetBlender( ) const
+{
+  return( this->m_ImageBlender );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+SetBlender( ImageBlender* blender )
+{
+  this->m_ImageBlender = blender;
+
+  // Create mapper and actors
+  this->m_ImageMapper = vtkSmartPointer< vtkImageSliceMapper >::New( );
+  this->m_ImageMapper->SetInputConnection(
+    this->m_ImageBlender->GetOutputPort( )
+    );
+  this->m_ImageMapper->SetOrientation( 0 );
+  this->m_ImageMapper->Update( );
+
+  // Create actor
+  this->m_ImageActor = vtkSmartPointer< vtkImageActor >::New( );
+  this->m_ImageActor->SetMapper( this->m_ImageMapper );
+  this->m_ImageActor->SetInterpolate( this->m_Interpolate );
+  this->m_ImageActor->Modified( );
+
+  if( this->m_Style.GetPointer( ) != NULL )
+    this->m_Style->AssociateImageActor( this->m_ImageActor );
+  this->AddItem( this->m_ImageActor );
+
+  this->SetSliceNumber( this->GetSliceNumberMinValue( ) );
+  this->ResetCursor( );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+SetAxis( int axis )
+{
+  this->m_ImageMapper->SetOrientation( axis );
+  this->m_ImageMapper->Update( );
+  this->SetSliceNumber( this->GetSliceNumberMinValue( ) );
+  this->m_ImageActor->Modified( );
+  this->Modified( );
+  this->ResetCamera( );
+}
+
 // -------------------------------------------------------------------------
 void cpExtensions::Visualization::ImageSliceActors::
-AddInputConnection( vtkAlgorithmOutput* aout, int axis )
+AddInputConnection( vtkAlgorithmOutput* aout )
 {
   // Get input vtkImageData
   if( aout == NULL )
     return;
-  vtkAlgorithm* producer = aout->GetProducer( );
-  vtkImageData* data = dynamic_cast< vtkImageData* >(
-    producer->GetOutputDataObject( aout->GetIndex( ) )
-    );
-  if( data == NULL )
-    return;
 
-  // Try to infere if input comes from a color mapping filter
-  vtkImageMapToColors* new_map =
-    dynamic_cast< vtkImageMapToColors* >( producer );
-  if( new_map == NULL )
+  if( this->m_ImageBlender.GetPointer( ) == NULL )
   {
-    // Configure LUT, if possible (NULL is returned if not)
-    this->_ConfigureNewLUT( data );
-    new_map = *( this->m_ImageMaps.rbegin( ) );
-    if( new_map != NULL )
+    // Try to infere if input comes from a color mapping filter
+    vtkAlgorithm* producer = aout->GetProducer( );
+    vtkSmartPointer< ImageBlender > blender =
+      dynamic_cast< ImageBlender* >( producer );
+    if( blender.GetPointer( ) == NULL )
     {
-      new_map->SetInputConnection( aout );
-      new_map->Update( );
+      // Ok, create a new blender with default window level
+      vtkImageData* data = dynamic_cast< vtkImageData* >(
+        producer->GetOutputDataObject( aout->GetIndex( ) )
+        );
+      double r[ 2 ];
+      data->GetScalarRange( r );
+
+      blender = vtkSmartPointer< ImageBlender >::New( );
+      blender->AddInputConnection( aout );
+      blender->SetWindow( r[ 1 ] - r[ 0 ] );
+      blender->SetLevel( ( r[ 1 ] + r[ 0 ] ) / double( 2 ) );
 
     } // fi
+    this->SetBlender( blender );
   }
   else
-    this->m_ImageMaps.push_back( new_map );
-
-  // Update window level values
-  if( new_map != NULL )
-  {
-    double range[ 2 ];
-    dynamic_cast< vtkImageData* >( new_map->GetInput( ) )->
-      GetScalarRange( range );
-    this->m_MinWindow = double( 0 );
-    this->m_MaxWindow = range[ 1 ] - range[ 0 ];
-    this->m_MinLevel = range[ 0 ];
-    this->m_MaxLevel = range[ 1 ];
-
-  } // fi
-
-  // Create mapper and actors
-  vtkSmartPointer< vtkImageSliceMapper > mapper =
-    vtkSmartPointer< vtkImageSliceMapper >::New( );
-  if( new_map != NULL )
-    mapper->SetInputConnection( new_map->GetOutputPort( ) );
-  else
-    mapper->SetInputConnection( aout );
-  this->m_SliceMappers.push_back( mapper );
-  this->_ConfigureNewInput( axis );
+    this->m_ImageBlender->AddInputConnection( aout );
 }
 
 // -------------------------------------------------------------------------
 void cpExtensions::Visualization::ImageSliceActors::
-AddInputData( vtkImageData* data, int axis )
+AddInputData( vtkImageData* data )
 {
-  // Update window level values
-  if( this->m_ImageMaps.size( ) == 0 )
-  {
-    double range[ 2 ];
-    data->GetScalarRange( range );
-    this->m_MinWindow = double( 0 );
-    this->m_MaxWindow = range[ 1 ] - range[ 0 ];
-    this->m_MinLevel = range[ 0 ];
-    this->m_MaxLevel = range[ 1 ];
-
-  } // fi
+  // Get input vtkImageData
+  if( data == NULL )
+    return;
 
-  // Configure LUT, if possible (NULL is returned if not)
-  this->_ConfigureNewLUT( data );
-  vtkImageMapToColors* new_map = *( this->m_ImageMaps.rbegin( ) );
-  if( new_map != NULL )
+  if( this->m_ImageBlender.GetPointer( ) == NULL )
   {
-    new_map->SetInputData( data );
-    new_map->Update( );
-
-  } // fi
-
-  // Create mapper and actors
-  vtkSmartPointer< vtkImageSliceMapper > mapper =
-    vtkSmartPointer< vtkImageSliceMapper >::New( );
-  if( new_map != NULL )
-    mapper->SetInputConnection( new_map->GetOutputPort( ) );
+    // Create a new blender with default window level
+    double r[ 2 ];
+    data->GetScalarRange( r );
+
+    vtkSmartPointer< ImageBlender > blender =
+      vtkSmartPointer< ImageBlender >::New( );
+    blender->AddInputData( data );
+    blender->SetWindow( r[ 1 ] - r[ 0 ] );
+    blender->SetLevel( ( r[ 1 ] + r[ 0 ] ) / double( 2 ) );
+    this->SetBlender( blender );
+  }
   else
-    mapper->SetInputData( data );
-  this->m_SliceMappers.push_back( mapper );
-  this->_ConfigureNewInput( axis );
+    this->m_ImageBlender->AddInputData( data );
 }
 
 // -------------------------------------------------------------------------
@@ -125,10 +144,6 @@ void cpExtensions::Visualization::ImageSliceActors::
 Clear( )
 {
   // Reset values
-  this->m_MinWindow = double( 0 );
-  this->m_MaxWindow = double( 0 );
-  this->m_MinLevel = double( 0 );
-  this->m_MaxLevel = double( 0 );
   this->m_VisibleExtent[ 0 ] =
     this->m_VisibleExtent[ 2 ] =
     this->m_VisibleExtent[ 4 ] = -1;
@@ -146,9 +161,9 @@ Clear( )
   this->RemoveAllItems( );
 
   // Delete all images
-  this->m_ImageMaps.clear( );
-  this->m_SliceMappers.clear( );
-  this->m_ImageActors.clear( );
+  this->m_ImageActor   = NULL;
+  this->m_ImageMapper  = NULL;
+  this->m_ImageBlender = NULL;
 
   // Reconfigure unique objects
   this->m_Cursor               = vtkSmartPointer< vtkPolyData >::New( );
@@ -293,22 +308,26 @@ GetStyle( ) const
 vtkImageData* cpExtensions::Visualization::ImageSliceActors::
 GetInputImage( unsigned int id )
 {
-  vtkAlgorithmOutput* aout = this->m_ImageMaps[ id ]->GetOutputPort( );
-  vtkImageData* image = dynamic_cast< vtkImageData* >(
-    aout->GetProducer( )->GetOutputDataObject( aout->GetIndex( ) )
-    );
-  return( image );
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
+    return(
+      dynamic_cast< vtkImageData* >( this->m_ImageBlender->GetInput( id ) )
+      );
+  else
+    return( NULL );
 }
 
 // -------------------------------------------------------------------------
 const vtkImageData* cpExtensions::Visualization::ImageSliceActors::
 GetInputImage( unsigned int id ) const
 {
-  vtkAlgorithmOutput* aout = this->m_ImageMaps[ id ]->GetOutputPort( );
-  const vtkImageData* image = dynamic_cast< const vtkImageData* >(
-    aout->GetProducer( )->GetOutputDataObject( aout->GetIndex( ) )
-    );
-  return( image );
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
+    return(
+      dynamic_cast< const vtkImageData* >(
+        this->m_ImageBlender->GetInput( )
+        )
+      );
+  else
+    return( NULL );
 }
 
 // -------------------------------------------------------------------------
@@ -360,8 +379,8 @@ PushActorsInto( vtkRenderWindow* window, bool force_style )
     }
     else // if( axis == 2 )
     {
-      camera->SetPosition( double( 0 ), double(  0 ), double( -1 ) );
-      camera->SetViewUp  ( double( 0 ), double( -1 ), double(  0 ) );
+      camera->SetPosition( double( 0 ), double(  0 ), double( 1 ) );
+      camera->SetViewUp  ( double( 0 ), double( -1 ), double( 0 ) );
 
     } // fi
 
@@ -391,31 +410,18 @@ PopActorsFrom( vtkRenderWindow* window )
     rwi->Render( );
 }
 
-// -------------------------------------------------------------------------
-unsigned int cpExtensions::Visualization::ImageSliceActors::
-GetNumberOfImageActors( ) const
-{
-  return( this->m_ImageActors.size( ) );
-}
-
 // -------------------------------------------------------------------------
 vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
-GetImageActor( unsigned int id )
+GetImageActor( )
 {
-  if( id < this->m_ImageActors.size( ) )
-    return( this->m_ImageActors[ id ] );
-  else
-    return( NULL );
+  return( this->m_ImageActor );
 }
 
 // -------------------------------------------------------------------------
 const vtkImageActor* cpExtensions::Visualization::ImageSliceActors::
-GetImageActor( unsigned int id ) const
+GetImageActor( ) const
 {
-  if( id < this->m_ImageActors.size( ) )
-    return( this->m_ImageActors[ id ] );
-  else
-    return( NULL );
+  return( this->m_ImageActor );
 }
 
 // -------------------------------------------------------------------------
@@ -450,14 +456,20 @@ GetPlaneActor( ) const
 vtkPlane* cpExtensions::Visualization::ImageSliceActors::
 GetPlaneFunction( )
 {
-  return( this->m_SliceMappers[ 0 ]->GetSlicePlane( ) );
+  if( this->m_ImageMapper.GetPointer( ) != NULL )
+    return( this->m_ImageMapper->GetSlicePlane( ) );
+  else
+    return( NULL );
 }
 
 // -------------------------------------------------------------------------
 const vtkPlane* cpExtensions::Visualization::ImageSliceActors::
 GetPlaneFunction( ) const
 {
-  return( this->m_SliceMappers[ 0 ]->GetSlicePlane( ) );
+  if( this->m_ImageMapper.GetPointer( ) != NULL )
+    return( this->m_ImageMapper->GetSlicePlane( ) );
+  else
+    return( NULL );
 }
 
 // -------------------------------------------------------------------------
@@ -466,8 +478,7 @@ SetInterpolate( bool v )
 {
   if( this->m_Interpolate != v )
   {
-    for( unsigned int i = 0; i < this->m_ImageActors.size( ); ++i )
-      this->m_ImageActors[ i ]->SetInterpolate( v );
+    this->m_ImageActor->SetInterpolate( v );
     this->m_Interpolate = v;
     this->Modified( );
 
@@ -492,8 +503,8 @@ InterpolateOff( )
 double* cpExtensions::Visualization::ImageSliceActors::
 GetDisplayBounds( ) const
 {
-  if( this->m_ImageActors.size( ) > 0 )
-    return( this->m_ImageActors[ 0 ]->GetDisplayBounds( ) );
+  if( this->m_ImageActor.GetPointer( ) != NULL )
+    return( this->m_ImageActor->GetDisplayBounds( ) );
   else
     return( NULL );
 }
@@ -502,23 +513,23 @@ GetDisplayBounds( ) const
 void cpExtensions::Visualization::ImageSliceActors::
 GetDisplayBounds( double bounds[ 6 ] ) const
 {
-  if( this->m_ImageActors.size( ) == 0 )
+  if( this->m_ImageActor.GetPointer( ) == NULL )
   {
     bounds[ 0 ] = bounds[ 2 ] = bounds[ 4 ] = double( -1 );
     bounds[ 1 ] = bounds[ 3 ] = bounds[ 5 ] = double( -1 );
   }
   else
-    this->m_ImageActors[ 0 ]->GetDisplayBounds( bounds );
+    this->m_ImageActor->GetDisplayBounds( bounds );
 }
 
 // -------------------------------------------------------------------------
 void cpExtensions::Visualization::ImageSliceActors::
 ResetCursor( )
 {
-  if( this->m_SliceMappers.size( ) > 0 )
+  if( this->m_ImageMapper.GetPointer( ) != NULL )
   {
     double bounds[ 6 ];
-    this->m_SliceMappers[ 0 ]->GetInput( )->GetBounds( bounds );
+    this->m_ImageMapper->GetInput( )->GetBounds( bounds );
     double pos[] =
       {
         this->m_VisibleBounds[ 0 ],
@@ -549,7 +560,7 @@ ResetCursor( )
 void cpExtensions::Visualization::ImageSliceActors::
 SetCursor( double pos[ 3 ] )
 {
-  if( this->m_SliceMappers.size( ) == 0 )
+  if( this->m_ImageMapper.GetPointer( ) == NULL )
     return;
 
   // Get ordered axes
@@ -589,69 +600,52 @@ SetCursor( double pos[ 3 ] )
   this->m_CursorActor->Modified( );
 }
 
-// -------------------------------------------------------------------------
-vtkImageMapToColors* cpExtensions::Visualization::ImageSliceActors::
-GetImageMap( unsigned int id )
-{
-  if( id < this->m_ImageMaps.size( ) )
-    return( this->m_ImageMaps[ id ].GetPointer( ) );
-  else
-    return( NULL );
-}
-
-// -------------------------------------------------------------------------
-const vtkImageMapToColors* cpExtensions::Visualization::ImageSliceActors::
-GetImageMap( unsigned int id ) const
-{
-  if( id < this->m_ImageMaps.size( ) )
-    return( this->m_ImageMaps[ id ].GetPointer( ) );
-  else
-    return( NULL );
-}
-
 // -------------------------------------------------------------------------
 double cpExtensions::Visualization::ImageSliceActors::
 GetMinWindow( ) const
 {
-  return( this->m_MinWindow );
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
+    return( this->m_ImageBlender->GetMinWindow( ) );
+  else
+    return( double( 0 ) );
 }
 
 // -------------------------------------------------------------------------
 double cpExtensions::Visualization::ImageSliceActors::
 GetMaxWindow( ) const
 {
-  return( this->m_MaxWindow );
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
+    return( this->m_ImageBlender->GetMaxWindow( ) );
+  else
+    return( double( 0 ) );
 }
 
 // -------------------------------------------------------------------------
 double cpExtensions::Visualization::ImageSliceActors::
 GetMinLevel( ) const
 {
-  return( this->m_MinLevel );
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
+    return( this->m_ImageBlender->GetMinLevel( ) );
+  else
+    return( double( 0 ) );
 }
 
 // -------------------------------------------------------------------------
 double cpExtensions::Visualization::ImageSliceActors::
 GetMaxLevel( ) const
 {
-  return( this->m_MaxLevel );
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
+    return( this->m_ImageBlender->GetMaxLevel( ) );
+  else
+    return( double( 0 ) );
 }
 
 // -------------------------------------------------------------------------
 double cpExtensions::Visualization::ImageSliceActors::
 GetWindow( ) const
 {
-  if( this->m_ImageMaps.size( ) == 0 )
-    return( double( 0 ) );
-  if( this->m_ImageMaps[ 0 ].GetPointer( ) == NULL )
-    return( double( 0 ) );
-
-  vtkWindowLevelLookupTable* lut =
-    dynamic_cast< vtkWindowLevelLookupTable* >(
-      this->m_ImageMaps[ 0 ]->GetLookupTable( )
-      );
-  if( lut != NULL )
-    return( lut->GetWindow( ) );
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
+    return( this->m_ImageBlender->GetWindow( ) );
   else
     return( double( 0 ) );
 }
@@ -660,17 +654,8 @@ GetWindow( ) const
 double cpExtensions::Visualization::ImageSliceActors::
 GetLevel( ) const
 {
-  if( this->m_ImageMaps.size( ) == 0 )
-    return( double( 0 ) );
-  if( this->m_ImageMaps[ 0 ].GetPointer( ) == NULL )
-    return( double( 0 ) );
-
-  vtkWindowLevelLookupTable* lut =
-    dynamic_cast< vtkWindowLevelLookupTable* >(
-      this->m_ImageMaps[ 0 ]->GetLookupTable( )
-      );
-  if( lut != NULL )
-    return( lut->GetLevel( ) );
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
+    return( this->m_ImageBlender->GetLevel( ) );
   else
     return( double( 0 ) );
 }
@@ -679,175 +664,53 @@ GetLevel( ) const
 void cpExtensions::Visualization::ImageSliceActors::
 SetWindow( double w )
 {
-  if( this->m_ImageMaps.size( ) == 0 )
-    return;
-  if( this->m_ImageMaps[ 0 ].GetPointer( ) == NULL )
-    return;
-  vtkWindowLevelLookupTable* lut =
-    dynamic_cast< vtkWindowLevelLookupTable* >(
-      this->m_ImageMaps[ 0 ]->GetLookupTable( )
-      );
-  if( lut == NULL )
-    return;
-
-  if( w < this->m_MinWindow )
-    w = this->m_MinWindow;
-  if( w > this->m_MaxWindow )
-    w = this->m_MaxWindow;
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
+  {
+    this->m_ImageBlender->SetWindow( w );
+    this->Modified( );
 
-  lut->SetWindow( w );
-  lut->Build( );
-  this->m_ImageMaps[ 0 ]->Modified( );
-  this->Modified( );
+  } // fi
 }
 
 // -------------------------------------------------------------------------
 void cpExtensions::Visualization::ImageSliceActors::
 SetLevel( double l )
 {
-  if( this->m_ImageMaps.size( ) == 0 )
-    return;
-  if( this->m_ImageMaps[ 0 ].GetPointer( ) == NULL )
-    return;
-  vtkWindowLevelLookupTable* lut =
-    dynamic_cast< vtkWindowLevelLookupTable* >(
-      this->m_ImageMaps[ 0 ]->GetLookupTable( )
-      );
-  if( lut == NULL )
-    return;
-
-  if( l < this->m_MinLevel )
-    l = this->m_MinLevel;
-  if( l > this->m_MaxLevel )
-    l = this->m_MaxLevel;
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
+  {
+    this->m_ImageBlender->SetLevel( l );
+    this->Modified( );
 
-  lut->SetLevel( l );
-  lut->Build( );
-  this->m_ImageMaps[ 0 ]->Modified( );
-  this->Modified( );
+  } // fi
 }
 
 // -------------------------------------------------------------------------
 void cpExtensions::Visualization::ImageSliceActors::
 SetWindowLevel( double w, double l )
 {
-  if( this->m_ImageMaps.size( ) == 0 )
-    return;
-  if( this->m_ImageMaps[ 0 ].GetPointer( ) == NULL )
-    return;
-  vtkWindowLevelLookupTable* lut =
-    dynamic_cast< vtkWindowLevelLookupTable* >(
-      this->m_ImageMaps[ 0 ]->GetLookupTable( )
-      );
-  if( lut == NULL )
-    return;
-
-  if( w < this->m_MinWindow )
-    w = this->m_MinWindow;
-  if( w > this->m_MaxWindow )
-    w = this->m_MaxWindow;
-  if( l < this->m_MinLevel )
-    l = this->m_MinLevel;
-  if( l > this->m_MaxLevel )
-    l = this->m_MaxLevel;
-
-  lut->SetWindow( w );
-  lut->SetLevel( l );
-  lut->Build( );
-  this->m_ImageMaps[ 0 ]->Modified( );
-  this->UpdateText( w, l );
-  this->Modified( );
-}
-
-// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageSliceActors::
-ResetWindowLevel( )
-{
-  static const double _2 = double( 2 );
-  this->SetWindowLevel(
-    this->m_MaxWindow, ( this->m_MaxLevel + this->m_MinLevel ) / _2
-    );
-}
-
-// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageSliceActors::
-SetLookupTable( unsigned int id, vtkLookupTable* lut )
-{
-  if( id < this->m_ImageMaps.size( ) && id > 0 )
+  if( this->m_ImageBlender.GetPointer( ) != NULL )
   {
-    if( this->m_ImageMaps[ id ].GetPointer( ) != NULL )
-    {
-      this->m_ImageMaps[ id ]->SetLookupTable( lut );
-      this->m_ImageMaps[ id ]->Modified( );
-      this->Modified( );
-
-    } // fi
+    this->m_ImageBlender->SetWindowLevel( w, l );
+    this->UpdateText( w, l );
+    this->Modified( );
 
   } // fi
 }
 
 // -------------------------------------------------------------------------
 void cpExtensions::Visualization::ImageSliceActors::
-SetLookupTableAsColor( unsigned int id, double r, double g, double b )
+ResetWindowLevel( )
 {
-  static const double _0 = double( 0 );
-  static const double _2 = double( 2 );
-  static const double _4 = double( 4 );
-  static const double _6 = double( 6 );
-  static const double _OPACITY = double( 0.6 );
-
-  // Check ID consistency
-  if( id == 0 || id >= this->m_ImageMaps.size( ) )
-    return;
-
-  // Get image scalar range
-  vtkAlgorithmOutput* aout = this->m_ImageMaps[ id ]->GetOutputPort( );
-  vtkImageData* image = dynamic_cast< vtkImageData* >(
-    aout->GetProducer( )->GetOutputDataObject( aout->GetIndex( ) )
-    );
-  double range[ 2 ];
-  image->GetScalarRange( range );
-
-  // Get HSV from display color
-  double cmax = ( r > g )? r: g; cmax = ( b > cmax )? b: cmax;
-  double cmin = ( r < g )? r: g; cmin = ( b < cmin )? b: cmin;
-  double d = cmax - cmin;
-
-  double saturation = ( std::fabs( cmax ) > _0 )? d / cmax: _0;
-  double value = cmax;
-  double hue = _0;
-  if( d > _0 )
-  {
-    if( r == cmax )
-      hue = std::fmod( ( g - b ) / d, _6 );
-    else if( g == cmax )
-      hue = ( ( b - r ) / d ) + _2;
-    else if( b == cmax )
-      hue = ( ( r - g ) / d ) + _4;
-    hue /= _6;
-
-  } // fi
-
-  // Define new lookup table
-  vtkSmartPointer< vtkLookupTable > lut =
-    vtkSmartPointer< vtkLookupTable >::New( );
-  lut->SetScaleToLinear( );
-  lut->SetNanColor( _0, _0, _0, _0 );
-  lut->SetTableRange( range[ 0 ], range[ 1 ] );
-  lut->SetAlphaRange( _0, _OPACITY );
-  lut->SetHueRange( _0, hue );
-  lut->SetSaturationRange( _0, saturation );
-  lut->SetValueRange( _0, value );
-  lut->Build( );
-  this->SetLookupTable( id, lut );
+  std::cerr << "ACA Resetear" << std::endl;
+  std::exit( 1 );
 }
 
 // -------------------------------------------------------------------------
 int cpExtensions::Visualization::ImageSliceActors::
 GetAxis( ) const
 {
-  if( this->m_SliceMappers.size( ) > 0 )
-    return( this->m_SliceMappers[ 0 ]->GetOrientation( ) );
+  if( this->m_ImageMapper.GetPointer( ) != NULL )
+    return( this->m_ImageMapper->GetOrientation( ) );
   else
     return( -1 );
 }
@@ -856,8 +719,8 @@ GetAxis( ) const
 int cpExtensions::Visualization::ImageSliceActors::
 GetSliceNumber( ) const
 {
-  if( this->m_SliceMappers.size( ) > 0 )
-    return( this->m_SliceMappers[ 0 ]->GetSliceNumber( ) );
+  if( this->m_ImageMapper.GetPointer( ) != NULL )
+    return( this->m_ImageMapper->GetSliceNumber( ) );
   else
     return( -1 );
 }
@@ -866,8 +729,8 @@ GetSliceNumber( ) const
 int cpExtensions::Visualization::ImageSliceActors::
 GetSliceNumberMinValue( ) const
 {
-  if( this->m_SliceMappers.size( ) > 0 )
-    return( this->m_SliceMappers[ 0 ]->GetSliceNumberMinValue( ) );
+  if( this->m_ImageMapper.GetPointer( ) != NULL )
+    return( this->m_ImageMapper->GetSliceNumberMinValue( ) );
   else
     return( -1 );
 }
@@ -876,8 +739,8 @@ GetSliceNumberMinValue( ) const
 int cpExtensions::Visualization::ImageSliceActors::
 GetSliceNumberMaxValue( ) const
 {
-  if( this->m_SliceMappers.size( ) > 0 )
-    return( this->m_SliceMappers[ 0 ]->GetSliceNumberMaxValue( ) );
+  if( this->m_ImageMapper.GetPointer( ) != NULL )
+    return( this->m_ImageMapper->GetSliceNumberMaxValue( ) );
   else
     return( -1 );
 }
@@ -886,52 +749,42 @@ GetSliceNumberMaxValue( ) const
 void cpExtensions::Visualization::ImageSliceActors::
 SetSliceNumber( const int& slice )
 {
-  unsigned int nImages = this->m_SliceMappers.size( );
-  if( nImages == 0 )
+  if( this->m_ImageMapper.GetPointer( ) == NULL )
     return;
 
   int axis = this->GetAxis( );
   double prev_pos = this->m_VisibleBounds[ axis << 1 ];
 
-  // Change visualization extent
-  for( unsigned int i = 0; i < nImages; ++i )
-  {
-    // Update mappers and display bounds
-    this->m_SliceMappers[ i ]->SetSliceNumber( slice );
-    this->m_SliceMappers[ i ]->Modified( );
-    this->m_ImageActors[ i ]->Modified( );
-    this->m_SliceMappers[ i ]->Update( );
-
-    // Update display extent (this isn't done automatically)
-    if( i == 0 )
-    {
-      this->m_SliceMappers[ i ]->GetInput( )->
-        GetExtent( this->m_VisibleExtent );
-      this->m_VisibleExtent[ axis << 1 ] = slice;
-      this->m_VisibleExtent[ ( axis << 1 ) + 1 ] = slice;
-
-    } // fi
-    this->m_ImageActors[ i ]->SetDisplayExtent( this->m_VisibleExtent );
+  // Update mappers and display bounds
+  this->m_ImageMapper->SetSliceNumber( slice );
+  this->m_ImageMapper->Modified( );
+  this->m_ImageActor->Modified( );
+  this->m_ImageMapper->Update( );
 
-  } // rof
+  // Update display extent (this isn't done automatically)
+  this->m_ImageMapper->GetInput( )->GetExtent( this->m_VisibleExtent );
+  this->m_VisibleExtent[ axis << 1 ] = slice;
+  this->m_VisibleExtent[ ( axis << 1 ) + 1 ] = slice;
+  this->m_ImageActor->SetDisplayExtent( this->m_VisibleExtent );
 
-  this->m_SliceMappers[ 0 ]->GetBounds( this->m_VisibleBounds );
+  // Prepare plane data
+  this->m_ImageMapper->GetBounds( this->m_VisibleBounds );
   double x0[][ 3 ] =
-  {
-    {
-      this->m_VisibleBounds[ 0 ],
-      this->m_VisibleBounds[ 2 ],
-      this->m_VisibleBounds[ 4 ]
-    },
     {
-      this->m_VisibleBounds[ 1 ],
-      this->m_VisibleBounds[ 3 ],
-      this->m_VisibleBounds[ 5 ]
-    }
-  };
+      {
+        this->m_VisibleBounds[ 0 ],
+        this->m_VisibleBounds[ 2 ],
+        this->m_VisibleBounds[ 4 ]
+      },
+      {
+        this->m_VisibleBounds[ 1 ],
+        this->m_VisibleBounds[ 3 ],
+        this->m_VisibleBounds[ 5 ]
+      }
+    };
   double p0[ 2 ][ 3 ];
 
-  vtkPlane* plane = this->m_SliceMappers[ 0 ]->GetSlicePlane( );
+  vtkPlane* plane = this->m_ImageMapper->GetSlicePlane( );
   plane->GeneralizedProjectPoint( x0[ 0 ], p0[ 0 ] );
   plane->GeneralizedProjectPoint( x0[ 1 ], p0[ 1 ] );
 
@@ -1011,12 +864,9 @@ SetSliceNumber( const int& slice )
 void cpExtensions::Visualization::ImageSliceActors::
 SetSlice( double* pos )
 {
-  vtkImageData* image;
-  if( this->m_ImageMaps[ 0 ] != NULL )
-    image =
-      dynamic_cast< vtkImageData* >( this->m_ImageMaps[ 0 ]->GetInput( ) );
-  else
-    image = this->m_SliceMappers[ 0 ]->GetInput( );
+  vtkImageData* image = this->GetInputImage( 0 );
+  if( image == NULL )
+    return;
 
   int ijk[ 3 ];
   double pcoords[ 3 ];
@@ -1028,17 +878,17 @@ SetSlice( double* pos )
 void cpExtensions::Visualization::ImageSliceActors::
 UpdateText( )
 {
-  if( this->m_SliceMappers.size( ) > 0 )
+  if( this->m_ImageMapper.GetPointer( ) != NULL )
   {
     char axis;
-    int axId = this->m_SliceMappers[ 0 ]->GetOrientation( );
+    int axId = this->m_ImageMapper->GetOrientation( );
     if     ( axId == 0 ) axis = 'X';
     else if( axId == 1 ) axis = 'Y';
     else if( axId == 2 ) axis = 'Z';
 
     std::sprintf(
       this->m_TextBuffer, "Axis: %c (%d)",
-      axis, this->m_SliceMappers[ 0 ]->GetSliceNumber( )
+      axis, this->m_ImageMapper->GetSliceNumber( )
       );
   }
   else
@@ -1052,22 +902,16 @@ UpdateText( )
 void cpExtensions::Visualization::ImageSliceActors::
 UpdateText( double pos[ 3 ] )
 {
-  if( this->m_SliceMappers.size( ) > 0 )
+  if( this->m_ImageMapper.GetPointer( ) != NULL )
   {
     char axis;
-    int axId = this->m_SliceMappers[ 0 ]->GetOrientation( );
+    int axId = this->m_ImageMapper->GetOrientation( );
     if     ( axId == 0 ) axis = 'X';
     else if( axId == 1 ) axis = 'Y';
     else if( axId == 2 ) axis = 'Z';
     int slice = this->GetSliceNumber( );
 
-    vtkImageData* image;
-    if( this->m_ImageMaps[ 0 ] != NULL )
-      image =
-        dynamic_cast< vtkImageData* >( this->m_ImageMaps[ 0 ]->GetInput( ) );
-    else
-      image = this->m_SliceMappers[ 0 ]->GetInput( );
-
+    vtkImageData* image = this->GetInputImage( 0 );
     int ijk[ 3 ];
     double pcoords[ 3 ];
     image->ComputeStructuredCoordinates( pos, ijk, pcoords );
@@ -1114,17 +958,17 @@ UpdateText( double pos[ 3 ] )
 void cpExtensions::Visualization::ImageSliceActors::
 UpdateText( const double& w, const double& l )
 {
-  if( this->m_SliceMappers.size( ) > 0 )
+  if( this->m_ImageMapper.GetPointer( ) != NULL )
   {
     char axis;
-    int axId = this->m_SliceMappers[ 0 ]->GetOrientation( );
+    int axId = this->m_ImageMapper->GetOrientation( );
     if     ( axId == 0 ) axis = 'X';
     else if( axId == 1 ) axis = 'Y';
     else if( axId == 2 ) axis = 'Z';
 
     std::sprintf(
       this->m_TextBuffer, "Axis: %c (%d)\nW/L (%.2f/%.2f)",
-      axis, this->m_SliceMappers[ 0 ]->GetSliceNumber( ), w, l
+      axis, this->m_ImageMapper->GetSliceNumber( ), w, l
       );
   }
   else
@@ -1192,74 +1036,6 @@ _ConfigureStyle( )
   this->m_Style->AddLeaveCommand( Self::_LeaveCommand, this );
 }
 
-// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageSliceActors::
-_ConfigureNewLUT( vtkImageData* data )
-{
-  // Does the new LUT is a window-level one?
-  unsigned int nImgs = this->m_ImageMaps.size( );
-  unsigned int nCmps = data->GetNumberOfScalarComponents( );
-
-  if( nCmps > 1 )
-  {
-    this->m_ImageMaps.push_back( NULL );
-    return;
-
-  } // fi
-
-  // Create LUT filter
-  this->m_ImageMaps.push_back( vtkSmartPointer< vtkImageMapToColors >::New( ) );
-  if( nImgs == 0 )
-  {
-    double range[ 2 ];
-    data->GetScalarRange( range );
-    vtkSmartPointer< vtkWindowLevelLookupTable > lut =
-      vtkSmartPointer< vtkWindowLevelLookupTable >::New( );
-    lut->SetScaleToLinear( );
-    lut->SetTableRange( range );
-    lut->SetWindow( range[ 1 ] - range[ 0 ] );
-    lut->SetLevel( ( range[ 1 ] + range[ 0 ] ) / double( 2 ) );
-    lut->Build( );
-    this->m_ImageMaps[ 0 ]->SetLookupTable( lut );
-  }
-  else
-    this->SetLookupTableAsColor( nImgs, 1, 0, 0 );
-}
-
-// -------------------------------------------------------------------------
-void cpExtensions::Visualization::ImageSliceActors::
-_ConfigureNewInput( int axis )
-{
-  unsigned int nImages = this->m_ImageActors.size( );
-
-  // Configure mapper
-  vtkImageSliceMapper* mapper = this->m_SliceMappers[ nImages ];
-  if( nImages == 0 )
-    mapper->SetOrientation( axis );
-  else
-    mapper->SetOrientation( this->m_SliceMappers[ 0 ]->GetOrientation( ) );
-  mapper->Update( );
-
-  // Create actor
-  vtkSmartPointer< vtkImageActor > actor =
-    vtkSmartPointer< vtkImageActor >::New( );
-  this->m_ImageActors.push_back( actor );
-  actor->SetMapper( mapper );
-  actor->SetInterpolate( this->m_Interpolate );
-  actor->Modified( );
-
-  if( nImages == 0 )
-    this->m_Style->AssociateImageActor( actor );
-  this->AddItem( actor );
-
-  if( nImages > 1 )
-    this->SetSliceNumber( this->GetSliceNumber( ) );
-  else
-    this->SetSliceNumber( this->GetSliceNumberMaxValue( ) );
-  this->ResetCursor( );
-  this->Modified( );
-}
-
 // -------------------------------------------------------------------------
 void cpExtensions::Visualization::ImageSliceActors::
 _MouseMoveCommand(
@@ -1296,7 +1072,7 @@ _MouseMoveCommand(
     {
       // Change image window level
       double bounds[ 6 ];
-      actors->m_SliceMappers[ 0 ]->GetBounds( bounds );
+      actors->m_ImageMapper->GetBounds( bounds );
 
       int a0 = actors->GetAxis( );
       int a1 = ( a0 + 1 ) % 3;
index e086901c32044dd6164e05fac6fe91d9911b6a44..8fff84881d01249d7283f281382366de4a7a510d 100644 (file)
@@ -3,13 +3,9 @@
 
 #include <cpExtensions/cpExtensions_Export.h>
 
-#include <map>
-#include <utility>
-
 #include <vtkSmartPointer.h>
 #include <vtkActor.h>
 #include <vtkImageActor.h>
-#include <vtkImageMapToColors.h>
 #include <vtkImageSliceMapper.h>
 #include <vtkPlane.h>
 #include <vtkPolyData.h>
@@ -18,6 +14,7 @@
 #include <vtkTextActor.h>
 
 #include <cpExtensions/Interaction/ImageInteractorStyle.h>
+#include <cpExtensions/Visualization/ImageBlender.h>
 
 // -------------------------------------------------------------------------
 class vtkAlgorithmOutput;
@@ -65,8 +62,12 @@ namespace cpExtensions
       // Creation
       static ImageSliceActors* New( );
 
-      void AddInputConnection( vtkAlgorithmOutput* aout, int axis = 2 );
-      void AddInputData( vtkImageData* data, int axis = 2 );
+      ImageBlender* GetBlender( );
+      const ImageBlender* GetBlender( ) const;
+      void SetBlender( ImageBlender* blender );
+      void SetAxis( int axis );
+      void AddInputConnection( vtkAlgorithmOutput* aout );
+      void AddInputData( vtkImageData* data );
       void Clear( );
 
       void AssociateSlice( Self* slice );
@@ -79,9 +80,9 @@ namespace cpExtensions
 
       void PushActorsInto( vtkRenderWindow* window, bool force_style = true );
       void PopActorsFrom( vtkRenderWindow* window );
-      unsigned int GetNumberOfImageActors( ) const;
-      vtkImageActor* GetImageActor( unsigned int id );
-      const vtkImageActor* GetImageActor( unsigned int id ) const;
+      unsigned int GetNumberOfImages( ) const;
+      vtkImageActor* GetImageActor( );
+      const vtkImageActor* GetImageActor( ) const;
       vtkTextActor* GetTextActor( );
       const vtkTextActor* GetTextActor( ) const;
       vtkActor* GetPlaneActor( );
@@ -99,9 +100,6 @@ namespace cpExtensions
       void ResetCursor( );
       void SetCursor( double pos[ 3 ] );
 
-      vtkImageMapToColors* GetImageMap( unsigned int id );
-      const vtkImageMapToColors* GetImageMap( unsigned int id ) const;
-
       double GetMinWindow( ) const;
       double GetMaxWindow( ) const;
       double GetMinLevel( ) const;
@@ -113,11 +111,6 @@ namespace cpExtensions
       void SetWindowLevel( double w, double l );
       void ResetWindowLevel( );
 
-      void SetLookupTable( unsigned int id, vtkLookupTable* lut );
-      void SetLookupTableAsColor(
-        unsigned int id, double r, double g, double b
-        );
-
       int GetAxis( ) const;
       int GetSliceNumber( ) const;
       int GetSliceNumberMinValue( ) const;
@@ -136,8 +129,6 @@ namespace cpExtensions
       virtual ~ImageSliceActors( );
 
       void _ConfigureStyle( );
-      void _ConfigureNewLUT( vtkImageData* data );
-      void _ConfigureNewInput( int axis );
 
       // Events
       static void _MouseMoveCommand(
@@ -173,9 +164,9 @@ namespace cpExtensions
       vtkRenderWindow* m_Window;
 
       // Multiple actors
-      std::vector< vtkSmartPointer< vtkImageMapToColors > > m_ImageMaps;
-      std::vector< vtkSmartPointer< vtkImageSliceMapper > > m_SliceMappers;
-      std::vector< vtkSmartPointer< vtkImageActor > >       m_ImageActors;
+      vtkSmartPointer< ImageBlender >        m_ImageBlender;
+      vtkSmartPointer< vtkImageSliceMapper > m_ImageMapper;
+      vtkSmartPointer< vtkImageActor >       m_ImageActor;
       bool m_Interpolate;
 
       int    m_VisibleExtent[ 6 ];
@@ -184,10 +175,6 @@ namespace cpExtensions
       // Associated slices
       std::vector< Self* > m_AssociatedSlices;
 
-      // Window-Level values
-      double m_MinWindow, m_MaxWindow;
-      double m_MinLevel, m_MaxLevel;
-
       // Unique objects
       vtkSmartPointer< vtkPolyData >       m_Cursor;
       vtkSmartPointer< vtkPolyDataMapper > m_CursorMapper;
index 00d27dc6e8411c62388b6f29a4487f2719cc1a5d..a7803b2ad77864d2ed9ce81bd316a6d827ff1e10 100644 (file)
@@ -31,174 +31,65 @@ GetSliceActors( const int& i ) const
 int cpExtensions::Visualization::MPRActors::
 AddInputConnection( vtkAlgorithmOutput* aout )
 {
-  int N = this->Slices[ 0 ][ 0 ]->GetNumberOfImageActors( );
-  if( N == 0 )
+  ImageBlender* blender = this->Slices[ 0 ][ 0 ]->GetBlender( );
+  if( blender == NULL )
   {
-    this->Slices[ 0 ][ 0 ]->AddInputConnection( aout, 0 );
-    vtkImageMapToColors* imap = this->Slices[ 0 ][ 0 ]->GetImageMap( 0 );
+    this->Slices[ 0 ][ 0 ]->AddInputConnection( aout );
+    blender = this->Slices[ 0 ][ 0 ]->GetBlender( );
     for( unsigned int i = 0; i < 2; ++i )
+    {
       for( unsigned int j = 0; j < 3; ++j )
+      {
         if( i != 0 || j != 0 )
-          this->Slices[ i ][ j ]->AddInputConnection(
-            ( ( imap != NULL )? imap->GetOutputPort( ): aout ), j
-            );
-
-    // Create bounding box
-    vtkImageData* new_image = dynamic_cast< vtkImageData* >(
-      aout->GetProducer( )->GetOutputDataObject( aout->GetIndex( ) )
-      );
+          this->Slices[ i ][ j ]->SetBlender( blender );
+        this->Slices[ i ][ j ]->SetAxis( j );
 
-    // Create 3D outline
-    double bb[ 6 ];
-    new_image->GetBounds( bb );
+      } // rof
 
-    vtkSmartPointer< vtkOutlineSource > img_ol =
-      vtkSmartPointer< vtkOutlineSource >::New( );
-    img_ol->SetBounds( bb );
-
-    vtkSmartPointer< vtkPolyDataMapper > img_ol_mapper =
-      vtkSmartPointer< vtkPolyDataMapper >::New( );
-    img_ol_mapper->SetInputConnection( img_ol->GetOutputPort( ) );
-    this->ImageOutlineActor->SetMapper( img_ol_mapper );
-    this->ImageOutlineActor->GetProperty( )->SetColor( 1, 1, 1 );
-    this->ImageOutlineActor->GetProperty( )->SetLineWidth( 1 );
-
-    this->AddItem( this->ImageOutlineActor );
+    } // rof
+    this->_CreateBoundingBox( );
   }
   else
-  {
-    // Check if the image share the same space
-    vtkImageData* new_image = dynamic_cast< vtkImageData* >(
-      aout->GetProducer( )->GetOutputDataObject( aout->GetIndex( ) )
-      );
-    if( new_image != NULL )
-    {
-      vtkAlgorithmOutput* ref_aout =
-        this->Slices[ 0 ][ 0 ]->GetImageMap( 0 )->GetOutputPort( );
-      vtkImageData* ref_image = dynamic_cast< vtkImageData* >(
-        ref_aout->GetProducer( )->GetOutputDataObject( ref_aout->GetIndex( ) )
-        );
-      if( ref_image != NULL )
-      {
-        int ref_ext[ 6 ], new_ext[ 6 ];
-        ref_image->GetExtent( ref_ext );
-        new_image->GetExtent( new_ext );
-        if(
-          ref_ext[ 0 ] == new_ext[ 0 ] && ref_ext[ 1 ] == new_ext[ 1 ] &&
-          ref_ext[ 2 ] == new_ext[ 2 ] && ref_ext[ 3 ] == new_ext[ 3 ] &&
-          ref_ext[ 4 ] == new_ext[ 4 ] && ref_ext[ 5 ] == new_ext[ 5 ]
-          )
-        {
-          this->Slices[ 0 ][ 0 ]->AddInputConnection( aout, 0 );
-          vtkImageMapToColors* imap = this->Slices[ 0 ][ 0 ]->GetImageMap( N );
-          for( unsigned int i = 0; i < 2; ++i )
-            for( unsigned int j = 0; j < 3; ++j )
-              if( i != 0 || j != 0 )
-                this->Slices[ i ][ j ]->AddInputConnection(
-                  ( ( imap != NULL )? imap->GetOutputPort( ): aout ), j
-                  );
-        }
-        else
-          N = -1;
-      }
-      else
-        N = -1;
-    }
-    else
-      N = -1;
-
-  } // fi
-  return( N );
+    blender->AddInputConnection( aout );
+  return( blender->GetNumberOfImages( ) - 1 );
 }
 
 // -------------------------------------------------------------------------
 int cpExtensions::Visualization::MPRActors::
 AddInputData( vtkImageData* new_image )
 {
-  int N = this->Slices[ 0 ][ 0 ]->GetNumberOfImageActors( );
-  if( N == 0 )
+  ImageBlender* blender = this->Slices[ 0 ][ 0 ]->GetBlender( );
+  if( blender == NULL )
   {
-    this->Slices[ 0 ][ 0 ]->AddInputData( new_image, 0 );
-    vtkImageMapToColors* imap = this->Slices[ 0 ][ 0 ]->GetImageMap( 0 );
+    this->Slices[ 0 ][ 0 ]->AddInputData( new_image );
+    blender = this->Slices[ 0 ][ 0 ]->GetBlender( );
     for( unsigned int i = 0; i < 2; ++i )
+    {
       for( unsigned int j = 0; j < 3; ++j )
+      {
         if( i != 0 || j != 0 )
-        {
-          if( imap != NULL )
-            this->Slices[ i ][ j ]->AddInputConnection(
-              imap->GetOutputPort( ), j
-              );
-          else
-            this->Slices[ i ][ j ]->AddInputData( new_image, j );
-
-        } // fi
-
-    // Create 3D outline
-    double bb[ 6 ];
-    new_image->GetBounds( bb );
+          this->Slices[ i ][ j ]->SetBlender( blender );
+        this->Slices[ i ][ j ]->SetAxis( j );
 
-    vtkSmartPointer< vtkOutlineSource > img_ol =
-      vtkSmartPointer< vtkOutlineSource >::New( );
-    img_ol->SetBounds( bb );
-
-    vtkSmartPointer< vtkPolyDataMapper > img_ol_mapper =
-      vtkSmartPointer< vtkPolyDataMapper >::New( );
-    img_ol_mapper->SetInputConnection( img_ol->GetOutputPort( ) );
-    this->ImageOutlineActor->SetMapper( img_ol_mapper );
-    this->ImageOutlineActor->GetProperty( )->SetColor( 1, 1, 1 );
-    this->ImageOutlineActor->GetProperty( )->SetLineWidth( 1 );
+      } // rof
 
-    this->AddItem( this->ImageOutlineActor );
+    } // rof
+    this->_CreateBoundingBox( );
   }
   else
-  {
-    // Check if the image share the same space
-    vtkAlgorithmOutput* ref_aout =
-      this->Slices[ 0 ][ 0 ]->GetImageMap( 0 )->GetOutputPort( );
-    vtkImageData* ref_image = dynamic_cast< vtkImageData* >(
-      ref_aout->GetProducer( )->GetOutputDataObject( ref_aout->GetIndex( ) )
-      );
-    if( ref_image != NULL )
-    {
-      int ref_ext[ 6 ], new_ext[ 6 ];
-      ref_image->GetExtent( ref_ext );
-      new_image->GetExtent( new_ext );
-      if(
-        ref_ext[ 0 ] == new_ext[ 0 ] && ref_ext[ 1 ] == new_ext[ 1 ] &&
-        ref_ext[ 2 ] == new_ext[ 2 ] && ref_ext[ 3 ] == new_ext[ 3 ] &&
-        ref_ext[ 4 ] == new_ext[ 4 ] && ref_ext[ 5 ] == new_ext[ 5 ]
-        )
-      {
-        this->Slices[ 0 ][ 0 ]->AddInputData( new_image, 0 );
-        vtkImageMapToColors* imap = this->Slices[ 0 ][ 0 ]->GetImageMap( N );
-        for( unsigned int i = 0; i < 2; ++i )
-          for( unsigned int j = 0; j < 3; ++j )
-            if( i != 0 || j != 0 )
-            {
-              if( imap != NULL )
-                this->Slices[ i ][ j ]->AddInputConnection(
-                  imap->GetOutputPort( ), j
-                  );
-              else
-                this->Slices[ i ][ j ]->AddInputData( new_image, j );
-
-            } // fi
-      }
-      else
-        N = -1;
-    }
-    else
-      N = -1;
-
-  } // fi
-  return( N );
+    blender->AddInputData( new_image );
+  return( blender->GetNumberOfImages( ) - 1 );
 }
 
 // -------------------------------------------------------------------------
 unsigned int cpExtensions::Visualization::MPRActors::
 GetNumberOfImages( ) const
 {
-  return( this->Slices[ 0 ][ 0 ]->GetNumberOfImageActors( ) );
+  ImageBlender* blender = this->Slices[ 0 ][ 0 ]->GetBlender( );
+  if( blender != NULL )
+    return( blender->GetNumberOfImages( ) );
+  else
+    return( 0 );
 }
 
 // -------------------------------------------------------------------------
@@ -273,19 +164,6 @@ PopActorsFrom(
   this->Slices[ 1 ][ 2 ]->Clear( );
 }
 
-// -------------------------------------------------------------------------
-void cpExtensions::Visualization::MPRActors::
-SetLookupTableAsColor( unsigned int i, double r, double g, double b )
-{
-  this->Slices[ 0 ][ 0 ]->SetLookupTableAsColor( 0, r, g, b );
-  this->Slices[ 0 ][ 1 ]->Modified( );
-  this->Slices[ 0 ][ 2 ]->Modified( );
-  this->Slices[ 1 ][ 0 ]->Modified( );
-  this->Slices[ 1 ][ 1 ]->Modified( );
-  this->Slices[ 1 ][ 2 ]->Modified( );
-  this->Modified( );
-}
-
 // -------------------------------------------------------------------------
 double cpExtensions::Visualization::MPRActors::
 GetWindow( )
@@ -325,7 +203,11 @@ GetSlice( const int& axis ) const
 void cpExtensions::Visualization::MPRActors::
 SetSlice( const int& axis, const int& slice )
 {
-  vtkImageData* image = this->Slices[ 0 ][ 0 ]->GetInputImage( 0 );
+  ImageBlender* blender = this->Slices[ 0 ][ 0 ]->GetBlender( );
+  if( blender == NULL )
+    return;
+  vtkImageData* image =
+    dynamic_cast< vtkImageData* >( blender->GetInput( ) );
   if( image == NULL )
     return;
 
@@ -350,7 +232,11 @@ SetSlice( const int& axis, const int& slice )
 void cpExtensions::Visualization::MPRActors::
 SetSlice( const int& axis, const double& slice )
 {
-  vtkImageData* image = this->Slices[ 0 ][ 0 ]->GetInputImage( 0 );
+  ImageBlender* blender = this->Slices[ 0 ][ 0 ]->GetBlender( );
+  if( blender == NULL )
+    return;
+  vtkImageData* image =
+    dynamic_cast< vtkImageData* >( blender->GetInput( ) );
   if( image == NULL )
     return;
 
@@ -370,7 +256,7 @@ ResetSlices( )
   for( unsigned int i = 0; i < 2; ++i )
     for( unsigned int j = 0; j < 3; ++j )
       this->Slices[ i ][ j ]->SetSliceNumber(
-        this->Slices[ i ][ j ]->GetSliceNumberMaxValue( )
+        this->Slices[ i ][ j ]->GetSliceNumberMinValue( )
         );
 }
 
@@ -407,6 +293,38 @@ cpExtensions::Visualization::MPRActors::
 {
 }
 
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::MPRActors::
+_CreateBoundingBox( )
+{
+  ImageBlender* blender = this->Slices[ 0 ][ 0 ]->GetBlender( );
+  if( blender == NULL )
+    return;
+  if( blender->GetNumberOfImages( ) == 1 )
+  {
+    vtkImageData* image =
+      dynamic_cast< vtkImageData* >( blender->GetInput( ) );
+
+    // Create 3D outline
+    double bb[ 6 ];
+    image->GetBounds( bb );
+
+    vtkSmartPointer< vtkOutlineSource > img_ol =
+      vtkSmartPointer< vtkOutlineSource >::New( );
+    img_ol->SetBounds( bb );
+
+    vtkSmartPointer< vtkPolyDataMapper > img_ol_mapper =
+      vtkSmartPointer< vtkPolyDataMapper >::New( );
+    img_ol_mapper->SetInputConnection( img_ol->GetOutputPort( ) );
+    this->ImageOutlineActor->SetMapper( img_ol_mapper );
+    this->ImageOutlineActor->GetProperty( )->SetColor( 1, 1, 1 );
+    this->ImageOutlineActor->GetProperty( )->SetLineWidth( 1 );
+
+    this->AddItem( this->ImageOutlineActor );
+
+  } // fi
+}
+
 // -------------------------------------------------------------------------
 void cpExtensions::Visualization::MPRActors::
 _SlicesCommand( double* pos, int axis, void* data )
index fe8e43fd06d530cbeab6990a1d2dd12a59c44f7e..5eb3a202003712441265a4aada24d5990166d98f 100644 (file)
@@ -55,11 +55,6 @@ namespace cpExtensions
         vtkRenderWindow* w
         );
 
-      // Color lookup table
-      void SetLookupTableAsColor(
-        unsigned int i, double r, double g, double b
-        );
-
       double GetWindow( );
       double GetLevel( );
 
@@ -75,6 +70,8 @@ namespace cpExtensions
       MPRActors( );
       virtual ~MPRActors( );
 
+      void _CreateBoundingBox( );
+
       static void _SlicesCommand( double* pos, int axis, void* data );
       static void _WindowLevelCommand(
         double window, double level, void* data