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 11 // TODO: Shall we move toolbox to core? 12 #include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp> 13 #include <boost/gil/extension/toolbox/metafunctions/is_homogeneous.hpp> 14 #include <boost/gil/extension/toolbox/metafunctions/pixel_bit_size.hpp> 15 16 #include <boost/gil/detail/mp11.hpp> 17 #include <boost/gil/io/typedefs.hpp> 18 19 #include <cstddef> 20 #include <type_traits> 21 #include <vector> 22 23 namespace boost { namespace gil { namespace detail { 24 25 template< typename Pixel 26 , typename DummyT = void 27 > 28 struct row_buffer_helper 29 { 30 using element_t = Pixel; 31 using buffer_t = std::vector<element_t>; 32 using iterator_t = typename buffer_t::iterator; 33 row_buffer_helperboost::gil::detail::row_buffer_helper34 row_buffer_helper( std::size_t width 35 , bool 36 ) 37 : _row_buffer( width ) 38 {} 39 databoost::gil::detail::row_buffer_helper40 element_t* data() { return &_row_buffer[0]; } 41 beginboost::gil::detail::row_buffer_helper42 iterator_t begin() { return _row_buffer.begin(); } endboost::gil::detail::row_buffer_helper43 iterator_t end() { return _row_buffer.end(); } 44 bufferboost::gil::detail::row_buffer_helper45 buffer_t& buffer() { return _row_buffer; } 46 47 private: 48 49 buffer_t _row_buffer; 50 }; 51 52 template <typename Pixel> 53 struct row_buffer_helper 54 < 55 Pixel, 56 typename std::enable_if 57 < 58 is_bit_aligned<Pixel>::value 59 >::type 60 > 61 { 62 using element_t = byte_t; 63 using buffer_t = std::vector<element_t>; 64 using pixel_type = Pixel; 65 using iterator_t = bit_aligned_pixel_iterator<pixel_type>; 66 row_buffer_helperboost::gil::detail::row_buffer_helper67 row_buffer_helper(std::size_t width, bool in_bytes) 68 : _c{( width * pixel_bit_size< pixel_type >::value) >> 3} 69 , _r{width * pixel_bit_size< pixel_type >::value - (_c << 3)} 70 { 71 if (in_bytes) 72 { 73 _row_buffer.resize(width); 74 } 75 else 76 { 77 // add one byte if there are remaining bits 78 _row_buffer.resize(_c + (_r != 0)); 79 } 80 } 81 databoost::gil::detail::row_buffer_helper82 element_t* data() { return &_row_buffer[0]; } 83 beginboost::gil::detail::row_buffer_helper84 iterator_t begin() { return iterator_t( &_row_buffer.front(),0 ); } endboost::gil::detail::row_buffer_helper85 iterator_t end() { return _r == 0 ? iterator_t( &_row_buffer.back() + 1, 0 ) 86 : iterator_t( &_row_buffer.back() , (int) _r ); 87 } 88 bufferboost::gil::detail::row_buffer_helper89 buffer_t& buffer() { return _row_buffer; } 90 91 private: 92 93 // For instance 25 pixels of rgb2 type would be: 94 // overall 25 pixels * 3 channels * 2 bits/channel = 150 bits 95 // c = 18 bytes 96 // r = 6 bits 97 98 std::size_t _c; // number of full bytes 99 std::size_t _r; // number of remaining bits 100 101 buffer_t _row_buffer; 102 }; 103 104 template<typename Pixel> 105 struct row_buffer_helper 106 < 107 Pixel, 108 typename std::enable_if 109 < 110 mp11::mp_and 111 < 112 typename is_bit_aligned<Pixel>::type, 113 typename is_homogeneous<Pixel>::type 114 >::value 115 > 116 > 117 { 118 using element_t = byte_t; 119 using buffer_t = std::vector<element_t>; 120 using pixel_type = Pixel; 121 using iterator_t = bit_aligned_pixel_iterator<pixel_type>; 122 row_buffer_helperboost::gil::detail::row_buffer_helper123 row_buffer_helper( std::size_t width 124 , bool in_bytes 125 ) 126 : _c( ( width 127 * num_channels< pixel_type >::value 128 * channel_type< pixel_type >::type::num_bits 129 ) 130 >> 3 131 ) 132 133 , _r( width 134 * num_channels< pixel_type >::value 135 * channel_type< pixel_type >::type::num_bits 136 - ( _c << 3 ) 137 ) 138 { 139 if( in_bytes ) 140 { 141 _row_buffer.resize( width ); 142 } 143 else 144 { 145 // add one byte if there are remaining bits 146 _row_buffer.resize( _c + ( _r!=0 )); 147 } 148 } 149 databoost::gil::detail::row_buffer_helper150 element_t* data() { return &_row_buffer[0]; } 151 beginboost::gil::detail::row_buffer_helper152 iterator_t begin() { return iterator_t( &_row_buffer.front(),0 ); } endboost::gil::detail::row_buffer_helper153 iterator_t end() { return _r == 0 ? iterator_t( &_row_buffer.back() + 1, 0 ) 154 : iterator_t( &_row_buffer.back() , (int) _r ); 155 } 156 bufferboost::gil::detail::row_buffer_helper157 buffer_t& buffer() { return _row_buffer; } 158 159 private: 160 161 // For instance 25 pixels of rgb2 type would be: 162 // overall 25 pixels * 3 channels * 2 bits/channel = 150 bits 163 // c = 18 bytes 164 // r = 6 bits 165 166 std::size_t _c; // number of full bytes 167 std::size_t _r; // number of remaining bits 168 169 buffer_t _row_buffer; 170 }; 171 172 template <typename View, typename D = void> 173 struct row_buffer_helper_view : row_buffer_helper<typename View::value_type> 174 { row_buffer_helper_viewboost::gil::detail::row_buffer_helper_view175 row_buffer_helper_view(std::size_t width, bool in_bytes) 176 : row_buffer_helper<typename View::value_type>(width, in_bytes) 177 {} 178 }; 179 180 template <typename View> 181 struct row_buffer_helper_view 182 < 183 View, 184 typename std::enable_if 185 < 186 is_bit_aligned<typename View::value_type>::value 187 >::type 188 > : row_buffer_helper<typename View::reference> 189 { row_buffer_helper_viewboost::gil::detail::row_buffer_helper_view190 row_buffer_helper_view(std::size_t width, bool in_bytes) 191 : row_buffer_helper<typename View::reference>(width, in_bytes) 192 {} 193 }; 194 195 } // namespace detail 196 } // namespace gil 197 } // namespace boost 198 199 #endif 200