Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / gil / io / 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