Boost GIL


row_buffer_helper.hpp
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 
34  row_buffer_helper( std::size_t width
35  , bool
36  )
37  : _row_buffer( width )
38  {}
39 
40  element_t* data() { return &_row_buffer[0]; }
41 
42  iterator_t begin() { return _row_buffer.begin(); }
43  iterator_t end() { return _row_buffer.end(); }
44 
45  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 
67  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 
82  element_t* data() { return &_row_buffer[0]; }
83 
84  iterator_t begin() { return iterator_t( &_row_buffer.front(),0 ); }
85  iterator_t end() { return _r == 0 ? iterator_t( &_row_buffer.back() + 1, 0 )
86  : iterator_t( &_row_buffer.back() , (int) _r );
87  }
88 
89  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 
123  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 
150  element_t* data() { return &_row_buffer[0]; }
151 
152  iterator_t begin() { return iterator_t( &_row_buffer.front(),0 ); }
153  iterator_t end() { return _r == 0 ? iterator_t( &_row_buffer.back() + 1, 0 )
154  : iterator_t( &_row_buffer.back() , (int) _r );
155  }
156 
157  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 {
175  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 {
190  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