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