3rdParty/boost/1.78.0/libs/gil/doc/html/design/pixel.html
A pixel is a set of channels defining the color at a given point in an image. Conceptually, a pixel is little more than a color base whose elements model ChannelConcept. All properties of pixels inherit from color bases: pixels may be homogeneous if all of their channels have the same type; otherwise they are called heterogeneous. The channels of a pixel may be addressed using semantic or physical indexing, or by color; all color-base algorithms work on pixels as well. Two pixels are compatible if their color spaces are the same and their channels, paired semantically, are compatible. Note that constness, memory organization and reference/value are ignored. For example, an 8-bit RGB planar reference is compatible to a constant 8-bit BGR interleaved pixel value. Most pairwise pixel operations (copy construction, assignment, equality, etc.) are only defined for compatible pixels.
Pixels (as well as other GIL constructs built on pixels, such as iterators, locators, views and images) must provide metafunctions to access their color space, channel mapping, number of channels, and (for homogeneous pixels) the channel type:
conceptPixelBasedConcept\<typenameT\>{typenamecolor\_space\_type\<T\>;whereMetafunction\<color\_space\_type\<T\>\>;whereColorSpaceConcept\<color\_space\_type\<T\>::type\>;typenamechannel\_mapping\_type\<T\>;whereMetafunction\<channel\_mapping\_type\<T\>\>;whereChannelMappingConcept\<channel\_mapping\_type\<T\>::type\>;typenameis\_planar\<T\>;whereMetafunction\<is\_planar\<T\>\>;whereSameType\<is\_planar\<T\>::type,bool\>;};conceptHomogeneousPixelBasedConcept\<PixelBasedConceptT\>{typenamechannel\_type\<T\>;whereMetafunction\<channel\_type\<T\>\>;whereChannelConcept\<channel\_type\<T\>::type\>;};
Pixels model the following concepts:
conceptPixelConcept\<typenameP\>:ColorBaseConcept\<P\>,PixelBasedConcept\<P\>{whereis\_pixel\<P\>::value==true;// where for each K [0..size\<P\>::value-1]:// ChannelConcept\<kth\_element\_type\<K\> \>;typenamevalue\_type;wherePixelValueConcept\<value\_type\>;typenamereference;wherePixelConcept\<reference\>;typenameconst\_reference;wherePixelConcept\<const\_reference\>;staticconstboolP::is\_mutable;template\<PixelConceptP2\>where{PixelConcept\<P,P2\>}P::P(P2);template\<PixelConceptP2\>where{PixelConcept\<P,P2\>}booloperator==(constP&,constP2&);template\<PixelConceptP2\>where{PixelConcept\<P,P2\>}booloperator!=(constP&,constP2&);};conceptMutablePixelConcept\<typenameP\>:PixelConcept\<P\>,MutableColorBaseConcept\<P\>{whereis\_mutable==true;};conceptHomogeneousPixelConcept\<PixelConceptP\>:HomogeneousColorBaseConcept\<P\>,HomogeneousPixelBasedConcept\<P\>{P::templateelement\_const\_reference\_type\<P\>::typeoperator[](Pp,std::size\_ti)const{returndynamic\_at\_c(P,i);}};conceptMutableHomogeneousPixelConcept\<MutablePixelConceptP\>:MutableHomogeneousColorBaseConcept\<P\>{P::templateelement\_reference\_type\<P\>::typeoperator[](Pp,std::size\_ti){returndynamic\_at\_c(p,i);}};conceptPixelValueConcept\<typenameP\>:PixelConcept\<P\>,Regular\<P\>{whereSameType\<value\_type,P\>;};conceptPixelsCompatibleConcept\<PixelConceptP1,PixelConceptP2\>:ColorBasesCompatibleConcept\<P1,P2\>{// where for each K [0..size\<P1\>::value):// ChannelsCompatibleConcept\<kth\_semantic\_element\_type\<P1,K\>::type, kth\_semantic\_element\_type\<P2,K\>::type\>;};
A pixel is convertible to a second pixel if it is possible to approximate its color in the form of the second pixel. Conversion is an explicit, non-symmetric and often lossy operation (due to both channel and color space approximation). Convertibility requires modeling the following concept:
template\<PixelConceptSrcPixel,MutablePixelConceptDstPixel\>conceptPixelConvertibleConcept{voidcolor\_convert(constSrcPixel&,DstPixel&);};
The distinction between PixelConcept and PixelValueConcept is analogous to that for channels and color bases - pixel reference proxies model both, but only pixel values model the latter.
See also
The most commonly used pixel is a homogeneous pixel whose values are together in memory. For this purpose GIL provides the struct pixel, templated over the channel value and layout:
// models HomogeneousPixelValueConcepttemplate\<typenameChannelValue,typenameLayout\>structpixel;// Those typedefs are already provided by GILtypedefpixel\<bits8,rgb\_layout\_t\>rgb8\_pixel\_t;typedefpixel\<bits8,bgr\_layout\_t\>bgr8\_pixel\_t;bgr8\_pixel\_tbgr8(255,0,0);// pixels can be initialized with the channels directlyrgb8\_pixel\_trgb8(bgr8);// compatible pixels can also be copy-constructedrgb8=bgr8;// assignment and equality is defined between compatible pixelsassert(rgb8==bgr8);// assignment and equality operate on the semantic channels// The first physical channels of the two pixels are differentassert(at\_c\<0\>(rgb8)!=at\_c\<0\>(bgr8));assert(dynamic\_at\_c(bgr8,0)!=dynamic\_at\_c(rgb8,0));assert(rgb8[0]!=bgr8[0]);// same as above (but operator[] is defined for pixels only)
Planar pixels have their channels distributed in memory. While they share the same value type (pixel) with interleaved pixels, their reference type is a proxy class containing references to each of the channels. This is implemented with the struct planar_pixel_reference:
// models HomogeneousPixeltemplate\<typenameChannelReference,typenameColorSpace\>structplanar\_pixel\_reference;// Define the type of a mutable and read-only reference. (These typedefs are already provided by GIL)typedefplanar\_pixel\_reference\<bits8&,rgb\_t\>rgb8\_planar\_ref\_t;typedefplanar\_pixel\_reference\<constbits8&,rgb\_t\>rgb8c\_planar\_ref\_t;
Note that, unlike the pixel struct, planar pixel references are templated over the color space, not over the pixel layout. They always use a canonical channel ordering. Ordering of their elements is unnecessary because their elements are references to the channels.
Sometimes the channels of a pixel may not be byte-aligned. For example an RGB pixel in ‘5-5-6’ format is a 16-bit pixel whose red, green and blue channels occupy bits [0..4],[5..9] and [10..15] respectively. GIL provides a model for such packed pixel formats:
// define an rgb565 pixeltypedefpacked\_pixel\_type\<uint16\_t,mpl::vector3\_c\<unsigned,5,6,5\>,rgb\_layout\_t\>::typergb565\_pixel\_t;function\_requires\<PixelValueConcept\<rgb565\_pixel\_t\>\>();static\_assert(sizeof(rgb565\_pixel\_t)==2,"");// define a bgr556 pixeltypedefpacked\_pixel\_type\<uint16\_t,mpl::vector3\_c\<unsigned,5,6,5\>,bgr\_layout\_t\>::typebgr556\_pixel\_t;function\_requires\<PixelValueConcept\<bgr556\_pixel\_t\>\>();// rgb565 is compatible with bgr556.function\_requires\<PixelsCompatibleConcept\<rgb565\_pixel\_t,bgr556\_pixel\_t\>\>();
In some cases, the pixel itself may not be byte aligned. For example, consider an RGB pixel in ‘2-3-2’ format. Its size is 7 bits. GIL refers to such pixels, pixel iterators and images as “bit-aligned”. Bit-aligned pixels (and images) are more complex than packed ones. Since packed pixels are byte-aligned, we can use a C++ reference as the reference type to a packed pixel, and a C pointer as an x_iterator over a row of packed pixels. For bit-aligned constructs we need a special reference proxy class (bit_aligned_pixel_reference) and iterator class (bit_aligned_pixel_iterator). The value type of bit-aligned pixels is a packed_pixel. Here is how to use bit_aligned pixels and pixel iterators:
// Mutable reference to a BGR232 pixeltypedefconstbit\_aligned\_pixel\_reference\<unsignedchar,mpl::vector3\_c\<unsigned,2,3,2\>,bgr\_layout\_t,true\>bgr232\_ref\_t;// A mutable iterator over BGR232 pixelstypedefbit\_aligned\_pixel\_iterator\<bgr232\_ref\_t\>bgr232\_ptr\_t;// BGR232 pixel value. It is a packed\_pixel of size 1 byte. (The last bit is unused)typedefstd::iterator\_traits\<bgr232\_ptr\_t\>::value\_typebgr232\_pixel\_t;static\_assert(sizeof(bgr232\_pixel\_t)==1,"");bgr232\_pixel\_tred(0,0,3);// = 0RRGGGBB, = 01100000 = 0x60// a buffer of 7 bytes fits exactly 8 BGR232 pixels.unsignedcharpix\_buffer[7];std::fill(pix\_buffer,pix\_buffer+7,0);// Fill the 8 pixels with redbgr232\_ptr\_tpix\_it(&pix\_buffer[0],0);// start at bit 0 of the first pixelfor(inti=0;i\<8;++i){\*pix\_it++=red;}// Result: 0x60 0x30 0x11 0x0C 0x06 0x83 0xC1
Since pixels model ColorBaseConcept and PixelBasedConcept all algorithms and metafunctions of color bases can work with them as well:
// This is how to access the first semantic channel (red)assert(semantic\_at\_c\<0\>(rgb8)==semantic\_at\_c\<0\>(bgr8));// This is how to access the red channel by nameassert(get\_color\<red\_t\>(rgb8)==get\_color\<red\_t\>(bgr8));// This is another way of doing it (some compilers don't like the first one)assert(get\_color(rgb8,red\_t())==get\_color(bgr8,red\_t()));// This is how to use the PixelBasedConcept metafunctionsBOOST\_MPL\_ASSERT(num\_channels\<rgb8\_pixel\_t\>::value==3);BOOST\_MPL\_ASSERT((is\_same\<channel\_type\<rgb8\_pixel\_t\>::type,bits8\>));BOOST\_MPL\_ASSERT((is\_same\<color\_space\_type\<bgr8\_pixel\_t\>::type,rgb\_t\>));BOOST\_MPL\_ASSERT((is\_same\<channel\_mapping\_type\<bgr8\_pixel\_t\>::type,mpl::vector3\_c\<int,2,1,0\>\>));// Pixels contain just the three channels and nothing extraBOOST\_MPL\_ASSERT(sizeof(rgb8\_pixel\_t)==3);rgb8\_planar\_ref\_tref(bgr8);// copy construction is allowed from a compatible mutable pixel typeget\_color\<red\_t\>(ref)=10;// assignment is ok because the reference is mutableassert(get\_color\<red\_t\>(bgr8)==10);// references modify the value they are bound to// Create a zero packed pixel and a full regular unpacked pixel.rgb565\_pixel\_tr565;rgb8\_pixel\_trgb\_full(255,255,255);// Convert all channels of the unpacked pixel to the packed one & assert the packed one is fullget\_color(r565,red\_t())=channel\_convert\<rgb565\_channel0\_t\>(get\_color(rgb\_full,red\_t()));get\_color(r565,green\_t())=channel\_convert\<rgb565\_channel1\_t\>(get\_color(rgb\_full,green\_t()));get\_color(r565,blue\_t())=channel\_convert\<rgb565\_channel2\_t\>(get\_color(rgb\_full,blue\_t()));assert(r565==rgb565\_pixel\_t((uint16\_t)65535));
GIL also provides the color_convert algorithm to convert between pixels of different color spaces and channel types:
rgb8\_pixel\_tred\_in\_rgb8(255,0,0);cmyk16\_pixel\_tred\_in\_cmyk16;color\_convert(red\_in\_rgb8,red\_in\_cmyk16);