]> Creatis software - clitk.git/blob - filters/clitkImageArithmGenericFilter.txx
added the new headers
[clitk.git] / filters / clitkImageArithmGenericFilter.txx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to: 
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
18 #ifndef CLITKIMAGEARITHMGENERICFILTER_TXX
19 #define CLITKIMAGEARITHMGENERICFILTER_TXX
20 namespace clitk
21 {
22   
23   //--------------------------------------------------------------------
24   template<class args_info_type>
25   ImageArithmGenericFilter<args_info_type>::ImageArithmGenericFilter()
26     :ImageToImageGenericFilter<Self>("ImageArithmGenericFilter"),mTypeOfOperation(0) {
27     InitializeImageType<2>();
28     InitializeImageType<3>();
29     InitializeImageType<4>();  
30     mIsOperationUseASecondImage = false;
31     mOverwriteInputImage = true;
32   }
33   //--------------------------------------------------------------------
34
35
36   //--------------------------------------------------------------------
37   template<class args_info_type>
38   template<unsigned int Dim>
39   void ImageArithmGenericFilter<args_info_type>::InitializeImageType() {      
40     ADD_IMAGE_TYPE(Dim, char);
41     ADD_IMAGE_TYPE(Dim, uchar);
42     ADD_IMAGE_TYPE(Dim, short);
43     ADD_IMAGE_TYPE(Dim, float);
44   }
45   //--------------------------------------------------------------------
46
47
48   //--------------------------------------------------------------------
49   template<class args_info_type>
50   void ImageArithmGenericFilter<args_info_type>::EnableOverwriteInputImage(bool b) {      
51     mOverwriteInputImage = b;
52   }
53   //--------------------------------------------------------------------
54
55
56   //--------------------------------------------------------------------
57   template<class args_info_type>
58   void ImageArithmGenericFilter<args_info_type>::SetArgsInfo(const args_info_type & a) {
59     mArgsInfo=a;
60
61     // Set value
62     SetIOVerbose(mArgsInfo.verbose_flag);
63     mTypeOfOperation = mArgsInfo.operation_arg;
64     mDefaultPixelValue = mArgsInfo.pixelValue_arg;
65     mScalar = mArgsInfo.scalar_arg;
66     mOutputIsFloat = mArgsInfo.setFloatOutput_flag;
67
68     if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
69
70     if (mArgsInfo.input1_given) AddInputFilename(mArgsInfo.input1_arg);
71     if (mArgsInfo.input2_given) {
72       mIsOperationUseASecondImage = true;
73       AddInputFilename(mArgsInfo.input2_arg);
74     }
75     
76     if (mArgsInfo.output_given) SetOutputFilename(mArgsInfo.output_arg);
77
78     // Check type of operation (with scalar or with other image)
79     if ((mArgsInfo.input2_given) && (mArgsInfo.scalar_given)) {
80       std::cerr << "ERROR : you cannot provide both --scalar and --input2 option" << std::endl;
81       exit(-1);
82     }
83     if ((!mArgsInfo.input2_given) && (!mArgsInfo.scalar_given)) {
84       if (mArgsInfo.operation_arg < 5) {
85         std::cerr << "Such operation need the --scalar option." << std::endl;
86         exit(-1);
87       }
88     }
89   }
90   //--------------------------------------------------------------------
91
92
93   //--------------------------------------------------------------------
94   template<class args_info_type>
95   template<class ImageType>
96   void ImageArithmGenericFilter<args_info_type>::UpdateWithInputImageType() {
97     // Read input1
98     typename ImageType::Pointer input1 = this->template GetInput<ImageType>(0);
99     typename ImageType::PixelType PixelType;
100
101     // Set input image iterator
102     typedef itk::ImageRegionIterator<ImageType> IteratorType;
103     IteratorType it(input1, input1->GetLargestPossibleRegion());
104
105     // typedef input2
106     typename ImageType::Pointer input2 = this->template GetInput<ImageType>(1);
107     IteratorType it2;
108
109     if (mIsOperationUseASecondImage) {
110       // Read input2
111       input2 = this->template GetInput<ImageType>(1);
112       // Set input image iterator
113       it2 = IteratorType(input2, input2->GetLargestPossibleRegion());  
114     }
115
116     // Check if overwrite and outputisfloat and pixeltype is not float -> do not overwrite
117     if (mOverwriteInputImage && mOutputIsFloat && (typeid(PixelType) != typeid(float))) {
118       // std::cerr << "Warning. Could not use both mOverwriteInputImage and mOutputIsFloat, because input is " 
119       //                     << typeid(PixelType).name()
120       //                     << std::endl;
121       mOverwriteInputImage = false;
122     }
123
124     // ---------------- Overwrite input Image ---------------------
125     if (mOverwriteInputImage) {
126       // Set output iterator (to input1)
127       IteratorType ito = IteratorType(input1, input1->GetLargestPossibleRegion());
128       if (mIsOperationUseASecondImage) ComputeImage(it, it2, ito);
129       else ComputeImage(it, ito);
130       this->template SetNextOutput<ImageType>(input1);
131     }
132     
133     // ---------------- Create new output Image ---------------------
134     else {
135       if (mOutputIsFloat) {
136         // Create output image
137         typedef itk::Image<float,ImageType::ImageDimension> OutputImageType;
138         typename OutputImageType::Pointer output = OutputImageType::New();
139         output->SetRegions(input1->GetLargestPossibleRegion());
140         output->SetOrigin(input1->GetOrigin());
141         output->SetSpacing(input1->GetSpacing());
142         output->Allocate();
143         // Set output iterator
144         typedef itk::ImageRegionIterator<OutputImageType> IteratorOutputType;
145         IteratorOutputType ito = IteratorOutputType(output, output->GetLargestPossibleRegion());
146         if (mIsOperationUseASecondImage) ComputeImage(it, it2, ito);
147         else ComputeImage(it, ito);
148         this->template SetNextOutput<OutputImageType>(output);
149       }
150       else {
151         // Create output image
152         typedef ImageType OutputImageType;
153         typename OutputImageType::Pointer output = OutputImageType::New();
154         output->SetRegions(input1->GetLargestPossibleRegion());
155         output->SetOrigin(input1->GetOrigin());
156         output->SetSpacing(input1->GetSpacing());
157         output->Allocate();
158         // Set output iterator
159         typedef itk::ImageRegionIterator<OutputImageType> IteratorOutputType;
160         IteratorOutputType ito = IteratorOutputType(output, output->GetLargestPossibleRegion());
161         if (mIsOperationUseASecondImage) ComputeImage(it, it2, ito);
162         else ComputeImage(it, ito);
163         this->template SetNextOutput<OutputImageType>(output);
164       }
165     }
166   }
167   //--------------------------------------------------------------------
168
169   //--------------------------------------------------------------------
170   template<class args_info_type>
171   template<class Iter1, class Iter2, class Iter3>
172   void  ImageArithmGenericFilter<args_info_type>::ComputeImage(Iter1 it1, Iter2 it2, Iter3 ito) {
173     it1.GoToBegin();  
174     it2.GoToBegin();  
175     ito.GoToBegin();
176     typedef typename Iter3::PixelType PixelType;
177     
178     switch (mTypeOfOperation) {
179     case 0: // Addition
180       while (!ito.IsAtEnd()) {
181         ito.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() + (double)it2.Get()) ); 
182         ++it1; ++it2; ++ito;
183       }
184       break;
185     case 1: // Multiply
186       while (!ito.IsAtEnd()) {
187         ito.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() * (double)it2.Get()) ); 
188         ++it1; ++it2; ++ito;
189       }
190       break;
191     case 2: // Divide
192       while (!ito.IsAtEnd()) {
193         if (it1.Get() != 0)
194           ito.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() / (double)it2.Get())); 
195         else ito.Set(mDefaultPixelValue);
196         ++it1; ++it2; ++ito;
197       }
198       break;
199     case 3: // Max 
200       while (!ito.IsAtEnd()) {
201         if (it1.Get() < it2.Get()) ito.Set(PixelTypeDownCast<double, PixelType>(it2.Get())); 
202         ++it1; ++it2; ++ito;
203       }
204       break;
205     case 4: // Min
206       while (!ito.IsAtEnd()) {
207         if (it1.Get() > it2.Get()) ito.Set(PixelTypeDownCast<double, PixelType>(it2.Get())); 
208         ++it1; ++it2; ++ito;
209       }
210       break;
211     case 5: // Absolute difference
212       while (!ito.IsAtEnd()) {
213         ito.Set(PixelTypeDownCast<double, PixelType>(fabs(it2.Get()-it1.Get()))); 
214         ++it1; ++it2; ++ito;
215       }
216       break;
217     case 6: // Squared differences
218       while (!ito.IsAtEnd()) {
219         ito.Set(PixelTypeDownCast<double, PixelType>(pow((double)it1.Get()-(double)it2.Get(),2))); 
220         ++it1; ++it2; ++ito;
221       }
222       break;
223     case 7: // Difference
224       while (!ito.IsAtEnd()) {
225         ito.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get()-(double)it2.Get())); 
226         ++it1; ++it2; ++ito;
227       }
228       break;
229     case 8: // Relative Difference
230       while (!ito.IsAtEnd()) {
231         if (it1.Get() != 0) ito.Set(PixelTypeDownCast<double, PixelType>(((double)it1.Get()-(double)it2.Get()))/(double)it1.Get()); 
232         else ito.Set(0.0);
233         ++it1; ++it2; ++ito;
234       }
235       break;
236     default: // error ?
237       std::cerr << "ERROR : the operation number (" << mTypeOfOperation << ") is not known." << std::endl;
238       exit(-1);
239     }
240   }
241   //--------------------------------------------------------------------
242
243
244   //--------------------------------------------------------------------
245   template<class args_info_type>
246   template<class Iter1, class Iter2>
247   void clitk::ImageArithmGenericFilter<args_info_type>::ComputeImage(Iter1 it, Iter2 ito) {
248     ito.GoToBegin();
249     it.GoToBegin();  
250     typedef typename Iter2::PixelType PixelType;
251
252     // Perform operation
253     switch (mTypeOfOperation) {
254     case 0: // Addition
255       while (!it.IsAtEnd()) {
256         ito.Set(clitk::PixelTypeDownCast<double, PixelType>((double)it.Get() + mScalar) ); 
257         ++it; ++ito;
258       }
259       break;
260     case 1: // Multiply
261       while (!it.IsAtEnd()) {
262         ito.Set(PixelTypeDownCast<double, PixelType>((double)it.Get() * mScalar) ); 
263         ++it; ++ito;
264       }
265       break;
266     case 2: // Inverse
267       while (!it.IsAtEnd()) {
268         if (it.Get() != 0)
269           ito.Set(PixelTypeDownCast<double, PixelType>(mScalar / (double)it.Get())); 
270         else ito.Set(mDefaultPixelValue);
271         ++it; ++ito;
272       }
273       break;
274     case 3: // Max 
275       while (!it.IsAtEnd()) {
276         if (it.Get() < mScalar) ito.Set(PixelTypeDownCast<double, PixelType>(mScalar)); 
277         else ito.Set(PixelTypeDownCast<double, PixelType>(it.Get()));
278         ++it; ++ito;
279       }
280       break;
281     case 4: // Min
282       while (!it.IsAtEnd()) {
283         if (it.Get() > mScalar) ito.Set(PixelTypeDownCast<double, PixelType>(mScalar)); 
284         else ito.Set(PixelTypeDownCast<double, PixelType>(it.Get()));
285         ++it; ++ito;
286       }
287       break;
288     case 5: // Absolute value 
289       while (!it.IsAtEnd()) {
290         if (it.Get() <= 0) ito.Set(PixelTypeDownCast<double, PixelType>(-it.Get())); 
291         // <= zero to avoid warning for unsigned types
292         else ito.Set(PixelTypeDownCast<double, PixelType>(it.Get()));
293         ++it; ++ito;
294       }
295       break;
296     case 6: // Squared value
297       while (!it.IsAtEnd()) {
298         ito.Set(PixelTypeDownCast<double, PixelType>((double)it.Get()*(double)it.Get())); 
299         ++it; ++ito;
300       }
301       break;
302     case 7: // Log
303       while (!it.IsAtEnd()) {
304         if (it.Get() > 0) 
305           ito.Set(PixelTypeDownCast<double, PixelType>(log((double)it.Get()))); 
306         else ito.Set(mDefaultPixelValue);
307         ++it; ++ito;
308       }
309       break;
310     case 8: // exp
311       while (!it.IsAtEnd()) {
312         ito.Set(PixelTypeDownCast<double, PixelType>(exp((double)it.Get()))); 
313         ++it; ++ito;
314       }
315       break;
316     case 9: // sqrt
317       while (!it.IsAtEnd()) {
318         if (it.Get() > 0) 
319           ito.Set(PixelTypeDownCast<double, PixelType>(sqrt((double)it.Get()))); 
320         else {
321           if (it.Get() ==0) ito.Set(0);
322           else ito.Set(mDefaultPixelValue);
323         }
324         ++it; ++ito;
325       }
326       break;
327     default: // error ?
328       std::cerr << "ERROR : the operation number (" << mTypeOfOperation << ") is not known." << std::endl;
329       exit(-1);
330     }
331   }
332   //--------------------------------------------------------------------
333
334 } // end namespace
335
336 #endif  //#define CLITKIMAGEARITHMGENERICFILTER_TXX