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 #ifndef itkImageAlgorithm_h
19 #define itkImageAlgorithm_h
20 
21 #include "itkImageRegionIterator.h"
22 
23 #include <type_traits>
24 
25 namespace itk
26 {
27 
28 template <typename TPixelType, unsigned int VImageDimension > class VectorImage;
29 
30 
31 /** \class ImageAlgorithm
32  *  \brief A container of static functions which can operate on Images
33  *  with Iterators.
34  *
35  *  These methods are modeled after the STL algorithms. They may use
36  *  special optimization techniques to implement enhanced versions of
37  *  the methods.
38  *
39  *  \ingroup ITKCommon
40  */
41 struct ImageAlgorithm
42 {
43 
44     using TrueType = std::true_type;
45     using FalseType = std::false_type;
46 
47 /**
48  * \brief This generic function copies a region from one image to
49  * another. It may perform optimizations on the copy for efficiency.
50  *
51  * This method performs the equivalent to the following:
52    \code
53        itk::ImageRegionConstIterator<TInputImage> it( inImage, inRegion );
54        itk::ImageRegionIterator<TOutputImage> ot( outImage, outRegion );
55 
56        while( !it.IsAtEnd() )
57          {
58          ot.Set( static_cast< typename TInputImage::PixelType >( it.Get() ) );
59          ++ot;
60          ++it;
61          }
62    \endcode
63  *
64  * \note: It is important not to explicitly pass the template
65  * arguments to this method as it may not result in an optimized
66  * method being called.
67  */
68   template<typename InputImageType, typename OutputImageType>
CopyImageAlgorithm69   static void Copy( const InputImageType *inImage, OutputImageType *outImage,
70                     const typename InputImageType::RegionType &inRegion,
71                     const typename OutputImageType::RegionType &outRegion )
72   {
73     ImageAlgorithm::DispatchedCopy( inImage, outImage, inRegion, outRegion );
74   }
75 
76 /// \cond HIDE_SPECIALIZATION_DOCUMENTATION
77   template<typename TPixel1, typename TPixel2, unsigned int VImageDimension>
CopyImageAlgorithm78   static void Copy( const Image<TPixel1, VImageDimension> * inImage,
79                                Image<TPixel2, VImageDimension> * outImage,
80                                const typename Image<TPixel1, VImageDimension>::RegionType &inRegion,
81                                const typename Image<TPixel2, VImageDimension>::RegionType &outRegion )
82   {
83     using _ImageType1 = Image<TPixel1, VImageDimension>;
84     using _ImageType2 = Image<TPixel2, VImageDimension>;
85     ImageAlgorithm::DispatchedCopy( inImage, outImage, inRegion, outRegion,
86                                     std::is_convertible<typename _ImageType1::PixelType,
87                                     typename _ImageType2::PixelType>()
88                                    );
89   }
90 
91   template<typename TPixel1, typename TPixel2, unsigned int VImageDimension>
CopyImageAlgorithm92   static void Copy( const VectorImage<TPixel1, VImageDimension> * inImage,
93                                VectorImage<TPixel2, VImageDimension> * outImage,
94                                const typename VectorImage<TPixel1, VImageDimension>::RegionType &inRegion,
95                                const typename VectorImage<TPixel2, VImageDimension>::RegionType &outRegion )
96   {
97     using _ImageType1 = VectorImage<TPixel1, VImageDimension>;
98     using _ImageType2 = VectorImage<TPixel2, VImageDimension>;
99     ImageAlgorithm::DispatchedCopy( inImage, outImage, inRegion, outRegion,
100                                     std::is_convertible<typename _ImageType1::PixelType,
101                                     typename _ImageType2::PixelType>()
102                                    );
103   }
104 
105 /// \endcond
106 
107   /**
108    * \brief Sets the output region to the smallest
109    * region of the output image that fully contains
110    * the physical space covered by the input
111    * region of the input image
112    */
113   template<typename InputImageType, typename OutputImageType>
114   static typename OutputImageType::RegionType
115   EnlargeRegionOverBox(const typename InputImageType::RegionType & inputRegion,
116                        const InputImageType* inputImage,
117                        const OutputImageType* outputImage);
118 
119   template<typename InputImageType, typename OutputImageType, typename TransformType>
120   static typename OutputImageType::RegionType
121   EnlargeRegionOverBox(const typename InputImageType::RegionType & inputRegion,
122                        const InputImageType* inputImage,
123                        const OutputImageType* outputImage,
124                        const TransformType* transform);
125 
126 private:
127 
128   /** This is an optimized method which requires the input and
129    * output images to be the same, and the pixel being POD (Plain Old
130    * Data).
131    */
132   template<typename InputImageType, typename OutputImageType>
133   static void DispatchedCopy( const InputImageType *inImage, OutputImageType *outImage,
134                               const typename InputImageType::RegionType &inRegion,
135                               const typename OutputImageType::RegionType &outRegion, TrueType isSpecialized );
136 
137   /** this is the reference image iterator implementation */
138   template<typename InputImageType, typename OutputImageType>
139   static void DispatchedCopy( const InputImageType *inImage, OutputImageType *outImage,
140                               const typename InputImageType::RegionType &inRegion,
141                               const typename OutputImageType::RegionType &outRegion, FalseType isSpecialized = FalseType() );
142 
143 
144   /** A utility class to get the number of internal pixels to make up
145    * a pixel.
146    */
147   template <typename TImageType>
148   struct PixelSize
149   {
GetImageAlgorithm::PixelSize150     static size_t Get( const TImageType *)
151       {
152       return 1;
153       }
154   };
155 
156 /// \cond HIDE_SPECIALIZATION_DOCUMENTATION
157   template <typename TPixelType, unsigned int VImageDimension>
158   struct PixelSize< VectorImage<TPixelType, VImageDimension> >
159   {
160     using ImageType = VectorImage<TPixelType, VImageDimension>;
161     static size_t Get( const  ImageType * i )
162       {
163       const size_t vectorLength = ImageType::AccessorFunctorType::GetVectorLength(i);
164       return vectorLength;
165       }
166   };
167 /// \endcond
168 
169   /** Unary functor just for static_cast operator */
170   template<typename TInputType, typename TOutputType>
171   struct StaticCast
172     {
173     TOutputType operator() (const TInputType i) { return static_cast<TOutputType>(i); }
174     };
175 
176 
177   /** Function to dispatch to std::copy or std::transform. */
178   template<typename TType>
179   static TType* CopyHelper(const TType *first, const TType *last, TType *result)
180     {
181     // Note: On some MS compilers the following may generate a
182     // warning. Please include itkMacro.h before <algorithm> or
183     // another stl header to avoid.
184     return std::copy(first, last, result);
185     }
186 
187 /// \cond HIDE_SPECIALIZATION_DOCUMENTATION
188   template<typename TInputType, typename TOutputType>
189   static TOutputType* CopyHelper(const TInputType *first, const TInputType *last, TOutputType *result)
190     {
191     return std::transform(first, last, result, StaticCast<TInputType,TOutputType>());
192     }
193 /// \endcond
194 
195 
196 };
197 } // end namespace itk
198 
199 
200 #ifndef ITK_MANUAL_INSTANTIATION
201 #include "itkImageAlgorithm.hxx"
202 #endif
203 
204 
205 #endif //itkImageAlgorithm_h
206