]> Creatis software - clitk.git/blob - filters/clitkImageArithmGenericFilter.cxx
preliminary fixes for multi-component images
[clitk.git] / filters / clitkImageArithmGenericFilter.cxx
1 /*=========================================================================
2
3   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
4   l'Image). All rights reserved. See Doc/License.txt or
5   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
6                                                                                 
7      This software is distributed WITHOUT ANY WARRANTY; without even
8      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9      PURPOSE.  See the above copyright notices for more information.
10                                                                              
11 =========================================================================*/
12
13 #ifndef CLITKIMAGEARITHMGENERICFILTER_CXX
14 #define CLITKIMAGEARITHMGENERICFILTER_CXX
15
16 /**
17  -------------------------------------------------------------------
18  * @file   clitkImageArithmGenericFilter.cxx
19  * @author David Sarrut <David.Sarrut@creatis.insa-lyon.fr>
20  * @date   23 Feb 2008
21
22  * @brief  
23  -------------------------------------------------------------------*/
24
25 #include "clitkImageArithmGenericFilter.h"
26
27 //--------------------------------------------------------------------
28 clitk::ImageArithmGenericFilter::ImageArithmGenericFilter()
29   :ImageToImageGenericFilter<Self>("ImageArithmGenericFilter"),mTypeOfOperation(0) {
30   InitializeImageType<2>();
31   InitializeImageType<3>();
32   InitializeImageType<4>();  
33   mIsOperationUseASecondImage = false;
34 }
35 //--------------------------------------------------------------------
36
37 //--------------------------------------------------------------------
38 template<unsigned int Dim>
39 void clitk::ImageArithmGenericFilter::InitializeImageType() {      
40   ADD_IMAGE_TYPE(Dim, char);
41   ADD_IMAGE_TYPE(Dim, short);
42   ADD_IMAGE_TYPE(Dim, float);
43   /*  ADD_IMAGE_TYPE(Dim, short);
44   ADD_IMAGE_TYPE(Dim, ushort;
45   ADD_IMAGE_TYPE(Dim, int);
46   ADD_IMAGE_TYPE(Dim, unsigned int);
47   ADD_IMAGE_TYPE(Dim, double);
48   */
49 }
50 //--------------------------------------------------------------------
51
52
53 //--------------------------------------------------------------------
54 template<class ImageType>
55 void clitk::ImageArithmGenericFilter::UpdateWithInputImageType() {
56
57   // Check Input
58
59   //DS TO BE CHANGED IN GetNumberOfInput() !!!!!!!!
60
61   if (mInputFilenames.size() == 0) {
62     std::cerr << "ERROR : please provide at least a input filename." << std::endl;
63   }
64   if (mInputFilenames.size() == 1) {
65     mIsOperationUseASecondImage = false;
66   }
67   if (mInputFilenames.size() == 2) {
68     mIsOperationUseASecondImage = true;
69   }
70   if (mInputFilenames.size() > 2) {
71     std::cerr << "ERROR : please provide only 1 or 2 input filenames." << std::endl;
72   }
73
74   // Read input1
75   //  typename ImageType::Pointer input1 = clitk::readImage<ImageType>(mInputFilenames[0], mIOVerbose);
76   typename ImageType::Pointer input1 = this->template GetInput<ImageType>(0);
77   typename ImageType::Pointer outputImage;  
78
79   // Read input2 (float is ok altough it could take too memory ...)
80   if (mIsOperationUseASecondImage) {
81     typedef itk::Image<float,ImageType::ImageDimension> ImageType2;
82     //    typename ImageType2::Pointer input2 = clitk::readImage<ImageType2>(mInputFilenames[1], mIOVerbose);
83     typename ImageType2::Pointer input2 = this->template GetInput<ImageType2>(1);
84     outputImage = ComputeImage<ImageType, ImageType2>(input1, input2);
85   }
86   else {
87     outputImage = ComputeImage<ImageType>(input1);
88   }
89
90   // Write results
91   this->SetNextOutput<ImageType>(outputImage);
92 }
93 //--------------------------------------------------------------------
94
95 //--------------------------------------------------------------------
96 template<class ImageType>
97 typename ImageType::Pointer 
98 clitk::ImageArithmGenericFilter::ComputeImage(typename ImageType::Pointer inputImage) {
99
100   typedef typename ImageType::PixelType PixelType;
101   typedef itk::ImageRegionIterator<ImageType> IteratorType;
102   IteratorType it(inputImage, inputImage->GetLargestPossibleRegion());
103   it.GoToBegin();
104   
105   switch (mTypeOfOperation) {
106   case 0: // Addition
107     while (!it.IsAtEnd()) {
108       it.Set(PixelTypeDownCast<double, PixelType>((double)it.Get() + mScalar) ); 
109       ++it;
110     }
111     break;
112   case 1: // Multiply
113     while (!it.IsAtEnd()) {
114       it.Set(PixelTypeDownCast<double, PixelType>((double)it.Get() * mScalar) ); 
115       ++it;
116     }
117     break;
118   case 2: // Inverse
119     while (!it.IsAtEnd()) {
120       if (it.Get() != 0)
121         it.Set(PixelTypeDownCast<double, PixelType>(mScalar / (double)it.Get())); 
122       else it.Set(mDefaultPixelValue);
123       ++it;
124     }
125     break;
126   case 3: // Max 
127     while (!it.IsAtEnd()) {
128       if (it.Get() < mScalar) it.Set(PixelTypeDownCast<double, PixelType>(mScalar)); 
129       ++it;
130     }
131     break;
132   case 4: // Min
133     while (!it.IsAtEnd()) {
134       if (it.Get() > mScalar) it.Set(PixelTypeDownCast<double, PixelType>(mScalar)); 
135       ++it;
136     }
137     break;
138   case 5: // Absolute value 
139     while (!it.IsAtEnd()) {
140       if (it.Get() <= 0) it.Set(PixelTypeDownCast<double, PixelType>(-it.Get())); 
141       // <= zero to avoid warning for unsigned types
142       ++it;
143     }
144     break;
145   case 6: // Squared value
146     while (!it.IsAtEnd()) {
147       it.Set(PixelTypeDownCast<double, PixelType>((double)it.Get()*(double)it.Get())); 
148       ++it;
149     }
150     break;
151   case 7: // Log
152     while (!it.IsAtEnd()) {
153       if (it.Get() > 0) 
154         it.Set(PixelTypeDownCast<double, PixelType>(log((double)it.Get()))); 
155       else it.Set(mDefaultPixelValue);
156       ++it;
157     }
158     break;
159   case 8: // exp
160     while (!it.IsAtEnd()) {
161       it.Set(PixelTypeDownCast<double, PixelType>(exp((double)it.Get()))); 
162       ++it;
163     }
164     break;
165   case 9: // sqrt
166     while (!it.IsAtEnd()) {
167       if (it.Get() > 0) 
168         it.Set(PixelTypeDownCast<double, PixelType>(sqrt((double)it.Get()))); 
169       else {
170         if (it.Get() ==0) it.Set(0);
171         else it.Set(mDefaultPixelValue);
172       }
173       ++it;
174     }
175     break;
176   default: // error ?
177     std::cerr << "ERROR : the operation number (" << mTypeOfOperation << ") is not known." << std::endl;
178     exit(-1);
179   }
180
181   return inputImage;
182 }
183 //--------------------------------------------------------------------
184
185 //--------------------------------------------------------------------
186 template<class ImageType1, class ImageType2>
187 typename ImageType1::Pointer
188 clitk::ImageArithmGenericFilter::ComputeImage(typename ImageType1::Pointer inputImage1, 
189                                        typename ImageType2::Pointer inputImage2) {
190
191   typedef typename ImageType1::PixelType PixelType;
192   typedef itk::ImageRegionIterator<ImageType1> IteratorType;
193   IteratorType it1(inputImage1, inputImage1->GetLargestPossibleRegion());
194   it1.GoToBegin();
195   
196   typedef itk::ImageRegionConstIterator<ImageType2> ConstIteratorType;
197   ConstIteratorType it2(inputImage2, inputImage2->GetLargestPossibleRegion());
198   it2.GoToBegin();
199   
200   switch (mTypeOfOperation) {
201   case 0: // Addition
202     while (!it1.IsAtEnd()) {
203       it1.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() + (double)it2.Get()) ); 
204       ++it1; ++it2;
205     }
206     break;
207   case 1: // Multiply
208     while (!it1.IsAtEnd()) {
209       it1.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() * (double)it2.Get()) ); 
210       ++it1; ++it2;
211     }
212     break;
213   case 2: // Divide
214     while (!it1.IsAtEnd()) {
215       if (it1.Get() != 0)
216         it1.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() / (double)it2.Get())); 
217       else it1.Set(mDefaultPixelValue);
218       ++it1; ++it2;
219     }
220     break;
221   case 3: // Max 
222     while (!it1.IsAtEnd()) {
223       if (it1.Get() < it2.Get()) it1.Set(PixelTypeDownCast<double, PixelType>(it2.Get())); 
224       ++it1; ++it2;
225     }
226     break;
227   case 4: // Min
228     while (!it1.IsAtEnd()) {
229       if (it1.Get() > it2.Get()) it1.Set(PixelTypeDownCast<double, PixelType>(it2.Get())); 
230       ++it1; ++it2;
231     }
232     break;
233   case 5: // Absolute difference
234     while (!it1.IsAtEnd()) {
235       it1.Set(PixelTypeDownCast<double, PixelType>(fabs(it2.Get()-it1.Get()))); 
236       ++it1; ++it2;
237     }
238     break;
239   case 6: // Squared differences
240     while (!it1.IsAtEnd()) {
241       it1.Set(PixelTypeDownCast<double, PixelType>(pow((double)it1.Get()-(double)it2.Get(),2))); 
242       ++it1; ++it2;
243     }
244     break;
245   case 7: // Difference
246     while (!it1.IsAtEnd()) {
247       it1.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get()-(double)it2.Get())); 
248       ++it1; ++it2;
249     }
250     break;
251   case 8: // Relative Difference
252     while (!it1.IsAtEnd()) {
253       if (it1.Get() != 0) it1.Set(PixelTypeDownCast<double, PixelType>(((double)it1.Get()-(double)it2.Get()))/(double)it1.Get()); 
254       else it1.Set(0.0);
255       ++it1; ++it2;
256     }
257     break;
258   default: // error ?
259     std::cerr << "ERROR : the operation number (" << mTypeOfOperation << ") is not known." << std::endl;
260     exit(-1);
261   }
262
263   return inputImage1;
264 }
265 //--------------------------------------------------------------------
266
267 #endif //define CLITKIMAGEARITHMGENERICFILTER_CXX