pixel.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. Pixel
  2. =====
  3. .. contents::
  4. :local:
  5. :depth: 2
  6. Overview
  7. --------
  8. A pixel is a set of channels defining the color at a given point in an
  9. image. Conceptually, a pixel is little more than a color base whose
  10. elements model ``ChannelConcept``. All properties of pixels inherit
  11. from color bases: pixels may be *homogeneous* if all of their channels
  12. have the same type; otherwise they are called *heterogeneous*. The
  13. channels of a pixel may be addressed using semantic or physical
  14. indexing, or by color; all color-base algorithms work on pixels as
  15. well. Two pixels are *compatible* if their color spaces are the same
  16. and their channels, paired semantically, are compatible. Note that
  17. constness, memory organization and reference/value are ignored. For
  18. example, an 8-bit RGB planar reference is compatible to a constant
  19. 8-bit BGR interleaved pixel value. Most pairwise pixel operations
  20. (copy construction, assignment, equality, etc.) are only defined for
  21. compatible pixels.
  22. Pixels (as well as other GIL constructs built on pixels, such as
  23. iterators, locators, views and images) must provide metafunctions to
  24. access their color space, channel mapping, number of channels, and
  25. (for homogeneous pixels) the channel type:
  26. .. code-block:: cpp
  27. concept PixelBasedConcept<typename T>
  28. {
  29. typename color_space_type<T>;
  30. where Metafunction<color_space_type<T> >;
  31. where ColorSpaceConcept<color_space_type<T>::type>;
  32. typename channel_mapping_type<T>;
  33. where Metafunction<channel_mapping_type<T> >;
  34. where ChannelMappingConcept<channel_mapping_type<T>::type>;
  35. typename is_planar<T>;
  36. where Metafunction<is_planar<T> >;
  37. where SameType<is_planar<T>::type, bool>;
  38. };
  39. concept HomogeneousPixelBasedConcept<PixelBasedConcept T>
  40. {
  41. typename channel_type<T>;
  42. where Metafunction<channel_type<T> >;
  43. where ChannelConcept<channel_type<T>::type>;
  44. };
  45. Pixels model the following concepts:
  46. .. code-block:: cpp
  47. concept PixelConcept<typename P> : ColorBaseConcept<P>, PixelBasedConcept<P>
  48. {
  49. where is_pixel<P>::value==true;
  50. // where for each K [0..size<P>::value-1]:
  51. // ChannelConcept<kth_element_type<K> >;
  52. typename value_type; where PixelValueConcept<value_type>;
  53. typename reference; where PixelConcept<reference>;
  54. typename const_reference; where PixelConcept<const_reference>;
  55. static const bool P::is_mutable;
  56. template <PixelConcept P2> where { PixelConcept<P,P2> }
  57. P::P(P2);
  58. template <PixelConcept P2> where { PixelConcept<P,P2> }
  59. bool operator==(const P&, const P2&);
  60. template <PixelConcept P2> where { PixelConcept<P,P2> }
  61. bool operator!=(const P&, const P2&);
  62. };
  63. concept MutablePixelConcept<typename P> : PixelConcept<P>, MutableColorBaseConcept<P>
  64. {
  65. where is_mutable==true;
  66. };
  67. concept HomogeneousPixelConcept<PixelConcept P> : HomogeneousColorBaseConcept<P>, HomogeneousPixelBasedConcept<P>
  68. {
  69. P::template element_const_reference_type<P>::type operator[](P p, std::size_t i) const { return dynamic_at_c(P,i); }
  70. };
  71. concept MutableHomogeneousPixelConcept<MutablePixelConcept P> : MutableHomogeneousColorBaseConcept<P>
  72. {
  73. P::template element_reference_type<P>::type operator[](P p, std::size_t i) { return dynamic_at_c(p,i); }
  74. };
  75. concept PixelValueConcept<typename P> : PixelConcept<P>, Regular<P>
  76. {
  77. where SameType<value_type,P>;
  78. };
  79. concept PixelsCompatibleConcept<PixelConcept P1, PixelConcept P2> : ColorBasesCompatibleConcept<P1,P2>
  80. {
  81. // where for each K [0..size<P1>::value):
  82. // ChannelsCompatibleConcept<kth_semantic_element_type<P1,K>::type, kth_semantic_element_type<P2,K>::type>;
  83. };
  84. A pixel is *convertible* to a second pixel if it is possible to
  85. approximate its color in the form of the second pixel. Conversion is
  86. an explicit, non-symmetric and often lossy operation (due to both
  87. channel and color space approximation). Convertibility requires
  88. modeling the following concept:
  89. .. code-block:: cpp
  90. template <PixelConcept SrcPixel, MutablePixelConcept DstPixel>
  91. concept PixelConvertibleConcept
  92. {
  93. void color_convert(const SrcPixel&, DstPixel&);
  94. };
  95. The distinction between ``PixelConcept`` and ``PixelValueConcept`` is
  96. analogous to that for channels and color bases - pixel reference proxies model
  97. both, but only pixel values model the latter.
  98. .. seealso::
  99. - `PixelBasedConcept<P> <reference/structboost_1_1gil_1_1_pixel_based_concept.html>`_
  100. - `PixelConcept<Pixel> <reference/structboost_1_1gil_1_1_pixel_concept.html>`_
  101. - `MutablePixelConcept<Pixel> <reference/structboost_1_1gil_1_1_mutable_pixel_concept.html>`_
  102. - `PixelValueConcept<Pixel> <reference/structboost_1_1gil_1_1_pixel_value_concept.html>`_
  103. - `HomogeneousPixelConcept<Pixel> <reference/structboost_1_1gil_1_1_homogeneous_pixel_based_concept.html>`_
  104. - `MutableHomogeneousPixelConcept<Pixel> <reference/structboost_1_1gil_1_1_mutable_homogeneous_pixel_concept.html>`_
  105. - `HomogeneousPixelValueConcept<Pixel> <reference/structboost_1_1gil_1_1_homogeneous_pixel_value_concept.html>`_
  106. - `PixelsCompatibleConcept<Pixel1, Pixel2> <reference/structboost_1_1gil_1_1_pixels_compatible_concept.html>`_
  107. - `PixelConvertibleConcept<SrcPixel, DstPixel> <reference/structboost_1_1gil_1_1_pixel_convertible_concept.html>`_
  108. Models
  109. ------
  110. The most commonly used pixel is a homogeneous pixel whose values are
  111. together in memory. For this purpose GIL provides the struct
  112. ``pixel``, templated over the channel value and layout:
  113. .. code-block:: cpp
  114. // models HomogeneousPixelValueConcept
  115. template <typename ChannelValue, typename Layout> struct pixel;
  116. // Those typedefs are already provided by GIL
  117. typedef pixel<bits8, rgb_layout_t> rgb8_pixel_t;
  118. typedef pixel<bits8, bgr_layout_t> bgr8_pixel_t;
  119. bgr8_pixel_t bgr8(255,0,0); // pixels can be initialized with the channels directly
  120. rgb8_pixel_t rgb8(bgr8); // compatible pixels can also be copy-constructed
  121. rgb8 = bgr8; // assignment and equality is defined between compatible pixels
  122. assert(rgb8 == bgr8); // assignment and equality operate on the semantic channels
  123. // The first physical channels of the two pixels are different
  124. assert(at_c<0>(rgb8) != at_c<0>(bgr8));
  125. assert(dynamic_at_c(bgr8,0) != dynamic_at_c(rgb8,0));
  126. assert(rgb8[0] != bgr8[0]); // same as above (but operator[] is defined for pixels only)
  127. Planar pixels have their channels distributed in memory. While they share the
  128. same value type (``pixel``) with interleaved pixels, their reference type is a
  129. proxy class containing references to each of the channels.
  130. This is implemented with the struct ``planar_pixel_reference``:
  131. .. code-block:: cpp
  132. // models HomogeneousPixel
  133. template <typename ChannelReference, typename ColorSpace> struct planar_pixel_reference;
  134. // Define the type of a mutable and read-only reference. (These typedefs are already provided by GIL)
  135. typedef planar_pixel_reference< bits8&,rgb_t> rgb8_planar_ref_t;
  136. typedef planar_pixel_reference<const bits8&,rgb_t> rgb8c_planar_ref_t;
  137. Note that, unlike the ``pixel`` struct, planar pixel references are templated
  138. over the color space, not over the pixel layout. They always use a canonical
  139. channel ordering. Ordering of their elements is unnecessary because their
  140. elements are references to the channels.
  141. Sometimes the channels of a pixel may not be byte-aligned. For example an RGB
  142. pixel in '5-5-6' format is a 16-bit pixel whose red, green and blue channels
  143. occupy bits [0..4],[5..9] and [10..15] respectively. GIL provides a model for
  144. such packed pixel formats:
  145. .. code-block:: cpp
  146. // define an rgb565 pixel
  147. typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,5,6,5>, rgb_layout_t>::type rgb565_pixel_t;
  148. function_requires<PixelValueConcept<rgb565_pixel_t> >();
  149. static_assert(sizeof(rgb565_pixel_t) == 2, "");
  150. // define a bgr556 pixel
  151. typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,5,6,5>, bgr_layout_t>::type bgr556_pixel_t;
  152. function_requires<PixelValueConcept<bgr556_pixel_t> >();
  153. // rgb565 is compatible with bgr556.
  154. function_requires<PixelsCompatibleConcept<rgb565_pixel_t,bgr556_pixel_t> >();
  155. In some cases, the pixel itself may not be byte aligned. For example,
  156. consider an RGB pixel in '2-3-2' format. Its size is 7 bits. GIL
  157. refers to such pixels, pixel iterators and images as
  158. "bit-aligned". Bit-aligned pixels (and images) are more complex than
  159. packed ones. Since packed pixels are byte-aligned, we can use a C++
  160. reference as the reference type to a packed pixel, and a C pointer as
  161. an x_iterator over a row of packed pixels. For bit-aligned constructs
  162. we need a special reference proxy class (bit_aligned_pixel_reference)
  163. and iterator class (bit_aligned_pixel_iterator). The value type of
  164. bit-aligned pixels is a packed_pixel. Here is how to use bit_aligned
  165. pixels and pixel iterators:
  166. .. code-block:: cpp
  167. // Mutable reference to a BGR232 pixel
  168. typedef const bit_aligned_pixel_reference<unsigned char, mpl::vector3_c<unsigned,2,3,2>, bgr_layout_t, true> bgr232_ref_t;
  169. // A mutable iterator over BGR232 pixels
  170. typedef bit_aligned_pixel_iterator<bgr232_ref_t> bgr232_ptr_t;
  171. // BGR232 pixel value. It is a packed_pixel of size 1 byte. (The last bit is unused)
  172. typedef std::iterator_traits<bgr232_ptr_t>::value_type bgr232_pixel_t;
  173. static_assert(sizeof(bgr232_pixel_t) == 1, "");
  174. bgr232_pixel_t red(0,0,3); // = 0RRGGGBB, = 01100000 = 0x60
  175. // a buffer of 7 bytes fits exactly 8 BGR232 pixels.
  176. unsigned char pix_buffer[7];
  177. std::fill(pix_buffer,pix_buffer+7,0);
  178. // Fill the 8 pixels with red
  179. bgr232_ptr_t pix_it(&pix_buffer[0],0); // start at bit 0 of the first pixel
  180. for (int i=0; i<8; ++i)
  181. {
  182. *pix_it++ = red;
  183. }
  184. // Result: 0x60 0x30 0x11 0x0C 0x06 0x83 0xC1
  185. Algorithms
  186. ----------
  187. Since pixels model ``ColorBaseConcept`` and ``PixelBasedConcept`` all
  188. algorithms and metafunctions of color bases can work with them as well:
  189. .. code-block:: cpp
  190. // This is how to access the first semantic channel (red)
  191. assert(semantic_at_c<0>(rgb8) == semantic_at_c<0>(bgr8));
  192. // This is how to access the red channel by name
  193. assert(get_color<red_t>(rgb8) == get_color<red_t>(bgr8));
  194. // This is another way of doing it (some compilers don't like the first one)
  195. assert(get_color(rgb8,red_t()) == get_color(bgr8,red_t()));
  196. // This is how to use the PixelBasedConcept metafunctions
  197. BOOST_MPL_ASSERT(num_channels<rgb8_pixel_t>::value == 3);
  198. BOOST_MPL_ASSERT((is_same<channel_type<rgb8_pixel_t>::type, bits8>));
  199. BOOST_MPL_ASSERT((is_same<color_space_type<bgr8_pixel_t>::type, rgb_t> ));
  200. BOOST_MPL_ASSERT((is_same<channel_mapping_type<bgr8_pixel_t>::type, mpl::vector3_c<int,2,1,0> > ));
  201. // Pixels contain just the three channels and nothing extra
  202. BOOST_MPL_ASSERT(sizeof(rgb8_pixel_t)==3);
  203. rgb8_planar_ref_t ref(bgr8); // copy construction is allowed from a compatible mutable pixel type
  204. get_color<red_t>(ref) = 10; // assignment is ok because the reference is mutable
  205. assert(get_color<red_t>(bgr8)==10); // references modify the value they are bound to
  206. // Create a zero packed pixel and a full regular unpacked pixel.
  207. rgb565_pixel_t r565;
  208. rgb8_pixel_t rgb_full(255,255,255);
  209. // Convert all channels of the unpacked pixel to the packed one & assert the packed one is full
  210. get_color(r565,red_t()) = channel_convert<rgb565_channel0_t>(get_color(rgb_full,red_t()));
  211. get_color(r565,green_t()) = channel_convert<rgb565_channel1_t>(get_color(rgb_full,green_t()));
  212. get_color(r565,blue_t()) = channel_convert<rgb565_channel2_t>(get_color(rgb_full,blue_t()));
  213. assert(r565 == rgb565_pixel_t((uint16_t)65535));
  214. GIL also provides the ``color_convert`` algorithm to convert between pixels of
  215. different color spaces and channel types:
  216. .. code-block:: cpp
  217. rgb8_pixel_t red_in_rgb8(255,0,0);
  218. cmyk16_pixel_t red_in_cmyk16;
  219. color_convert(red_in_rgb8,red_in_cmyk16);