row_buffer_helper.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. //
  2. // Copyright 2007-2008 Christian Henning
  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_IO_ROW_BUFFER_HELPER_HPP
  9. #define BOOST_GIL_IO_ROW_BUFFER_HELPER_HPP
  10. // TODO: Shall we move toolbox to core?
  11. #include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
  12. #include <boost/gil/extension/toolbox/metafunctions/is_homogeneous.hpp>
  13. #include <boost/gil/extension/toolbox/metafunctions/pixel_bit_size.hpp>
  14. #include <boost/gil/detail/mp11.hpp>
  15. #include <boost/gil/io/typedefs.hpp>
  16. #include <cstddef>
  17. #include <type_traits>
  18. #include <vector>
  19. namespace boost { namespace gil { namespace detail {
  20. template< typename Pixel
  21. , typename DummyT = void
  22. >
  23. struct row_buffer_helper
  24. {
  25. using element_t = Pixel;
  26. using buffer_t = std::vector<element_t>;
  27. using iterator_t = typename buffer_t::iterator;
  28. row_buffer_helper( std::size_t width
  29. , bool
  30. )
  31. : _row_buffer( width )
  32. {}
  33. element_t* data() { return &_row_buffer[0]; }
  34. iterator_t begin() { return _row_buffer.begin(); }
  35. iterator_t end() { return _row_buffer.end(); }
  36. buffer_t& buffer() { return _row_buffer; }
  37. private:
  38. buffer_t _row_buffer;
  39. };
  40. template <typename Pixel>
  41. struct row_buffer_helper
  42. <
  43. Pixel,
  44. typename std::enable_if
  45. <
  46. is_bit_aligned<Pixel>::value
  47. >::type
  48. >
  49. {
  50. using element_t = byte_t;
  51. using buffer_t = std::vector<element_t>;
  52. using pixel_type = Pixel;
  53. using iterator_t = bit_aligned_pixel_iterator<pixel_type>;
  54. row_buffer_helper(std::size_t width, bool in_bytes)
  55. : _c{( width * pixel_bit_size< pixel_type >::value) >> 3}
  56. , _r{width * pixel_bit_size< pixel_type >::value - (_c << 3)}
  57. {
  58. if (in_bytes)
  59. {
  60. _row_buffer.resize(width);
  61. }
  62. else
  63. {
  64. // add one byte if there are remaining bits
  65. _row_buffer.resize(_c + (_r != 0));
  66. }
  67. }
  68. element_t* data() { return &_row_buffer[0]; }
  69. iterator_t begin() { return iterator_t( &_row_buffer.front(),0 ); }
  70. iterator_t end() { return _r == 0 ? iterator_t( &_row_buffer.back() + 1, 0 )
  71. : iterator_t( &_row_buffer.back() , (int) _r );
  72. }
  73. buffer_t& buffer() { return _row_buffer; }
  74. private:
  75. // For instance 25 pixels of rgb2 type would be:
  76. // overall 25 pixels * 3 channels * 2 bits/channel = 150 bits
  77. // c = 18 bytes
  78. // r = 6 bits
  79. std::size_t _c; // number of full bytes
  80. std::size_t _r; // number of remaining bits
  81. buffer_t _row_buffer;
  82. };
  83. template<typename Pixel>
  84. struct row_buffer_helper
  85. <
  86. Pixel,
  87. typename std::enable_if
  88. <
  89. mp11::mp_and
  90. <
  91. typename is_bit_aligned<Pixel>::type,
  92. typename is_homogeneous<Pixel>::type
  93. >::value
  94. >
  95. >
  96. {
  97. using element_t = byte_t;
  98. using buffer_t = std::vector<element_t>;
  99. using pixel_type = Pixel;
  100. using iterator_t = bit_aligned_pixel_iterator<pixel_type>;
  101. row_buffer_helper( std::size_t width
  102. , bool in_bytes
  103. )
  104. : _c( ( width
  105. * num_channels< pixel_type >::value
  106. * channel_type< pixel_type >::type::num_bits
  107. )
  108. >> 3
  109. )
  110. , _r( width
  111. * num_channels< pixel_type >::value
  112. * channel_type< pixel_type >::type::num_bits
  113. - ( _c << 3 )
  114. )
  115. {
  116. if( in_bytes )
  117. {
  118. _row_buffer.resize( width );
  119. }
  120. else
  121. {
  122. // add one byte if there are remaining bits
  123. _row_buffer.resize( _c + ( _r!=0 ));
  124. }
  125. }
  126. element_t* data() { return &_row_buffer[0]; }
  127. iterator_t begin() { return iterator_t( &_row_buffer.front(),0 ); }
  128. iterator_t end() { return _r == 0 ? iterator_t( &_row_buffer.back() + 1, 0 )
  129. : iterator_t( &_row_buffer.back() , (int) _r );
  130. }
  131. buffer_t& buffer() { return _row_buffer; }
  132. private:
  133. // For instance 25 pixels of rgb2 type would be:
  134. // overall 25 pixels * 3 channels * 2 bits/channel = 150 bits
  135. // c = 18 bytes
  136. // r = 6 bits
  137. std::size_t _c; // number of full bytes
  138. std::size_t _r; // number of remaining bits
  139. buffer_t _row_buffer;
  140. };
  141. template <typename View, typename D = void>
  142. struct row_buffer_helper_view : row_buffer_helper<typename View::value_type>
  143. {
  144. row_buffer_helper_view(std::size_t width, bool in_bytes)
  145. : row_buffer_helper<typename View::value_type>(width, in_bytes)
  146. {}
  147. };
  148. template <typename View>
  149. struct row_buffer_helper_view
  150. <
  151. View,
  152. typename std::enable_if
  153. <
  154. is_bit_aligned<typename View::value_type>::value
  155. >::type
  156. > : row_buffer_helper<typename View::reference>
  157. {
  158. row_buffer_helper_view(std::size_t width, bool in_bytes)
  159. : row_buffer_helper<typename View::reference>(width, in_bytes)
  160. {}
  161. };
  162. } // namespace detail
  163. } // namespace gil
  164. } // namespace boost
  165. #endif