]> Creatis software - cpPlugins.git/blob - lib/cpExtensions/Visualization/ImageBlender.cxx
Merge branch 'master' of ssh://git.creatis.insa-lyon.fr/cpPlugins
[cpPlugins.git] / lib / cpExtensions / Visualization / ImageBlender.cxx
1 #include <cpExtensions/Visualization/ImageBlender.h>
2
3 #include <vtkDataObject.h>
4 #include <vtkImageData.h>
5 #include <vtkImageIterator.h>
6 #include <vtkImageProgressIterator.h>
7 #include <vtkInformation.h>
8 #include <vtkInformationVector.h>
9
10 // -------------------------------------------------------------------------
11 cpExtensions::Visualization::ImageBlender::
12 Self* cpExtensions::Visualization::ImageBlender::
13 New( )
14 {
15   return( new Self( ) );
16 }
17
18 // -------------------------------------------------------------------------
19 void cpExtensions::Visualization::ImageBlender::
20 PrintSelf( std::ostream& os, vtkIndent indent )
21 {
22   this->Superclass::PrintSelf( os, indent );
23
24   // Objects
25   os << indent << "Colors: " << std::endl;
26   auto i = this->m_Colors.begin( );
27   for( ; i != this->m_Colors.end( ); ++i )
28     os
29       << indent << indent << i->first << " : ["
30       << i->second.R << ", "
31       << i->second.G << ", "
32       << i->second.B << "]"
33       << std::endl;
34 }
35
36 // -------------------------------------------------------------------------
37 const double& cpExtensions::Visualization::ImageBlender::
38 GetMaxWindow( ) const
39 {
40   return( this->m_MaxWindow );
41 }
42
43 // -------------------------------------------------------------------------
44 const double& cpExtensions::Visualization::ImageBlender::
45 GetMaxLevel( ) const
46 {
47   return( this->m_MaxLevel );
48 }
49
50 // -------------------------------------------------------------------------
51 const double& cpExtensions::Visualization::ImageBlender::
52 GetMinWindow( ) const
53 {
54   return( this->m_MinWindow );
55 }
56
57 // -------------------------------------------------------------------------
58 const double& cpExtensions::Visualization::ImageBlender::
59 GetMinLevel( ) const
60 {
61   return( this->m_MinLevel );
62 }
63
64 // -------------------------------------------------------------------------
65 const double& cpExtensions::Visualization::ImageBlender::
66 GetWindow( ) const
67 {
68   return( this->m_Window );
69 }
70
71 // -------------------------------------------------------------------------
72 const double& cpExtensions::Visualization::ImageBlender::
73 GetLevel( ) const
74 {
75   return( this->m_Level );
76 }
77
78 // -------------------------------------------------------------------------
79 void cpExtensions::Visualization::ImageBlender::
80 SetWindow( const double& w )
81 {
82   if( this->m_Window != w )
83   {
84     this->m_Window = w;
85     this->Modified( );
86
87   } // fi
88 }
89
90 // -------------------------------------------------------------------------
91 void cpExtensions::Visualization::ImageBlender::
92 SetLevel( const double& l )
93 {
94   if( this->m_Level != l )
95   {
96     this->m_Level = l;
97     this->Modified( );
98
99   } // fi
100 }
101
102 // -------------------------------------------------------------------------
103 void cpExtensions::Visualization::ImageBlender::
104 SetWindowLevel( const double& w, const double& l )
105 {
106   this->SetWindow( w );
107   this->SetLevel( l );
108 }
109
110 // -------------------------------------------------------------------------
111 void cpExtensions::Visualization::ImageBlender::
112 GetColor(
113   const unsigned int& i,
114   double& r,
115   double& g,
116   double& b
117   ) const
118 {
119   auto c = this->m_Colors.find( i );
120   if( c != this->m_Colors.end( ) )
121   {
122     r = c->second.R;
123     g = c->second.G;
124     b = c->second.B;
125   }
126   else
127     r = g = b = double( 1 );
128 }
129
130 // -------------------------------------------------------------------------
131 void cpExtensions::Visualization::ImageBlender::
132 SetColor(
133   const unsigned int& i,
134   const double& r,
135   const double& g,
136   const double& b
137   )
138 {
139   this->m_Colors[ i ] = TColor( r, g, b );
140   this->Modified( );
141 }
142
143 // -------------------------------------------------------------------------
144 cpExtensions::Visualization::ImageBlender::
145 ImageBlender( )
146   : Superclass( ),
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 ) )
153 {
154   this->SetNumberOfInputPorts( 1 );
155 }
156
157 // -------------------------------------------------------------------------
158 cpExtensions::Visualization::ImageBlender::
159 ~ImageBlender( )
160 {
161 }
162
163 // -------------------------------------------------------------------------
164 int cpExtensions::Visualization::ImageBlender::
165 RequestInformation(
166   vtkInformation* request,
167   vtkInformationVector** inputVector,
168   vtkInformationVector* outputVector
169   )
170 {
171   int numInputs = this->GetNumberOfInputConnections( 0 );
172   if( numInputs == 0 )
173     return( 0 );
174
175   vtkDataObject::SetPointDataActiveScalarInfo(
176     outputVector->GetInformationObject( 0 ),
177     VTK_UNSIGNED_CHAR, 4
178     );
179   return( 1 );
180 }
181
182 // -------------------------------------------------------------------------
183 void cpExtensions::Visualization::ImageBlender::
184 ThreadedRequestData(
185   vtkInformation* request,
186   vtkInformationVector** inputVector,
187   vtkInformationVector* outputVector,
188   vtkImageData*** inData,
189   vtkImageData** outData,
190   int outExt[ 6 ], int id
191   )
192 {
193   if( inData[ 0 ][ 0 ] == NULL )
194   {
195     vtkErrorMacro( << "Input " << 0 << " must be specified." );
196     return;
197
198   } // fi
199
200   int numInputs = this->GetNumberOfInputConnections( 0 );
201   int numComp = inData[ 0 ][ 0 ]->GetNumberOfScalarComponents( );
202   if( numComp > 1 )
203   {
204     vtkErrorMacro(
205       "ThreadedRequestData: Input has " << numComp
206       << " components, but just 1 is supported"
207       );
208     return;
209
210   } // fi
211
212   for( int i = 1; i < numInputs; ++i )
213   {
214     int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( );
215     if( otherComp != numComp )
216     {
217       if( id == 0 )
218         vtkErrorMacro(
219           "ThreadedRequestData: Input " << i
220           << " has " << otherComp
221           << " components, but input 0 has " << numComp
222           << " components"
223           );
224       return;
225
226     } // fi
227
228   } // rof
229
230   // Initialize window/level
231   vtkImageData* main_image = inData[ 0 ][ 0 ];
232   double range[ 2 ];
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 ];
238
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;
248   
249   // Real update
250   this->_GenerateData( inData[ 0 ], numInputs, outData[ 0 ], outExt, id );
251 }
252
253 // -------------------------------------------------------------------------
254 int cpExtensions::Visualization::ImageBlender::
255 FillInputPortInformation( int i, vtkInformation* info )
256 {
257   info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 );
258   return( this->Superclass::FillInputPortInformation( i, info ) );
259 }
260
261 // -------------------------------------------------------------------------
262 void cpExtensions::Visualization::ImageBlender::
263 _GenerateData(
264   vtkImageData** inDatas,
265   int numInputs,
266   vtkImageData* outData,
267   int outExt[6],
268   int id
269   )
270 {
271   vtkImageIterator< unsigned char > inItsFast[ 256 ];
272   unsigned char* inSIFast[ 256 ];
273   vtkImageProgressIterator< unsigned char > outIt( outData, outExt, this, id );
274
275   /*
276     double *weights =
277     static_cast<vtkDoubleArray *>(this->GetWeights())->GetPointer(0);
278     double totalWeight = this->CalculateTotalWeight();
279     int normalize = this->GetNormalizeByWeight();
280   */
281
282   vtkImageIterator< unsigned char > *inIts;
283   unsigned char** inSI;
284   if( numInputs < 256 )
285   {
286     inIts = inItsFast;
287     inSI = inSIFast;
288   }
289   else
290   {
291     inIts = new vtkImageIterator< unsigned char >[ numInputs ];
292     inSI = new unsigned char*[ numInputs ];
293
294   } // fi
295
296   // Loop through all input ImageData to initialize iterators
297   for( int i = 0; i < numInputs; ++i )
298     inIts[ i ].Initialize( inDatas[ i ], outExt );
299
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( ) )
304   {
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( );
310
311     // Pixel operation
312     while( outSI != outSIEnd )
313     {
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 );
318
319       // Prepare color values
320       double r = wl;
321       double g = wl;
322       double b = wl;
323       double a = double( 1 );
324
325       /*
326         double sum = 0.;
327         for(int k=0; k < numInputs; ++k)
328         {
329         sum += weights[k] * *inSI[k];
330         }
331       */
332
333       r *= double( 255 );
334       g *= double( 255 );
335       b *= double( 255 );
336       a *= double( 255 );
337
338       // Assign RGBA value
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++;
343
344       // Advance inputs
345       for( int l = 0; l < numInputs; ++l )
346         inSI[ l ]++;
347
348     } // elihw
349
350     // Advance all iterators
351     for( int j = 0; j < numInputs; ++j )
352       inIts[ j ].NextSpan( );
353     outIt.NextSpan( );
354
355   } // elihw
356
357   // Free auxiliary buffers
358   if( numInputs >= 256 )
359   {
360     delete [] inIts;
361     delete [] inSI;
362
363   } // fi
364 }
365
366 // eof - $RCSfile$