1 //
2 // Copyright 2008 Christian Henning, Lubomir Bourdev
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 #ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_IS_ALLOWED_HPP
9 #define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_IS_ALLOWED_HPP
10
11 #include <boost/gil/extension/io/tiff/tags.hpp>
12 #include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
13 #include <boost/gil/detail/mp11.hpp>
14 #include <boost/gil/io/base.hpp>
15
16 #include <type_traits>
17
18 namespace boost { namespace gil { namespace detail {
19
20 using channel_sizes_t = std::vector<tiff_bits_per_sample::type>;
21
22 template <typename View, typename Channel, typename Enable = void>
23 struct Format_Type {};
24
25 // is_bit_aligned< View >
26 template <typename View, typename Channel>
27 struct Format_Type
28 <
29 View,
30 Channel,
31 typename std::enable_if
32 <
33 is_bit_aligned
34 <
35 typename get_pixel_type<View>::type
36 >::value
37 >::type
38 >
39 {
40 static const int value = SAMPLEFORMAT_UINT;
41 };
42
43 // is_not_bit_aligned< View > && is_unsigned< Channel >
44 template <typename View, typename Channel>
45 struct Format_Type
46 <
47 View,
48 Channel,
49 typename std::enable_if
50 <
51 mp11::mp_and
52 <
53 mp11::mp_not
54 <
55 typename is_bit_aligned<typename get_pixel_type<View>::type>::type
56 >,
57 std::is_unsigned<Channel>
58 >::value
59 >::type
60 >
61 {
62 static const int value = SAMPLEFORMAT_UINT;
63 };
64
65 // is_not_bit_aligned< View > && is_signed< Channel >
66 template <typename View, typename Channel>
67 struct Format_Type
68 <
69 View,
70 Channel,
71 typename std::enable_if
72 <
73 mp11::mp_and
74 <
75 mp11::mp_not
76 <
77 typename is_bit_aligned<typename get_pixel_type<View>::type>::type
78 >,
79 std::is_signed<Channel>
80 >::value
81 >::type
82 >
83 {
84 static const int value = SAMPLEFORMAT_INT;
85 };
86
87 // is_not_bit_aligned< View > && is_floating_point< Channel >
88 template <typename View, typename Channel>
89 struct Format_Type
90 <
91 View,
92 Channel,
93 typename std::enable_if
94 <
95 mp11::mp_and
96 <
97 mp11::mp_not
98 <
99 typename is_bit_aligned<typename get_pixel_type<View>::type>::type
100 >,
101 is_floating_point<Channel>
102 >::value
103 >::type
104 >
105 {
106 static const int value = SAMPLEFORMAT_IEEEFP;
107 };
108
109 //template< typename Channel >
110 //int format_value( std::true_type ) // is_bit_aligned
111 //{
112 // return SAMPLEFORMAT_UINT;
113 //}
114 //
115 //template< typename Channel >
116 //int format_value( std::false_type ) // is_bit_aligned
117 //{
118 // if( is_unsigned< Channel >::value )
119 // {
120 // return SAMPLEFORMAT_UINT;
121 // }
122 //
123 // if( is_signed< Channel >::value )
124 // {
125 // return SAMPLEFORMAT_INT;
126 // }
127 //
128 // else if( is_floating_point< Channel >::value )
129 // {
130 // return SAMPLEFORMAT_IEEEFP;
131 // }
132 //
133 // io_error( "Unkown channel format." );
134 //}
135
136 // The following two functions look the same but are different since one is using
137 // a pixel_t as template parameter whereas the other is using reference_t.
138 template< typename View >
compare_channel_sizes(const channel_sizes_t & channel_sizes,std::false_type,std::true_type)139 bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
140 , std::false_type // is_bit_aligned
141 , std::true_type // is_homogeneous
142 )
143 {
144 using pixel_t = typename View::value_type;
145 using channel_t = typename channel_traits<typename element_type<pixel_t>::type>::value_type;
146
147 unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value;
148
149 return ( s == channel_sizes[0] );
150 }
151
152
153 template< typename View >
compare_channel_sizes(const channel_sizes_t & channel_sizes,std::true_type,std::true_type)154 bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
155 , std::true_type // is_bit_aligned
156 , std::true_type // is_homogeneous
157 )
158 {
159 using ref_t = typename View::reference;
160 using channel_t = typename channel_traits<typename element_type<ref_t>::type>::value_type;
161
162 unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value;
163 return ( s == channel_sizes[0] );
164 }
165
166 struct compare_channel_sizes_fn
167 {
compare_channel_sizes_fnboost::gil::detail::compare_channel_sizes_fn168 compare_channel_sizes_fn( uint16_t* a )
169 : _a( a )
170 , _b( true )
171 {}
172
173 template< typename ChannelSize >
operator ()boost::gil::detail::compare_channel_sizes_fn174 void operator()( ChannelSize x)
175 {
176 if( x != *_a++ )
177 {
178 _b = false;
179 }
180 }
181
182 uint16_t* _a;
183 bool _b;
184 };
185
186 template< typename T >
187 struct channel_sizes_type {};
188
189 template< typename B, typename C, typename L, bool M >
190 struct channel_sizes_type< bit_aligned_pixel_reference< B, C, L, M > > { using type = C; };
191
192 template< typename B, typename C, typename L, bool M >
193 struct channel_sizes_type< const bit_aligned_pixel_reference< B, C, L, M > > { using type = C; };
194
195 template< typename View >
compare_channel_sizes(channel_sizes_t & channel_sizes,std::true_type,std::false_type)196 bool compare_channel_sizes( channel_sizes_t& channel_sizes // in bits
197 , std::true_type // is_bit_aligned
198 , std::false_type // is_homogeneous
199 )
200 {
201 // loop through all channels and compare
202
203 using ref_t = typename View::reference;
204 using cs_t = typename channel_sizes_type<ref_t>::type;
205
206 compare_channel_sizes_fn fn( &channel_sizes.front() );
207 mp11::mp_for_each<cs_t>(fn);
208
209 return fn._b;
210 }
211
212 template< typename View >
is_allowed(const image_read_info<tiff_tag> & info,std::true_type)213 bool is_allowed( const image_read_info< tiff_tag >& info
214 , std::true_type // is read_and_no_convert
215 )
216 {
217 channel_sizes_t channel_sizes( info._samples_per_pixel
218 , info._bits_per_sample
219 );
220
221 using pixel_t = typename get_pixel_type<View>::type;
222 using channel_t = typename channel_traits<typename element_type<pixel_t>::type>::value_type;
223
224 using num_channel_t = typename num_channels<pixel_t>::value_type;
225
226 const num_channel_t dst_samples_per_pixel = num_channels< pixel_t >::value;
227
228 //const num_channel_t dst_sample_format = format_value< channel_t >( typename is_bit_aligned< pixel_t >::type() );
229 const num_channel_t dst_sample_format = Format_Type<View, channel_t>::value;
230
231
232 return ( dst_samples_per_pixel == info._samples_per_pixel
233 && compare_channel_sizes< View >( channel_sizes
234 , typename is_bit_aligned< pixel_t >::type()
235 , typename is_homogeneous< pixel_t >::type()
236 )
237 && dst_sample_format == info._sample_format
238 );
239 }
240
241 template< typename View >
is_allowed(const image_read_info<tiff_tag> &,std::false_type)242 bool is_allowed( const image_read_info< tiff_tag >& /* info */
243 , std::false_type // is read_and_no_convert
244 )
245 {
246 return true;
247 }
248
249 } // namespace detail
250 } // namespace gil
251 } // namespace boost
252
253 #endif
254