Boost GIL


bit_operations.hpp
1//
2// Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
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_BIT_OPERATIONS_HPP
9#define BOOST_GIL_IO_BIT_OPERATIONS_HPP
10
11#include <boost/gil/io/typedefs.hpp>
12
13#include <array>
14#include <cstddef>
15#include <type_traits>
16
17namespace boost { namespace gil { namespace detail {
18
19// 1110 1100 -> 0011 0111
20template <typename Buffer, typename IsBitAligned>
21struct mirror_bits
22{
23 mirror_bits(bool) {};
24
25 void operator()(Buffer&) {}
26 void operator()(byte_t*, std::size_t){}
27};
28
29// The functor will generate a lookup table since the
30// mirror operation is quite costly.
31template <typename Buffer>
32struct mirror_bits<Buffer, std::true_type>
33{
34 mirror_bits(bool apply_operation = true)
35 : apply_operation_(apply_operation)
36 {
37 if(apply_operation_)
38 {
39 byte_t i = 0;
40 do
41 {
42 lookup_[i] = mirror(i);
43 }
44 while (i++ != 255);
45 }
46 }
47
48 void operator()(Buffer& buffer)
49 {
50 if (apply_operation_)
51 for_each(buffer.begin(), buffer.end(), [this](byte_t& c) { lookup(c); });
52 }
53
54 void operator()(byte_t *dst, std::size_t size)
55 {
56 for (std::size_t i = 0; i < size; ++i)
57 {
58 lookup(*dst);
59 ++dst;
60 }
61 }
62
63private:
64
65 void lookup(byte_t& c)
66 {
67 c = lookup_[c];
68 }
69
70 static byte_t mirror(byte_t c)
71 {
72 byte_t result = 0;
73 for (int i = 0; i < 8; ++i)
74 {
75 result = result << 1;
76 result |= (c & 1);
77 c = c >> 1;
78 }
79
80 return result;
81 }
82
83 std::array<byte_t, 256> lookup_;
84 bool apply_operation_;
85
86};
87
88// 0011 1111 -> 1100 0000
89template <typename Buffer, typename IsBitAligned>
90struct negate_bits
91{
92 void operator()(Buffer&) {};
93};
94
95template <typename Buffer>
96struct negate_bits<Buffer, std::true_type>
97{
98 void operator()(Buffer& buffer)
99 {
100 for_each(buffer.begin(), buffer.end(),
101 negate_bits<Buffer, std::true_type>::negate);
102 }
103
104 void operator()(byte_t* dst, std::size_t size)
105 {
106 for (std::size_t i = 0; i < size; ++i)
107 {
108 negate(*dst);
109 ++dst;
110 }
111 }
112
113private:
114
115 static void negate(byte_t& b)
116 {
117 b = ~b;
118 }
119};
120
121// 11101100 -> 11001110
122template <typename Buffer, typename IsBitAligned>
123struct swap_half_bytes
124{
125 void operator()(Buffer&) {};
126};
127
128template <typename Buffer>
129struct swap_half_bytes<Buffer, std::true_type>
130{
131 void operator()(Buffer& buffer)
132 {
133 for_each(buffer.begin(), buffer.end(),
134 swap_half_bytes<Buffer, std::true_type>::swap);
135 }
136
137 void operator()(byte_t* dst, std::size_t size)
138 {
139 for (std::size_t i = 0; i < size; ++i)
140 {
141 swap(*dst);
142 ++dst;
143 }
144 }
145
146private:
147
148 static void swap(byte_t& c)
149 {
150 c = ((c << 4) & 0xF0) | ((c >> 4) & 0x0F);
151 }
152};
153
154template <typename Buffer>
155struct do_nothing
156{
157 do_nothing() = default;
158
159 void operator()(Buffer&) {}
160};
161
163template <typename T>
164inline unsigned int trailing_zeros(T x) noexcept
165{
166 unsigned int n = 0;
167
168 x = ~x & (x - 1);
169 while (x)
170 {
171 n = n + 1;
172 x = x >> 1;
173 }
174
175 return n;
176}
177
179template <typename T>
180inline
181unsigned int count_ones(T x) noexcept
182{
183 unsigned int n = 0;
184
185 while (x)
186 {
187 // clear the least significant bit set
188 x &= x - 1;
189 ++n;
190 }
191
192 return n;
193}
194
195}}} // namespace boost::gil::detail
196
197#endif
BOOST_FORCEINLINE auto apply_operation(Variant1 &&arg1, Visitor &&op)
Applies the visitor op to the variants.
Definition apply_operation.hpp:20
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition algorithm.hpp:36