1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 /**
19  * This file contains classes that can be used to drive an image-to-image
20  * type filter in or out of an itk pipeline for testing purposes.
21  */
22 
23 #ifndef itkNullImageToImageFilterDriver_hxx
24 #define itkNullImageToImageFilterDriver_hxx
25 
26 #include "itkPixelTraits.h"
27 #include "itkImage.h"
28 #include "itkImageToImageFilter.h"
29 #include "itkIndex.h"
30 #include <iostream>
31 #include <ctime>
32 
33 namespace itk {
34 
35 /**
36  * \class NullImageToImageFilterDriver
37  * \brief Drives an image-to-image type itk process object with null inputs and
38  *  null outputs.
39  *
40  * Provides a non-pipeline framework for testing image-to-image
41  * filters. Allocates an input image and sets up an output image, then calls
42  * Update on the filter.  Times the execution of the filter.
43  */
44 
45 template <typename TInputImage, typename TOutputImage>
46 class NullImageToImageFilterDriver
47 {
48 public:
NullImageToImageFilterDriver()49   NullImageToImageFilterDriver():
50     m_Filter( nullptr )
51     {};
52 
53   using ImageSizeType = typename TInputImage::SizeType;
54   using InputPixelType = typename TInputImage::PixelType;
55   enum {InputPixelDimension=PixelTraits<InputPixelType>::Dimension};
56 
57   /**
58    * Set the image-to-image filter to drive.
59    */
SetFilter(ImageToImageFilter<TInputImage,TOutputImage> * filter)60   void SetFilter(ImageToImageFilter<TInputImage, TOutputImage> * filter)
61   {    m_Filter = filter;   }
62 
63   /**
64    * Set the size of the input and output image.
65    */
SetImageSize(const ImageSizeType size)66   void SetImageSize(const ImageSizeType size)
67     { m_ImageSize = size; }
68 
69   /**
70    * Drive the filter without using the itk pipeline.
71    */
72   void Execute();
73 
74 protected:
75   struct DispatchBase {};
76   template<unsigned int VDimension>
77   struct Dispatch : public DispatchBase {};
78 
79   void InitializePixel(InputPixelType &pixel);
80   void InitializePixel(const DispatchBase&, InputPixelType &pixel);
81   void InitializePixel(const Dispatch<1>&, InputPixelType &pixel);
82 
83 private:
84   ImageToImageFilter<TInputImage, TOutputImage> *m_Filter;
85   ImageSizeType                                  m_ImageSize;
86 };
87 
88 
89 template <typename TInputImage, typename TOutputImage>
90 void
91 NullImageToImageFilterDriver<TInputImage, TOutputImage>
InitializePixel(InputPixelType & pixel)92 ::InitializePixel(InputPixelType &pixel)
93 {
94   this->InitializePixel(Dispatch<InputPixelDimension>(), pixel);
95 }
96 
97 template <typename TInputImage, typename TOutputImage>
98 void
99 NullImageToImageFilterDriver<TInputImage, TOutputImage>
InitializePixel(const DispatchBase &,InputPixelType & pixel)100 ::InitializePixel(const DispatchBase &, InputPixelType &pixel)
101 {
102   for (unsigned int i=0; i < InputPixelDimension; ++i)
103     {
104     pixel[i] = NumericTraits<typename PixelTraits<InputPixelType>::ValueType>::ZeroValue();
105     }
106 }
107 
108 template <typename TInputImage, typename TOutputImage>
109 void
110 NullImageToImageFilterDriver<TInputImage, TOutputImage>
InitializePixel(const Dispatch<1> &,InputPixelType & pixel)111 ::InitializePixel(const Dispatch<1> &, InputPixelType &pixel)
112 {
113   pixel = NumericTraits<InputPixelType>::ZeroValue();
114 }
115 
116 /**
117  *  Drive the filter without using the itk pipeline
118  */
119 template <typename TInputImage, typename TOutputImage>
120 void
121 NullImageToImageFilterDriver<TInputImage, TOutputImage>
Execute()122 ::Execute()
123 {
124   enum { ImageDimension = TInputImage::ImageDimension };
125 
126   // Set up input images
127   typename TInputImage::Pointer ip = TInputImage::New();
128   typename TOutputImage::IndexType index;
129   typename TOutputImage::RegionType region;
130 
131   for (unsigned int i = 0; i < ImageDimension; ++i) index[i] = 0;
132   region.SetSize( m_ImageSize );
133   region.SetIndex( index);
134 
135   // Allocate the input
136   ip->SetLargestPossibleRegion( region );
137   ip->SetBufferedRegion(region);
138   ip->SetRequestedRegion(region);
139   ip->Allocate();
140 
141   // Construct a pixel to fill the image
142   InputPixelType pixel;
143   this->InitializePixel(pixel);
144   ip->FillBuffer(pixel);
145 
146   // Setup the filter
147   m_Filter->SetInput(ip);
148 
149   // print out the output object so we can see it modified times and regions
150   //  std::cout << "Output object before filter execution" << std::endl
151   //            << m_Filter->GetOutput() << std::endl;
152 
153   using ImageFilterType = ImageToImageFilter<TInputImage, TOutputImage>;
154   typename ImageFilterType::Pointer sourceBefore =
155      dynamic_cast< ImageFilterType * >( m_Filter->GetOutput()->GetSource().GetPointer() );
156 
157   // Execute the filter
158   clock_t start = ::clock();
159   m_Filter->UpdateLargestPossibleRegion();
160   clock_t stop = ::clock();
161 
162   // print out the output object so we can see it modified times and regions
163   std::cout << "Output object after filter execution" << std::endl
164             << m_Filter->GetOutput() << std::endl;
165 
166   typename ImageFilterType::Pointer sourceAfter =
167     dynamic_cast< ImageFilterType * >( m_Filter->GetOutput()->GetSource().GetPointer() );
168 
169   std::cout << sourceBefore.GetPointer() << ", " << sourceAfter.GetPointer() << std::endl;
170   if (sourceBefore != sourceAfter.GetPointer())
171     {
172     std::cout << std::endl << "Pipeline corrupt, filter output source different after execution." << std::endl;
173     }
174   else
175     {
176     std::cout << std::endl << "Pipeline intact" << std::endl;
177     }
178 
179   std::cout << "Execution time was approximately " << (stop - start)
180             << " clock cycles." << std::endl;
181 }
182 
183 }  // end namespace itk
184 #endif
185