UNPKG

boost-react-native-bundle

Version:

Boost library as in https://sourceforge.net/projects/boost/files/boost/1.57.0/

468 lines (417 loc) 213 kB
<!-- Copyright 2008 Lubomir Bourdev and Hailin Jin Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) --> <!-- Copyright 2005-2007 Adobe Systems Incorporated Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt or a copy at http://stlab.adobe.com/licenses.html) Some files are held under additional license. Please see "http://stlab.adobe.com/licenses.html" for more information. --> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <TITLE>Generic Image Library: Generic Image Library Design Guide</TITLE> <META HTTP-EQUIV="content-type" CONTENT="text/html;charset=ISO-8859-1"/> <LINK TYPE="text/css" REL="stylesheet" HREF="adobe_source.css"/> </head> <body> <table border="0" cellspacing="0" cellpadding="0" style='width: 100%; margin: 0; padding: 0'><tr> <td width="100%" valign="top" style='padding-left: 10px; padding-right: 10px; padding-bottom: 10px'> <div class="qindex"><a class="qindex" href="index.html">Modules</a> | <a class="qindex" href="classes.html">Alphabetical List</a> | <a class="qindex" href="annotated.html">Class List</a> | <a class="qindex" href="dirs.html">Directories</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="../index.html">GIL Home Page</a> </div> <!-- End Header --> <!-- Generated by Doxygen 1.5.6 --> <div class="contents"> <h1><a class="anchor" name="GILDesignGuide">Generic Image Library Design Guide </a></h1><dl class="author" compact><dt><b>Author:</b></dt><dd>Lubomir Bourdev (<a href="mailto:lbourdev@adobe.com">lbourdev@adobe.com</a>) and Hailin Jin (<a href="mailto:hljin@adobe.com">hljin@adobe.com</a>) <br> Adobe Systems Incorporated </dd></dl> <dl class="version" compact><dt><b>Version:</b></dt><dd>2.1 </dd></dl> <dl class="date" compact><dt><b>Date:</b></dt><dd>September 15, 2007</dd></dl> <p> This document describes the design of the Generic Image Library, a C++ image-processing library that abstracts image representation from algorithms on images. It covers more than you need to know for a causal use of GIL. You can find a quick, jump-start GIL tutorial on the main GIL page at <a href="http://stlab.adobe.com/gil">http://stlab.adobe.com/gil</a><p> <ul> <li><a class="el" href="gildesignguide.html#OverviewSectionDG">1. Overview</a></li><li><a class="el" href="gildesignguide.html#ConceptsSectionDG">2. About Concepts</a></li><li><a class="el" href="gildesignguide.html#PointSectionDG">3. Point</a></li><li><a class="el" href="gildesignguide.html#ChannelSectionDG">4. Channel</a></li><li><a class="el" href="gildesignguide.html#ColorSpaceSectionDG">5. Color Space and Layout</a></li><li><a class="el" href="gildesignguide.html#ColorBaseSectionDG">6. Color Base</a></li><li><a class="el" href="gildesignguide.html#PixelSectionDG">7. Pixel</a></li><li><a class="el" href="gildesignguide.html#PixelIteratorSectionDG">8. Pixel Iterator</a><ul> <li><a class="el" href="gildesignguide.html#FundamentalIteratorDG">Fundamental Iterator</a></li><li><a class="el" href="gildesignguide.html#IteratorAdaptorDG">Iterator Adaptor</a></li><li><a class="el" href="gildesignguide.html#PixelDereferenceAdaptorAG">Pixel Dereference Adaptor</a></li><li><a class="el" href="gildesignguide.html#StepIteratorDG">Step Iterator</a></li><li><a class="el" href="gildesignguide.html#LocatorDG">Pixel Locator</a></li><li><a class="el" href="gildesignguide.html#IteratorFrom2DDG">Iterator over 2D image</a></li></ul> </li><li><a class="el" href="gildesignguide.html#ImageViewSectionDG">9. Image View</a><ul> <li><a class="el" href="gildesignguide.html#ImageViewFrowRawDG">Creating Views from Raw Pixels</a></li><li><a class="el" href="gildesignguide.html#ImageViewFrowImageViewDG">Creating Image Views from Other Image Views</a></li></ul> </li><li><a class="el" href="gildesignguide.html#ImageSectionDG">10. Image</a></li><li><a class="el" href="gildesignguide.html#VariantSecDG">11. Run-time specified images and image views</a></li><li><a class="el" href="gildesignguide.html#MetafunctionsDG">12. Useful Metafunctions and Typedefs</a></li><li><a class="el" href="gildesignguide.html#IO_DG">13. I/O Extension</a></li><li><a class="el" href="gildesignguide.html#SampleImgCodeDG">14. Sample Code</a><ul> <li><a class="el" href="gildesignguide.html#PixelLevelExampleDG">Pixel-level Sample Code</a></li><li><a class="el" href="gildesignguide.html#SafeAreaExampleDG">Creating a Copy of an Image with a Safe Buffer</a></li><li><a class="el" href="gildesignguide.html#HistogramExampleDG">Histogram</a></li><li><a class="el" href="gildesignguide.html#ImageViewsExampleDG">Using Image Views</a></li></ul> </li><li><a class="el" href="gildesignguide.html#ExtendingGIL_DG">15. Extending the Generic Image Library</a><ul> <li><a class="el" href="gildesignguide.html#NewColorSpacesDG">Defining New Color Spaces</a></li><li><a class="el" href="gildesignguide.html#NewColorConversionDG">Overloading Color Conversion</a></li><li><a class="el" href="gildesignguide.html#NewChannelsDG">Defining New Channel Types</a></li><li><a class="el" href="gildesignguide.html#NewImagesDG">Defining New Image Views</a></li></ul> </li><li><a class="el" href="gildesignguide.html#TechnicalitiesDG">16. Technicalities</a></li><li><a class="el" href="gildesignguide.html#ConclusionDG">17. Conclusion</a></li></ul> <p> <br> <hr> <h2><a class="anchor" name="OverviewSectionDG"> 1. Overview</a></h2> Images are essential in any image processing, vision and video project, and yet the variability in image representations makes it difficult to write imaging algorithms that are both generic and efficient. In this section we will describe some of the challenges that we would like to address.<p> In the following discussion an <em>image</em> is a 2D array of pixels. A <em>pixel</em> is a set of color channels that represents the color at a given point in an image. Each <em>channel</em> represents the value of a color component. There are two common memory structures for an image. <em>Interleaved</em> images are represented by grouping the pixels together in memory and interleaving all channels together, whereas <em>planar</em> images keep the channels in separate color planes. Here is a 4x3 RGB image in which the second pixel of the first row is marked in red, in interleaved form:<p> <div align="center"> <img src="interleaved.jpg" alt="interleaved.jpg"> </div> and in planar form:<p> <div align="center"> <img src="planar.jpg" alt="planar.jpg"> </div> <p> Note also that rows may optionally be aligned resulting in a potential padding at the end of rows. <p> The Generic Image Library (GIL) provides models for images that vary in:<ul> <li>Structure (planar vs. interleaved)</li><li>Color space and presence of alpha (RGB, RGBA, CMYK, etc.)</li><li>Channel depth (8-bit, 16-bit, etc.)</li><li>Order of channels (RGB vs. BGR, etc.)</li><li>Row alignment policy (no alignment, word-alignment, etc.)</li></ul> <p> It also supports user-defined models of images, and images whose parameters are specified at run-time. GIL abstracts image representation from algorithms applied on images and allows us to write the algorithm once and have it work on any of the above image variations while generating code that is comparable in speed to that of hand-writing the algorithm for a specific image type.<p> This document follows bottom-up design. Each section defines concepts that build on top of concepts defined in previous sections. It is recommended to read the sections in order.<p> <hr> <h2><a class="anchor" name="ConceptsSectionDG"> 2. About Concepts</a></h2> All constructs in GIL are models of GIL concepts. A <em>concept</em> is a set of requirements that a type (or a set of related types) must fulfill to be used correctly in generic algorithms. The requirements include syntactic and algorithming guarantees. For example, GIL's class <code>pixel</code> is a model of GIL's <code>PixelConcept</code>. The user may substitute the pixel class with one of their own, and, as long as it satisfies the requirements of <code>PixelConcept</code>, all other GIL classes and algorithms can be used with it. See more about concepts here: <a href="http://www.generic-programming.org/languages/conceptcpp/">http://www.generic-programming.org/languages/conceptcpp/</a><p> In this document we will use a syntax for defining concepts that is described in a proposal for a Concepts extension to C++0x specified here: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf</a><p> Here are some common concepts that will be used in GIL. Most of them are defined here: <a href="http://www.generic-programming.org/languages/conceptcpp/concept_web.php">http://www.generic-programming.org/languages/conceptcpp/concept_web.php</a><p> <div class="fragment"><pre class="fragment"><span class="keyword">auto</span> concept DefaultConstructible&lt;typename T&gt; { T::T(); }; <span class="keyword">auto</span> concept CopyConstructible&lt;typename T&gt; { T::T(T); T::~T(); }; <span class="keyword">auto</span> concept Assignable&lt;typename T, typename U = T&gt; { <span class="keyword">typename</span> result_type; result_type operator=(T&amp;, U); }; <span class="keyword">auto</span> concept EqualityComparable&lt;typename T, typename U = T&gt; { <span class="keywordtype">bool</span> operator==(T x, T y); <span class="keywordtype">bool</span> operator!=(T x, T y) { <span class="keywordflow">return</span> !(x==y); } }; concept SameType&lt;typename T, typename U&gt; { <span class="comment">/* unspecified */</span> }; <span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt; concept_map SameType&lt;T, T&gt; { <span class="comment">/* unspecified */</span> }; <span class="keyword">auto</span> concept Swappable&lt;typename T&gt; { <span class="keywordtype">void</span> swap(T&amp; t, T&amp; u); }; </pre></div><p> Here are some additional basic concepts that GIL needs:<p> <div class="fragment"><pre class="fragment"><span class="keyword">auto</span> concept Regular&lt;typename T&gt; : DefaultConstructible&lt;T&gt;, CopyConstructible&lt;T&gt;, EqualityComparable&lt;T&gt;, Assignable&lt;T&gt;, Swappable&lt;T&gt; {}; <span class="keyword">auto</span> concept Metafunction&lt;typename T&gt; { <span class="keyword">typename</span> type; }; </pre></div><h2><a class="anchor" name="PointSectionDG"> 3. Point</a></h2> A point defines the location of a pixel inside an image. It can also be used to describe the dimensions of an image. In most general terms, points are N-dimensional and model the following concept:<p> <div class="fragment"><pre class="fragment">concept PointNDConcept&lt;typename T&gt; : Regular&lt;T&gt; { <span class="comment">// the type of a coordinate along each axis</span> <span class="keyword">template</span> &lt;<span class="keywordtype">size_t</span> K&gt; <span class="keyword">struct </span>axis; where Metafunction&lt;axis&gt;; <span class="keyword">const</span> <span class="keywordtype">size_t</span> num_dimensions; <span class="comment">// accessor/modifier of the value of each axis.</span> <span class="keyword">template</span> &lt;<span class="keywordtype">size_t</span> K&gt; <span class="keyword">const</span> <span class="keyword">typename</span> axis&lt;K&gt;::type&amp; T::axis_value() <span class="keyword">const</span>; <span class="keyword">template</span> &lt;<span class="keywordtype">size_t</span> K&gt; <span class="keyword">typename</span> axis&lt;K&gt;::type&amp; T::axis_value(); }; </pre></div><p> GIL uses a two-dimensional point, which is a refinement of <code>PointNDConcept</code> in which both dimensions are of the same type:<p> <div class="fragment"><pre class="fragment">concept Point2DConcept&lt;typename T&gt; : PointNDConcept&lt;T&gt; { where num_dimensions == 2; where SameType&lt;axis&lt;0&gt;::type, axis&lt;1&gt;::type&gt;; <span class="keyword">typename</span> value_type = axis&lt;0&gt;::type; <span class="keyword">const</span> value_type&amp; operator[](<span class="keyword">const</span> T&amp;, <span class="keywordtype">size_t</span> i); value_type&amp; operator[]( T&amp;, <span class="keywordtype">size_t</span> i); value_type x,y; }; </pre></div><p> <b>Related Concepts:</b><p> <ul> <li>PointNDConcept&lt;T&gt;</li><li>Point2DConcept&lt;T&gt;</li></ul> <p> <b>Models:</b><p> GIL provides a model of <code>Point2DConcept</code>, <code>point2&lt;T&gt;</code> where <code>T</code> is the coordinate type.<p> <hr> <h2><a class="anchor" name="ChannelSectionDG"> 4. Channel</a></h2> A channel indicates the intensity of a color component (for example, the red channel in an RGB pixel). Typical channel operations are getting, comparing and setting the channel values. Channels have associated minimum and maximum value. GIL channels model the following concept:<p> <div class="fragment"><pre class="fragment">concept ChannelConcept&lt;typename T&gt; : EqualityComparable&lt;T&gt; { <span class="keyword">typename</span> value_type = T; <span class="comment">// use channel_traits&lt;T&gt;::value_type to access it</span> where ChannelValueConcept&lt;value_type&gt;; <span class="keyword">typename</span> reference = T&amp;; <span class="comment">// use channel_traits&lt;T&gt;::reference to access it</span> <span class="keyword">typename</span> pointer = T*; <span class="comment">// use channel_traits&lt;T&gt;::pointer to access it</span> <span class="keyword">typename</span> const_reference = <span class="keyword">const</span> T&amp;; <span class="comment">// use channel_traits&lt;T&gt;::const_reference to access it</span> <span class="keyword">typename</span> const_pointer = <span class="keyword">const</span> T*; <span class="comment">// use channel_traits&lt;T&gt;::const_pointer to access it</span> <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">bool</span> is_mutable; <span class="comment">// use channel_traits&lt;T&gt;::is_mutable to access it</span> <span class="keyword">static</span> T min_value(); <span class="comment">// use channel_traits&lt;T&gt;::min_value to access it</span> <span class="keyword">static</span> T max_value(); <span class="comment">// use channel_traits&lt;T&gt;::min_value to access it</span> }; concept MutableChannelConcept&lt;ChannelConcept T&gt; : Swappable&lt;T&gt;, Assignable&lt;T&gt; {}; concept ChannelValueConcept&lt;ChannelConcept T&gt; : Regular&lt;T&gt; {}; </pre></div><p> GIL allows built-in integral and floating point types to be channels. Therefore the associated types and range information are defined in <code>channel_traits</code> with the following default implementation:<p> <div class="fragment"><pre class="fragment"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt; <span class="keyword">struct </span>channel_traits { <span class="keyword">typedef</span> T value_type; <span class="keyword">typedef</span> T&amp; reference; <span class="keyword">typedef</span> T* pointer; <span class="keyword">typedef</span> T&amp; <span class="keyword">const</span> const_reference; <span class="keyword">typedef</span> T* <span class="keyword">const</span> const_pointer; <span class="keyword">static</span> value_type min_value() { <span class="keywordflow">return</span> std::numeric_limits&lt;T&gt;::min(); } <span class="keyword">static</span> value_type max_value() { <span class="keywordflow">return</span> std::numeric_limits&lt;T&gt;::max(); } }; </pre></div><p> Two channel types are <em>compatible</em> if they have the same value type:<p> <div class="fragment"><pre class="fragment">concept ChannelsCompatibleConcept&lt;ChannelConcept T1, ChannelConcept T2&gt; { where SameType&lt;T1::value_type, T2::value_type&gt;; }; </pre></div><p> A channel may be <em>convertible</em> to another channel:<p> <div class="fragment"><pre class="fragment"><span class="keyword">template</span> &lt;ChannelConcept Src, ChannelValueConcept Dst&gt; concept ChannelConvertibleConcept { Dst <a class="code" href="g_i_l_0099.html#gf04e6ac30a35a1f68a8bb84730e34786" title="Converting from one channel type to another.">channel_convert</a>(Src); }; </pre></div><p> Note that <code>ChannelConcept</code> and <code>MutableChannelConcept</code> do not require a default constructor. Channels that also support default construction (and thus are regular types) model <code>ChannelValueConcept</code>. To understand the motivation for this distinction, consider a 16-bit RGB pixel in a "565" bit pattern. Its channels correspond to bit ranges. To support such channels, we need to create a custom proxy class corresponding to a reference to a subbyte channel. Such a proxy reference class models only <code>ChannelConcept</code>, because, similar to native C++ references, it may not have a default constructor.<p> Note also that algorithms may impose additional requirements on channels, such as support for arithmentic operations.<p> <b>Related Concepts:</b><p> <ul> <li>ChannelConcept&lt;T&gt;</li><li>ChannelValueConcept&lt;T&gt;</li><li>MutableChannelConcept&lt;T&gt;</li><li>ChannelsCompatibleConcept&lt;T1,T2&gt;</li><li>ChannelConvertibleConcept&lt;SrcChannel,DstChannel&gt;</li></ul> <p> <b>Models:</b><p> All built-in integral and floating point types are valid channels. GIL provides standard typedefs for some integral channels:<p> <div class="fragment"><pre class="fragment"><span class="keyword">typedef</span> boost::uint8_t bits8; <span class="keyword">typedef</span> boost::uint16_t bits16; <span class="keyword">typedef</span> boost::uint32_t bits32; <span class="keyword">typedef</span> boost::int8_t bits8s; <span class="keyword">typedef</span> boost::int16_t bits16s; <span class="keyword">typedef</span> boost::int32_t bits32s; </pre></div><p> The minimum and maximum values of a channel modeled by a built-in type correspond to the minimum and maximum physical range of the built-in type, as specified by its <code>std::numeric_limits</code>. Sometimes the physical range is not appropriate. GIL provides <code>scoped_channel_value</code>, a model for a channel adapter that allows for specifying a custom range. We use it to define a [0..1] floating point channel type as follows:<p> <div class="fragment"><pre class="fragment"><span class="keyword">struct </span>float_zero { <span class="keyword">static</span> <span class="keywordtype">float</span> apply() { <span class="keywordflow">return</span> 0.0f; } }; <span class="keyword">struct </span>float_one { <span class="keyword">static</span> <span class="keywordtype">float</span> apply() { <span class="keywordflow">return</span> 1.0f; } }; <span class="keyword">typedef</span> scoped_channel_value&lt;float,float_zero,float_one&gt; bits32f; </pre></div><p> GIL also provides models for channels corresponding to ranges of bits:<p> <div class="fragment"><pre class="fragment"><span class="comment">// Value of a channel defined over NumBits bits. Models ChannelValueConcept</span> <span class="keyword">template</span> &lt;<span class="keywordtype">int</span> NumBits&gt; <span class="keyword">class </span>packed_channel_value; <span class="comment">// Reference to a channel defined over NumBits bits. Models ChannelConcept</span> <span class="keyword">template</span> &lt;<span class="keywordtype">int</span> FirstBit, <span class="keywordtype">int</span> NumBits, <span class="comment">// Defines the sequence of bits in the data value that contain the channel </span> <span class="keywordtype">bool</span> Mutable&gt; <span class="comment">// true if the reference is mutable </span> <span class="keyword">class </span>packed_channel_reference; <span class="comment">// Reference to a channel defined over NumBits bits. Its FirstBit is a run-time parameter. Models ChannelConcept</span> <span class="keyword">template</span> &lt;<span class="keywordtype">int</span> NumBits, <span class="comment">// Defines the sequence of bits in the data value that contain the channel </span> <span class="keywordtype">bool</span> Mutable&gt; <span class="comment">// true if the reference is mutable </span> <span class="keyword">class </span>packed_dynamic_channel_reference; </pre></div><p> Note that there are two models of a reference proxy which differ based on whether the offset of the channel range is specified as a template or a run-time parameter. The first model is faster and more compact while the second model is more flexible. For example, the second model allows us to construct an iterator over bitrange channels.<p> <b>Algorithms:</b><p> Here is how to construct the three channels of a 16-bit "565" pixel and set them to their maximum value:<p> <div class="fragment"><pre class="fragment"><span class="keyword">typedef</span> packed_channel_reference&lt;0,5,true&gt; channel16_0_5_reference_t; <span class="keyword">typedef</span> packed_channel_reference&lt;5,6,true&gt; channel16_5_6_reference_t; <span class="keyword">typedef</span> packed_channel_reference&lt;11,5,true&gt; channel16_11_5_reference_t; boost::uint16_t data=0; channel16_0_5_reference_t channel1(&amp;data); channel16_5_6_reference_t channel2(&amp;data); channel16_11_5_reference_t channel3(&amp;data); channel1=channel_traits&lt;channel16_0_5_reference_t&gt;::max_value(); channel2=channel_traits&lt;channel16_5_6_reference_t&gt;::max_value(); channel3=channel_traits&lt;channel16_11_5_reference_t&gt;::max_value(); assert(data==65535); </pre></div><p> Assignment, equality comparison and copy construction are defined only between compatible channels:<p> <div class="fragment"><pre class="fragment">packed_channel_value&lt;5&gt; channel_6bit = channel1; channel_6bit = channel3; <span class="comment">//channel_6bit = channel2; // compile error: Assignment between incompatible channels.</span> </pre></div><p> All channel models provided by GIL are pairwise convertible:<p> <div class="fragment"><pre class="fragment">channel1 = channel_traits&lt;channel16_0_5_reference_t&gt;::max_value(); assert(channel1 == 31); bits16 chan16 = channel_convert&lt;bits16&gt;(channel1); assert(chan16 == 65535); </pre></div><p> Channel conversion is a lossy operation. GIL's channel conversion is a linear transformation between the ranges of the source and destination channel. It maps precisely the minimum to the minimum and the maximum to the maximum. (For example, to convert from uint8_t to uint16_t GIL does not do a bit shift because it will not properly match the maximum values. Instead GIL multiplies the source by 257).<p> All channel models that GIL provides are convertible from/to an integral or floating point type. Thus they support arithmetic operations. Here are the channel-level algorithms that GIL provides:<p> <div class="fragment"><pre class="fragment"><span class="comment">// Converts a source channel value into a destrination channel. Linearly maps the value of the source</span> <span class="comment">// into the range of the destination</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> DstChannel, <span class="keyword">typename</span> SrcChannel&gt; <span class="keyword">typename</span> channel_traits&lt;DstChannel&gt;::value_type <a class="code" href="g_i_l_0099.html#gf04e6ac30a35a1f68a8bb84730e34786" title="Converting from one channel type to another.">channel_convert</a>(SrcChannel src); <span class="comment">// returns max_value - x + min_value</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> Channel&gt; <span class="keyword">typename</span> channel_traits&lt;Channel&gt;::value_type <a class="code" href="g_i_l_0101.html#ge2e0267865f89610ef26148874a04bb5" title="Default implementation. Provide overloads for performance.">channel_invert</a>(Channel x); <span class="comment">// returns a * b / max_value</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> Channel&gt; <span class="keyword">typename</span> channel_traits&lt;Channel&gt;::value_type <a class="code" href="g_i_l_0103.html#gf73b2a47a7877767534df0eee46dda17" title="A function multiplying two channels. result = a * b / max_value.">channel_multiply</a>(Channel a, Channel b); </pre></div><p> <hr> <h2><a class="anchor" name="ColorSpaceSectionDG"> 5. Color Space and Layout</a></h2> A color space captures the set and interpretation of channels comprising a pixel. It is an MPL random access sequence containing the types of all elements in the color space. Two color spaces are considered <em>compatible</em> if they are equal (i.e. have the same set of colors in the same order).<p> <b>Related Concepts:</b><p> <ul> <li>ColorSpaceConcept&lt;ColorSpace&gt;</li><li>ColorSpacesCompatibleConcept&lt;ColorSpace1,ColorSpace2&gt;</li><li>ChannelMappingConcept&lt;Mapping&gt;</li></ul> <p> <b>Models:</b><p> GIL currently provides the following color spaces: <code>gray_t</code>, <code>rgb_t</code>, <code>rgba_t</code>, and <code>cmyk_t</code>. It also provides unnamed N-channel color spaces of two to five channels, <code>devicen_t&lt;2&gt;</code>, <code>devicen_t&lt;3&gt;</code>, <code>devicen_t&lt;4&gt;</code>, <code>devicen_t&lt;5&gt;</code>. Besides the standard layouts, it provides <code>bgr_layout_t</code>, <code>bgra_layout_t</code>, <code>abgr_layout_t</code> and <code>argb_layout_t</code>.<p> As an example, here is how GIL defines the RGBA color space:<p> <div class="fragment"><pre class="fragment"><span class="keyword">struct </span>red_t{}; <span class="keyword">struct </span>green_t{}; <span class="keyword">struct </span>blue_t{}; <span class="keyword">struct </span>alpha_t{}; <span class="keyword">typedef</span> mpl::vector4&lt;red_t,green_t,blue_t,alpha_t&gt; rgba_t; </pre></div><p> The ordering of the channels in the color space definition specifies their semantic order. For example, <code>red_t</code> is the first semantic channel of <code>rgba_t</code>. While there is a unique semantic ordering of the channels in a color space, channels may vary in their physical ordering in memory. The mapping of channels is specified by <code>ChannelMappingConcept</code>, which is an MPL random access sequence of integral types. A color space and its associated mapping are often used together. Thus they are grouped in GIL's layout:<p> <div class="fragment"><pre class="fragment"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> ColorSpace, <span class="keyword">typename</span> ChannelMapping = mpl::range_c&lt;int,0,mpl::size&lt;ColorSpace&gt;::value&gt; &gt; <span class="keyword">struct </span>layout { <span class="keyword">typedef</span> ColorSpace color_space_t; <span class="keyword">typedef</span> ChannelMapping channel_mapping_t; }; </pre></div><p> Here is how to create layouts for the RGBA color space:<p> <div class="fragment"><pre class="fragment"><span class="keyword">typedef</span> layout&lt;rgba_t&gt; rgba_layout_t; <span class="comment">// default ordering is 0,1,2,3...</span> <span class="keyword">typedef</span> layout&lt;rgba_t, mpl::vector4_c&lt;int,2,1,0,3&gt; &gt; bgra_layout_t; <span class="keyword">typedef</span> layout&lt;rgba_t, mpl::vector4_c&lt;int,1,2,3,0&gt; &gt; argb_layout_t; <span class="keyword">typedef</span> layout&lt;rgba_t, mpl::vector4_c&lt;int,3,2,1,0&gt; &gt; abgr_layout_t; </pre></div><p> <hr> <h2><a class="anchor" name="ColorBaseSectionDG"> 6. Color Base</a></h2> A color base is a container of color elements. The most common use of color base is in the implementation of a pixel, in which case the color elements are channel values. The color base concept, however, can be used in other scenarios. For example, a planar pixel has channels that are not contiguous in memory. Its reference is a proxy class that uses a color base whose elements are channel references. Its iterator uses a color base whose elements are channel iterators.<p> Color base models must satisfy the following concepts:<p> <div class="fragment"><pre class="fragment">concept ColorBaseConcept&lt;typename T&gt; : CopyConstructible&lt;T&gt;, EqualityComparable&lt;T&gt; { <span class="comment">// a GIL layout (the color space and element permutation)</span> <span class="keyword">typename</span> layout_t; <span class="comment">// The type of K-th element</span> <span class="keyword">template</span> &lt;<span class="keywordtype">int</span> K&gt; <span class="keyword">struct </span>kth_element_type; where Metafunction&lt;kth_element_type&gt;; <span class="comment">// The result of at_c</span> <span class="keyword">template</span> &lt;<span class="keywordtype">int</span> K&gt; <span class="keyword">struct </span>kth_element_const_reference_type; where Metafunction&lt;kth_element_const_reference_type&gt;; <span class="keyword">template</span> &lt;<span class="keywordtype">int</span> K&gt; kth_element_const_reference_type&lt;T,K&gt;::type at_c(T); <span class="keyword">template</span> &lt;ColorBaseConcept T2&gt; where { ColorBasesCompatibleConcept&lt;T,T2&gt; } T::T(T2); <span class="keyword">template</span> &lt;ColorBaseConcept T2&gt; where { ColorBasesCompatibleConcept&lt;T,T2&gt; } <span class="keywordtype">bool</span> operator==(<span class="keyword">const</span> T&amp;, <span class="keyword">const</span> T2&amp;); <span class="keyword">template</span> &lt;ColorBaseConcept T2&gt; where { ColorBasesCompatibleConcept&lt;T,T2&gt; } <span class="keywordtype">bool</span> operator!=(<span class="keyword">const</span> T&amp;, <span class="keyword">const</span> T2&amp;); }; concept MutableColorBaseConcept&lt;ColorBaseConcept T&gt; : Assignable&lt;T&gt;, Swappable&lt;T&gt; { <span class="keyword">template</span> &lt;<span class="keywordtype">int</span> K&gt; <span class="keyword">struct </span>kth_element_reference_type; where Metafunction&lt;kth_element_reference_type&gt;; <span class="keyword">template</span> &lt;<span class="keywordtype">int</span> K&gt; kth_element_reference_type&lt;T,K&gt;::type at_c(T); <span class="keyword">template</span> &lt;ColorBaseConcept T2&gt; where { ColorBasesCompatibleConcept&lt;T,T2&gt; } T&amp; operator=(T&amp;, <span class="keyword">const</span> T2&amp;); }; concept ColorBaseValueConcept&lt;typename T&gt; : MutableColorBaseConcept&lt;T&gt;, Regular&lt;T&gt; { }; concept HomogeneousColorBaseConcept&lt;ColorBaseConcept CB&gt; { <span class="comment">// For all K in [0 ... size&lt;C1&gt;::value-1):</span> <span class="comment">// where SameType&lt;kth_element_type&lt;K&gt;::type, kth_element_type&lt;K+1&gt;::type&gt;; </span> kth_element_const_reference_type&lt;0&gt;::type dynamic_at_c(<span class="keyword">const</span> CB&amp;, std::size_t n) <span class="keyword">const</span>; }; concept MutableHomogeneousColorBaseConcept&lt;MutableColorBaseConcept CB&gt; : HomogeneousColorBaseConcept&lt;CB&gt; { kth_element_reference_type&lt;0&gt;::type dynamic_at_c(<span class="keyword">const</span> CB&amp;, std::size_t n); }; concept HomogeneousColorBaseValueConcept&lt;typename T&gt; : MutableHomogeneousColorBaseConcept&lt;T&gt;, Regular&lt;T&gt; { }; concept ColorBasesCompatibleConcept&lt;ColorBaseConcept C1, ColorBaseConcept C2&gt; { where SameType&lt;C1::layout_t::color_space_t, C2::layout_t::color_space_t&gt;; <span class="comment">// also, for all K in [0 ... size&lt;C1&gt;::value):</span> <span class="comment">// where Convertible&lt;kth_semantic_element_type&lt;C1,K&gt;::type, kth_semantic_element_type&lt;C2,K&gt;::type&gt;;</span> <span class="comment">// where Convertible&lt;kth_semantic_element_type&lt;C2,K&gt;::type, kth_semantic_element_type&lt;C1,K&gt;::type&gt;;</span> }; </pre></div><p> A color base must have an associated layout (which consists of a color space, as well as an ordering of the channels). There are two ways to index the elements of a color base: A physical index corresponds to the way they are ordered in memory, and a semantic index corresponds to the way the elements are ordered in their color space. For example, in the RGB color space the elements are ordered as {red_t, green_t, blue_t}. For a color base with a BGR layout, the first element in physical ordering is the blue element, whereas the first semantic element is the red one. Models of <code>ColorBaseConcept</code> are required to provide the <code>at_c&lt;K&gt;(ColorBase)</code> function, which allows for accessing the elements based on their physical order. GIL provides a <code>semantic_at_c&lt;K&gt;(ColorBase)</code> function (described later) which can operate on any model of ColorBaseConcept and returns the corresponding semantic element.<p> Two color bases are <em>compatible</em> if they have the same color space and their elements (paired semantically) are convertible to each other.<p> <b>Models:</b><p> GIL provides a model for a homogeneous color base (a color base whose elements all have the same type).<p> <div class="fragment"><pre class="fragment"><span class="keyword">namespace </span>detail { <span class="keyword">template</span> &lt;<span class="keyword">typename</span> Element, <span class="keyword">typename</span> Layout, <span class="keywordtype">int</span> K&gt; <span class="keyword">struct </span>homogeneous_color_base; } </pre></div><p> It is used in the implementation of GIL's pixel, planar pixel reference and planar pixel iterator. Another model of <code>ColorBaseConcept</code> is <code>packed_pixel</code> - it is a pixel whose channels are bit ranges. See the <a class="el" href="gildesignguide.html#PixelSectionDG">7. Pixel</a> section for more.<p> <b>Algorithms:</b><p> GIL provides the following functions and metafunctions operating on color bases:<p> <div class="fragment"><pre class="fragment"><span class="comment">// Metafunction returning an mpl::int_ equal to the number of elements in the color base</span> <span class="keyword">template</span> &lt;<span class="keyword">class</span> ColorBase&gt; <span class="keyword">struct </span>size; <span class="comment">// Returns the type of the return value of semantic_at_c&lt;K&gt;(color_base)</span> <span class="keyword">template</span> &lt;<span class="keyword">class</span> ColorBase, <span class="keywordtype">int</span> K&gt; <span class="keyword">struct </span>kth_semantic_element_reference_type; <span class="keyword">template</span> &lt;<span class="keyword">class</span> ColorBase, <span class="keywordtype">int</span> K&gt; <span class="keyword">struct </span>kth_semantic_element_const_reference_type; <span class="comment">// Returns a reference to the element with K-th semantic index.</span> <span class="keyword">template</span> &lt;<span class="keyword">class</span> ColorBase, <span class="keywordtype">int</span> K&gt; <span class="keyword">typename</span> kth_semantic_element_reference_type&lt;ColorBase,K&gt;::type <a class="code" href="g_i_l_0114.html#g2cdd9bfd1b27576659b8c79a3a0233de" title="A mutable accessor to the K-th semantic element of a color base.">semantic_at_c</a>(ColorBase&amp; p) <span class="keyword">template</span> &lt;<span class="keyword">class</span> ColorBase, <span class="keywordtype">int</span> K&gt; <span class="keyword">typename</span> kth_semantic_element_const_reference_type&lt;ColorBase,K&gt;::type <a class="code" href="g_i_l_0114.html#g2cdd9bfd1b27576659b8c79a3a0233de" title="A mutable accessor to the K-th semantic element of a color base.">semantic_at_c</a>(<span class="keyword">const</span> ColorBase&amp; p) <span class="comment">// Returns the type of the return value of get_color&lt;Color&gt;(color_base)</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> Color, <span class="keyword">typename</span> ColorBase&gt; <span class="keyword">struct </span>color_reference_t; <span class="keyword">template</span> &lt;<span class="keyword">typename</span> Color, <span class="keyword">typename</span> ColorBase&gt; <span class="keyword">struct </span>color_const_reference_t; <span class="comment">// Returns a reference to the element corresponding to the given color</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ColorBase, <span class="keyword">typename</span> Color&gt; <span class="keyword">typename</span> color_reference_t&lt;Color,ColorBase&gt;::type <a class="code" href="g_i_l_0106.html#gab1205781ba628ca806c47a51f40f5f6" title="Mutable accessor to the element associated with a given color name.">get_color</a>(ColorBase&amp; cb, Color=Color()); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ColorBase, <span class="keyword">typename</span> Color&gt; <span class="keyword">typename</span> color_const_reference_t&lt;Color,ColorBase&gt;::type <a class="code" href="g_i_l_0106.html#gab1205781ba628ca806c47a51f40f5f6" title="Mutable accessor to the element associated with a given color name.">get_color</a>(<span class="keyword">const</span> ColorBase&amp; cb, Color=Color()); <span class="comment">// Returns the element type of the color base. Defined for homogeneous color bases only</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ColorBase&gt; <span class="keyword">struct </span>element_type; <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ColorBase&gt; <span class="keyword">struct </span>element_reference_type; <span class="keyword">template</span> &lt;<span class="keyword">typename</span> ColorBase&gt; <span class="keyword">struct </span>element_const_reference_type; </pre></div><p> GIL also provides the following algorithms which operate on color bases. Note that they all pair the elements semantically:<p> <div class="fragment"><pre class="fragment"><span class="comment">// Equivalents to std::equal, std::copy, std::fill, std::generate</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2&gt; <span class="keywordtype">bool</span> static_equal(<span class="keyword">const</span> CB1&amp; p1, <span class="keyword">const</span> CB2&amp; p2); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> Src,<span class="keyword">typename</span> Dst&gt; <span class="keywordtype">void</span> static_copy(<span class="keyword">const</span> Src&amp; src, Dst&amp; dst); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB, <span class="keyword">typename</span> Op&gt; <span class="keywordtype">void</span> static_generate(CB&amp; dst,Op op); <span class="comment">// Equivalents to std::transform</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB , <span class="keyword">typename</span> Dst,<span class="keyword">typename</span> Op&gt; Op static_transform( CB&amp;,Dst&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB , <span class="keyword">typename</span> Dst,<span class="keyword">typename</span> Op&gt; Op static_transform(<span class="keyword">const</span> CB&amp;,Dst&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> Dst,<span class="keyword">typename</span> Op&gt; Op static_transform( CB1&amp;, CB2&amp;,Dst&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> Dst,<span class="keyword">typename</span> Op&gt; Op static_transform(<span class="keyword">const</span> CB1&amp;, CB2&amp;,Dst&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> Dst,<span class="keyword">typename</span> Op&gt; Op static_transform( CB1&amp;,<span class="keyword">const</span> CB2&amp;,Dst&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> Dst,<span class="keyword">typename</span> Op&gt; Op static_transform(<span class="keyword">const</span> CB1&amp;,<span class="keyword">const</span> CB2&amp;,Dst&amp;,Op); <span class="comment">// Equivalents to std::for_each</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1, <span class="keyword">typename</span> Op&gt; Op static_for_each( CB1&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1, <span class="keyword">typename</span> Op&gt; Op static_for_each(<span class="keyword">const</span> CB1&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2, <span class="keyword">typename</span> Op&gt; Op static_for_each( CB1&amp;, CB2&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2, <span class="keyword">typename</span> Op&gt; Op static_for_each( CB1&amp;,<span class="keyword">const</span> CB2&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2, <span class="keyword">typename</span> Op&gt; Op static_for_each(<span class="keyword">const</span> CB1&amp;, CB2&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2, <span class="keyword">typename</span> Op&gt; Op static_for_each(<span class="keyword">const</span> CB1&amp;,<span class="keyword">const</span> CB2&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> CB3,<span class="keyword">typename</span> Op&gt; Op static_for_each( CB1&amp;, CB2&amp;, CB3&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> CB3,<span class="keyword">typename</span> Op&gt; Op static_for_each( CB1&amp;, CB2&amp;,<span class="keyword">const</span> CB3&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> CB3,<span class="keyword">typename</span> Op&gt; Op static_for_each( CB1&amp;,<span class="keyword">const</span> CB2&amp;, CB3&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> CB3,<span class="keyword">typename</span> Op&gt; Op static_for_each( CB1&amp;,<span class="keyword">const</span> CB2&amp;,<span class="keyword">const</span> CB3&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> CB3,<span class="keyword">typename</span> Op&gt; Op static_for_each(<span class="keyword">const</span> CB1&amp;, CB2&amp;, CB3&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> CB3,<span class="keyword">typename</span> Op&gt; Op static_for_each(<span class="keyword">const</span> CB1&amp;, CB2&amp;,<span class="keyword">const</span> CB3&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> CB3,<span class="keyword">typename</span> Op&gt; Op static_for_each(<span class="keyword">const</span> CB1&amp;,<span class="keyword">const</span> CB2&amp;, CB3&amp;,Op); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> CB1,<span class="keyword">typename</span> CB2,<span class="keyword">typename</span> CB3,<span class="keyword">typename</span> Op&gt; Op static_for_each(<span class="keyword">const</span> CB1&amp;,<span class="keyword">const</span> CB2&amp;,<span class="keyword">const</span> CB3&amp;,Op); <span class="comment">// The following algorithms are only defined for homogeneous color bases:</span> <span class="comment">// Equivalent to std::fill</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> HCB, <span class="keyword">typename</span> Element&gt; <span class="keywordtype">void</span> static_fill(HCB&amp; p, <span class="keyword">const</span> Element&amp; v); <span class="comment">// Equivalents to std::min_element and std::max_element</span> <span class="keyword">template</span> &lt;<span class="keyword">typename</span> HCB&gt; <span class="keyword">typename</span> element_const_reference_type&lt;HCB&gt;::type static_min(<span class="keyword">const</span> HCB&amp;); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> HCB&gt; <span class="keyword">typename</span> element_reference_type&lt;HCB&gt;::type static_min( HCB&amp;); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> HCB&gt; <span class="keyword">typename</span> element_const_reference_type&lt;HCB&gt;::type static_max(<span class="keyword">const</span> HCB&amp;); <span class="keyword">template</span> &lt;<span class="keyword">typename</span> HCB&gt; <span class="keyword">typename</span> element_reference_type&lt;HCB&gt;::type static_max( HCB&amp;); </pre></div><p> These algorithms are designed after the corresponding STL algorithms, except that instead of ranges they take color bases and operate on their elements. In addition, they are implemented with a compile-time recursion (thus the prefix "static_"). Finally, they pair the elements semantically instead of based on their physical order in memory. For example, here is the implementation of <code>static_equal:</code> <p> <div class="fragment"><pre class="fragment"><span class="keyword">namespace </span>detail { <span class="keyword">template</span> &lt;<span class="keywordtype">int</span> K&gt; <span class="keyword">struct </span>element_recursion { <span class="keyword">template</span> &lt;<span class="keyword">typename</span> P1,<span class="keyword">typename</span> P2&gt; <span class="keyword">static</span> <span class="keywordtype">bool</span> static_equal(<span class="keyword">const</span> P1&amp; p1, <span class="keyword">const</span> P2&amp; p2) { <span class="keywordflow">return</span> element_recursion&lt;K-1&gt;::static_equal(p1,p2) &amp;&amp; <a class="code" href="g_i_l_0114.html#g2cdd9bfd1b27576659b8c79a3a0233de" title="A mutable accessor to the K-th semantic element of a color base.">semantic_at_c</a>&lt;K-1&gt;(p1)==semantic_at_c&lt;N-1&gt;(p2); } }; <span class="keyword">template</span> &lt;&gt; <span class="keyword">struct </span>element_recursion&lt;0&gt; { <span class="keyword">template</span> &lt;<span class="keyword">typename</span> P1,<span class="keyword">typename</span> P2&gt; <span class="keyword">static</span> <span class="keywordtype">bool</span> static_equal(<span class="keyword">const</span> P1&amp;, <span class="keyword">const</span> P2&amp;) { <span class="keywordflow">return</span> <span class="keyword">true</span>; } }; } <span class="keyword">template</span> &lt;<span class="keyword">typename</span> P1,<span class="keyword">typename</span> P2&gt; <span class="keywordtype">bool</span> static_equal(<span class="keyword">const</span> P1&amp; p1, <span class="keyword">const</span> P2&amp; p2) { gil_function_requires&lt;ColorSpacesCompatibleConcept&lt;P1::layout_t::color_space_t,P2::layout_t::color_space_t&gt; &gt;(); <span class="keywordflow">return</span> detail::element_recursion&lt;size&lt;P1&gt;::value&gt;::static_equal(p1,p2); } </pre></div><p> This algorithm is used when invoking <code>operator==</code> on two pixels, for example. By using semantic accessors we are properly comparing an RGB pixel to a BGR pixel. Notice also that all of the above algorithms taking more than one color base require that they all have the same color space.<p> <hr> <h2><a class="anchor" name="PixelSectionDG"> 7. Pixel</a></h2> A pixel is a set of channels defining the color at a given point i