1 #include <cpExtensions/Visualization/ImageBlender.h>
3 #include <vtkDataObject.h>
4 #include <vtkImageData.h>
5 #include <vtkImageIterator.h>
6 #include <vtkImageProgressIterator.h>
7 #include <vtkInformation.h>
8 #include <vtkInformationVector.h>
10 // -------------------------------------------------------------------------
11 cpExtensions::Visualization::ImageBlender::
12 Self* cpExtensions::Visualization::ImageBlender::
15 return( new Self( ) );
18 // -------------------------------------------------------------------------
19 void cpExtensions::Visualization::ImageBlender::
20 PrintSelf( std::ostream& os, vtkIndent indent )
22 this->Superclass::PrintSelf( os, indent );
25 os << indent << "Colors: " << std::endl;
26 auto i = this->m_Colors.begin( );
27 for( ; i != this->m_Colors.end( ); ++i )
29 << indent << indent << i->first << " : ["
30 << i->second.R << ", "
31 << i->second.G << ", "
36 // -------------------------------------------------------------------------
37 const double& cpExtensions::Visualization::ImageBlender::
40 return( this->m_MaxWindow );
43 // -------------------------------------------------------------------------
44 const double& cpExtensions::Visualization::ImageBlender::
47 return( this->m_MaxLevel );
50 // -------------------------------------------------------------------------
51 const double& cpExtensions::Visualization::ImageBlender::
54 return( this->m_MinWindow );
57 // -------------------------------------------------------------------------
58 const double& cpExtensions::Visualization::ImageBlender::
61 return( this->m_MinLevel );
64 // -------------------------------------------------------------------------
65 const double& cpExtensions::Visualization::ImageBlender::
68 return( this->m_Window );
71 // -------------------------------------------------------------------------
72 const double& cpExtensions::Visualization::ImageBlender::
75 return( this->m_Level );
78 // -------------------------------------------------------------------------
79 void cpExtensions::Visualization::ImageBlender::
80 SetWindow( const double& w )
82 if( this->m_Window != w )
90 // -------------------------------------------------------------------------
91 void cpExtensions::Visualization::ImageBlender::
92 SetLevel( const double& l )
94 if( this->m_Level != l )
102 // -------------------------------------------------------------------------
103 void cpExtensions::Visualization::ImageBlender::
104 SetWindowLevel( const double& w, const double& l )
106 this->SetWindow( w );
110 // -------------------------------------------------------------------------
111 void cpExtensions::Visualization::ImageBlender::
113 const unsigned int& i,
119 auto c = this->m_Colors.find( i );
120 if( c != this->m_Colors.end( ) )
127 r = g = b = double( 1 );
130 // -------------------------------------------------------------------------
131 void cpExtensions::Visualization::ImageBlender::
133 const unsigned int& i,
139 this->m_Colors[ i ] = TColor( r, g, b );
143 // -------------------------------------------------------------------------
144 cpExtensions::Visualization::ImageBlender::
147 m_MaxWindow( double( 0 ) ),
148 m_MaxLevel( double( 0 ) ),
149 m_MinWindow( double( 0 ) ),
150 m_MinLevel( double( 0 ) ),
151 m_Window( double( 0 ) ),
152 m_Level( double( 0 ) )
154 this->SetNumberOfInputPorts( 1 );
157 // -------------------------------------------------------------------------
158 cpExtensions::Visualization::ImageBlender::
163 // -------------------------------------------------------------------------
164 int cpExtensions::Visualization::ImageBlender::
166 vtkInformation* request,
167 vtkInformationVector** inputVector,
168 vtkInformationVector* outputVector
171 int numInputs = this->GetNumberOfInputConnections( 0 );
175 vtkDataObject::SetPointDataActiveScalarInfo(
176 outputVector->GetInformationObject( 0 ),
182 // -------------------------------------------------------------------------
183 void cpExtensions::Visualization::ImageBlender::
185 vtkInformation* request,
186 vtkInformationVector** inputVector,
187 vtkInformationVector* outputVector,
188 vtkImageData*** inData,
189 vtkImageData** outData,
190 int outExt[ 6 ], int id
193 if( inData[ 0 ][ 0 ] == NULL )
195 vtkErrorMacro( << "Input " << 0 << " must be specified." );
200 int numInputs = this->GetNumberOfInputConnections( 0 );
201 int numComp = inData[ 0 ][ 0 ]->GetNumberOfScalarComponents( );
205 "ThreadedRequestData: Input has " << numComp
206 << " components, but just 1 is supported"
212 for( int i = 1; i < numInputs; ++i )
214 int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( );
215 if( otherComp != numComp )
219 "ThreadedRequestData: Input " << i
220 << " has " << otherComp
221 << " components, but input 0 has " << numComp
230 // Initialize window/level
231 vtkImageData* main_image = inData[ 0 ][ 0 ];
233 main_image->GetScalarRange( range );
234 this->m_MaxWindow = range[ 1 ] - range[ 0 ];
235 this->m_MinWindow = this->m_MaxWindow * double( 1e-2 );
236 this->m_MinLevel = range[ 0 ];
237 this->m_MaxLevel = range[ 1 ];
239 // Update window/level
240 if( this->m_Window < this->m_MinWindow )
241 this->m_Window = this->m_MinWindow;
242 if( this->m_Window > this->m_MaxWindow )
243 this->m_Window = this->m_MaxWindow;
244 if( this->m_Level < this->m_MinLevel )
245 this->m_Level = this->m_MinLevel;
246 if( this->m_Level > this->m_MaxLevel )
247 this->m_Level = this->m_MaxLevel;
250 this->_GenerateData( inData[ 0 ], numInputs, outData[ 0 ], outExt, id );
253 // -------------------------------------------------------------------------
254 int cpExtensions::Visualization::ImageBlender::
255 FillInputPortInformation( int i, vtkInformation* info )
257 info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 );
258 return( this->Superclass::FillInputPortInformation( i, info ) );
261 // -------------------------------------------------------------------------
262 void cpExtensions::Visualization::ImageBlender::
264 vtkImageData** inDatas,
266 vtkImageData* outData,
271 vtkImageIterator< unsigned char > inItsFast[ 256 ];
272 unsigned char* inSIFast[ 256 ];
273 vtkImageProgressIterator< unsigned char > outIt( outData, outExt, this, id );
277 static_cast<vtkDoubleArray *>(this->GetWeights())->GetPointer(0);
278 double totalWeight = this->CalculateTotalWeight();
279 int normalize = this->GetNormalizeByWeight();
282 vtkImageIterator< unsigned char > *inIts;
283 unsigned char** inSI;
284 if( numInputs < 256 )
291 inIts = new vtkImageIterator< unsigned char >[ numInputs ];
292 inSI = new unsigned char*[ numInputs ];
296 // Loop through all input ImageData to initialize iterators
297 for( int i = 0; i < numInputs; ++i )
298 inIts[ i ].Initialize( inDatas[ i ], outExt );
300 // Loop through output pixels
301 double m = double( 1 ) / this->m_Window;
302 double c = double( 0.5 ) - ( this->m_Level / this->m_Window );
303 while( !outIt.IsAtEnd( ) )
305 // Prepare all iterators
306 for( int j = 0; j < numInputs; ++j )
307 inSI[ j ] = inIts[ j ].BeginSpan( );
308 unsigned char* outSI = outIt.BeginSpan( );
309 unsigned char* outSIEnd = outIt.EndSpan( );
312 while( outSI != outSIEnd )
314 // Window/Level value from main image
315 double wl = ( *inSI[ 0 ] * m ) + c;
316 if( wl < double( 0 ) ) wl = double( 0 );
317 if( wl > double( 1 ) ) wl = double( 1 );
319 // Prepare color values
323 double a = double( 1 );
327 for(int k=0; k < numInputs; ++k)
329 sum += weights[k] * *inSI[k];
339 *outSI = static_cast< unsigned char >( r ); outSI++;
340 *outSI = static_cast< unsigned char >( g ); outSI++;
341 *outSI = static_cast< unsigned char >( b ); outSI++;
342 *outSI = static_cast< unsigned char >( a ); outSI++;
345 for( int l = 0; l < numInputs; ++l )
350 // Advance all iterators
351 for( int j = 0; j < numInputs; ++j )
352 inIts[ j ].NextSpan( );
357 // Free auxiliary buffers
358 if( numInputs >= 256 )