OTB  6.7.0
Orfeo Toolbox
otbConvertTypeFunctor.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbConvertTypeFunctor_h
22 #define otbConvertTypeFunctor_h
23 
24 #include <limits>
25 #include <type_traits>
26 #include <boost/type_traits/is_complex.hpp>
27 #include <boost/type_traits/is_scalar.hpp>
28 
29 #include "itkNumericTraits.h"
31 
32 namespace otb
33 {
34 namespace Functor
35 {
36 
37 template < class TInputPixelType , class TOutputPixelType >
39 {
40 public:
41  typedef TInputPixelType InputPixelType;
42  typedef TOutputPixelType OutputPixelType;
44 
47 
50 
51  static constexpr bool m_cInPix = boost::is_complex < InputPixelType > :: value ;
52  static constexpr bool m_cOutPix = boost::is_complex < OutputPixelType > :: value ;
53  static constexpr bool m_cInInternalPix = boost::is_complex < InputInternalPixelType > :: value ;
54  static constexpr bool m_cOutInternalPix = boost::is_complex < OutputInternalPixelType > :: value ;
55 
57  // m_cInPix ( boost::is_complex < InputPixelType > :: value ) ,
58  // m_cOutPix ( boost::is_complex < OutputPixelType > :: value ) ,
59  // m_cInInternalPix ( boost::is_complex < InputInternalPixelType > :: value ) ,
60  // m_cOutInternalPix ( boost::is_complex < OutputInternalPixelType > :: value )
61  {
62  m_LowestB = std::numeric_limits < OutputPixelValueType >::lowest();
63  m_HighestB = std::numeric_limits < OutputPixelValueType >::max();
64 
65  m_LowestBD = static_cast < double > ( m_LowestB );
66  m_HighestBD = static_cast < double > ( m_HighestB );
67 
68  // m_cInPix = boost::is_complex < InputPixelType > :: value ;
69  // m_cOutPix = boost::is_complex < OutputPixelType > :: value ;
70  // m_cInInternalPix = boost::is_complex < InputInternalPixelType > :: value ;
71  // m_cOutInternalPix = boost::is_complex < OutputInternalPixelType > :: value ;
72  }
73 
74  // template < class InternalPixelType >
75  void SetInputComponents( unsigned int sizeIn )
76  {
77  m_CompIn = sizeIn ;
78  if ( m_cInPix )
79  {
80  // needed as ITK thinks that one complex component is actually
81  // two components...
82  m_CompIn /= 2 ;
83  }
84  }
85 
86  unsigned int GetOutputSize()
87  {
88  if ( m_cInInternalPix || m_cInPix )
89  m_Scal = 2 * m_CompIn;
90  else
91  m_Scal = m_CompIn;
92 
93  OutputPixelType out;
94  unsigned int size =
95  itk::NumericTraits < OutputPixelType > :: GetLength( out );
96  if ( size == 0 ) // That means it is a variable size container
97  {
98  if ( m_cOutInternalPix )
99  m_CompOut = ( m_Scal + 1 ) / 2 ;
100  else
101  m_CompOut = m_Scal ;
102  }
103  // It is a fixed size container, m_CompOut should be equal to its size
104  else if ( m_cOutPix ) // one complex is one component
105  m_CompOut = 1 ;
106  else // fized size container or scalar
107  m_CompOut = size;
108 
109 
110  return m_CompOut ;
111  }
112 
114  {
115  m_LowestB = lowest;
116  m_LowestBD = static_cast < double > ( m_LowestB );
117  }
118 
120  {
121  m_HighestB = highest;
122  m_HighestBD = static_cast < double > ( m_HighestB );
123  }
124 
126  {
127  std::vector < double > vPixel;
128  for ( unsigned int i = 0 ; i < m_CompIn ; i ++)
129  FillIn < InputPixelType > ( i , in , vPixel );
130  assert( m_Scal == vPixel.size() );
131  if ( ( m_cOutPix || m_cOutInternalPix ) && vPixel.size()%2 )
132  {
133  vPixel.push_back(0); // last component has no imaginary part
134  }
135  Clamp( vPixel );
136  OutputPixelType out;
137 
138  int hack = 1;
139  if ( m_cOutPix )
140  hack += 1; // needed in case we have OutputPixelType == complex<t> as
141  // itk::NumericTraits::SetLength() will ask a length of 2!
142  itk::NumericTraits < OutputPixelType > :: SetLength( out ,
143  hack * m_CompOut );
144 
145  for ( unsigned int i = 0 ; i < m_CompOut ; i ++)
146  FillOut < OutputPixelType > ( i , out , vPixel );
147  return out;
148  }
149 
151 
152 protected:
153 
154  template <class PixelType ,
155  std::enable_if_t < std::is_arithmetic < PixelType > ::value , int > = 0 >
156  void FillIn( unsigned int i ,
157  InputPixelType const & pix ,
158  std::vector < double > & vPix ) const
159  {
161  GetNthComponent( i , pix ) );
162  }
163 
164  template <class PixelType ,
165  std::enable_if_t < boost::is_complex < PixelType > :: value , int > = 0 >
166  void FillIn( unsigned int i ,
167  InputPixelType const & pix ,
168  std::vector < double > & vPix ) const
169  {
171  GetNthComponent( i , pix );
172  vPix.push_back( static_cast < double > ( real( comp ) ) );
173  vPix.push_back( static_cast < double > ( imag( comp ) ) );
174  }
175 
176  template <class PixelType ,
177  std::enable_if_t < !( boost::is_complex < PixelType > :: value
178  || std::is_arithmetic < PixelType > ::value ) , int > = 0 >
179  void FillIn( unsigned int i ,
180  InputPixelType const & pix ,
181  std::vector < double > & vPix ) const
182  {
183  FillIn < InputInternalPixelType > ( i , pix , vPix );
184  }
185 
186  void Clamp( std::vector < double > & vPixel ) const
187  {
188  for ( double & comp : vPixel )
189  {
190  if ( comp >= m_HighestBD )
191  comp = m_HighestBD;
192  else if ( comp <= m_LowestBD )
193  comp = m_LowestBD;
194  }
195  }
196 
197  template <class PixelType ,
198  std::enable_if_t < std::is_arithmetic < PixelType > ::value , int > = 0 >
199  void FillOut( unsigned int i ,
200  OutputPixelType & pix ,
201  std::vector < double > & vPix ) const
202  {
204  SetNthComponent( i , pix , vPix[i] );
205  }
206 
207  template <class PixelType ,
208  std::enable_if_t < boost::is_complex < PixelType > :: value , int > = 0 >
209  void FillOut( unsigned int i ,
210  OutputPixelType & pix ,
211  std::vector < double > & vPix ) const
212  {
214  SetNthComponent( i , pix ,
215  PixelType ( vPix[ 2 * i] , vPix[ 2 * i + 1] ) );
216  }
217 
218  template <class PixelType ,
219  std::enable_if_t < !( boost::is_complex < PixelType > :: value
220  || std::is_arithmetic < PixelType > ::value ) , int > = 0 >
221  void FillOut( unsigned int i ,
222  OutputPixelType & pix ,
223  std::vector < double > & vPix ) const
224  {
225  FillOut < OutputInternalPixelType > ( i , pix , vPix );
226  }
227 
228 private:
229  ConvertTypeFunctor(const Self &) = delete;
230  void operator =(const Self&) = delete;
231 
234  unsigned int m_CompIn , m_CompOut , m_Scal ;
235  // const bool m_cInPix , m_cOutPix , m_cInInternalPix , m_cOutInternalPix ;
236 
237 };
238 
239 } //end namespace Functor
240 
241 } //end namespace otb
242 
243 #endif
itk::NumericTraits< InputPixelType >::ValueType InputInternalPixelType
void Clamp(std::vector< double > &vPixel) const
OutputPixelType operator()(InputPixelType const &in) const
void SetLowest(OutputPixelValueType &lowest)
void SetInputComponents(unsigned int sizeIn)
void operator=(const Self &)=delete
void FillIn(unsigned int i, InputPixelType const &pix, std::vector< double > &vPix) const
itk::NumericTraits< InputInternalPixelType >::ValueType InputPixelValueType
itk::NumericTraits< OutputInternalPixelType >::ValueType OutputPixelValueType
itk::NumericTraits< OutputPixelType >::ValueType OutputInternalPixelType
void FillOut(unsigned int i, OutputPixelType &pix, std::vector< double > &vPix) const
void SetHighest(OutputPixelValueType &highest)