Warning, file /include/boost/gil/bit_aligned_pixel_reference.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GIL_BIT_ALIGNED_PIXEL_REFERENCE_HPP
0010 #define BOOST_GIL_BIT_ALIGNED_PIXEL_REFERENCE_HPP
0011
0012 #include <boost/gil/pixel.hpp>
0013 #include <boost/gil/channel.hpp>
0014 #include <boost/gil/detail/mp11.hpp>
0015
0016 #include <boost/assert.hpp>
0017 #include <boost/config.hpp>
0018
0019 #include <functional>
0020 #include <type_traits>
0021
0022 namespace boost { namespace gil {
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 template <int RangeSize, bool IsMutable>
0034 class bit_range {
0035 public:
0036 using byte_t = mp11::mp_if_c<IsMutable, unsigned char, unsigned char const>;
0037 using difference_type = std::ptrdiff_t;
0038 template <int RS, bool M> friend class bit_range;
0039 private:
0040 byte_t* _current_byte;
0041 int _bit_offset;
0042
0043 public:
0044 bit_range() : _current_byte(nullptr), _bit_offset(0) {}
0045 bit_range(byte_t* current_byte, int bit_offset)
0046 : _current_byte(current_byte)
0047 , _bit_offset(bit_offset)
0048 {
0049 BOOST_ASSERT(bit_offset >= 0 && bit_offset < 8);
0050 }
0051
0052 bit_range(bit_range const& br) : _current_byte(br._current_byte), _bit_offset(br._bit_offset) {}
0053 template <bool M> bit_range(const bit_range<RangeSize,M>& br) : _current_byte(br._current_byte), _bit_offset(br._bit_offset) {}
0054
0055 auto operator=(bit_range const& br) -> bit_range& { _current_byte = br._current_byte; _bit_offset=br._bit_offset; return *this; }
0056 bool operator==(bit_range const& br) const { return _current_byte==br._current_byte && _bit_offset==br._bit_offset; }
0057
0058 auto operator++() -> bit_range& {
0059 _current_byte += (_bit_offset+RangeSize) / 8;
0060 _bit_offset = (_bit_offset+RangeSize) % 8;
0061 return *this;
0062 }
0063 auto operator--() -> bit_range& { bit_advance(-RangeSize); return *this; }
0064
0065 void bit_advance(difference_type num_bits) {
0066 int new_offset = int(_bit_offset+num_bits);
0067 _current_byte += new_offset / 8;
0068 _bit_offset = new_offset % 8;
0069 if (_bit_offset<0) {
0070 _bit_offset+=8;
0071 --_current_byte;
0072 }
0073 }
0074
0075 auto bit_distance_to(bit_range const& b) const -> difference_type
0076 {
0077 return (b.current_byte() - current_byte())*8 + b.bit_offset()-bit_offset();
0078 }
0079 auto current_byte() const -> byte_t* { return _current_byte; }
0080 auto bit_offset() const -> int { return _bit_offset; }
0081 };
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116 template <typename BitField, typename ChannelBitSizes, typename Layout, bool IsMutable>
0117 struct bit_aligned_pixel_reference
0118 {
0119 static constexpr int bit_size =
0120 mp11::mp_fold
0121 <
0122 ChannelBitSizes,
0123 std::integral_constant<int, 0>,
0124 mp11::mp_plus
0125 >::value;
0126
0127 using bit_range_t = boost::gil::bit_range<bit_size,IsMutable>;
0128 using bitfield_t = BitField;
0129 using data_ptr_t = mp11::mp_if_c<IsMutable, unsigned char*, const unsigned char*>;
0130
0131 using layout_t = Layout;
0132
0133 using value_type = typename packed_pixel_type<bitfield_t,ChannelBitSizes,Layout>::type;
0134 using reference = const bit_aligned_pixel_reference<BitField, ChannelBitSizes, Layout, IsMutable>;
0135 using const_reference = bit_aligned_pixel_reference<BitField,ChannelBitSizes,Layout,false> const;
0136
0137 static constexpr bool is_mutable = IsMutable;
0138
0139 bit_aligned_pixel_reference(){}
0140 bit_aligned_pixel_reference(data_ptr_t data_ptr, int bit_offset) : _bit_range(data_ptr, bit_offset) {}
0141 explicit bit_aligned_pixel_reference(bit_range_t const& bit_range) : _bit_range(bit_range) {}
0142
0143 template <bool IsMutable2>
0144 bit_aligned_pixel_reference(bit_aligned_pixel_reference<BitField,ChannelBitSizes,Layout,IsMutable2> const& p) : _bit_range(p._bit_range) {}
0145
0146
0147 explicit bit_aligned_pixel_reference(typename kth_element_type<bit_aligned_pixel_reference,0>::type const channel0)
0148 : _bit_range(static_cast<data_ptr_t>(&channel0), channel0.first_bit())
0149 {
0150 static_assert(num_channels<bit_aligned_pixel_reference>::value == 1, "");
0151 }
0152
0153
0154 bit_aligned_pixel_reference(bit_aligned_pixel_reference const& p)
0155 : _bit_range(p._bit_range) {}
0156
0157
0158 template <typename BF, typename CR>
0159 bit_aligned_pixel_reference(packed_pixel<BF, CR, Layout>& p)
0160 : _bit_range(static_cast<data_ptr_t>(&gil::at_c<0>(p)), gil::at_c<0>(p).first_bit())
0161 {
0162 check_compatible<packed_pixel<BF, CR, Layout>>();
0163 }
0164
0165 auto operator=(bit_aligned_pixel_reference const& p) const
0166 -> bit_aligned_pixel_reference const&
0167 {
0168 static_copy(p, *this);
0169 return *this;
0170 }
0171
0172 template <typename P>
0173 auto operator=(P const& p) const -> bit_aligned_pixel_reference const&
0174 {
0175 assign(p, is_pixel<P>());
0176 return *this;
0177 }
0178
0179 template <typename P>
0180 bool operator==(P const& p) const
0181 {
0182 return equal(p, is_pixel<P>());
0183 }
0184
0185 template <typename P>
0186 bool operator!=(P const& p) const { return !(*this==p); }
0187
0188 auto operator->() const -> bit_aligned_pixel_reference const* { return this; }
0189
0190 auto bit_range() const -> bit_range_t const& { return _bit_range; }
0191
0192 private:
0193 mutable bit_range_t _bit_range;
0194 template <typename B, typename C, typename L, bool M>
0195 friend struct bit_aligned_pixel_reference;
0196
0197 template <typename Pixel> static void check_compatible() { gil_function_requires<PixelsCompatibleConcept<Pixel,bit_aligned_pixel_reference> >(); }
0198
0199 template <typename Pixel>
0200 void assign(Pixel const& p, std::true_type) const
0201 {
0202 check_compatible<Pixel>();
0203 static_copy(p, *this);
0204 }
0205
0206 template <typename Pixel>
0207 bool equal(Pixel const& p, std::true_type) const
0208 {
0209 check_compatible<Pixel>();
0210 return static_equal(*this, p);
0211 }
0212
0213 private:
0214 static void check_gray()
0215 {
0216 static_assert(std::is_same<typename Layout::color_space_t, gray_t>::value, "");
0217 }
0218
0219 template <typename Channel>
0220 void assign(Channel const& channel, std::false_type) const
0221 {
0222 check_gray();
0223 gil::at_c<0>(*this) = channel;
0224 }
0225
0226 template <typename Channel>
0227 bool equal (Channel const& channel, std::false_type) const
0228 {
0229 check_gray();
0230 return gil::at_c<0>(*this) == channel;
0231 }
0232 };
0233
0234
0235
0236
0237
0238 template <typename BitField, typename ChannelBitSizes, typename L, bool IsMutable, int K>
0239 struct kth_element_type
0240 <
0241 bit_aligned_pixel_reference<BitField, ChannelBitSizes, L, IsMutable>,
0242 K
0243 >
0244 {
0245 using type = packed_dynamic_channel_reference
0246 <
0247 BitField,
0248 mp11::mp_at_c<ChannelBitSizes, K>::value,
0249 IsMutable
0250 > const;
0251 };
0252
0253 template <typename B, typename C, typename L, bool M, int K>
0254 struct kth_element_reference_type<bit_aligned_pixel_reference<B,C,L,M>, K>
0255 : public kth_element_type<bit_aligned_pixel_reference<B,C,L,M>, K> {};
0256
0257 template <typename B, typename C, typename L, bool M, int K>
0258 struct kth_element_const_reference_type<bit_aligned_pixel_reference<B,C,L,M>, K>
0259 : public kth_element_type<bit_aligned_pixel_reference<B,C,L,M>, K> {};
0260
0261 namespace detail {
0262
0263
0264 template <typename IntegralVector, int K>
0265 struct sum_k
0266 : mp11::mp_plus
0267 <
0268 sum_k<IntegralVector, K - 1>,
0269 typename mp11::mp_at_c<IntegralVector, K - 1>::type
0270 >
0271 {};
0272
0273 template <typename IntegralVector>
0274 struct sum_k<IntegralVector, 0> : std::integral_constant<int, 0> {};
0275
0276 }
0277
0278
0279 template <int K, typename BitField, typename ChannelBitSizes, typename L, bool IsMutable>
0280 inline
0281 auto at_c(const bit_aligned_pixel_reference<BitField, ChannelBitSizes, L, IsMutable>& p)
0282 -> typename kth_element_reference_type<bit_aligned_pixel_reference<BitField, ChannelBitSizes, L, IsMutable>, K>::type
0283 {
0284 using pixel_t = bit_aligned_pixel_reference<BitField, ChannelBitSizes, L, IsMutable>;
0285 using channel_t = typename kth_element_reference_type<pixel_t, K>::type;
0286 using bit_range_t = typename pixel_t::bit_range_t;
0287
0288 bit_range_t bit_range(p.bit_range());
0289 bit_range.bit_advance(detail::sum_k<ChannelBitSizes, K>::value);
0290
0291 return channel_t(bit_range.current_byte(), bit_range.bit_offset());
0292 }
0293
0294
0295
0296
0297
0298
0299 template <typename B, typename C, typename L, bool M>
0300 struct is_pixel<bit_aligned_pixel_reference<B, C, L, M> > : std::true_type {};
0301
0302
0303
0304
0305
0306 template <typename B, typename C, typename L, bool M>
0307 struct color_space_type<bit_aligned_pixel_reference<B, C, L, M>>
0308 {
0309 using type = typename L::color_space_t;
0310 };
0311
0312 template <typename B, typename C, typename L, bool M>
0313 struct channel_mapping_type<bit_aligned_pixel_reference<B, C, L, M>>
0314 {
0315 using type = typename L::channel_mapping_t;
0316 };
0317
0318 template <typename B, typename C, typename L, bool M>
0319 struct is_planar<bit_aligned_pixel_reference<B, C, L, M>> : std::false_type {};
0320
0321
0322
0323
0324
0325
0326 template <typename BitField, int NumBits, typename Layout>
0327 struct pixel_reference_type
0328 <
0329 packed_dynamic_channel_reference<BitField, NumBits, false> const,
0330 Layout, false, false
0331 >
0332 {
0333 private:
0334 using channel_bit_sizes_t = mp11::mp_repeat
0335 <
0336 mp11::mp_list<std::integral_constant<unsigned, NumBits>>,
0337 mp11::mp_size<typename Layout::color_space_t>
0338 >;
0339
0340 public:
0341 using type =
0342 bit_aligned_pixel_reference<BitField, channel_bit_sizes_t, Layout, false>;
0343 };
0344
0345
0346
0347 template <typename BitField, int NumBits, typename Layout>
0348 struct pixel_reference_type
0349 <
0350 packed_dynamic_channel_reference<BitField, NumBits, true> const,
0351 Layout, false, true
0352 >
0353 {
0354 private:
0355 using channel_bit_sizes_t = mp11::mp_repeat
0356 <
0357 mp11::mp_list<std::integral_constant<unsigned, NumBits>>,
0358 mp11::mp_size<typename Layout::color_space_t>
0359 >;
0360
0361 public:
0362 using type = bit_aligned_pixel_reference<BitField, channel_bit_sizes_t, Layout, true>;
0363 };
0364
0365 } }
0366
0367 namespace std {
0368
0369
0370
0371
0372
0373
0374
0375
0376 template <typename B, typename C, typename L, typename R> inline
0377 void swap(boost::gil::bit_aligned_pixel_reference<B,C,L,true> const x, R& y) {
0378 boost::gil::swap_proxy<typename boost::gil::bit_aligned_pixel_reference<B,C,L,true>::value_type>(x,y);
0379 }
0380
0381
0382 template <typename B, typename C, typename L> inline
0383 void swap(typename boost::gil::bit_aligned_pixel_reference<B,C,L,true>::value_type& x, const boost::gil::bit_aligned_pixel_reference<B,C,L,true> y) {
0384 boost::gil::swap_proxy<typename boost::gil::bit_aligned_pixel_reference<B,C,L,true>::value_type>(x,y);
0385 }
0386
0387
0388 template <typename B, typename C, typename L> inline
0389 void swap(boost::gil::bit_aligned_pixel_reference<B,C,L,true> const x, const boost::gil::bit_aligned_pixel_reference<B,C,L,true> y) {
0390 boost::gil::swap_proxy<typename boost::gil::bit_aligned_pixel_reference<B,C,L,true>::value_type>(x,y);
0391 }
0392
0393 }
0394
0395 #endif