bit_operations.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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. #include <boost/gil/io/typedefs.hpp>
  11. #include <array>
  12. #include <cstddef>
  13. #include <type_traits>
  14. namespace boost { namespace gil { namespace detail {
  15. // 1110 1100 -> 0011 0111
  16. template <typename Buffer, typename IsBitAligned>
  17. struct mirror_bits
  18. {
  19. mirror_bits(bool) {};
  20. void operator()(Buffer&) {}
  21. void operator()(byte_t*, std::size_t){}
  22. };
  23. // The functor will generate a lookup table since the
  24. // mirror operation is quite costly.
  25. template <typename Buffer>
  26. struct mirror_bits<Buffer, std::true_type>
  27. {
  28. mirror_bits(bool apply_operation = true)
  29. : apply_operation_(apply_operation)
  30. {
  31. if(apply_operation_)
  32. {
  33. byte_t i = 0;
  34. do
  35. {
  36. lookup_[i] = mirror(i);
  37. }
  38. while (i++ != 255);
  39. }
  40. }
  41. void operator()(Buffer& buffer)
  42. {
  43. if (apply_operation_)
  44. for_each(buffer.begin(), buffer.end(), [this](byte_t& c) { lookup(c); });
  45. }
  46. void operator()(byte_t *dst, std::size_t size)
  47. {
  48. for (std::size_t i = 0; i < size; ++i)
  49. {
  50. lookup(*dst);
  51. ++dst;
  52. }
  53. }
  54. private:
  55. void lookup(byte_t& c)
  56. {
  57. c = lookup_[c];
  58. }
  59. static byte_t mirror(byte_t c)
  60. {
  61. byte_t result = 0;
  62. for (int i = 0; i < 8; ++i)
  63. {
  64. result = result << 1;
  65. result |= (c & 1);
  66. c = c >> 1;
  67. }
  68. return result;
  69. }
  70. std::array<byte_t, 256> lookup_;
  71. bool apply_operation_;
  72. };
  73. // 0011 1111 -> 1100 0000
  74. template <typename Buffer, typename IsBitAligned>
  75. struct negate_bits
  76. {
  77. void operator()(Buffer&) {};
  78. };
  79. template <typename Buffer>
  80. struct negate_bits<Buffer, std::true_type>
  81. {
  82. void operator()(Buffer& buffer)
  83. {
  84. for_each(buffer.begin(), buffer.end(),
  85. negate_bits<Buffer, std::true_type>::negate);
  86. }
  87. void operator()(byte_t* dst, std::size_t size)
  88. {
  89. for (std::size_t i = 0; i < size; ++i)
  90. {
  91. negate(*dst);
  92. ++dst;
  93. }
  94. }
  95. private:
  96. static void negate(byte_t& b)
  97. {
  98. b = ~b;
  99. }
  100. };
  101. // 11101100 -> 11001110
  102. template <typename Buffer, typename IsBitAligned>
  103. struct swap_half_bytes
  104. {
  105. void operator()(Buffer&) {};
  106. };
  107. template <typename Buffer>
  108. struct swap_half_bytes<Buffer, std::true_type>
  109. {
  110. void operator()(Buffer& buffer)
  111. {
  112. for_each(buffer.begin(), buffer.end(),
  113. swap_half_bytes<Buffer, std::true_type>::swap);
  114. }
  115. void operator()(byte_t* dst, std::size_t size)
  116. {
  117. for (std::size_t i = 0; i < size; ++i)
  118. {
  119. swap(*dst);
  120. ++dst;
  121. }
  122. }
  123. private:
  124. static void swap(byte_t& c)
  125. {
  126. c = ((c << 4) & 0xF0) | ((c >> 4) & 0x0F);
  127. }
  128. };
  129. template <typename Buffer>
  130. struct do_nothing
  131. {
  132. do_nothing() = default;
  133. void operator()(Buffer&) {}
  134. };
  135. /// Count consecutive zeros on the right
  136. template <typename T>
  137. inline unsigned int trailing_zeros(T x) noexcept
  138. {
  139. unsigned int n = 0;
  140. x = ~x & (x - 1);
  141. while (x)
  142. {
  143. n = n + 1;
  144. x = x >> 1;
  145. }
  146. return n;
  147. }
  148. /// Counts ones in a bit-set
  149. template <typename T>
  150. inline
  151. unsigned int count_ones(T x) noexcept
  152. {
  153. unsigned int n = 0;
  154. while (x)
  155. {
  156. // clear the least significant bit set
  157. x &= x - 1;
  158. ++n;
  159. }
  160. return n;
  161. }
  162. }}} // namespace boost::gil::detail
  163. #endif