is_allowed.hpp 6.9 KB

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