1 #include <cpExtensions/Visualization/ImageBlender.h>
5 #include <vtkDataObject.h>
6 #include <vtkImageData.h>
7 #include <vtkImageIterator.h>
8 #include <vtkImageProgressIterator.h>
9 #include <vtkInformation.h>
10 #include <vtkInformationVector.h>
12 // -------------------------------------------------------------------------
13 cpExtensions::Visualization::ImageBlender::
14 Self* cpExtensions::Visualization::ImageBlender::
17 return( new Self( ) );
20 // -------------------------------------------------------------------------
21 void cpExtensions::Visualization::ImageBlender::
22 PrintSelf( std::ostream& os, vtkIndent indent )
24 this->Superclass::PrintSelf( os, indent );
27 os << indent << "Colors: " << std::endl;
28 auto i = this->m_Colors.begin( );
29 for( ; i != this->m_Colors.end( ); ++i )
31 << indent << indent << i->first << " : ["
32 << i->second.R << ", "
33 << i->second.G << ", "
38 // -------------------------------------------------------------------------
39 unsigned int cpExtensions::Visualization::ImageBlender::
40 GetNumberOfImages( ) const
42 return( ( const_cast< Self* >( this ) )->GetNumberOfInputConnections( 0 ) );
45 // -------------------------------------------------------------------------
46 const double& cpExtensions::Visualization::ImageBlender::
49 return( this->m_MaxWindow );
52 // -------------------------------------------------------------------------
53 const double& cpExtensions::Visualization::ImageBlender::
56 return( this->m_MaxLevel );
59 // -------------------------------------------------------------------------
60 const double& cpExtensions::Visualization::ImageBlender::
63 return( this->m_MinWindow );
66 // -------------------------------------------------------------------------
67 const double& cpExtensions::Visualization::ImageBlender::
70 return( this->m_MinLevel );
73 // -------------------------------------------------------------------------
74 const double& cpExtensions::Visualization::ImageBlender::
77 return( this->m_Window );
80 // -------------------------------------------------------------------------
81 const double& cpExtensions::Visualization::ImageBlender::
84 return( this->m_Level );
87 // -------------------------------------------------------------------------
88 void cpExtensions::Visualization::ImageBlender::
89 SetWindow( const double& w )
91 if( this->m_Window != w )
99 // -------------------------------------------------------------------------
100 void cpExtensions::Visualization::ImageBlender::
101 SetLevel( const double& l )
103 if( this->m_Level != l )
111 // -------------------------------------------------------------------------
112 void cpExtensions::Visualization::ImageBlender::
113 SetWindowLevel( const double& w, const double& l )
115 this->SetWindow( w );
119 // -------------------------------------------------------------------------
120 void cpExtensions::Visualization::ImageBlender::
122 const unsigned int& i,
128 auto c = this->m_Colors.find( i );
129 if( c != this->m_Colors.end( ) )
145 // -------------------------------------------------------------------------
146 void cpExtensions::Visualization::ImageBlender::
148 const unsigned int& i,
154 this->m_Colors[ i ] = TColor( r, g, b );
158 // -------------------------------------------------------------------------
159 cpExtensions::Visualization::ImageBlender::
162 m_MaxWindow( double( 0 ) ),
163 m_MaxLevel( double( 0 ) ),
164 m_MinWindow( double( 0 ) ),
165 m_MinLevel( double( 0 ) ),
166 m_Window( double( 0 ) ),
167 m_Level( double( 0 ) )
169 this->SetNumberOfInputPorts( 1 );
172 // -------------------------------------------------------------------------
173 cpExtensions::Visualization::ImageBlender::
178 // -------------------------------------------------------------------------
179 int cpExtensions::Visualization::ImageBlender::
181 vtkInformation* request,
182 vtkInformationVector** inputVector,
183 vtkInformationVector* outputVector
186 // Check number of inputs
187 int numInputs = this->GetNumberOfInputConnections( 0 );
192 vtkInformation* inInfo = inputVector[ 0 ]->GetInformationObject( 0 );
195 vtkImageData* inData = vtkImageData::SafeDownCast(
196 inInfo->Get( vtkDataObject::DATA_OBJECT( ) )
201 // Configure buffer extent
202 inData->GetExtent( this->m_Extent );
203 this->m_Extent[ 1 ] -= this->m_Extent[ 0 ];
204 this->m_Extent[ 3 ] -= this->m_Extent[ 2 ];
205 this->m_Extent[ 5 ] -= this->m_Extent[ 4 ];
206 this->m_Extent[ 1 ] += 1;
207 this->m_Extent[ 3 ] += 1;
208 this->m_Extent[ 5 ] += 1;
210 // Configure window/level
212 inData->GetScalarRange( range );
213 this->m_MaxWindow = range[ 1 ] - range[ 0 ];
214 this->m_MinWindow = this->m_MaxWindow * double( 1e-2 );
215 this->m_MinLevel = range[ 0 ];
216 this->m_MaxLevel = range[ 1 ];
217 if( this->m_Window < this->m_MinWindow )
218 this->m_Window = this->m_MinWindow;
219 if( this->m_Window > this->m_MaxWindow )
220 this->m_Window = this->m_MaxWindow;
221 if( this->m_Level < this->m_MinLevel )
222 this->m_Level = this->m_MinLevel;
223 if( this->m_Level > this->m_MaxLevel )
224 this->m_Level = this->m_MaxLevel;
225 this->m_WLSlope = double( 1 ) / this->m_Window;
226 this->m_WLOffset = double( 0.5 ) - ( this->m_Level / this->m_Window );
228 // Configure output type
229 vtkDataObject::SetPointDataActiveScalarInfo(
230 outputVector->GetInformationObject( 0 ),
236 // -------------------------------------------------------------------------
237 void cpExtensions::Visualization::ImageBlender::
239 vtkInformation* request,
240 vtkInformationVector** inputVector,
241 vtkInformationVector* outputVector,
242 vtkImageData*** inData,
243 vtkImageData** outData,
244 int outExt[ 6 ], int id
247 if( inData[ 0 ][ 0 ] == NULL )
249 vtkErrorMacro( << "Input " << 0 << " must be specified." );
254 int numInputs = this->GetNumberOfInputConnections( 0 );
255 int numComp = inData[ 0 ][ 0 ]->GetNumberOfScalarComponents( );
259 "ThreadedRequestData: Input has " << numComp
260 << " components, but just 1 is supported"
266 for( int i = 1; i < numInputs; ++i )
268 int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( );
269 if( otherComp != numComp )
273 "ThreadedRequestData: Input " << i
274 << " has " << otherComp
275 << " components, but input 0 has " << numComp
285 this->_GenerateData( inData[ 0 ], numInputs, outData[ 0 ], outExt, id );
288 // -------------------------------------------------------------------------
289 int cpExtensions::Visualization::ImageBlender::
290 FillInputPortInformation( int i, vtkInformation* info )
292 info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 );
293 return( this->Superclass::FillInputPortInformation( i, info ) );
297 // -------------------------------------------------------------------------
298 #define cpExtensions_ImageBlender_Type( O, V, T, B ) \
303 V = O( *( reinterpret_cast< char* >( B ) ) ); \
306 V = O( *( reinterpret_cast< short* >( B ) ) ); \
309 V = O( *( reinterpret_cast< int* >( B ) ) ); \
312 V = O( *( reinterpret_cast< long* >( B ) ) ); \
314 case VTK_UNSIGNED_CHAR: \
315 V = O( *( reinterpret_cast< unsigned char* >( B ) ) ); \
317 case VTK_UNSIGNED_SHORT: \
318 V = O( *( reinterpret_cast< unsigned short* >( B ) ) ); \
320 case VTK_UNSIGNED_INT: \
321 V = O( *( reinterpret_cast< unsigned int* >( B ) ) ); \
323 case VTK_UNSIGNED_LONG: \
324 V = O( *( reinterpret_cast< unsigned long* >( B ) ) ); \
327 V = O( *( reinterpret_cast< float* >( B ) ) ); \
330 V = O( *( reinterpret_cast< double* >( B ) ) ); \
334 // -------------------------------------------------------------------------
335 void cpExtensions::Visualization::ImageBlender::
337 vtkImageData** inDatas,
339 vtkImageData* outData,
344 static const double _0 = double( 0 );
345 static const double _1 = double( 1 );
346 static const double _255 = double( 255 );
348 unsigned char* mBuffer =
349 reinterpret_cast< unsigned char* >( inDatas[ 0 ]->GetScalarPointer( ) );
350 unsigned char* oBuffer =
351 reinterpret_cast< unsigned char* >( outData->GetScalarPointer( ) );
352 int mType = inDatas[ 0 ]->GetScalarType( );
353 int mSize = inDatas[ 0 ]->GetScalarSize( );
356 int e13 = this->m_Extent[ 1 ] * this->m_Extent[ 3 ];
357 for( int k = outExt[ 4 ]; k <= outExt[ 5 ]; ++k )
359 int dk = ( k - this->m_Extent[ 4 ] ) * e13;
360 for( int j = outExt[ 2 ]; j <= outExt[ 3 ]; ++j )
362 int dj = ( ( j - this->m_Extent[ 2 ] ) * this->m_Extent[ 3 ] ) + dk;
363 for( int i = outExt[ 0 ]; i <= outExt[ 1 ]; ++i )
365 int di = ( i - this->m_Extent[ 0 ] ) + dj;
368 cpExtensions_ImageBlender_Type(
369 double, v, mType, mBuffer + ( di * mSize )
371 v *= this->m_WLSlope;
372 v += this->m_WLOffset;
381 for( int i = 1; i < numInputs; ++i )
383 unsigned char* cBuffer =
384 reinterpret_cast< unsigned char* >(
385 inDatas[ i ]->GetScalarPointer( )
387 int cType = inDatas[ i ]->GetScalarType( );
388 int cSize = inDatas[ i ]->GetScalarSize( );
389 cpExtensions_ImageBlender_Type(
390 double, c, cType, cBuffer + ( di * cSize )
392 if( c > double( 0 ) )
394 TColor rgb = this->m_Colors[ i ];
406 oBuffer[ di4 + 0 ] = static_cast< unsigned char >( r * _255 );
407 oBuffer[ di4 + 1 ] = static_cast< unsigned char >( g * _255 );
408 oBuffer[ di4 + 2 ] = static_cast< unsigned char >( b * _255 );
409 oBuffer[ di4 + 3 ] = static_cast< unsigned char >( a * _255 );