packed_pixel.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. //
  2. // Copyright 2005-2007 Adobe Systems Incorporated
  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_PACKED_PIXEL_HPP
  9. #define BOOST_GIL_PACKED_PIXEL_HPP
  10. #include <boost/gil/pixel.hpp>
  11. #include <boost/core/ignore_unused.hpp>
  12. #include <boost/mpl/bool.hpp>
  13. #include <boost/mpl/front.hpp>
  14. #include <functional>
  15. #include <type_traits>
  16. namespace boost { namespace gil {
  17. /// A model of a heterogeneous pixel whose channels are bit ranges.
  18. /// For example 16-bit RGB in '565' format.
  19. /// \defgroup ColorBaseModelPackedPixel packed_pixel
  20. /// \ingroup ColorBaseModel
  21. /// \brief A heterogeneous color base whose elements are reference proxies to channels in a pixel. Models ColorBaseValueConcept. This class is used to model packed pixels, such as 16-bit packed RGB.
  22. /// \defgroup PixelModelPackedPixel packed_pixel
  23. /// \ingroup PixelModel
  24. /// \brief A heterogeneous pixel used to represent packed pixels with non-byte-aligned channels. Models PixelValueConcept
  25. ///
  26. /// Example:
  27. /// \code
  28. /// using rgb565_pixel_t = packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,5,6,5>, rgb_layout_t>::type;
  29. /// static_assert(sizeof(rgb565_pixel_t) == 2, "");
  30. ///
  31. /// rgb565_pixel_t r565;
  32. /// get_color(r565,red_t()) = 31;
  33. /// get_color(r565,green_t()) = 63;
  34. /// get_color(r565,blue_t()) = 31;
  35. /// assert(r565 == rgb565_pixel_t((uint16_t)0xFFFF));
  36. /// \endcode
  37. /// \ingroup ColorBaseModelPackedPixel PixelModelPackedPixel PixelBasedModel
  38. /// \brief Heterogeneous pixel value whose channel references can be constructed from the pixel bitfield and their index. Models ColorBaseValueConcept, PixelValueConcept, PixelBasedConcept
  39. /// Typical use for this is a model of a packed pixel (like 565 RGB)
  40. template <typename BitField, // A type that holds the bits of the pixel. Typically an integral type, like std::uint16_t
  41. typename ChannelRefVec, // An MPL vector whose elements are packed channels. They must be constructible from BitField. GIL uses packed_channel_reference
  42. typename Layout> // Layout defining the color space and ordering of the channels. Example value: rgb_layout_t
  43. struct packed_pixel
  44. {
  45. BitField _bitfield;
  46. using layout_t = Layout;
  47. using value_type = packed_pixel<BitField, ChannelRefVec, Layout>;
  48. using reference = value_type&;
  49. using const_reference = value_type const&;
  50. static constexpr bool is_mutable =
  51. channel_traits<typename mpl::front<ChannelRefVec>::type>::is_mutable;
  52. packed_pixel(){}
  53. explicit packed_pixel(const BitField& bitfield) : _bitfield(bitfield) {}
  54. // Construct from another compatible pixel type
  55. packed_pixel(const packed_pixel& p) : _bitfield(p._bitfield) {}
  56. template <typename P>
  57. packed_pixel(P const& p,
  58. typename std::enable_if<is_pixel<P>::value>::type* /*dummy*/ = nullptr)
  59. {
  60. check_compatible<P>();
  61. static_copy(p, *this);
  62. }
  63. packed_pixel(int chan0, int chan1) : _bitfield(0) {
  64. static_assert(num_channels<packed_pixel>::value == 2, "");
  65. gil::at_c<0>(*this)=chan0; gil::at_c<1>(*this)=chan1;
  66. }
  67. packed_pixel(int chan0, int chan1, int chan2) : _bitfield(0) {
  68. static_assert(num_channels<packed_pixel>::value == 3, "");
  69. gil::at_c<0>(*this) = chan0;
  70. gil::at_c<1>(*this) = chan1;
  71. gil::at_c<2>(*this) = chan2;
  72. }
  73. packed_pixel(int chan0, int chan1, int chan2, int chan3) : _bitfield(0) {
  74. static_assert(num_channels<packed_pixel>::value == 4, "");
  75. gil::at_c<0>(*this)=chan0; gil::at_c<1>(*this)=chan1; gil::at_c<2>(*this)=chan2; gil::at_c<3>(*this)=chan3;
  76. }
  77. packed_pixel(int chan0, int chan1, int chan2, int chan3, int chan4) : _bitfield(0) {
  78. static_assert(num_channels<packed_pixel>::value == 5, "");
  79. gil::at_c<0>(*this)=chan0; gil::at_c<1>(*this)=chan1; gil::at_c<2>(*this)=chan2; gil::at_c<3>(*this)=chan3; gil::at_c<4>(*this)=chan4;
  80. }
  81. packed_pixel& operator=(const packed_pixel& p) { _bitfield=p._bitfield; return *this; }
  82. template <typename P> packed_pixel& operator=(const P& p) { assign(p, mpl::bool_<is_pixel<P>::value>()); return *this; }
  83. template <typename P> bool operator==(const P& p) const { return equal(p, mpl::bool_<is_pixel<P>::value>()); }
  84. template <typename P> bool operator!=(const P& p) const { return !(*this==p); }
  85. private:
  86. template <typename Pixel> static void check_compatible() { gil_function_requires<PixelsCompatibleConcept<Pixel,packed_pixel> >(); }
  87. template <typename Pixel> void assign(const Pixel& p, mpl::true_) { check_compatible<Pixel>(); static_copy(p,*this); }
  88. template <typename Pixel> bool equal(const Pixel& p, mpl::true_) const { check_compatible<Pixel>(); return static_equal(*this,p); }
  89. // Support for assignment/equality comparison of a channel with a grayscale pixel
  90. static void check_gray()
  91. {
  92. static_assert(is_same<typename Layout::color_space_t, gray_t>::value, "");
  93. }
  94. template <typename Channel> void assign(const Channel& chan, mpl::false_) { check_gray(); gil::at_c<0>(*this)=chan; }
  95. template <typename Channel> bool equal (const Channel& chan, mpl::false_) const { check_gray(); return gil::at_c<0>(*this)==chan; }
  96. public:
  97. packed_pixel& operator= (int chan) { check_gray(); gil::at_c<0>(*this)=chan; return *this; }
  98. bool operator==(int chan) const { check_gray(); return gil::at_c<0>(*this)==chan; }
  99. };
  100. /////////////////////////////
  101. // ColorBasedConcept
  102. /////////////////////////////
  103. template <typename BitField, typename ChannelRefVec, typename Layout, int K>
  104. struct kth_element_type<packed_pixel<BitField,ChannelRefVec,Layout>,K> : public mpl::at_c<ChannelRefVec,K> {};
  105. template <typename BitField, typename ChannelRefVec, typename Layout, int K>
  106. struct kth_element_reference_type<packed_pixel<BitField,ChannelRefVec,Layout>,K> : public mpl::at_c<ChannelRefVec,K> {};
  107. template <typename BitField, typename ChannelRefVec, typename Layout, int K>
  108. struct kth_element_const_reference_type<packed_pixel<BitField,ChannelRefVec,Layout>,K>
  109. {
  110. using type = typename channel_traits<typename mpl::at_c<ChannelRefVec,K>::type>::const_reference;
  111. };
  112. template <int K, typename P, typename C, typename L> inline
  113. typename kth_element_reference_type<packed_pixel<P,C,L>, K>::type
  114. at_c(packed_pixel<P,C,L>& p) {
  115. return typename kth_element_reference_type<packed_pixel<P,C,L>, K>::type(&p._bitfield);
  116. }
  117. template <int K, typename P, typename C, typename L> inline
  118. typename kth_element_const_reference_type<packed_pixel<P,C,L>, K>::type
  119. at_c(const packed_pixel<P,C,L>& p) {
  120. return typename kth_element_const_reference_type<packed_pixel<P,C,L>, K>::type(&p._bitfield);
  121. }
  122. /////////////////////////////
  123. // PixelConcept
  124. /////////////////////////////
  125. // Metafunction predicate that flags packed_pixel as a model of PixelConcept. Required by PixelConcept
  126. template <typename BitField, typename ChannelRefVec, typename Layout>
  127. struct is_pixel<packed_pixel<BitField,ChannelRefVec,Layout> > : public mpl::true_{};
  128. /////////////////////////////
  129. // PixelBasedConcept
  130. /////////////////////////////
  131. template <typename P, typename C, typename Layout>
  132. struct color_space_type<packed_pixel<P,C,Layout> > {
  133. using type = typename Layout::color_space_t;
  134. };
  135. template <typename P, typename C, typename Layout>
  136. struct channel_mapping_type<packed_pixel<P,C,Layout> > {
  137. using type = typename Layout::channel_mapping_t;
  138. };
  139. template <typename P, typename C, typename Layout>
  140. struct is_planar<packed_pixel<P,C,Layout> > : mpl::false_ {};
  141. ////////////////////////////////////////////////////////////////////////////////
  142. ///
  143. /// Support for interleaved iterators over packed pixel
  144. ///
  145. ////////////////////////////////////////////////////////////////////////////////
  146. /// \defgroup PixelIteratorModelPackedInterleavedPtr Pointer to packed_pixel<P,CR,Layout>
  147. /// \ingroup PixelIteratorModel
  148. /// \brief Iterators over interleaved pixels.
  149. /// The pointer packed_pixel<P,CR,Layout>* is used as an iterator over interleaved pixels of packed format. Models PixelIteratorConcept, HasDynamicXStepTypeConcept, MemoryBasedIteratorConcept
  150. template <typename P, typename C, typename L>
  151. struct iterator_is_mutable<packed_pixel<P,C,L>*> : public mpl::bool_<packed_pixel<P,C,L>::is_mutable> {};
  152. template <typename P, typename C, typename L>
  153. struct iterator_is_mutable<const packed_pixel<P,C,L>*> : public mpl::false_ {};
  154. } } // namespace boost::gil
  155. namespace boost {
  156. template <typename P, typename C, typename L>
  157. struct has_trivial_constructor<gil::packed_pixel<P,C,L> > : public has_trivial_constructor<P> {};
  158. }
  159. #endif