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