#include "clitkImageArithmGenericFilter.h"
//--------------------------------------------------------------------
-clitk::ImageArithmGenericFilter::ImageArithmGenericFilter():mTypeOfOperation(0) {
+clitk::ImageArithmGenericFilter::ImageArithmGenericFilter()
+ :ImageToImageGenericFilter<Self>("ImageArithmGenericFilter"),mTypeOfOperation(0) {
+ InitializeImageType<2>();
+ InitializeImageType<3>();
+ InitializeImageType<4>();
mIsOperationUseASecondImage = false;
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
-void clitk::ImageArithmGenericFilter::Update () {
-
- // Load image header
- itk::ImageIOBase::Pointer header = clitk::readImageHeader(mInputFilenames[0]);
-
- // Determine dim, pixel type, number of components
- mDim = header->GetNumberOfDimensions();
- mPixelTypeName = header->GetComponentTypeAsString(header->GetComponentType());
- mNbOfComponents = header->GetNumberOfComponents();
-
+template<unsigned int Dim>
+void clitk::ImageArithmGenericFilter::InitializeImageType() {
+ ADD_IMAGE_TYPE(Dim, char);
+ ADD_IMAGE_TYPE(Dim, short);
+ ADD_IMAGE_TYPE(Dim, float);
+ /* ADD_IMAGE_TYPE(Dim, short);
+ ADD_IMAGE_TYPE(Dim, ushort;
+ ADD_IMAGE_TYPE(Dim, int);
+ ADD_IMAGE_TYPE(Dim, unsigned int);
+ ADD_IMAGE_TYPE(Dim, double);
+ */
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+template<class ImageType>
+void clitk::ImageArithmGenericFilter::UpdateWithInputImageType() {
+
+ // Check Input
+
+ //DS TO BE CHANGED IN GetNumberOfInput() !!!!!!!!
+
if (mInputFilenames.size() == 0) {
std::cerr << "ERROR : please provide at least a input filename." << std::endl;
}
std::cerr << "ERROR : please provide only 1 or 2 input filenames." << std::endl;
}
- // Switch by dimension
- if (mDim == 2) { Update_WithDim<2>(); return; }
- if (mDim == 3) { Update_WithDim<3>(); return; }
- if (mDim == 4) { Update_WithDim<4>(); return; }
+ // Read input1
+ // typename ImageType::Pointer input1 = clitk::readImage<ImageType>(mInputFilenames[0], mIOVerbose);
+ typename ImageType::Pointer input1 = this->template GetInput<ImageType>(0);
+ typename ImageType::Pointer outputImage;
+
+ // Read input2 (float is ok altough it could take too memory ...)
+ if (mIsOperationUseASecondImage) {
+ typedef itk::Image<float,ImageType::ImageDimension> ImageType2;
+ // typename ImageType2::Pointer input2 = clitk::readImage<ImageType2>(mInputFilenames[1], mIOVerbose);
+ typename ImageType2::Pointer input2 = this->template GetInput<ImageType2>(1);
+ outputImage = ComputeImage<ImageType, ImageType2>(input1, input2);
+ }
+ else {
+ outputImage = ComputeImage<ImageType>(input1);
+ }
+
+ // Write results
+ this->SetNextOutput<ImageType>(outputImage);
+ //clitk::writeImage<ImageType>(outputImage, mOutputFilename, mIOVerbose);
+}
+//--------------------------------------------------------------------
+
+//--------------------------------------------------------------------
+template<class ImageType>
+typename ImageType::Pointer
+clitk::ImageArithmGenericFilter::ComputeImage(typename ImageType::Pointer inputImage) {
+
+ typedef typename ImageType::PixelType PixelType;
+ typedef itk::ImageRegionIterator<ImageType> IteratorType;
+ IteratorType it(inputImage, inputImage->GetLargestPossibleRegion());
+ it.GoToBegin();
+
+ switch (mTypeOfOperation) {
+ case 0: // Addition
+ while (!it.IsAtEnd()) {
+ it.Set(PixelTypeDownCast<double, PixelType>((double)it.Get() + mScalar) );
+ ++it;
+ }
+ break;
+ case 1: // Multiply
+ while (!it.IsAtEnd()) {
+ it.Set(PixelTypeDownCast<double, PixelType>((double)it.Get() * mScalar) );
+ ++it;
+ }
+ break;
+ case 2: // Inverse
+ while (!it.IsAtEnd()) {
+ if (it.Get() != 0)
+ it.Set(PixelTypeDownCast<double, PixelType>(mScalar / (double)it.Get()));
+ else it.Set(mDefaultPixelValue);
+ ++it;
+ }
+ break;
+ case 3: // Max
+ while (!it.IsAtEnd()) {
+ if (it.Get() < mScalar) it.Set(PixelTypeDownCast<double, PixelType>(mScalar));
+ ++it;
+ }
+ break;
+ case 4: // Min
+ while (!it.IsAtEnd()) {
+ if (it.Get() > mScalar) it.Set(PixelTypeDownCast<double, PixelType>(mScalar));
+ ++it;
+ }
+ break;
+ case 5: // Absolute value
+ while (!it.IsAtEnd()) {
+ if (it.Get() <= 0) it.Set(PixelTypeDownCast<double, PixelType>(-it.Get()));
+ // <= zero to avoid warning for unsigned types
+ ++it;
+ }
+ break;
+ case 6: // Squared value
+ while (!it.IsAtEnd()) {
+ it.Set(PixelTypeDownCast<double, PixelType>((double)it.Get()*(double)it.Get()));
+ ++it;
+ }
+ break;
+ case 7: // Log
+ while (!it.IsAtEnd()) {
+ if (it.Get() > 0)
+ it.Set(PixelTypeDownCast<double, PixelType>(log((double)it.Get())));
+ else it.Set(mDefaultPixelValue);
+ ++it;
+ }
+ break;
+ case 8: // exp
+ while (!it.IsAtEnd()) {
+ it.Set(PixelTypeDownCast<double, PixelType>(exp((double)it.Get())));
+ ++it;
+ }
+ break;
+ case 9: // sqrt
+ while (!it.IsAtEnd()) {
+ if (it.Get() > 0)
+ it.Set(PixelTypeDownCast<double, PixelType>(sqrt((double)it.Get())));
+ else {
+ if (it.Get() ==0) it.Set(0);
+ else it.Set(mDefaultPixelValue);
+ }
+ ++it;
+ }
+ break;
+ default: // error ?
+ std::cerr << "ERROR : the operation number (" << mTypeOfOperation << ") is not known." << std::endl;
+ exit(-1);
+ }
+
+ return inputImage;
+}
+//--------------------------------------------------------------------
+
+//--------------------------------------------------------------------
+template<class ImageType1, class ImageType2>
+typename ImageType1::Pointer
+clitk::ImageArithmGenericFilter::ComputeImage(typename ImageType1::Pointer inputImage1,
+ typename ImageType2::Pointer inputImage2) {
+
+ typedef typename ImageType1::PixelType PixelType;
+ typedef itk::ImageRegionIterator<ImageType1> IteratorType;
+ IteratorType it1(inputImage1, inputImage1->GetLargestPossibleRegion());
+ it1.GoToBegin();
+
+ typedef itk::ImageRegionConstIterator<ImageType2> ConstIteratorType;
+ ConstIteratorType it2(inputImage2, inputImage2->GetLargestPossibleRegion());
+ it2.GoToBegin();
+
+ switch (mTypeOfOperation) {
+ case 0: // Addition
+ while (!it1.IsAtEnd()) {
+ it1.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() + (double)it2.Get()) );
+ ++it1; ++it2;
+ }
+ break;
+ case 1: // Multiply
+ while (!it1.IsAtEnd()) {
+ it1.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() * (double)it2.Get()) );
+ ++it1; ++it2;
+ }
+ break;
+ case 2: // Divide
+ while (!it1.IsAtEnd()) {
+ if (it1.Get() != 0)
+ it1.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() / (double)it2.Get()));
+ else it1.Set(mDefaultPixelValue);
+ ++it1; ++it2;
+ }
+ break;
+ case 3: // Max
+ while (!it1.IsAtEnd()) {
+ if (it1.Get() < it2.Get()) it1.Set(PixelTypeDownCast<double, PixelType>(it2.Get()));
+ ++it1; ++it2;
+ }
+ break;
+ case 4: // Min
+ while (!it1.IsAtEnd()) {
+ if (it1.Get() > it2.Get()) it1.Set(PixelTypeDownCast<double, PixelType>(it2.Get()));
+ ++it1; ++it2;
+ }
+ break;
+ case 5: // Absolute difference
+ while (!it1.IsAtEnd()) {
+ it1.Set(PixelTypeDownCast<double, PixelType>(fabs(it2.Get()-it1.Get())));
+ ++it1; ++it2;
+ }
+ break;
+ case 6: // Squared differences
+ while (!it1.IsAtEnd()) {
+ it1.Set(PixelTypeDownCast<double, PixelType>(pow((double)it1.Get()-(double)it2.Get(),2)));
+ ++it1; ++it2;
+ }
+ break;
+ case 7: // Difference
+ while (!it1.IsAtEnd()) {
+ it1.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get()-(double)it2.Get()));
+ ++it1; ++it2;
+ }
+ break;
+ case 8: // Relative Difference
+ while (!it1.IsAtEnd()) {
+ if (it1.Get() != 0) it1.Set(PixelTypeDownCast<double, PixelType>(((double)it1.Get()-(double)it2.Get()))/(double)it1.Get());
+ else it1.Set(0.0);
+ ++it1; ++it2;
+ }
+ break;
+ default: // error ?
+ std::cerr << "ERROR : the operation number (" << mTypeOfOperation << ") is not known." << std::endl;
+ exit(-1);
+ }
- std::cerr << "Error, dimension of input image is " << mDim << ", but I only work with 2,3." << std::endl;
- exit(0);
+ return inputImage1;
}
//--------------------------------------------------------------------