1 #include <cpExtensions/Visualization/ImageBlender.h>
6 #include <vtkDataObject.h>
7 #include <vtkImageData.h>
8 #include <vtkImageIterator.h>
9 #include <vtkImageProgressIterator.h>
10 #include <vtkInformation.h>
11 #include <vtkInformationVector.h>
13 // -------------------------------------------------------------------------
14 cpExtensions::Visualization::ImageBlender::
15 Self* cpExtensions::Visualization::ImageBlender::
18 return( new Self( ) );
21 // -------------------------------------------------------------------------
22 void cpExtensions::Visualization::ImageBlender::
23 PrintSelf( std::ostream& os, vtkIndent indent )
25 this->Superclass::PrintSelf( os, indent );
28 os << indent << "Colors: " << std::endl;
29 auto i = this->m_Colors.begin( );
30 for( ; i != this->m_Colors.end( ); ++i )
32 << indent << indent << i->first << " : ["
33 << i->second.R << ", "
34 << i->second.G << ", "
39 // -------------------------------------------------------------------------
40 unsigned int cpExtensions::Visualization::ImageBlender::
41 GetNumberOfImages( ) const
43 return( ( const_cast< Self* >( this ) )->GetNumberOfInputConnections( 0 ) );
46 // -------------------------------------------------------------------------
47 const double& cpExtensions::Visualization::ImageBlender::
50 return( this->m_MaxWindow );
53 // -------------------------------------------------------------------------
54 const double& cpExtensions::Visualization::ImageBlender::
57 return( this->m_MaxLevel );
60 // -------------------------------------------------------------------------
61 const double& cpExtensions::Visualization::ImageBlender::
64 return( this->m_MinWindow );
67 // -------------------------------------------------------------------------
68 const double& cpExtensions::Visualization::ImageBlender::
71 return( this->m_MinLevel );
74 // -------------------------------------------------------------------------
75 const double& cpExtensions::Visualization::ImageBlender::
78 return( this->m_Window );
81 // -------------------------------------------------------------------------
82 const double& cpExtensions::Visualization::ImageBlender::
85 return( this->m_Level );
88 // -------------------------------------------------------------------------
89 void cpExtensions::Visualization::ImageBlender::
90 SetWindow( const double& w )
92 if( this->m_Window != w )
100 // -------------------------------------------------------------------------
101 void cpExtensions::Visualization::ImageBlender::
102 SetLevel( const double& l )
104 if( this->m_Level != l )
112 // -------------------------------------------------------------------------
113 void cpExtensions::Visualization::ImageBlender::
114 SetWindowLevel( const double& w, const double& l )
116 this->SetWindow( w );
120 // -------------------------------------------------------------------------
121 void cpExtensions::Visualization::ImageBlender::
123 const unsigned int& i,
129 auto c = this->m_Colors.find( i );
130 if( c != this->m_Colors.end( ) )
144 // -------------------------------------------------------------------------
145 void cpExtensions::Visualization::ImageBlender::
147 const unsigned int& i,
153 this->m_Colors[ i ] = TColor( r, g, b );
157 // -------------------------------------------------------------------------
158 cpExtensions::Visualization::ImageBlender::
161 m_MaxWindow( double( 0 ) ),
162 m_MaxLevel( double( 0 ) ),
163 m_MinWindow( double( 0 ) ),
164 m_MinLevel( double( 0 ) ),
165 m_Window( double( 0 ) ),
166 m_Level( double( 0 ) )
168 this->SetNumberOfInputPorts( 1 );
171 // -------------------------------------------------------------------------
172 cpExtensions::Visualization::ImageBlender::
177 // -------------------------------------------------------------------------
178 int cpExtensions::Visualization::ImageBlender::
180 vtkInformation* request,
181 vtkInformationVector** inputVector,
182 vtkInformationVector* outputVector
185 // Check number of inputs
186 int numInputs = this->GetNumberOfInputConnections( 0 );
191 vtkInformation* inInfo = inputVector[ 0 ]->GetInformationObject( 0 );
194 vtkImageData* inData = vtkImageData::SafeDownCast(
195 inInfo->Get( vtkDataObject::DATA_OBJECT( ) )
200 // Configure buffer extent
201 inData->GetExtent( this->m_Extent );
202 this->m_Extent[ 1 ] -= this->m_Extent[ 0 ];
203 this->m_Extent[ 3 ] -= this->m_Extent[ 2 ];
204 this->m_Extent[ 5 ] -= this->m_Extent[ 4 ];
205 this->m_Extent[ 1 ] += 1;
206 this->m_Extent[ 3 ] += 1;
207 this->m_Extent[ 5 ] += 1;
209 // Configure window/level
211 inData->GetScalarRange( range );
212 this->m_MaxWindow = range[ 1 ] - range[ 0 ];
213 this->m_MinWindow = this->m_MaxWindow * double( 1e-2 );
214 this->m_MinLevel = range[ 0 ];
215 this->m_MaxLevel = range[ 1 ];
216 if( this->m_Window < this->m_MinWindow )
217 this->m_Window = this->m_MinWindow;
218 if( this->m_Window > this->m_MaxWindow )
219 this->m_Window = this->m_MaxWindow;
220 if( this->m_Level < this->m_MinLevel )
221 this->m_Level = this->m_MinLevel;
222 if( this->m_Level > this->m_MaxLevel )
223 this->m_Level = this->m_MaxLevel;
224 this->m_WLSlope = double( 1 ) / this->m_Window;
225 this->m_WLOffset = double( 0.5 ) - ( this->m_Level / this->m_Window );
227 // Configure output type
228 vtkDataObject::SetPointDataActiveScalarInfo(
229 outputVector->GetInformationObject( 0 ),
235 // -------------------------------------------------------------------------
236 void cpExtensions::Visualization::ImageBlender::
238 vtkInformation* request,
239 vtkInformationVector** inputVector,
240 vtkInformationVector* outputVector,
241 vtkImageData*** inData,
242 vtkImageData** outData,
243 int outExt[ 6 ], int id
246 if( inData[ 0 ][ 0 ] == NULL )
248 vtkErrorMacro( << "Input " << 0 << " must be specified." );
253 int numInputs = this->GetNumberOfInputConnections( 0 );
254 int numComp = inData[ 0 ][ 0 ]->GetNumberOfScalarComponents( );
258 "ThreadedRequestData: Input has " << numComp
259 << " components, but just 1 is supported"
265 for( int i = 1; i < numInputs; ++i )
267 int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( );
268 if( otherComp != numComp )
272 "ThreadedRequestData: Input " << i
273 << " has " << otherComp
274 << " components, but input 0 has " << numComp
284 this->_GenerateData( inData[ 0 ], numInputs, outData[ 0 ], outExt, id );
287 // -------------------------------------------------------------------------
288 int cpExtensions::Visualization::ImageBlender::
289 FillInputPortInformation( int i, vtkInformation* info )
291 info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 );
292 return( this->Superclass::FillInputPortInformation( i, info ) );
296 // -------------------------------------------------------------------------
297 #define cpExtensions_ImageBlender_Type( O, V, T, B ) \
302 V = O( *( reinterpret_cast< char* >( B ) ) ); \
305 V = O( *( reinterpret_cast< short* >( B ) ) ); \
308 V = O( *( reinterpret_cast< int* >( B ) ) ); \
311 V = O( *( reinterpret_cast< long* >( B ) ) ); \
313 case VTK_UNSIGNED_CHAR: \
314 V = O( *( reinterpret_cast< unsigned char* >( B ) ) ); \
316 case VTK_UNSIGNED_SHORT: \
317 V = O( *( reinterpret_cast< unsigned short* >( B ) ) ); \
319 case VTK_UNSIGNED_INT: \
320 V = O( *( reinterpret_cast< unsigned int* >( B ) ) ); \
322 case VTK_UNSIGNED_LONG: \
323 V = O( *( reinterpret_cast< unsigned long* >( B ) ) ); \
326 V = O( *( reinterpret_cast< float* >( B ) ) ); \
329 V = O( *( reinterpret_cast< double* >( B ) ) ); \
333 // -------------------------------------------------------------------------
334 void cpExtensions::Visualization::ImageBlender::
336 vtkImageData** inDatas,
338 vtkImageData* outData,
343 static const double _0 = double( 0 );
344 static const double _1 = double( 1 );
345 static const double _255 = double( 255 );
347 unsigned char* mBuffer =
348 reinterpret_cast< unsigned char* >( inDatas[ 0 ]->GetScalarPointer( ) );
349 unsigned char* oBuffer =
350 reinterpret_cast< unsigned char* >( outData->GetScalarPointer( ) );
351 int mType = inDatas[ 0 ]->GetScalarType( );
352 int mSize = inDatas[ 0 ]->GetScalarSize( );
355 int e13 = this->m_Extent[ 1 ] * this->m_Extent[ 3 ];
356 for( int k = outExt[ 4 ]; k <= outExt[ 5 ]; ++k )
358 int dk = ( k - this->m_Extent[ 4 ] ) * e13;
359 for( int j = outExt[ 2 ]; j <= outExt[ 3 ]; ++j )
361 int dj = ( ( j - this->m_Extent[ 2 ] ) * this->m_Extent[ 3 ] ) + dk;
362 for( int i = outExt[ 0 ]; i <= outExt[ 1 ]; ++i )
364 int di = ( i - this->m_Extent[ 0 ] ) + dj;
367 cpExtensions_ImageBlender_Type(
368 double, v, mType, mBuffer + ( di * mSize )
370 v *= this->m_WLSlope;
371 v += this->m_WLOffset;
380 for( int i = 1; i < numInputs; ++i )
382 unsigned char* cBuffer =
383 reinterpret_cast< unsigned char* >(
384 inDatas[ i ]->GetScalarPointer( )
386 int cType = inDatas[ i ]->GetScalarType( );
387 int cSize = inDatas[ i ]->GetScalarSize( );
388 cpExtensions_ImageBlender_Type(
389 double, c, cType, cBuffer + ( di * cSize )
391 if( c > double( 0 ) )
394 this->GetColor( i, cr, cg, cb );
395 double n = std::sqrt( ( cr * cr ) + ( cg * cg ) + ( cb * cb ) );
407 oBuffer[ di4 + 0 ] = static_cast< unsigned char >( r * _255 );
408 oBuffer[ di4 + 1 ] = static_cast< unsigned char >( g * _255 );
409 oBuffer[ di4 + 2 ] = static_cast< unsigned char >( b * _255 );
410 oBuffer[ di4 + 3 ] = static_cast< unsigned char >( a * _255 );