11 A pixel is a set of channels defining the color at a given point in an
12 image. Conceptually, a pixel is little more than a color base whose
13 elements model ``ChannelConcept``. All properties of pixels inherit
14 from color bases: pixels may be *homogeneous* if all of their channels
15 have the same type; otherwise they are called *heterogeneous*. The
16 channels of a pixel may be addressed using semantic or physical
17 indexing, or by color; all color-base algorithms work on pixels as
18 well. Two pixels are *compatible* if their color spaces are the same
19 and their channels, paired semantically, are compatible. Note that
20 constness, memory organization and reference/value are ignored. For
21 example, an 8-bit RGB planar reference is compatible to a constant
22 8-bit BGR interleaved pixel value. Most pairwise pixel operations
23 (copy construction, assignment, equality, etc.) are only defined for
26 Pixels (as well as other GIL constructs built on pixels, such as
27 iterators, locators, views and images) must provide metafunctions to
28 access their color space, channel mapping, number of channels, and
29 (for homogeneous pixels) the channel type:
33 concept PixelBasedConcept<typename T>
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>;
46 concept HomogeneousPixelBasedConcept<PixelBasedConcept T>
48 typename channel_type<T>;
49 where Metafunction<channel_type<T> >;
50 where ChannelConcept<channel_type<T>::type>;
53 Pixels model the following concepts:
57 concept PixelConcept<typename P> : ColorBaseConcept<P>, PixelBasedConcept<P>
59 where is_pixel<P>::value==true;
60 // where for each K [0..size<P>::value-1]:
61 // ChannelConcept<kth_element_type<K> >;
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;
68 template <PixelConcept P2> where { PixelConcept<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&);
76 concept MutablePixelConcept<typename P> : PixelConcept<P>, MutableColorBaseConcept<P>
78 where is_mutable==true;
81 concept HomogeneousPixelConcept<PixelConcept P> : HomogeneousColorBaseConcept<P>, HomogeneousPixelBasedConcept<P>
83 P::template element_const_reference_type<P>::type operator[](P p, std::size_t i) const { return dynamic_at_c(P,i); }
86 concept MutableHomogeneousPixelConcept<MutablePixelConcept P> : MutableHomogeneousColorBaseConcept<P>
88 P::template element_reference_type<P>::type operator[](P p, std::size_t i) { return dynamic_at_c(p,i); }
91 concept PixelValueConcept<typename P> : PixelConcept<P>, Regular<P>
93 where SameType<value_type,P>;
96 concept PixelsCompatibleConcept<PixelConcept P1, PixelConcept P2> : ColorBasesCompatibleConcept<P1,P2>
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>;
102 A pixel is *convertible* to a second pixel if it is possible to
103 approximate its color in the form of the second pixel. Conversion is
104 an explicit, non-symmetric and often lossy operation (due to both
105 channel and color space approximation). Convertibility requires
106 modeling the following concept:
110 template <PixelConcept SrcPixel, MutablePixelConcept DstPixel>
111 concept PixelConvertibleConcept
113 void color_convert(const SrcPixel&, DstPixel&);
116 The distinction between ``PixelConcept`` and ``PixelValueConcept`` is
117 analogous to that for channels and color bases - pixel reference proxies model
118 both, but only pixel values model the latter.
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>`_
135 The most commonly used pixel is a homogeneous pixel whose values are
136 together in memory. For this purpose GIL provides the struct
137 ``pixel``, templated over the channel value and layout:
141 // models HomogeneousPixelValueConcept
142 template <typename ChannelValue, typename Layout> struct pixel;
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;
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
151 rgb8 = bgr8; // assignment and equality is defined between compatible pixels
152 assert(rgb8 == bgr8); // assignment and equality operate on the semantic channels
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)
159 Planar pixels have their channels distributed in memory. While they share the
160 same value type (``pixel``) with interleaved pixels, their reference type is a
161 proxy class containing references to each of the channels.
162 This is implemented with the struct ``planar_pixel_reference``:
166 // models HomogeneousPixel
167 template <typename ChannelReference, typename ColorSpace> struct planar_pixel_reference;
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;
173 Note that, unlike the ``pixel`` struct, planar pixel references are templated
174 over the color space, not over the pixel layout. They always use a canonical
175 channel ordering. Ordering of their elements is unnecessary because their
176 elements are references to the channels.
178 Sometimes the channels of a pixel may not be byte-aligned. For example an RGB
179 pixel in '5-5-6' format is a 16-bit pixel whose red, green and blue channels
180 occupy bits [0..4],[5..9] and [10..15] respectively. GIL provides a model for
181 such packed pixel formats:
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;
188 function_requires<PixelValueConcept<rgb565_pixel_t> >();
189 static_assert(sizeof(rgb565_pixel_t) == 2, "");
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;
194 function_requires<PixelValueConcept<bgr556_pixel_t> >();
196 // rgb565 is compatible with bgr556.
197 function_requires<PixelsCompatibleConcept<rgb565_pixel_t,bgr556_pixel_t> >();
199 In some cases, the pixel itself may not be byte aligned. For example,
200 consider an RGB pixel in '2-3-2' format. Its size is 7 bits. GIL
201 refers to such pixels, pixel iterators and images as
202 "bit-aligned". Bit-aligned pixels (and images) are more complex than
203 packed ones. Since packed pixels are byte-aligned, we can use a C++
204 reference as the reference type to a packed pixel, and a C pointer as
205 an x_iterator over a row of packed pixels. For bit-aligned constructs
206 we need a special reference proxy class (bit_aligned_pixel_reference)
207 and iterator class (bit_aligned_pixel_iterator). The value type of
208 bit-aligned pixels is a packed_pixel. Here is how to use bit_aligned
209 pixels and pixel iterators:
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;
216 // A mutable iterator over BGR232 pixels
217 typedef bit_aligned_pixel_iterator<bgr232_ref_t> bgr232_ptr_t;
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, "");
223 bgr232_pixel_t red(0,0,3); // = 0RRGGGBB, = 01100000 = 0x60
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);
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)
235 // Result: 0x60 0x30 0x11 0x0C 0x06 0x83 0xC1
240 Since pixels model ``ColorBaseConcept`` and ``PixelBasedConcept`` all
241 algorithms and metafunctions of color bases can work with them as well:
245 // This is how to access the first semantic channel (red)
246 assert(semantic_at_c<0>(rgb8) == semantic_at_c<0>(bgr8));
248 // This is how to access the red channel by name
249 assert(get_color<red_t>(rgb8) == get_color<red_t>(bgr8));
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()));
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> > ));
260 // Pixels contain just the three channels and nothing extra
261 BOOST_MPL_ASSERT(sizeof(rgb8_pixel_t)==3);
263 rgb8_planar_ref_t ref(bgr8); // copy construction is allowed from a compatible mutable pixel type
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
268 // Create a zero packed pixel and a full regular unpacked pixel.
270 rgb8_pixel_t rgb_full(255,255,255);
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));
278 GIL also provides the ``color_convert`` algorithm to convert between pixels of
279 different color spaces and channel types:
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);