2
0
mirror of https://github.com/boostorg/gil.git synced 2026-01-29 19:42:11 +00:00
Files
gil/develop/doc/html/design_guide.html
2019-09-03 19:40:56 +00:00

2985 lines
390 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Design Guide - Boost.GIL documentation</title>
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/style.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html'
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/language_data.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="top" title="Boost.GIL documentation" href="index.html" />
<link rel="next" title="Image Processing" href="image_processing/index.html" />
<link rel="prev" title="Naming Conventions" href="naming.html" />
</head>
<body>
<div class="header">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="index.html"><img
alt="C++ Boost" src="_static/gil.png" border="0"></a></h3>
</td>
<td >
<h1 align="center"><a href="index.html"></a></h1>
</td>
<td>
<div id="searchbox" style="display: none">
<form class="search" action="search.html" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</td>
</tr>
</table>
</div>
<hr/>
<div class="content">
<div class="navbar" style="text-align:right;">
<a class="prev" title="Naming Conventions" href="naming.html"><img src="_static/prev.png" alt="prev"/></a>
<a class="next" title="Image Processing" href="image_processing/index.html"><img src="_static/next.png" alt="next"/></a>
</div>
<div class="section" id="design-guide">
<h1>Design Guide</h1>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><p><a class="reference internal" href="#overview" id="id15">Overview</a></p></li>
<li><p><a class="reference internal" href="#about-concepts" id="id16">About Concepts</a></p></li>
<li><p><a class="reference internal" href="#point" id="id17">Point</a></p></li>
<li><p><a class="reference internal" href="#channel" id="id18">Channel</a></p></li>
<li><p><a class="reference internal" href="#color-space-and-layout" id="id19">Color Space and Layout</a></p></li>
<li><p><a class="reference internal" href="#color-base" id="id20">Color Base</a></p></li>
<li><p><a class="reference internal" href="#pixel" id="id21">Pixel</a></p></li>
<li><p><a class="reference internal" href="#pixel-iterator" id="id22">Pixel Iterator</a></p></li>
<li><p><a class="reference internal" href="#pixel-locator" id="id23">Pixel Locator</a></p></li>
<li><p><a class="reference internal" href="#image-view" id="id24">Image View</a></p></li>
<li><p><a class="reference internal" href="#image" id="id25">Image</a></p></li>
<li><p><a class="reference internal" href="#run-time-specified-images-and-image-views" id="id26">Run-time specified images and image views</a></p></li>
<li><p><a class="reference internal" href="#useful-metafunctions-and-typedefs" id="id27">Useful Metafunctions and Typedefs</a></p></li>
<li><p><a class="reference internal" href="#i-o-extension" id="id28">I/O Extension</a></p></li>
<li><p><a class="reference internal" href="#sample-code" id="id29">Sample Code</a></p></li>
<li><p><a class="reference internal" href="#extending-the-generic-image-library" id="id30">Extending the Generic Image Library</a></p></li>
<li><p><a class="reference internal" href="#technicalities" id="id31">Technicalities</a></p></li>
<li><p><a class="reference internal" href="#conclusion" id="id32">Conclusion</a></p></li>
</ul>
</div>
<div class="section" id="overview">
<h2><a class="toc-backref" href="#id15">Overview</a></h2>
<p>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>
<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>
<img alt="_images/interleaved.jpg" src="_images/interleaved.jpg" />
<p>and in planar form:</p>
<img alt="_images/planar.jpg" src="_images/planar.jpg" />
<p>Note also that rows may optionally be aligned resulting in a potential padding
at the end of rows.</p>
<p>The Generic Image Library (GIL) provides models for images that vary in:</p>
<ul class="simple">
<li><p>Structure (planar vs. interleaved)</p></li>
<li><p>Color space and presence of alpha (RGB, RGBA, CMYK, etc.)</p></li>
<li><p>Channel depth (8-bit, 16-bit, etc.)</p></li>
<li><p>Order of channels (RGB vs. BGR, etc.)</p></li>
<li><p>Row alignment policy (no alignment, word-alignment, etc.)</p></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>
<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>
</div>
<div class="section" id="about-concepts">
<h2><a class="toc-backref" href="#id16">About Concepts</a></h2>
<p>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
algorithmic guarantees. For example, GIL class <code class="docutils literal notranslate"><span class="pre">pixel</span></code> is a model of GIL
<code class="docutils literal notranslate"><span class="pre">PixelConcept</span></code>. The user may substitute the pixel class with one of their
own, and, as long as it satisfies the requirements of <code class="docutils literal notranslate"><span class="pre">PixelConcept</span></code>,
all other GIL classes and algorithms can be used with it.
See more about concepts is avaialble at
<a class="reference external" href="https://web.archive.org/web/20160324115943/http://www.generic-programming.org/languages/conceptcpp/">Generic Programming in ConceptC++</a></p>
<p>In this document we will use a syntax for defining concepts that is described
in the C++ standard proposal paper
<a class="reference external" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf">[N2081] Concepts</a>.</p>
<p>Here are some common concepts that will be used in GIL.
Most of them are defined at the
<a class="reference external" href="https://web.archive.org/web/20160326060858/http://www.generic-programming.org/languages/conceptcpp/concept_web.php">ConceptC++ Concept Web</a>:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">auto</span> <span class="n">concept</span> <span class="n">DefaultConstructible</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">T</span><span class="o">::</span><span class="n">T</span><span class="p">();</span>
<span class="p">};</span>
<span class="k">auto</span> <span class="n">concept</span> <span class="n">CopyConstructible</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">T</span><span class="o">::</span><span class="n">T</span><span class="p">(</span><span class="n">T</span><span class="p">);</span>
<span class="n">T</span><span class="o">::~</span><span class="n">T</span><span class="p">();</span>
<span class="p">};</span>
<span class="k">auto</span> <span class="n">concept</span> <span class="n">Assignable</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span> <span class="n">U</span> <span class="o">=</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">result_type</span><span class="p">;</span>
<span class="n">result_type</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">U</span><span class="p">);</span>
<span class="p">};</span>
<span class="k">auto</span> <span class="n">concept</span> <span class="n">EqualityComparable</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span> <span class="n">U</span> <span class="o">=</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">T</span> <span class="n">x</span><span class="p">,</span> <span class="n">T</span> <span class="n">y</span><span class="p">);</span>
<span class="kt">bool</span> <span class="k">operator</span><span class="o">!=</span><span class="p">(</span><span class="n">T</span> <span class="n">x</span><span class="p">,</span> <span class="n">T</span> <span class="n">y</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="o">!</span><span class="p">(</span><span class="n">x</span><span class="o">==</span><span class="n">y</span><span class="p">);</span> <span class="p">}</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span> <span class="n">U</span><span class="o">&gt;</span> <span class="p">{</span> <span class="cm">/* unspecified */</span> <span class="p">};</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="n">concept_map</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">T</span><span class="o">&gt;</span> <span class="p">{</span> <span class="cm">/* unspecified */</span> <span class="p">};</span>
<span class="k">auto</span> <span class="n">concept</span> <span class="n">Swappable</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="kt">void</span> <span class="n">swap</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span> <span class="n">t</span><span class="p">,</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">u</span><span class="p">);</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Here are some additional basic concepts that GIL needs:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">auto</span> <span class="n">concept</span> <span class="n">Regular</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="o">:</span>
<span class="n">DefaultConstructible</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="n">CopyConstructible</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="n">EqualityComparable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="n">Assignable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="n">Swappable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{};</span>
<span class="k">auto</span> <span class="n">concept</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">type</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
</div>
<div class="section" id="point">
<h2><a class="toc-backref" href="#id17">Point</a></h2>
<p>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="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">PointNDConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">Regular</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="c1">// the type of a coordinate along each axis</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">size_t</span> <span class="n">K</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">axis</span><span class="p">;</span> <span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">axis</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">size_t</span> <span class="n">num_dimensions</span><span class="p">;</span>
<span class="c1">// accessor/modifier of the value of each axis.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">size_t</span> <span class="n">K</span><span class="o">&gt;</span> <span class="k">const</span> <span class="k">typename</span> <span class="n">axis</span><span class="o">&lt;</span><span class="n">K</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&amp;</span> <span class="n">T</span><span class="o">::</span><span class="n">axis_value</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">size_t</span> <span class="n">K</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">axis</span><span class="o">&lt;</span><span class="n">K</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&amp;</span> <span class="n">T</span><span class="o">::</span><span class="n">axis_value</span><span class="p">();</span>
<span class="p">};</span>
</pre></div>
</div>
<p>GIL uses a two-dimensional point, which is a refinement of <code class="docutils literal notranslate"><span class="pre">PointNDConcept</span></code>
in which both dimensions are of the same type:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">Point2DConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">PointNDConcept</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">num_dimensions</span> <span class="o">==</span> <span class="mi">2</span><span class="p">;</span>
<span class="n">where</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="n">axis</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">,</span> <span class="n">axis</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">value_type</span> <span class="o">=</span> <span class="n">axis</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">;</span>
<span class="k">const</span> <span class="n">value_type</span><span class="o">&amp;</span> <span class="k">operator</span><span class="p">[](</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">i</span><span class="p">);</span>
<span class="n">value_type</span><span class="o">&amp;</span> <span class="k">operator</span><span class="p">[](</span> <span class="n">T</span><span class="o">&amp;</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">i</span><span class="p">);</span>
<span class="n">value_type</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<ul class="simple">
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_point_n_d_concept.html">PointNDConcept</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_point2_d_concept.html">Point2DConcept</a></p></li>
</ul>
</div>
<div class="section" id="models">
<h3>Models</h3>
<p>GIL provides a model of <code class="docutils literal notranslate"><span class="pre">Point2DConcept</span></code>, <code class="docutils literal notranslate"><span class="pre">point&lt;T&gt;</span></code> where <code class="docutils literal notranslate"><span class="pre">T</span></code> is the
coordinate type.</p>
</div>
</div>
<div class="section" id="channel">
<h2><a class="toc-backref" href="#id18">Channel</a></h2>
<p>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="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">ChannelConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">EqualityComparable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">value_type</span> <span class="o">=</span> <span class="n">T</span><span class="p">;</span> <span class="c1">// use channel_traits&lt;T&gt;::value_type to access it</span>
<span class="n">where</span> <span class="n">ChannelValueConcept</span><span class="o">&lt;</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">reference</span> <span class="o">=</span> <span class="n">T</span><span class="o">&amp;</span><span class="p">;</span> <span class="c1">// use channel_traits&lt;T&gt;::reference to access it</span>
<span class="k">typename</span> <span class="n">pointer</span> <span class="o">=</span> <span class="n">T</span><span class="o">*</span><span class="p">;</span> <span class="c1">// use channel_traits&lt;T&gt;::pointer to access it</span>
<span class="k">typename</span> <span class="n">const_reference</span> <span class="o">=</span> <span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span><span class="p">;</span> <span class="c1">// use channel_traits&lt;T&gt;::const_reference to access it</span>
<span class="k">typename</span> <span class="n">const_pointer</span> <span class="o">=</span> <span class="k">const</span> <span class="n">T</span><span class="o">*</span><span class="p">;</span> <span class="c1">// use channel_traits&lt;T&gt;::const_pointer to access it</span>
<span class="k">static</span> <span class="k">const</span> <span class="kt">bool</span> <span class="n">is_mutable</span><span class="p">;</span> <span class="c1">// use channel_traits&lt;T&gt;::is_mutable to access it</span>
<span class="k">static</span> <span class="n">T</span> <span class="nf">min_value</span><span class="p">();</span> <span class="c1">// use channel_traits&lt;T&gt;::min_value to access it</span>
<span class="k">static</span> <span class="n">T</span> <span class="nf">max_value</span><span class="p">();</span> <span class="c1">// use channel_traits&lt;T&gt;::min_value to access it</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutableChannelConcept</span><span class="o">&lt;</span><span class="n">ChannelConcept</span> <span class="n">T</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">Swappable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Assignable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="p">{};</span>
<span class="n">concept</span> <span class="n">ChannelValueConcept</span><span class="o">&lt;</span><span class="n">ChannelConcept</span> <span class="n">T</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">Regular</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="p">{};</span>
</pre></div>
</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 class="docutils literal notranslate"><span class="pre">channel_traits</span></code> with the following default implementation:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">channel_traits</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="n">T</span> <span class="n">value_type</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">reference</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">T</span><span class="o">*</span> <span class="n">pointer</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">T</span><span class="o">&amp;</span> <span class="k">const</span> <span class="n">const_reference</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">T</span><span class="o">*</span> <span class="k">const</span> <span class="n">const_pointer</span><span class="p">;</span>
<span class="k">static</span> <span class="n">value_type</span> <span class="nf">min_value</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">min</span><span class="p">();</span> <span class="p">}</span>
<span class="k">static</span> <span class="n">value_type</span> <span class="nf">max_value</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">max</span><span class="p">();</span> <span class="p">}</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Two channel types are <em>compatible</em> if they have the same value type:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">ChannelsCompatibleConcept</span><span class="o">&lt;</span><span class="n">ChannelConcept</span> <span class="n">T1</span><span class="p">,</span> <span class="n">ChannelConcept</span> <span class="n">T2</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">::</span><span class="n">value_type</span><span class="p">,</span> <span class="n">T2</span><span class="o">::</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>A channel may be <em>convertible</em> to another channel:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="n">ChannelConcept</span> <span class="n">Src</span><span class="p">,</span> <span class="n">ChannelValueConcept</span> <span class="n">Dst</span><span class="o">&gt;</span>
<span class="n">concept</span> <span class="n">ChannelConvertibleConcept</span>
<span class="p">{</span>
<span class="n">Dst</span> <span class="n">channel_convert</span><span class="p">(</span><span class="n">Src</span><span class="p">);</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Note that <code class="docutils literal notranslate"><span class="pre">ChannelConcept</span></code> and <code class="docutils literal notranslate"><span class="pre">MutableChannelConcept</span></code> do not require a
default constructor. Channels that also support default construction (and thus
are regular types) model <code class="docutils literal notranslate"><span class="pre">ChannelValueConcept</span></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 sub-byte channel.
Such a proxy reference class models only <code class="docutils literal notranslate"><span class="pre">ChannelConcept</span></code>, because, similar
to native C++ references, it may not have a default constructor.</p>
<p>Note also that algorithms may impose additional requirements on channels,
such as support for arithmetic operations.</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<ul class="simple">
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_concept.html">ChannelConcept&lt;T&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_value_concept.html">ChannelValueConcept&lt;T&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_channel_concept.html">MutableChannelConcept&lt;T&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_channels_compatible_concept.html">ChannelsCompatibleConcept&lt;T1,T2&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_convertible_concept.html">ChannelConvertibleConcept&lt;SrcChannel,DstChannel&gt;</a></p></li>
</ul>
</div>
<div class="section" id="id1">
<h3>Models</h3>
<p>All C++11 fundamental integer and float point types are valid channels.</p>
<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 class="docutils literal notranslate"><span class="pre">std::numeric_limits</span></code>. Sometimes the physical range is not
appropriate. GIL provides <code class="docutils literal notranslate"><span class="pre">scoped_channel_value</span></code>, a model for a channel
adapter that allows for specifying a custom range.
We use it to define a <code class="docutils literal notranslate"><span class="pre">[0..1]</span></code> floating point channel type as follows:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">struct</span> <span class="n">float_zero</span> <span class="p">{</span> <span class="k">static</span> <span class="kt">float</span> <span class="n">apply</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="mf">0.0f</span><span class="p">;</span> <span class="p">}</span> <span class="p">};</span>
<span class="k">struct</span> <span class="n">float_one</span> <span class="p">{</span> <span class="k">static</span> <span class="kt">float</span> <span class="n">apply</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="mf">1.0f</span><span class="p">;</span> <span class="p">}</span> <span class="p">};</span>
<span class="k">typedef</span> <span class="n">scoped_channel_value</span><span class="o">&lt;</span><span class="kt">float</span><span class="p">,</span><span class="n">float_zero</span><span class="p">,</span><span class="n">float_one</span><span class="o">&gt;</span> <span class="n">bits32f</span><span class="p">;</span>
</pre></div>
</div>
<p>GIL also provides models for channels corresponding to ranges of bits:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Value of a channel defined over NumBits bits. Models ChannelValueConcept</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">int</span> <span class="n">NumBits</span><span class="o">&gt;</span> <span class="k">class</span> <span class="nc">packed_channel_value</span><span class="p">;</span>
<span class="c1">// Reference to a channel defined over NumBits bits. Models ChannelConcept</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">int</span> <span class="n">FirstBit</span><span class="p">,</span>
<span class="kt">int</span> <span class="n">NumBits</span><span class="p">,</span> <span class="c1">// Defines the sequence of bits in the data value that contain the channel</span>
<span class="kt">bool</span> <span class="n">Mutable</span><span class="o">&gt;</span> <span class="c1">// true if the reference is mutable</span>
<span class="k">class</span> <span class="nc">packed_channel_reference</span><span class="p">;</span>
<span class="c1">// Reference to a channel defined over NumBits bits. Its FirstBit is a run-time parameter. Models ChannelConcept</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">int</span> <span class="n">NumBits</span><span class="p">,</span> <span class="c1">// Defines the sequence of bits in the data value that contain the channel</span>
<span class="kt">bool</span> <span class="n">Mutable</span><span class="o">&gt;</span> <span class="c1">// true if the reference is mutable</span>
<span class="k">class</span> <span class="nc">packed_dynamic_channel_reference</span><span class="p">;</span>
</pre></div>
</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 bit range channels.</p>
</div>
<div class="section" id="algorithms">
<h3>Algorithms</h3>
<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="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">using</span> <span class="n">channel16_0_5_reference_t</span> <span class="o">=</span> <span class="n">packed_channel_reference</span><span class="o">&lt;</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="nb">true</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">using</span> <span class="n">channel16_5_6_reference_t</span> <span class="o">=</span> <span class="n">packed_channel_reference</span><span class="o">&lt;</span><span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="nb">true</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">using</span> <span class="n">channel16_11_5_reference_t</span> <span class="o">=</span> <span class="n">packed_channel_reference</span><span class="o">&lt;</span><span class="mi">11</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="nb">true</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="kt">uint16_t</span> <span class="n">data</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
<span class="n">channel16_0_5_reference_t</span> <span class="nf">channel1</span><span class="p">(</span><span class="o">&amp;</span><span class="n">data</span><span class="p">);</span>
<span class="n">channel16_5_6_reference_t</span> <span class="nf">channel2</span><span class="p">(</span><span class="o">&amp;</span><span class="n">data</span><span class="p">);</span>
<span class="n">channel16_11_5_reference_t</span> <span class="nf">channel3</span><span class="p">(</span><span class="o">&amp;</span><span class="n">data</span><span class="p">);</span>
<span class="n">channel1</span> <span class="o">=</span> <span class="n">channel_traits</span><span class="o">&lt;</span><span class="n">channel16_0_5_reference_t</span><span class="o">&gt;::</span><span class="n">max_value</span><span class="p">();</span>
<span class="n">channel2</span> <span class="o">=</span> <span class="n">channel_traits</span><span class="o">&lt;</span><span class="n">channel16_5_6_reference_t</span><span class="o">&gt;::</span><span class="n">max_value</span><span class="p">();</span>
<span class="n">channel3</span> <span class="o">=</span> <span class="n">channel_traits</span><span class="o">&lt;</span><span class="n">channel16_11_5_reference_t</span><span class="o">&gt;::</span><span class="n">max_value</span><span class="p">();</span>
<span class="n">assert</span><span class="p">(</span><span class="n">data</span> <span class="o">==</span> <span class="mi">65535</span><span class="p">);</span>
</pre></div>
</div>
<p>Assignment, equality comparison and copy construction are defined only between
compatible channels:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">packed_channel_value</span><span class="o">&lt;</span><span class="mi">5</span><span class="o">&gt;</span> <span class="n">channel_6bit</span> <span class="o">=</span> <span class="n">channel1</span><span class="p">;</span>
<span class="n">channel_6bit</span> <span class="o">=</span> <span class="n">channel3</span><span class="p">;</span>
<span class="c1">// compile error: Assignment between incompatible channels</span>
<span class="c1">//channel_6bit = channel2;</span>
</pre></div>
</div>
<p>All channel models provided by GIL are pairwise convertible:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">channel1</span> <span class="o">=</span> <span class="n">channel_traits</span><span class="o">&lt;</span><span class="n">channel16_0_5_reference_t</span><span class="o">&gt;::</span><span class="n">max_value</span><span class="p">();</span>
<span class="n">assert</span><span class="p">(</span><span class="n">channel1</span> <span class="o">==</span> <span class="mi">31</span><span class="p">);</span>
<span class="n">bits16</span> <span class="n">chan16</span> <span class="o">=</span> <span class="n">channel_convert</span><span class="o">&lt;</span><span class="n">bits16</span><span class="o">&gt;</span><span class="p">(</span><span class="n">channel1</span><span class="p">);</span>
<span class="n">assert</span><span class="p">(</span><span class="n">chan16</span> <span class="o">==</span> <span class="mi">65535</span><span class="p">);</span>
</pre></div>
</div>
<p>Channel conversion is a lossy operation. GILs 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>
<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="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Converts a source channel value into a destination channel.</span>
<span class="c1">// Linearly maps the value of the source into the range of the destination.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">DstChannel</span><span class="p">,</span> <span class="k">typename</span> <span class="n">SrcChannel</span><span class="o">&gt;</span>
<span class="k">typename</span> <span class="n">channel_traits</span><span class="o">&lt;</span><span class="n">DstChannel</span><span class="o">&gt;::</span><span class="n">value_type</span> <span class="n">channel_convert</span><span class="p">(</span><span class="n">SrcChannel</span> <span class="n">src</span><span class="p">);</span>
<span class="c1">// returns max_value - x + min_value</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Channel</span><span class="o">&gt;</span>
<span class="k">typename</span> <span class="n">channel_traits</span><span class="o">&lt;</span><span class="n">Channel</span><span class="o">&gt;::</span><span class="n">value_type</span> <span class="n">channel_invert</span><span class="p">(</span><span class="n">Channel</span> <span class="n">x</span><span class="p">);</span>
<span class="c1">// returns a * b / max_value</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Channel</span><span class="o">&gt;</span>
<span class="k">typename</span> <span class="n">channel_traits</span><span class="o">&lt;</span><span class="n">Channel</span><span class="o">&gt;::</span><span class="n">value_type</span> <span class="n">channel_multiply</span><span class="p">(</span><span class="n">Channel</span> <span class="n">a</span><span class="p">,</span> <span class="n">Channel</span> <span class="n">b</span><span class="p">);</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="color-space-and-layout">
<h2><a class="toc-backref" href="#id19">Color Space and Layout</a></h2>
<p>A color space captures the set and interpretation of channels comprising a
pixel. In Boost.GIL, color space is defined as an MPL random access sequence
containing the types of all elements in the color space.</p>
<p>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>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<ul class="simple">
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_color_space_concept.html">ColorSpaceConcept&lt;ColorSpace&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_color_spaces_compatible_concept.html">ColorSpacesCompatibleConcept&lt;ColorSpace1,ColorSpace2&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_mapping_concept.html">ChannelMappingConcept&lt;Mapping&gt;</a></p></li>
</ul>
</div>
<div class="section" id="id2">
<h3>Models</h3>
<p>GIL currently provides the following color spaces:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">gray_t</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">rgb_t</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">rgba_t</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">cmyk_t</span></code></p></li>
</ul>
<p>It also provides unnamed N-channel color spaces of two to five channels:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">devicen_t&lt;2&gt;</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">devicen_t&lt;3&gt;</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">devicen_t&lt;4&gt;</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">devicen_t&lt;5&gt;</span></code></p></li>
</ul>
<p>Besides the standard layouts, it also provides:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">bgr_layout_t</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">bgra_layout_t</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">abgr_layout_t</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">argb_layout_t</span></code></p></li>
</ul>
<p>As an example, here is how GIL defines the RGBA color space:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="p">..</span> <span class="n">code</span><span class="o">-</span><span class="n">block</span><span class="o">::</span> <span class="n">cpp</span>
</pre></div>
</div>
<blockquote>
<div><p>struct red_t {};
struct green_t {};
struct blue_t {};
struct alpha_t {};
rgba_t = using mpl::vector4&lt;red_t, green_t, blue_t, alpha_t&gt;;</p>
</div></blockquote>
<p>The ordering of the channels in the color space definition specifies their
semantic order. For example, <code class="docutils literal notranslate"><span class="pre">red_t</span></code> is the first semantic channel of
<code class="docutils literal notranslate"><span class="pre">rgba_t</span></code>. While there is a unique semantic ordering of the channels in a
color space, channels may vary in their physical ordering in memory</p>
<p>The mapping of channels is specified by <code class="docutils literal notranslate"><span class="pre">ChannelMappingConcept</span></code>, which is
an MPL random access sequence of integral types.
A color space and its associated mapping are often used together.</p>
<p>Thus they are grouped in GILs layout:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span>
<span class="o">&lt;</span>
<span class="k">typename</span> <span class="n">ColorSpace</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">ChannelMapping</span> <span class="o">=</span> <span class="n">mpl</span><span class="o">::</span><span class="n">range_c</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">size</span><span class="o">&lt;</span><span class="n">ColorSpace</span><span class="o">&gt;::</span><span class="n">value</span><span class="o">&gt;</span>
<span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">layout</span>
<span class="p">{</span>
<span class="k">using</span> <span class="n">color_space_t</span> <span class="o">=</span> <span class="n">ColorSpace</span><span class="p">;</span>
<span class="k">using</span> <span class="n">channel_mapping_t</span> <span class="o">=</span> <span class="n">ChannelMapping</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Here is how to create layouts for the RGBA color space:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">using</span> <span class="n">rgba_layout_t</span> <span class="o">=</span> <span class="n">layout</span><span class="o">&lt;</span><span class="n">rgba_t</span><span class="o">&gt;</span><span class="p">;</span> <span class="c1">// default ordering is 0,1,2,3...</span>
<span class="k">using</span> <span class="n">bgra_layout_t</span> <span class="o">=</span> <span class="n">layout</span><span class="o">&lt;</span><span class="n">rgba_t</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">vector4_c</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="o">&gt;&gt;</span><span class="p">;</span>
<span class="k">using</span> <span class="n">argb_layout_t</span> <span class="o">=</span> <span class="n">layout</span><span class="o">&lt;</span><span class="n">rgba_t</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">vector4_c</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="o">&gt;&gt;</span><span class="p">;</span>
<span class="k">using</span> <span class="n">abgr_layout_t</span> <span class="o">=</span> <span class="n">layout</span><span class="o">&lt;</span><span class="n">rgba_t</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">vector4_c</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="o">&gt;&gt;</span><span class="p">;</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="color-base">
<h2><a class="toc-backref" href="#id20">Color Base</a></h2>
<p>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>
<p>Color base models must satisfy the following concepts:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">ColorBaseConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="o">:</span> <span class="n">CopyConstructible</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">EqualityComparable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="c1">// a GIL layout (the color space and element permutation)</span>
<span class="k">typename</span> <span class="n">layout_t</span><span class="p">;</span>
<span class="c1">// The type of K-th element</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">kth_element_type</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">kth_element_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="c1">// The result of at_c</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">kth_element_const_reference_type</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">kth_element_const_reference_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span> <span class="n">kth_element_const_reference_type</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="n">K</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">at_c</span><span class="p">(</span><span class="n">T</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">ColorBaseConcept</span> <span class="n">T2</span><span class="o">&gt;</span> <span class="n">where</span> <span class="p">{</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="n">T2</span><span class="o">&gt;</span> <span class="p">}</span>
<span class="n">T</span><span class="o">::</span><span class="n">T</span><span class="p">(</span><span class="n">T2</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">ColorBaseConcept</span> <span class="n">T2</span><span class="o">&gt;</span> <span class="n">where</span> <span class="p">{</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="n">T2</span><span class="o">&gt;</span> <span class="p">}</span>
<span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">T2</span><span class="o">&amp;</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">ColorBaseConcept</span> <span class="n">T2</span><span class="o">&gt;</span> <span class="n">where</span> <span class="p">{</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="n">T2</span><span class="o">&gt;</span> <span class="p">}</span>
<span class="kt">bool</span> <span class="k">operator</span><span class="o">!=</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">T2</span><span class="o">&amp;</span><span class="p">);</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutableColorBaseConcept</span><span class="o">&lt;</span><span class="n">ColorBaseConcept</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="o">:</span> <span class="n">Assignable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Swappable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">kth_element_reference_type</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">kth_element_reference_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span> <span class="n">kth_element_reference_type</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="n">K</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">at_c</span><span class="p">(</span><span class="n">T</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">ColorBaseConcept</span> <span class="n">T2</span><span class="o">&gt;</span> <span class="n">where</span> <span class="p">{</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="n">T2</span><span class="o">&gt;</span> <span class="p">}</span>
<span class="n">T</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">T2</span><span class="o">&amp;</span><span class="p">);</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">ColorBaseValueConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">MutableColorBaseConcept</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Regular</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">HomogeneousColorBaseConcept</span><span class="o">&lt;</span><span class="n">ColorBaseConcept</span> <span class="n">CB</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="c1">// For all K in [0 ... size&lt;C1&gt;::value-1):</span>
<span class="c1">// where SameType&lt;kth_element_type&lt;K&gt;::type, kth_element_type&lt;K+1&gt;::type&gt;;</span>
<span class="n">kth_element_const_reference_type</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">dynamic_at_c</span><span class="p">(</span><span class="k">const</span> <span class="n">CB</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">n</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutableHomogeneousColorBaseConcept</span><span class="o">&lt;</span><span class="n">MutableColorBaseConcept</span> <span class="n">CB</span><span class="o">&gt;</span>
<span class="o">:</span> <span class="n">HomogeneousColorBaseConcept</span><span class="o">&lt;</span><span class="n">CB</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">kth_element_reference_type</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">dynamic_at_c</span><span class="p">(</span><span class="k">const</span> <span class="n">CB</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">n</span><span class="p">);</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">HomogeneousColorBaseValueConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="o">:</span> <span class="n">MutableHomogeneousColorBaseConcept</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Regular</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o">&lt;</span><span class="n">ColorBaseConcept</span> <span class="n">C1</span><span class="p">,</span> <span class="n">ColorBaseConcept</span> <span class="n">C2</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="n">C1</span><span class="o">::</span><span class="n">layout_t</span><span class="o">::</span><span class="n">color_space_t</span><span class="p">,</span> <span class="n">C2</span><span class="o">::</span><span class="n">layout_t</span><span class="o">::</span><span class="n">color_space_t</span><span class="o">&gt;</span><span class="p">;</span>
<span class="c1">// also, for all K in [0 ... size&lt;C1&gt;::value):</span>
<span class="c1">// 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="c1">// where Convertible&lt;kth_semantic_element_type&lt;C2,K&gt;::type, kth_semantic_element_type&lt;C1,K&gt;::type&gt;;</span>
<span class="p">};</span>
</pre></div>
</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 <code class="docutils literal notranslate"><span class="pre">{red_t,</span> <span class="pre">green_t,</span> <span class="pre">blue_t}</span></code>. 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 class="docutils literal notranslate"><span class="pre">ColorBaseConcept</span></code> are required to provide the <code class="docutils literal notranslate"><span class="pre">at_c&lt;K&gt;(ColorBase)</span></code>
function, which allows for accessing the elements based on their physical
order. GIL provides a <code class="docutils literal notranslate"><span class="pre">semantic_at_c&lt;K&gt;(ColorBase)</span></code> function (described
later) which can operate on any model of ColorBaseConcept and returns the
corresponding semantic element.</p>
<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>
<div class="section" id="id3">
<h3>Models</h3>
<p>GIL provides a model for a homogeneous color base (a color base whose elements
all have the same type).</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">namespace</span> <span class="n">detail</span>
<span class="p">{</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Element</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">homogeneous_color_base</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>It is used in the implementation of GILs pixel, planar pixel reference and
planar pixel iterator. Another model of <code class="docutils literal notranslate"><span class="pre">ColorBaseConcept</span></code> is
<code class="docutils literal notranslate"><span class="pre">packed_pixel</span></code> - it is a pixel whose channels are bit ranges.</p>
<p>See the <a class="reference internal" href="#pixel"><span class="std std-ref">Pixel</span></a> section for more.</p>
</div>
<div class="section" id="id4">
<h3>Algorithms</h3>
<p>GIL provides the following functions and metafunctions operating on color
bases:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Metafunction returning an mpl::int_ equal to the number of elements in the color base</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">ColorBase</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">size</span><span class="p">;</span>
<span class="c1">// Returns the type of the return value of semantic_at_c&lt;K&gt;(color_base)</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">ColorBase</span><span class="p">,</span> <span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">kth_semantic_element_reference_type</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">ColorBase</span><span class="p">,</span> <span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">kth_semantic_element_const_reference_type</span><span class="p">;</span>
<span class="c1">// Returns a reference to the element with K-th semantic index.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">ColorBase</span><span class="p">,</span> <span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span>
<span class="k">typename</span> <span class="n">kth_semantic_element_reference_type</span><span class="o">&lt;</span><span class="n">ColorBase</span><span class="p">,</span><span class="n">K</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">semantic_at_c</span><span class="p">(</span><span class="n">ColorBase</span><span class="o">&amp;</span> <span class="n">p</span><span class="p">)</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">ColorBase</span><span class="p">,</span> <span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span>
<span class="k">typename</span> <span class="n">kth_semantic_element_const_reference_type</span><span class="o">&lt;</span><span class="n">ColorBase</span><span class="p">,</span><span class="n">K</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">semantic_at_c</span><span class="p">(</span><span class="k">const</span> <span class="n">ColorBase</span><span class="o">&amp;</span> <span class="n">p</span><span class="p">)</span>
<span class="c1">// Returns the type of the return value of get_color&lt;Color&gt;(color_base)</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Color</span><span class="p">,</span> <span class="k">typename</span> <span class="n">ColorBase</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">color_reference_t</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Color</span><span class="p">,</span> <span class="k">typename</span> <span class="n">ColorBase</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">color_const_reference_t</span><span class="p">;</span>
<span class="c1">// Returns a reference to the element corresponding to the given color</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ColorBase</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Color</span><span class="o">&gt;</span>
<span class="k">typename</span> <span class="n">color_reference_t</span><span class="o">&lt;</span><span class="n">Color</span><span class="p">,</span><span class="n">ColorBase</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">get_color</span><span class="p">(</span><span class="n">ColorBase</span><span class="o">&amp;</span> <span class="n">cb</span><span class="p">,</span> <span class="n">Color</span><span class="o">=</span><span class="n">Color</span><span class="p">());</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ColorBase</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Color</span><span class="o">&gt;</span>
<span class="k">typename</span> <span class="n">color_const_reference_t</span><span class="o">&lt;</span><span class="n">Color</span><span class="p">,</span><span class="n">ColorBase</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">get_color</span><span class="p">(</span><span class="k">const</span> <span class="n">ColorBase</span><span class="o">&amp;</span> <span class="n">cb</span><span class="p">,</span> <span class="n">Color</span><span class="o">=</span><span class="n">Color</span><span class="p">());</span>
<span class="c1">// Returns the element type of the color base. Defined for homogeneous color bases only</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ColorBase</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">element_type</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ColorBase</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">element_reference_type</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ColorBase</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">element_const_reference_type</span><span class="p">;</span>
</pre></div>
</div>
<p>GIL also provides the following algorithms which operate on color bases.
Note that they all pair the elements semantically:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Equivalents to std::equal, std::copy, std::fill, std::generate</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="o">&gt;</span> <span class="kt">bool</span> <span class="n">static_equal</span><span class="p">(</span><span class="k">const</span> <span class="n">CB1</span><span class="o">&amp;</span> <span class="n">p1</span><span class="p">,</span> <span class="k">const</span> <span class="n">CB2</span><span class="o">&amp;</span> <span class="n">p2</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Src</span><span class="p">,</span><span class="k">typename</span> <span class="n">Dst</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">static_copy</span><span class="p">(</span><span class="k">const</span> <span class="n">Src</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="n">Dst</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">static_generate</span><span class="p">(</span><span class="n">CB</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">,</span><span class="n">Op</span> <span class="n">op</span><span class="p">);</span>
<span class="c1">// Equivalents to std::transform</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB</span> <span class="p">,</span> <span class="k">typename</span> <span class="n">Dst</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_transform</span><span class="p">(</span> <span class="n">CB</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Dst</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB</span> <span class="p">,</span> <span class="k">typename</span> <span class="n">Dst</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_transform</span><span class="p">(</span><span class="k">const</span> <span class="n">CB</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Dst</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">Dst</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_transform</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Dst</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">Dst</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_transform</span><span class="p">(</span><span class="k">const</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Dst</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">Dst</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_transform</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Dst</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">Dst</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_transform</span><span class="p">(</span><span class="k">const</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Dst</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="c1">// Equivalents to std::for_each</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span><span class="k">const</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span><span class="k">const</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span><span class="k">const</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB3</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB3</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB3</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB3</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB3</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB3</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB3</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB3</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB3</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span><span class="k">const</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB3</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB3</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span><span class="k">const</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB3</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB3</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span><span class="k">const</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CB3</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">CB1</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB2</span><span class="p">,</span><span class="k">typename</span> <span class="n">CB3</span><span class="p">,</span><span class="k">typename</span> <span class="n">Op</span><span class="o">&gt;</span> <span class="n">Op</span> <span class="n">static_for_each</span><span class="p">(</span><span class="k">const</span> <span class="n">CB1</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">CB3</span><span class="o">&amp;</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
<span class="c1">// The following algorithms are only defined for homogeneous color bases:</span>
<span class="c1">// Equivalent to std::fill</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">HCB</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Element</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">static_fill</span><span class="p">(</span><span class="n">HCB</span><span class="o">&amp;</span> <span class="n">p</span><span class="p">,</span> <span class="k">const</span> <span class="n">Element</span><span class="o">&amp;</span> <span class="n">v</span><span class="p">);</span>
<span class="c1">// Equivalents to std::min_element and std::max_element</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">HCB</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">element_const_reference_type</span><span class="o">&lt;</span><span class="n">HCB</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">static_min</span><span class="p">(</span><span class="k">const</span> <span class="n">HCB</span><span class="o">&amp;</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">HCB</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">element_reference_type</span><span class="o">&lt;</span><span class="n">HCB</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">static_min</span><span class="p">(</span> <span class="n">HCB</span><span class="o">&amp;</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">HCB</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">element_const_reference_type</span><span class="o">&lt;</span><span class="n">HCB</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">static_max</span><span class="p">(</span><span class="k">const</span> <span class="n">HCB</span><span class="o">&amp;</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">HCB</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">element_reference_type</span><span class="o">&lt;</span><span class="n">HCB</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">static_max</span><span class="p">(</span> <span class="n">HCB</span><span class="o">&amp;</span><span class="p">);</span>
</pre></div>
</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.</p>
<p>For example, here is the implementation of <code class="docutils literal notranslate"><span class="pre">static_equal</span></code>:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">namespace</span> <span class="n">detail</span>
<span class="p">{</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">int</span> <span class="n">K</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">element_recursion</span>
<span class="p">{</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">P1</span><span class="p">,</span><span class="k">typename</span> <span class="n">P2</span><span class="o">&gt;</span>
<span class="k">static</span> <span class="kt">bool</span> <span class="n">static_equal</span><span class="p">(</span><span class="k">const</span> <span class="n">P1</span><span class="o">&amp;</span> <span class="n">p1</span><span class="p">,</span> <span class="k">const</span> <span class="n">P2</span><span class="o">&amp;</span> <span class="n">p2</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">element_recursion</span><span class="o">&lt;</span><span class="n">K</span><span class="o">-</span><span class="mi">1</span><span class="o">&gt;::</span><span class="n">static_equal</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span><span class="n">p2</span><span class="p">)</span> <span class="o">&amp;&amp;</span>
<span class="n">semantic_at_c</span><span class="o">&lt;</span><span class="n">K</span><span class="o">-</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span><span class="o">==</span><span class="n">semantic_at_c</span><span class="o">&lt;</span><span class="n">N</span><span class="o">-</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">p2</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;&gt;</span> <span class="k">struct</span> <span class="n">element_recursion</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">P1</span><span class="p">,</span><span class="k">typename</span> <span class="n">P2</span><span class="o">&gt;</span>
<span class="k">static</span> <span class="kt">bool</span> <span class="n">static_equal</span><span class="p">(</span><span class="k">const</span> <span class="n">P1</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">P2</span><span class="o">&amp;</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> <span class="p">}</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">P1</span><span class="p">,</span><span class="k">typename</span> <span class="n">P2</span><span class="o">&gt;</span>
<span class="kt">bool</span> <span class="n">static_equal</span><span class="p">(</span><span class="k">const</span> <span class="n">P1</span><span class="o">&amp;</span> <span class="n">p1</span><span class="p">,</span> <span class="k">const</span> <span class="n">P2</span><span class="o">&amp;</span> <span class="n">p2</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">gil_function_requires</span><span class="o">&lt;</span><span class="n">ColorSpacesCompatibleConcept</span><span class="o">&lt;</span><span class="n">P1</span><span class="o">::</span><span class="n">layout_t</span><span class="o">::</span><span class="n">color_space_t</span><span class="p">,</span><span class="n">P2</span><span class="o">::</span><span class="n">layout_t</span><span class="o">::</span><span class="n">color_space_t</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">();</span>
<span class="k">return</span> <span class="n">detail</span><span class="o">::</span><span class="n">element_recursion</span><span class="o">&lt;</span><span class="n">size</span><span class="o">&lt;</span><span class="n">P1</span><span class="o">&gt;::</span><span class="n">value</span><span class="o">&gt;::</span><span class="n">static_equal</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span><span class="n">p2</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This algorithm is used when invoking <code class="docutils literal notranslate"><span class="pre">operator==</span></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>
</div>
</div>
<div class="section" id="pixel">
<h2><a class="toc-backref" href="#id21">Pixel</a></h2>
<p>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 <code class="docutils literal notranslate"><span class="pre">ChannelConcept</span></code>. All properties of pixels inherit
from color bases: pixels may be <em>homogeneous</em> if all of their channels
have the same type; otherwise they are called <em>heterogeneous</em>. 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 <em>compatible</em> 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.</p>
<p>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:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">PixelBasedConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">color_space_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">color_space_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">ColorSpaceConcept</span><span class="o">&lt;</span><span class="n">color_space_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">channel_mapping_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">channel_mapping_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">ChannelMappingConcept</span><span class="o">&lt;</span><span class="n">channel_mapping_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">is_planar</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">is_planar</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="n">is_planar</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">,</span> <span class="kt">bool</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">HomogeneousPixelBasedConcept</span><span class="o">&lt;</span><span class="n">PixelBasedConcept</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">channel_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">channel_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">ChannelConcept</span><span class="o">&lt;</span><span class="n">channel_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Pixels model the following concepts:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">PixelConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">P</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">ColorBaseConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">PixelBasedConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">is_pixel</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;::</span><span class="n">value</span><span class="o">==</span><span class="nb">true</span><span class="p">;</span>
<span class="c1">// where for each K [0..size&lt;P&gt;::value-1]:</span>
<span class="c1">// ChannelConcept&lt;kth_element_type&lt;K&gt; &gt;;</span>
<span class="k">typename</span> <span class="n">value_type</span><span class="p">;</span> <span class="n">where</span> <span class="n">PixelValueConcept</span><span class="o">&lt;</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">reference</span><span class="p">;</span> <span class="n">where</span> <span class="n">PixelConcept</span><span class="o">&lt;</span><span class="n">reference</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">const_reference</span><span class="p">;</span> <span class="n">where</span> <span class="n">PixelConcept</span><span class="o">&lt;</span><span class="n">const_reference</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">static</span> <span class="k">const</span> <span class="kt">bool</span> <span class="n">P</span><span class="o">::</span><span class="n">is_mutable</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">PixelConcept</span> <span class="n">P2</span><span class="o">&gt;</span> <span class="n">where</span> <span class="p">{</span> <span class="n">PixelConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="p">,</span><span class="n">P2</span><span class="o">&gt;</span> <span class="p">}</span>
<span class="n">P</span><span class="o">::</span><span class="n">P</span><span class="p">(</span><span class="n">P2</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">PixelConcept</span> <span class="n">P2</span><span class="o">&gt;</span> <span class="n">where</span> <span class="p">{</span> <span class="n">PixelConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="p">,</span><span class="n">P2</span><span class="o">&gt;</span> <span class="p">}</span>
<span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="k">const</span> <span class="n">P</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">P2</span><span class="o">&amp;</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">PixelConcept</span> <span class="n">P2</span><span class="o">&gt;</span> <span class="n">where</span> <span class="p">{</span> <span class="n">PixelConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="p">,</span><span class="n">P2</span><span class="o">&gt;</span> <span class="p">}</span>
<span class="kt">bool</span> <span class="k">operator</span><span class="o">!=</span><span class="p">(</span><span class="k">const</span> <span class="n">P</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">P2</span><span class="o">&amp;</span><span class="p">);</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutablePixelConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">P</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">PixelConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">MutableColorBaseConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">is_mutable</span><span class="o">==</span><span class="nb">true</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">HomogeneousPixelConcept</span><span class="o">&lt;</span><span class="n">PixelConcept</span> <span class="n">P</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">HomogeneousColorBaseConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">HomogeneousPixelBasedConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">P</span><span class="o">::</span><span class="k">template</span> <span class="n">element_const_reference_type</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;::</span><span class="n">type</span> <span class="k">operator</span><span class="p">[](</span><span class="n">P</span> <span class="n">p</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">i</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">dynamic_at_c</span><span class="p">(</span><span class="n">P</span><span class="p">,</span><span class="n">i</span><span class="p">);</span> <span class="p">}</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutableHomogeneousPixelConcept</span><span class="o">&lt;</span><span class="n">MutablePixelConcept</span> <span class="n">P</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">MutableHomogeneousColorBaseConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">P</span><span class="o">::</span><span class="k">template</span> <span class="n">element_reference_type</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;::</span><span class="n">type</span> <span class="k">operator</span><span class="p">[](</span><span class="n">P</span> <span class="n">p</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">dynamic_at_c</span><span class="p">(</span><span class="n">p</span><span class="p">,</span><span class="n">i</span><span class="p">);</span> <span class="p">}</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">PixelValueConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">P</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">PixelConcept</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Regular</span><span class="o">&lt;</span><span class="n">P</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="n">value_type</span><span class="p">,</span><span class="n">P</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">PixelsCompatibleConcept</span><span class="o">&lt;</span><span class="n">PixelConcept</span> <span class="n">P1</span><span class="p">,</span> <span class="n">PixelConcept</span> <span class="n">P2</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o">&lt;</span><span class="n">P1</span><span class="p">,</span><span class="n">P2</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="c1">// where for each K [0..size&lt;P1&gt;::value):</span>
<span class="c1">// ChannelsCompatibleConcept&lt;kth_semantic_element_type&lt;P1,K&gt;::type, kth_semantic_element_type&lt;P2,K&gt;::type&gt;;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>A pixel is <em>convertible</em> 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:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="n">PixelConcept</span> <span class="n">SrcPixel</span><span class="p">,</span> <span class="n">MutablePixelConcept</span> <span class="n">DstPixel</span><span class="o">&gt;</span>
<span class="n">concept</span> <span class="n">PixelConvertibleConcept</span>
<span class="p">{</span>
<span class="kt">void</span> <span class="n">color_convert</span><span class="p">(</span><span class="k">const</span> <span class="n">SrcPixel</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">DstPixel</span><span class="o">&amp;</span><span class="p">);</span>
<span class="p">};</span>
</pre></div>
</div>
<p>The distinction between <code class="docutils literal notranslate"><span class="pre">PixelConcept</span></code> and <code class="docutils literal notranslate"><span class="pre">PixelValueConcept</span></code> is
analogous to that for channels and color bases - pixel reference proxies model
both, but only pixel values model the latter.</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<ul class="simple">
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_based_concept.html">PixelBasedConcept&lt;P&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_concept.html">PixelConcept&lt;Pixel&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_pixel_concept.html">MutablePixelConcept&lt;Pixel&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_value_concept.html">PixelValueConcept&lt;Pixel&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_homogeneous_pixel_based_concept.html">HomogeneousPixelConcept&lt;Pixel&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_homogeneous_pixel_concept.html">MutableHomogeneousPixelConcept&lt;Pixel&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_homogeneous_pixel_value_concept.html">HomogeneousPixelValueConcept&lt;Pixel&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_pixels_compatible_concept.html">PixelsCompatibleConcept&lt;Pixel1, Pixel2&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_convertible_concept.html">PixelConvertibleConcept&lt;SrcPixel, DstPixel&gt;</a></p></li>
</ul>
</div>
<div class="section" id="id5">
<h3>Models</h3>
<p>The most commonly used pixel is a homogeneous pixel whose values are
together in memory. For this purpose GIL provides the struct
<code class="docutils literal notranslate"><span class="pre">pixel</span></code>, templated over the channel value and layout:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// models HomogeneousPixelValueConcept</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ChannelValue</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">pixel</span><span class="p">;</span>
<span class="c1">// Those typedefs are already provided by GIL</span>
<span class="k">typedef</span> <span class="n">pixel</span><span class="o">&lt;</span><span class="n">bits8</span><span class="p">,</span> <span class="n">rgb_layout_t</span><span class="o">&gt;</span> <span class="n">rgb8_pixel_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">pixel</span><span class="o">&lt;</span><span class="n">bits8</span><span class="p">,</span> <span class="n">bgr_layout_t</span><span class="o">&gt;</span> <span class="n">bgr8_pixel_t</span><span class="p">;</span>
<span class="n">bgr8_pixel_t</span> <span class="nf">bgr8</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// pixels can be initialized with the channels directly</span>
<span class="n">rgb8_pixel_t</span> <span class="nf">rgb8</span><span class="p">(</span><span class="n">bgr8</span><span class="p">);</span> <span class="c1">// compatible pixels can also be copy-constructed</span>
<span class="n">rgb8</span> <span class="o">=</span> <span class="n">bgr8</span><span class="p">;</span> <span class="c1">// assignment and equality is defined between compatible pixels</span>
<span class="n">assert</span><span class="p">(</span><span class="n">rgb8</span> <span class="o">==</span> <span class="n">bgr8</span><span class="p">);</span> <span class="c1">// assignment and equality operate on the semantic channels</span>
<span class="c1">// The first physical channels of the two pixels are different</span>
<span class="n">assert</span><span class="p">(</span><span class="n">at_c</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">rgb8</span><span class="p">)</span> <span class="o">!=</span> <span class="n">at_c</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">bgr8</span><span class="p">));</span>
<span class="n">assert</span><span class="p">(</span><span class="n">dynamic_at_c</span><span class="p">(</span><span class="n">bgr8</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span> <span class="o">!=</span> <span class="n">dynamic_at_c</span><span class="p">(</span><span class="n">rgb8</span><span class="p">,</span><span class="mi">0</span><span class="p">));</span>
<span class="n">assert</span><span class="p">(</span><span class="n">rgb8</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="n">bgr8</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="c1">// same as above (but operator[] is defined for pixels only)</span>
</pre></div>
</div>
<p>Planar pixels have their channels distributed in memory. While they share the
same value type (<code class="docutils literal notranslate"><span class="pre">pixel</span></code>) with interleaved pixels, their reference type is a
proxy class containing references to each of the channels.
This is implemented with the struct <code class="docutils literal notranslate"><span class="pre">planar_pixel_reference</span></code>:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// models HomogeneousPixel</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ChannelReference</span><span class="p">,</span> <span class="k">typename</span> <span class="n">ColorSpace</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">planar_pixel_reference</span><span class="p">;</span>
<span class="c1">// Define the type of a mutable and read-only reference. (These typedefs are already provided by GIL)</span>
<span class="k">typedef</span> <span class="n">planar_pixel_reference</span><span class="o">&lt;</span> <span class="n">bits8</span><span class="o">&amp;</span><span class="p">,</span><span class="n">rgb_t</span><span class="o">&gt;</span> <span class="n">rgb8_planar_ref_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">planar_pixel_reference</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">bits8</span><span class="o">&amp;</span><span class="p">,</span><span class="n">rgb_t</span><span class="o">&gt;</span> <span class="n">rgb8c_planar_ref_t</span><span class="p">;</span>
</pre></div>
</div>
<p>Note that, unlike the <code class="docutils literal notranslate"><span class="pre">pixel</span></code> 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.</p>
<p>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:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// define an rgb565 pixel</span>
<span class="k">typedef</span> <span class="n">packed_pixel_type</span><span class="o">&lt;</span><span class="kt">uint16_t</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">vector3_c</span><span class="o">&lt;</span><span class="kt">unsigned</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">5</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">rgb_layout_t</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">rgb565_pixel_t</span><span class="p">;</span>
<span class="n">function_requires</span><span class="o">&lt;</span><span class="n">PixelValueConcept</span><span class="o">&lt;</span><span class="n">rgb565_pixel_t</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">();</span>
<span class="k">static_assert</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">rgb565_pixel_t</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">);</span>
<span class="c1">// define a bgr556 pixel</span>
<span class="k">typedef</span> <span class="n">packed_pixel_type</span><span class="o">&lt;</span><span class="kt">uint16_t</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">vector3_c</span><span class="o">&lt;</span><span class="kt">unsigned</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">5</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">bgr_layout_t</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">bgr556_pixel_t</span><span class="p">;</span>
<span class="n">function_requires</span><span class="o">&lt;</span><span class="n">PixelValueConcept</span><span class="o">&lt;</span><span class="n">bgr556_pixel_t</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">();</span>
<span class="c1">// rgb565 is compatible with bgr556.</span>
<span class="n">function_requires</span><span class="o">&lt;</span><span class="n">PixelsCompatibleConcept</span><span class="o">&lt;</span><span class="n">rgb565_pixel_t</span><span class="p">,</span><span class="n">bgr556_pixel_t</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">();</span>
</pre></div>
</div>
<p>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:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Mutable reference to a BGR232 pixel</span>
<span class="k">typedef</span> <span class="k">const</span> <span class="n">bit_aligned_pixel_reference</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">vector3_c</span><span class="o">&lt;</span><span class="kt">unsigned</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">bgr_layout_t</span><span class="p">,</span> <span class="nb">true</span><span class="o">&gt;</span> <span class="n">bgr232_ref_t</span><span class="p">;</span>
<span class="c1">// A mutable iterator over BGR232 pixels</span>
<span class="k">typedef</span> <span class="n">bit_aligned_pixel_iterator</span><span class="o">&lt;</span><span class="n">bgr232_ref_t</span><span class="o">&gt;</span> <span class="n">bgr232_ptr_t</span><span class="p">;</span>
<span class="c1">// BGR232 pixel value. It is a packed_pixel of size 1 byte. (The last bit is unused)</span>
<span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">bgr232_ptr_t</span><span class="o">&gt;::</span><span class="n">value_type</span> <span class="n">bgr232_pixel_t</span><span class="p">;</span>
<span class="k">static_assert</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">bgr232_pixel_t</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">);</span>
<span class="n">bgr232_pixel_t</span> <span class="nf">red</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span> <span class="c1">// = 0RRGGGBB, = 01100000 = 0x60</span>
<span class="c1">// a buffer of 7 bytes fits exactly 8 BGR232 pixels.</span>
<span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">pix_buffer</span><span class="p">[</span><span class="mi">7</span><span class="p">];</span>
<span class="n">std</span><span class="o">::</span><span class="n">fill</span><span class="p">(</span><span class="n">pix_buffer</span><span class="p">,</span><span class="n">pix_buffer</span><span class="o">+</span><span class="mi">7</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="c1">// Fill the 8 pixels with red</span>
<span class="n">bgr232_ptr_t</span> <span class="nf">pix_it</span><span class="p">(</span><span class="o">&amp;</span><span class="n">pix_buffer</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// start at bit 0 of the first pixel</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="mi">8</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span>
<span class="p">{</span>
<span class="o">*</span><span class="n">pix_it</span><span class="o">++</span> <span class="o">=</span> <span class="n">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// Result: 0x60 0x30 0x11 0x0C 0x06 0x83 0xC1</span>
</pre></div>
</div>
</div>
<div class="section" id="id6">
<h3>Algorithms</h3>
<p>Since pixels model <code class="docutils literal notranslate"><span class="pre">ColorBaseConcept</span></code> and <code class="docutils literal notranslate"><span class="pre">PixelBasedConcept</span></code> all
algorithms and metafunctions of color bases can work with them as well:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// This is how to access the first semantic channel (red)</span>
<span class="n">assert</span><span class="p">(</span><span class="n">semantic_at_c</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">rgb8</span><span class="p">)</span> <span class="o">==</span> <span class="n">semantic_at_c</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">bgr8</span><span class="p">));</span>
<span class="c1">// This is how to access the red channel by name</span>
<span class="n">assert</span><span class="p">(</span><span class="n">get_color</span><span class="o">&lt;</span><span class="n">red_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">rgb8</span><span class="p">)</span> <span class="o">==</span> <span class="n">get_color</span><span class="o">&lt;</span><span class="n">red_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">bgr8</span><span class="p">));</span>
<span class="c1">// This is another way of doing it (some compilers don&#39;t like the first one)</span>
<span class="n">assert</span><span class="p">(</span><span class="n">get_color</span><span class="p">(</span><span class="n">rgb8</span><span class="p">,</span><span class="n">red_t</span><span class="p">())</span> <span class="o">==</span> <span class="n">get_color</span><span class="p">(</span><span class="n">bgr8</span><span class="p">,</span><span class="n">red_t</span><span class="p">()));</span>
<span class="c1">// This is how to use the PixelBasedConcept metafunctions</span>
<span class="n">BOOST_MPL_ASSERT</span><span class="p">(</span><span class="n">num_channels</span><span class="o">&lt;</span><span class="n">rgb8_pixel_t</span><span class="o">&gt;::</span><span class="n">value</span> <span class="o">==</span> <span class="mi">3</span><span class="p">);</span>
<span class="n">BOOST_MPL_ASSERT</span><span class="p">((</span><span class="n">is_same</span><span class="o">&lt;</span><span class="n">channel_type</span><span class="o">&lt;</span><span class="n">rgb8_pixel_t</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">,</span> <span class="n">bits8</span><span class="o">&gt;</span><span class="p">));</span>
<span class="n">BOOST_MPL_ASSERT</span><span class="p">((</span><span class="n">is_same</span><span class="o">&lt;</span><span class="n">color_space_type</span><span class="o">&lt;</span><span class="n">bgr8_pixel_t</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">,</span> <span class="n">rgb_t</span><span class="o">&gt;</span> <span class="p">));</span>
<span class="n">BOOST_MPL_ASSERT</span><span class="p">((</span><span class="n">is_same</span><span class="o">&lt;</span><span class="n">channel_mapping_type</span><span class="o">&lt;</span><span class="n">bgr8_pixel_t</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">vector3_c</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="p">));</span>
<span class="c1">// Pixels contain just the three channels and nothing extra</span>
<span class="n">BOOST_MPL_ASSERT</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">rgb8_pixel_t</span><span class="p">)</span><span class="o">==</span><span class="mi">3</span><span class="p">);</span>
<span class="n">rgb8_planar_ref_t</span> <span class="nf">ref</span><span class="p">(</span><span class="n">bgr8</span><span class="p">);</span> <span class="c1">// copy construction is allowed from a compatible mutable pixel type</span>
<span class="n">get_color</span><span class="o">&lt;</span><span class="n">red_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ref</span><span class="p">)</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span> <span class="c1">// assignment is ok because the reference is mutable</span>
<span class="n">assert</span><span class="p">(</span><span class="n">get_color</span><span class="o">&lt;</span><span class="n">red_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">bgr8</span><span class="p">)</span><span class="o">==</span><span class="mi">10</span><span class="p">);</span> <span class="c1">// references modify the value they are bound to</span>
<span class="c1">// Create a zero packed pixel and a full regular unpacked pixel.</span>
<span class="n">rgb565_pixel_t</span> <span class="n">r565</span><span class="p">;</span>
<span class="n">rgb8_pixel_t</span> <span class="nf">rgb_full</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">255</span><span class="p">);</span>
<span class="c1">// Convert all channels of the unpacked pixel to the packed one &amp; assert the packed one is full</span>
<span class="n">get_color</span><span class="p">(</span><span class="n">r565</span><span class="p">,</span><span class="n">red_t</span><span class="p">())</span> <span class="o">=</span> <span class="n">channel_convert</span><span class="o">&lt;</span><span class="n">rgb565_channel0_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">get_color</span><span class="p">(</span><span class="n">rgb_full</span><span class="p">,</span><span class="n">red_t</span><span class="p">()));</span>
<span class="n">get_color</span><span class="p">(</span><span class="n">r565</span><span class="p">,</span><span class="n">green_t</span><span class="p">())</span> <span class="o">=</span> <span class="n">channel_convert</span><span class="o">&lt;</span><span class="n">rgb565_channel1_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">get_color</span><span class="p">(</span><span class="n">rgb_full</span><span class="p">,</span><span class="n">green_t</span><span class="p">()));</span>
<span class="n">get_color</span><span class="p">(</span><span class="n">r565</span><span class="p">,</span><span class="n">blue_t</span><span class="p">())</span> <span class="o">=</span> <span class="n">channel_convert</span><span class="o">&lt;</span><span class="n">rgb565_channel2_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">get_color</span><span class="p">(</span><span class="n">rgb_full</span><span class="p">,</span><span class="n">blue_t</span><span class="p">()));</span>
<span class="n">assert</span><span class="p">(</span><span class="n">r565</span> <span class="o">==</span> <span class="n">rgb565_pixel_t</span><span class="p">((</span><span class="kt">uint16_t</span><span class="p">)</span><span class="mi">65535</span><span class="p">));</span>
</pre></div>
</div>
<p>GIL also provides the <code class="docutils literal notranslate"><span class="pre">color_convert</span></code> algorithm to convert between pixels of
different color spaces and channel types:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">rgb8_pixel_t</span> <span class="nf">red_in_rgb8</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="n">cmyk16_pixel_t</span> <span class="n">red_in_cmyk16</span><span class="p">;</span>
<span class="n">color_convert</span><span class="p">(</span><span class="n">red_in_rgb8</span><span class="p">,</span><span class="n">red_in_cmyk16</span><span class="p">);</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="pixel-iterator">
<h2><a class="toc-backref" href="#id22">Pixel Iterator</a></h2>
<p>Pixel iterators are random traversal iterators whose <code class="docutils literal notranslate"><span class="pre">value_type</span>
<span class="pre">models</span></code> <code class="docutils literal notranslate"><span class="pre">PixelValueConcept</span></code>.</p>
<div class="section" id="fundamental-iterator">
<h3>Fundamental Iterator</h3>
<p>Pixel iterators provide metafunctions to determine whether they are mutable
(i.e. whether they allow for modifying the pixel they refer to), to get the
immutable (read-only) type of the iterator, and to determine whether they are
plain iterators or adaptors over another pixel iterator:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">PixelIteratorConcept</span><span class="o">&lt;</span><span class="n">RandomAccessTraversalIteratorConcept</span> <span class="n">Iterator</span><span class="o">&gt;</span>
<span class="o">:</span> <span class="n">PixelBasedConcept</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">PixelValueConcept</span><span class="o">&lt;</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">const_iterator_type</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">;</span>
<span class="n">where</span> <span class="n">PixelIteratorConcept</span><span class="o">&lt;</span><span class="n">const_iterator_type</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">static</span> <span class="k">const</span> <span class="kt">bool</span> <span class="n">iterator_is_mutable</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">value</span><span class="p">;</span>
<span class="k">static</span> <span class="k">const</span> <span class="kt">bool</span> <span class="n">is_iterator_adaptor</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">value</span><span class="p">;</span> <span class="c1">// is it an iterator adaptor</span>
<span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Iterator</span><span class="o">&gt;</span>
<span class="n">concept</span> <span class="nl">MutablePixelIteratorConcept</span> <span class="p">:</span> <span class="n">PixelIteratorConcept</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">MutableRandomAccessIteratorConcept</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;</span> <span class="p">{};</span>
</pre></div>
</div>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<ul class="simple">
<li><p><a class="reference external" href="reference/group___pixel_iterator_concept_pixel_iterator.html">PixelIteratorConcept&lt;Iterator&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_pixel_iterator_concept.html">MutablePixelIteratorConcept&lt;Iterator&gt;</a></p></li>
</ul>
</div>
<div class="section" id="id7">
<h4>Models</h4>
<p>A built-in pointer to pixel, <code class="docutils literal notranslate"><span class="pre">pixel&lt;ChannelValue,Layout&gt;*</span></code>, is GIL model for
pixel iterator over interleaved homogeneous pixels. Similarly,
<code class="docutils literal notranslate"><span class="pre">packed_pixel&lt;PixelData,ChannelRefVec,Layout&gt;*</span></code> is GIL model for an iterator
over interleaved packed pixels.</p>
<p>For planar homogeneous pixels, GIL provides the class
<code class="docutils literal notranslate"><span class="pre">planar_pixel_iterator</span></code>, templated over a channel iterator and color space.
Here is how the standard mutable and read-only planar RGB iterators over
unsigned char are defined:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ChannelPtr</span><span class="p">,</span> <span class="k">typename</span> <span class="n">ColorSpace</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">planar_pixel_iterator</span><span class="p">;</span>
<span class="c1">// GIL provided typedefs</span>
<span class="k">typedef</span> <span class="n">planar_pixel_iterator</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">bits8</span><span class="o">*</span><span class="p">,</span> <span class="n">rgb_t</span><span class="o">&gt;</span> <span class="n">rgb8c_planar_ptr_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">planar_pixel_iterator</span><span class="o">&lt;</span> <span class="n">bits8</span><span class="o">*</span><span class="p">,</span> <span class="n">rgb_t</span><span class="o">&gt;</span> <span class="n">rgb8_planar_ptr_t</span><span class="p">;</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">planar_pixel_iterator</span></code> also models <code class="docutils literal notranslate"><span class="pre">HomogeneousColorBaseConcept</span></code> (it
subclasses from <code class="docutils literal notranslate"><span class="pre">homogeneous_color_base</span></code>) and, as a result, all color base
algorithms apply to it. The element type of its color base is a channel
iterator. For example, GIL implements <code class="docutils literal notranslate"><span class="pre">operator++</span></code> of planar iterators
approximately like this:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="nl">inc</span> <span class="p">:</span> <span class="k">public</span> <span class="n">std</span><span class="o">::</span><span class="n">unary_function</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">T</span> <span class="k">operator</span><span class="p">()(</span><span class="n">T</span> <span class="n">x</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="o">++</span><span class="n">x</span><span class="p">;</span> <span class="p">}</span>
<span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ChannelPtr</span><span class="p">,</span> <span class="k">typename</span> <span class="n">ColorSpace</span><span class="o">&gt;</span>
<span class="n">planar_pixel_iterator</span><span class="o">&lt;</span><span class="n">ChannelPtr</span><span class="p">,</span><span class="n">ColorSpace</span><span class="o">&gt;&amp;</span>
<span class="n">planar_pixel_iterator</span><span class="o">&lt;</span><span class="n">ChannelPtr</span><span class="p">,</span><span class="n">ColorSpace</span><span class="o">&gt;::</span><span class="k">operator</span><span class="o">++</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">static_transform</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">,</span><span class="o">*</span><span class="k">this</span><span class="p">,</span><span class="n">inc</span><span class="o">&lt;</span><span class="n">ChannelPtr</span><span class="o">&gt;</span><span class="p">());</span>
<span class="k">return</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Since <code class="docutils literal notranslate"><span class="pre">static_transform</span></code> uses compile-time recursion, incrementing an
instance of <code class="docutils literal notranslate"><span class="pre">rgb8_planar_ptr_t</span></code> amounts to three pointer increments.
GIL also uses the class <code class="docutils literal notranslate"><span class="pre">bit_aligned_pixel_iterator</span></code> as a model for a pixel
iterator over bit-aligned pixels. Internally it keeps track of the current
byte and the bit offset.</p>
</div>
</div>
<div class="section" id="iterator-adaptor">
<h3>Iterator Adaptor</h3>
<p>Iterator adaptor is an iterator that wraps around another iterator. Its
<code class="docutils literal notranslate"><span class="pre">is_iterator_adaptor</span></code> metafunction must evaluate to true, and it needs to
provide a member method to return the base iterator, a metafunction to get its
type, and a metafunction to rebind to another base iterator:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">IteratorAdaptorConcept</span><span class="o">&lt;</span><span class="n">RandomAccessTraversalIteratorConcept</span> <span class="n">Iterator</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="n">is_iterator_adaptor</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">true_</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">iterator_adaptor_get_base</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">iterator_adaptor_get_base</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">boost_concepts</span><span class="o">::</span><span class="n">ForwardTraversalConcept</span><span class="o">&lt;</span><span class="n">iterator_adaptor_get_base</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">another_iterator</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">iterator_adaptor_rebind</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="p">,</span><span class="n">another_iterator</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">;</span>
<span class="n">where</span> <span class="n">boost_concepts</span><span class="o">::</span><span class="n">ForwardTraversalConcept</span><span class="o">&lt;</span><span class="n">another_iterator</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">IteratorAdaptorConcept</span><span class="o">&lt;</span><span class="n">iterator_adaptor_rebind</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="p">,</span><span class="n">another_iterator</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">const</span> <span class="n">iterator_adaptor_get_base</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&amp;</span> <span class="n">Iterator</span><span class="o">::</span><span class="n">base</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">boost_concepts</span><span class="o">::</span><span class="n">Mutable_ForwardIteratorConcept</span> <span class="n">Iterator</span><span class="o">&gt;</span>
<span class="n">concept</span> <span class="nl">MutableIteratorAdaptorConcept</span> <span class="p">:</span> <span class="n">IteratorAdaptorConcept</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;</span> <span class="p">{};</span>
</pre></div>
</div>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<ul class="simple">
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_iterator_adaptor_concept.html">IteratorAdaptorConcept&lt;Iterator&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_iterator_adaptor_concept.html">MutableIteratorAdaptorConcept&lt;Iterator&gt;</a></p></li>
</ul>
</div>
<div class="section" id="id8">
<h4>Models</h4>
<p>GIL provides several models of <code class="docutils literal notranslate"><span class="pre">IteratorAdaptorConcept</span></code>:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">memory_based_step_iterator&lt;Iterator&gt;</span></code>: An iterator adaptor that changes
the fundamental step of the base iterator
(see <a class="reference internal" href="#step-iterator"><span class="std std-ref">Step Iterator</span></a>)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">dereference_iterator_adaptor&lt;Iterator,Fn&gt;</span></code>: An iterator that applies a
unary function <code class="docutils literal notranslate"><span class="pre">Fn</span></code> upon dereferencing. It is used, for example, for
on-the-fly color conversion. It can be used to construct a shallow image
“view” that pretends to have a different color space or channel depth.
See <a class="reference internal" href="#image-view"><span class="std std-ref">Image View</span></a> for more. The unary function <code class="docutils literal notranslate"><span class="pre">Fn</span></code> must
model <code class="docutils literal notranslate"><span class="pre">PixelDereferenceAdaptorConcept</span></code> (see below).</p></li>
</ul>
</div>
</div>
<div class="section" id="pixel-dereference-adaptor">
<h3>Pixel Dereference Adaptor</h3>
<p>Pixel dereference adaptor is a unary function that can be applied upon
dereferencing a pixel iterator. Its argument type could be anything (usually a
<code class="docutils literal notranslate"><span class="pre">PixelConcept</span></code>) and the result type must be convertible to <code class="docutils literal notranslate"><span class="pre">PixelConcept</span></code>:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="n">boost</span><span class="o">::</span><span class="n">UnaryFunctionConcept</span> <span class="n">D</span><span class="o">&gt;</span>
<span class="n">concept</span> <span class="nl">PixelDereferenceAdaptorConcept</span><span class="p">:</span>
<span class="n">DefaultConstructibleConcept</span><span class="o">&lt;</span><span class="n">D</span><span class="o">&gt;</span><span class="p">,</span>
<span class="n">CopyConstructibleConcept</span><span class="o">&lt;</span><span class="n">D</span><span class="o">&gt;</span><span class="p">,</span>
<span class="n">AssignableConcept</span><span class="o">&lt;</span><span class="n">D</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">const_t</span><span class="p">;</span> <span class="n">where</span> <span class="n">PixelDereferenceAdaptorConcept</span><span class="o">&lt;</span><span class="n">const_t</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">value_type</span><span class="p">;</span> <span class="n">where</span> <span class="n">PixelValueConcept</span><span class="o">&lt;</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">reference</span><span class="p">;</span> <span class="n">where</span> <span class="n">PixelConcept</span><span class="o">&lt;</span><span class="n">remove_reference</span><span class="o">&lt;</span><span class="n">reference</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span><span class="p">;</span> <span class="c1">// may be mutable</span>
<span class="k">typename</span> <span class="n">const_reference</span><span class="p">;</span> <span class="c1">// must not be mutable</span>
<span class="k">static</span> <span class="k">const</span> <span class="kt">bool</span> <span class="n">D</span><span class="o">::</span><span class="n">is_mutable</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Convertible</span><span class="o">&lt;</span><span class="n">value_type</span><span class="p">,</span> <span class="n">result_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<div class="section" id="id9">
<h4>Models</h4>
<p>GIL provides several models of <code class="docutils literal notranslate"><span class="pre">PixelDereferenceAdaptorConcept</span></code>:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">color_convert_deref_fn</span></code>: a function object that performs color conversion</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">detail::nth_channel_deref_fn</span></code>: a function object that returns a grayscale
pixel corresponding to the n-th channel of a given pixel</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">deref_compose</span></code>: a function object that composes two models of
<code class="docutils literal notranslate"><span class="pre">PixelDereferenceAdaptorConcept</span></code>. Similar to <code class="docutils literal notranslate"><span class="pre">std::unary_compose</span></code>,
except it needs to pull the additional typedefs required by
<code class="docutils literal notranslate"><span class="pre">PixelDereferenceAdaptorConcept</span></code></p></li>
</ul>
<p>GIL uses pixel dereference adaptors to implement image views that perform
color conversion upon dereferencing, or that return the N-th channel of the
underlying pixel. They can be used to model virtual image views that perform
an arbitrary function upon dereferencing, for example a view of the Mandelbrot
set. <code class="docutils literal notranslate"><span class="pre">dereference_iterator_adaptor&lt;Iterator,Fn&gt;</span></code> is an iterator wrapper over
a pixel iterator <code class="docutils literal notranslate"><span class="pre">Iterator</span></code> that invokes the given dereference iterator
adaptor <code class="docutils literal notranslate"><span class="pre">Fn</span></code> upon dereferencing.</p>
</div>
</div>
<div class="section" id="step-iterator">
<h3>Step Iterator</h3>
<p>Sometimes we want to traverse pixels with a unit step other than the one
provided by the fundamental pixel iterators. Examples where this would be
useful:</p>
<ul class="simple">
<li><p>a single-channel view of the red channel of an RGB interleaved image</p></li>
<li><p>left-to-right flipped image (step = -fundamental_step)</p></li>
<li><p>subsampled view, taking every N-th pixel (step = N*fundamental_step)</p></li>
<li><p>traversal in vertical direction (step = number of bytes per row)</p></li>
<li><p>any combination of the above (steps are multiplied)</p></li>
</ul>
<p>Step iterators are forward traversal iterators that allow changing the step
between adjacent values:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">StepIteratorConcept</span><span class="o">&lt;</span><span class="n">boost_concepts</span><span class="o">::</span><span class="n">ForwardTraversalConcept</span> <span class="n">Iterator</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">Integral</span> <span class="n">D</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">Iterator</span><span class="o">::</span><span class="n">set_step</span><span class="p">(</span><span class="n">D</span> <span class="n">step</span><span class="p">);</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutableStepIteratorConcept</span><span class="o">&lt;</span><span class="n">boost_concepts</span><span class="o">::</span><span class="n">Mutable_ForwardIteratorConcept</span> <span class="n">Iterator</span><span class="o">&gt;</span>
<span class="o">:</span> <span class="n">StepIteratorConcept</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;</span>
<span class="p">{};</span>
</pre></div>
</div>
<p>GIL currently provides a step iterator whose <code class="docutils literal notranslate"><span class="pre">value_type</span> <span class="pre">models</span></code>
<code class="docutils literal notranslate"><span class="pre">PixelValueConcept</span></code>. In addition, the step is specified in memory units
(which are bytes or bits). This is necessary, for example, when implementing
an iterator navigating along a column of pixels - the size of a row of pixels
may sometimes not be divisible by the size of a pixel; for example rows may be
word-aligned.</p>
<p>To advance in bytes/bits, the base iterator must model
<code class="docutils literal notranslate"><span class="pre">MemoryBasedIteratorConcept</span></code>. A memory-based iterator has an inherent memory
unit, which is either a bit or a byte. It must supply functions returning the
number of bits per memory unit (1 or 8), the current step in memory units, the
memory-unit distance between two iterators, and a reference a given distance
in memunits away. It must also supply a function that advances an iterator a
given distance in memory units. <code class="docutils literal notranslate"><span class="pre">memunit_advanced</span></code> and
<code class="docutils literal notranslate"><span class="pre">memunit_advanced_ref</span></code> have a default implementation but some iterators may
supply a more efficient version:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">MemoryBasedIteratorConcept</span>
<span class="o">&lt;</span>
<span class="n">boost_concepts</span><span class="o">::</span><span class="n">RandomAccessTraversalConcept</span> <span class="n">Iterator</span>
<span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">byte_to_memunit</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;</span><span class="p">;</span> <span class="n">where</span> <span class="n">metafunction</span><span class="o">&lt;</span><span class="n">byte_to_memunit</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">memunit_step</span><span class="p">(</span><span class="k">const</span> <span class="n">Iterator</span><span class="o">&amp;</span><span class="p">);</span>
<span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">memunit_distance</span><span class="p">(</span><span class="k">const</span> <span class="n">Iterator</span><span class="o">&amp;</span> <span class="p">,</span> <span class="k">const</span> <span class="n">Iterator</span><span class="o">&amp;</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">memunit_advance</span><span class="p">(</span><span class="n">Iterator</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">diff</span><span class="p">);</span>
<span class="n">Iterator</span> <span class="nf">memunit_advanced</span><span class="p">(</span><span class="k">const</span> <span class="n">Iterator</span><span class="o">&amp;</span> <span class="n">p</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">diff</span><span class="p">)</span> <span class="p">{</span> <span class="n">Iterator</span> <span class="n">tmp</span><span class="p">;</span> <span class="n">memunit_advance</span><span class="p">(</span><span class="n">tmp</span><span class="p">,</span><span class="n">diff</span><span class="p">);</span> <span class="k">return</span> <span class="n">tmp</span><span class="p">;</span> <span class="p">}</span>
<span class="n">Iterator</span><span class="o">::</span><span class="n">reference</span> <span class="n">memunit_advanced_ref</span><span class="p">(</span><span class="k">const</span> <span class="n">Iterator</span><span class="o">&amp;</span> <span class="n">p</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">diff</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="o">*</span><span class="n">memunit_advanced</span><span class="p">(</span><span class="n">p</span><span class="p">,</span><span class="n">diff</span><span class="p">);</span> <span class="p">}</span>
<span class="p">};</span>
</pre></div>
</div>
<p>It is useful to be able to construct a step iterator over another iterator.
More generally, given a type, we want to be able to construct an equivalent
type that allows for dynamically specified horizontal step:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">HasDynamicXStepTypeConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">dynamic_x_step_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>All models of pixel iterators, locators and image views that GIL provides
support <code class="docutils literal notranslate"><span class="pre">HasDynamicXStepTypeConcept</span></code>.</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<ul class="simple">
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_step_iterator_concept.html">StepIteratorConcept&lt;Iterator&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_step_iterator_concept.html">MutableStepIteratorConcept&lt;Iterator&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_memory_based_iterator_concept.html">MemoryBasedIteratorConcept&lt;Iterator&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_has_dynamic_x_step_type_concept.html">HasDynamicXStepTypeConcept&lt;T&gt;</a></p></li>
</ul>
</div>
<div class="section" id="id10">
<h4>Models</h4>
<p>All standard memory-based iterators GIL currently provides model
<code class="docutils literal notranslate"><span class="pre">MemoryBasedIteratorConcept</span></code>. GIL provides the class
<code class="docutils literal notranslate"><span class="pre">memory_based_step_iterator</span></code> which models <code class="docutils literal notranslate"><span class="pre">PixelIteratorConcept</span></code>,
<code class="docutils literal notranslate"><span class="pre">StepIteratorConcept</span></code>, and <code class="docutils literal notranslate"><span class="pre">MemoryBasedIteratorConcept</span></code>. It takes the base
iterator as a template parameter (which must model <code class="docutils literal notranslate"><span class="pre">PixelIteratorConcept</span></code>
and <code class="docutils literal notranslate"><span class="pre">MemoryBasedIteratorConcept</span></code>) and allows changing the step dynamically.
GIL implementation contains the base iterator and a <code class="docutils literal notranslate"><span class="pre">ptrdiff_t</span></code> denoting the
number of memory units (bytes or bits) to skip for a unit step. It may also be
used with a negative number. GIL provides a function to create a step iterator
from a base iterator and a step:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Iterator models MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Iterator</span><span class="o">&gt;</span>
<span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o">&lt;</span><span class="n">Iterator</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">make_step_iterator</span><span class="p">(</span><span class="n">Iterator</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">it</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">step</span><span class="p">);</span>
</pre></div>
</div>
<p>GIL also provides a model of an iterator over a virtual array of pixels,
<code class="docutils literal notranslate"><span class="pre">position_iterator</span></code>. It is a step iterator that keeps track of the pixel
position and invokes a function object to get the value of the pixel upon
dereferencing. It models <code class="docutils literal notranslate"><span class="pre">PixelIteratorConcept</span></code> and <code class="docutils literal notranslate"><span class="pre">StepIteratorConcept</span></code>
but not <code class="docutils literal notranslate"><span class="pre">MemoryBasedIteratorConcept</span></code>.</p>
</div>
</div>
</div>
<div class="section" id="pixel-locator">
<h2><a class="toc-backref" href="#id23">Pixel Locator</a></h2>
<p>A Locator allows for navigation in two or more dimensions. Locators are
N-dimensional iterators in spirit, but we use a different name because they
dont satisfy all the requirements of iterators. For example, they dont
supply increment and decrement operators because it is unclear which dimension
the operators should advance along.
N-dimensional locators model the following concept:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">RandomAccessNDLocatorConcept</span><span class="o">&lt;</span><span class="n">Regular</span> <span class="n">Loc</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">value_type</span><span class="p">;</span> <span class="c1">// value over which the locator navigates</span>
<span class="k">typename</span> <span class="n">reference</span><span class="p">;</span> <span class="c1">// result of dereferencing</span>
<span class="k">typename</span> <span class="n">difference_type</span><span class="p">;</span> <span class="n">where</span> <span class="n">PointNDConcept</span><span class="o">&lt;</span><span class="n">difference_type</span><span class="o">&gt;</span><span class="p">;</span> <span class="c1">// return value of operator-.</span>
<span class="k">typename</span> <span class="n">const_t</span><span class="p">;</span> <span class="c1">// same as Loc, but operating over immutable values</span>
<span class="k">typename</span> <span class="n">cached_location_t</span><span class="p">;</span> <span class="c1">// type to store relative location (for efficient repeated access)</span>
<span class="k">typename</span> <span class="n">point_t</span> <span class="o">=</span> <span class="n">difference_type</span><span class="p">;</span>
<span class="k">static</span> <span class="k">const</span> <span class="kt">size_t</span> <span class="n">num_dimensions</span><span class="p">;</span> <span class="c1">// dimensionality of the locator</span>
<span class="n">where</span> <span class="n">num_dimensions</span> <span class="o">=</span> <span class="n">point_t</span><span class="o">::</span><span class="n">num_dimensions</span><span class="p">;</span>
<span class="c1">// The difference_type and iterator type along each dimension. The iterators may only differ in</span>
<span class="c1">// difference_type. Their value_type must be the same as Loc::value_type</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">axis</span> <span class="p">{</span>
<span class="k">typename</span> <span class="n">coord_t</span> <span class="o">=</span> <span class="n">point_t</span><span class="o">::</span><span class="n">axis</span><span class="o">&lt;</span><span class="n">D</span><span class="o">&gt;::</span><span class="n">coord_t</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">iterator</span><span class="p">;</span> <span class="n">where</span> <span class="n">RandomAccessTraversalConcept</span><span class="o">&lt;</span><span class="n">iterator</span><span class="o">&gt;</span><span class="p">;</span> <span class="c1">// iterator along D-th axis.</span>
<span class="n">where</span> <span class="n">iterator</span><span class="o">::</span><span class="n">value_type</span> <span class="o">==</span> <span class="n">value_type</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">// Defines the type of a locator similar to this type, except it invokes Deref upon dereferencing</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">PixelDereferenceAdaptorConcept</span> <span class="n">Deref</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">add_deref</span> <span class="p">{</span>
<span class="k">typename</span> <span class="n">type</span><span class="p">;</span> <span class="n">where</span> <span class="n">RandomAccessNDLocatorConcept</span><span class="o">&lt;</span><span class="n">type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">static</span> <span class="n">type</span> <span class="nf">make</span><span class="p">(</span><span class="k">const</span> <span class="n">Loc</span><span class="o">&amp;</span> <span class="n">loc</span><span class="p">,</span> <span class="k">const</span> <span class="n">Deref</span><span class="o">&amp;</span> <span class="n">deref</span><span class="p">);</span>
<span class="p">};</span>
<span class="n">Loc</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">+=</span><span class="p">(</span><span class="n">Loc</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">);</span>
<span class="n">Loc</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">-=</span><span class="p">(</span><span class="n">Loc</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">);</span>
<span class="n">Loc</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="k">const</span> <span class="n">Loc</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">);</span>
<span class="n">Loc</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="k">const</span> <span class="n">Loc</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">);</span>
<span class="n">reference</span> <span class="k">operator</span><span class="o">*</span><span class="p">(</span><span class="k">const</span> <span class="n">Loc</span><span class="o">&amp;</span><span class="p">);</span>
<span class="n">reference</span> <span class="k">operator</span><span class="p">[](</span><span class="k">const</span> <span class="n">Loc</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">);</span>
<span class="c1">// Storing relative location for faster repeated access and accessing it</span>
<span class="n">cached_location_t</span> <span class="n">Loc</span><span class="o">::</span><span class="n">cache_location</span><span class="p">(</span><span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">reference</span> <span class="k">operator</span><span class="p">[](</span><span class="k">const</span> <span class="n">Loc</span><span class="o">&amp;</span><span class="p">,</span><span class="k">const</span> <span class="n">cached_location_t</span><span class="o">&amp;</span><span class="p">);</span>
<span class="c1">// Accessing iterators along a given dimension at the current location or at a given offset</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">&gt;</span> <span class="n">axis</span><span class="o">&lt;</span><span class="n">D</span><span class="o">&gt;::</span><span class="n">iterator</span><span class="o">&amp;</span> <span class="n">Loc</span><span class="o">::</span><span class="n">axis_iterator</span><span class="p">();</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">&gt;</span> <span class="n">axis</span><span class="o">&lt;</span><span class="n">D</span><span class="o">&gt;::</span><span class="n">iterator</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">Loc</span><span class="o">::</span><span class="n">axis_iterator</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">&gt;</span> <span class="n">axis</span><span class="o">&lt;</span><span class="n">D</span><span class="o">&gt;::</span><span class="n">iterator</span> <span class="n">Loc</span><span class="o">::</span><span class="n">axis_iterator</span><span class="p">(</span><span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Loc</span><span class="o">&gt;</span>
<span class="n">concept</span> <span class="nl">MutableRandomAccessNDLocatorConcept</span>
<span class="p">:</span> <span class="n">RandomAccessNDLocatorConcept</span><span class="o">&lt;</span><span class="n">Loc</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">Mutable</span><span class="o">&lt;</span><span class="n">reference</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Two-dimensional locators have additional requirements:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">RandomAccess2DLocatorConcept</span><span class="o">&lt;</span><span class="n">RandomAccessNDLocatorConcept</span> <span class="n">Loc</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">num_dimensions</span><span class="o">==</span><span class="mi">2</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Point2DConcept</span><span class="o">&lt;</span><span class="n">point_t</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">x_iterator</span> <span class="o">=</span> <span class="n">axis</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;::</span><span class="n">iterator</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">y_iterator</span> <span class="o">=</span> <span class="n">axis</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;::</span><span class="n">iterator</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">x_coord_t</span> <span class="o">=</span> <span class="n">axis</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;::</span><span class="n">coord_t</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">y_coord_t</span> <span class="o">=</span> <span class="n">axis</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;::</span><span class="n">coord_t</span><span class="p">;</span>
<span class="c1">// Only available to locators that have dynamic step in Y</span>
<span class="c1">//Loc::Loc(const Loc&amp; loc, y_coord_t);</span>
<span class="c1">// Only available to locators that have dynamic step in X and Y</span>
<span class="c1">//Loc::Loc(const Loc&amp; loc, x_coord_t, y_coord_t, bool transposed=false);</span>
<span class="n">x_iterator</span><span class="o">&amp;</span> <span class="n">Loc</span><span class="o">::</span><span class="n">x</span><span class="p">();</span>
<span class="n">x_iterator</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">Loc</span><span class="o">::</span><span class="n">x</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_iterator</span><span class="o">&amp;</span> <span class="n">Loc</span><span class="o">::</span><span class="n">y</span><span class="p">();</span>
<span class="n">y_iterator</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">Loc</span><span class="o">::</span><span class="n">y</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">x_iterator</span> <span class="n">Loc</span><span class="o">::</span><span class="n">x_at</span><span class="p">(</span><span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_iterator</span> <span class="n">Loc</span><span class="o">::</span><span class="n">y_at</span><span class="p">(</span><span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">Loc</span> <span class="n">Loc</span><span class="o">::</span><span class="n">xy_at</span><span class="p">(</span><span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="c1">// x/y versions of all methods that can take difference type</span>
<span class="n">x_iterator</span> <span class="n">Loc</span><span class="o">::</span><span class="n">x_at</span><span class="p">(</span><span class="n">x_coord_t</span><span class="p">,</span> <span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_iterator</span> <span class="n">Loc</span><span class="o">::</span><span class="n">y_at</span><span class="p">(</span><span class="n">x_coord_t</span><span class="p">,</span> <span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">Loc</span> <span class="n">Loc</span><span class="o">::</span><span class="n">xy_at</span><span class="p">(</span><span class="n">x_coord_t</span><span class="p">,</span> <span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">reference</span> <span class="nf">operator</span><span class="p">()(</span><span class="k">const</span> <span class="n">Loc</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">x_coord_t</span><span class="p">,</span> <span class="n">y_coord_t</span><span class="p">);</span>
<span class="n">cached_location_t</span> <span class="n">Loc</span><span class="o">::</span><span class="n">cache_location</span><span class="p">(</span><span class="n">x_coord_t</span><span class="p">,</span> <span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="kt">bool</span> <span class="n">Loc</span><span class="o">::</span><span class="n">is_1d_traversable</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_coord_t</span> <span class="n">Loc</span><span class="o">::</span><span class="n">y_distance_to</span><span class="p">(</span><span class="k">const</span> <span class="n">Loc</span><span class="o">&amp;</span> <span class="n">loc2</span><span class="p">,</span> <span class="n">x_coord_t</span> <span class="n">x_diff</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutableRandomAccess2DLocatorConcept</span><span class="o">&lt;</span><span class="n">RandomAccess2DLocatorConcept</span> <span class="n">Loc</span><span class="o">&gt;</span>
<span class="o">:</span> <span class="n">MutableRandomAccessNDLocatorConcept</span><span class="o">&lt;</span><span class="n">Loc</span><span class="o">&gt;</span> <span class="p">{};</span>
</pre></div>
</div>
<p>2D locators can have a dynamic step not just horizontally, but
vertically. This gives rise to the Y equivalent of
<code class="docutils literal notranslate"><span class="pre">HasDynamicXStepTypeConcept</span></code>:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">HasDynamicYStepTypeConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">dynamic_y_step_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">dynamic_y_step_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>All locators and image views that GIL provides model
<code class="docutils literal notranslate"><span class="pre">HasDynamicYStepTypeConcept</span></code>.</p>
<p>Sometimes it is necessary to swap the meaning of X and Y for a given locator
or image view type (for example, GIL provides a function to transpose an image
view). Such locators and views must be transposable:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">HasTransposedTypeConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">transposed_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">Metafunction</span><span class="o">&lt;</span><span class="n">transposed_type</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>All GIL provided locators and views model <code class="docutils literal notranslate"><span class="pre">HasTransposedTypeConcept</span></code>.</p>
<p>The locators GIL uses operate over models of <code class="docutils literal notranslate"><span class="pre">PixelConcept</span></code> and their x and
y dimension types are the same. They model the following concept:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">PixelLocatorConcept</span><span class="o">&lt;</span><span class="n">RandomAccess2DLocatorConcept</span> <span class="n">Loc</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">PixelValueConcept</span><span class="o">&lt;</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">PixelIteratorConcept</span><span class="o">&lt;</span><span class="n">x_iterator</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">PixelIteratorConcept</span><span class="o">&lt;</span><span class="n">y_iterator</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">x_coord_t</span> <span class="o">==</span> <span class="n">y_coord_t</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">coord_t</span> <span class="o">=</span> <span class="n">x_coord_t</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutablePixelLocatorConcept</span><span class="o">&lt;</span><span class="n">PixelLocatorConcept</span> <span class="n">Loc</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">MutableRandomAccess2DLocatorConcept</span><span class="o">&lt;</span><span class="n">Loc</span><span class="o">&gt;</span> <span class="p">{};</span>
</pre></div>
</div>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<ul class="simple">
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_has_dynamic_y_step_type_concept.html">HasDynamicYStepTypeConcept&lt;T&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_has_transposed_type_concept.html">HasTransposedTypeConcept&lt;T&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access_n_d_locator_concept.html">RandomAccessNDLocatorConcept&lt;Locator&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access_n_d_locator_concept.html">MutableRandomAccessNDLocatorConcept&lt;Locator&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access2_d_locator_concept.html">RandomAccess2DLocatorConcept&lt;Locator&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access2_d_locator_concept.html">MutableRandomAccess2DLocatorConcept&lt;Locator&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_locator_concept.html">PixelLocatorConcept&lt;Locator&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_pixel_locator_concept.html">MutablePixelLocatorConcept&lt;Locator&gt;</a></p></li>
</ul>
</div>
<div class="section" id="id11">
<h3>Models</h3>
<p>GIL provides two models of <code class="docutils literal notranslate"><span class="pre">PixelLocatorConcept</span></code> - a memory-based locator,
<code class="docutils literal notranslate"><span class="pre">memory_based_2d_locator</span></code> and a virtual locator <code class="docutils literal notranslate"><span class="pre">virtual_2d_locator</span></code>.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">memory_based_2d_locator</span></code> is a locator over planar or interleaved images
that have their pixels in memory. It takes a model of <code class="docutils literal notranslate"><span class="pre">StepIteratorConcept</span></code>
over pixels as a template parameter. (When instantiated with a model of
<code class="docutils literal notranslate"><span class="pre">MutableStepIteratorConcept</span></code>, it models <code class="docutils literal notranslate"><span class="pre">MutablePixelLocatorConcept</span></code>).</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// StepIterator models StepIteratorConcept, MemoryBasedIteratorConcept</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">StepIterator</span><span class="o">&gt;</span>
<span class="k">class</span> <span class="nc">memory_based_2d_locator</span><span class="p">;</span>
</pre></div>
</div>
<p>The step of <code class="docutils literal notranslate"><span class="pre">StepIterator</span></code> must be the number of memory units (bytes or
bits) per row (thus it must be memunit advanceable). The class
<code class="docutils literal notranslate"><span class="pre">memory_based_2d_locator</span></code> is a wrapper around <code class="docutils literal notranslate"><span class="pre">StepIterator</span></code> and uses it
to navigate vertically, while its base iterator is used to navigate
horizontally.</p>
<p>Combining fundamental iterator and step iterator allows us to create locators
that describe complex pixel memory organizations. First, we have a choice of
iterator to use for horizontal direction, i.e. for iterating over the pixels
on the same row. Using the fundamental and step iterators gives us four
choices:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">pixel&lt;T,C&gt;*</span></code> - for interleaved images</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">planar_pixel_iterator&lt;T*,C&gt;</span></code> - for planar images</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">memory_based_step_iterator&lt;pixel&lt;T,C&gt;*&gt;</span></code> - for interleaved images with
non-standard step)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">memory_based_step_iterator&lt;planar_pixel_iterator&lt;T*,C&gt;</span> <span class="pre">&gt;</span></code> - for planar
images with non-standard step</p></li>
</ul>
<p>Of course, one could provide their own custom x-iterator. One such example
described later is an iterator adaptor that performs color conversion when
dereferenced.</p>
<p>Given a horizontal iterator <code class="docutils literal notranslate"><span class="pre">XIterator</span></code>, we could choose the <code class="docutils literal notranslate"><span class="pre">y-iterator</span></code>,
the iterator that moves along a column, as
<code class="docutils literal notranslate"><span class="pre">memory_based_step_iterator&lt;XIterator&gt;</span></code> with a step equal to the number of
memory units (bytes or bits) per row. Again, one is free to provide their own
y-iterator.</p>
<p>Then we can instantiate
<code class="docutils literal notranslate"><span class="pre">memory_based_2d_locator&lt;memory_based_step_iterator&lt;XIterator&gt;</span> <span class="pre">&gt;</span></code> to obtain
a 2D pixel locator, as the diagram indicates:</p>
<img alt="_images/step_iterator.gif" src="_images/step_iterator.gif" />
<p>The <code class="docutils literal notranslate"><span class="pre">memory_based_2d_locator</span></code> also offers <cite>cached_location_t</cite> as mechanism
to store relative locations for optimized repeated access of neighborhood
pixels. The 2D coordinates of relative locations are cached as 1-dimensional
raw byte offsets. This provides efficient access if a neighboring locations
relative to a given locator are read or written frequently (e.g. in filters).</p>
<p>The <code class="docutils literal notranslate"><span class="pre">virtual_2d_locator</span></code> is a locator that is instantiated with a function
object invoked upon dereferencing a pixel. It returns the value of a pixel
given its X,Y coordinates. Virtual locators can be used to implement virtual
image views that can model any user-defined function. See the GIL tutorial for
an example of using virtual locators to create a view of the Mandelbrot set.</p>
<p>Both the virtual and the memory-based locators subclass from
<code class="docutils literal notranslate"><span class="pre">pixel_2d_locator_base</span></code>, a base class that provides most of the interface
required by <code class="docutils literal notranslate"><span class="pre">PixelLocatorConcept</span></code>. Users may find this base class useful if
they need to provide other models of <code class="docutils literal notranslate"><span class="pre">PixelLocatorConcept</span></code>.</p>
<p>Here is some sample code using locators:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">loc</span><span class="o">=</span><span class="n">img</span><span class="p">.</span><span class="n">xy_at</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">10</span><span class="p">);</span> <span class="c1">// start at pixel (x=10,y=10)</span>
<span class="n">above</span><span class="o">=</span><span class="n">loc</span><span class="p">.</span><span class="n">cache_location</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> <span class="c1">// remember relative locations of neighbors above and below</span>
<span class="n">below</span><span class="o">=</span><span class="n">loc</span><span class="p">.</span><span class="n">cache_location</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="o">++</span><span class="n">loc</span><span class="p">.</span><span class="n">x</span><span class="p">();</span> <span class="c1">// move to (11,10)</span>
<span class="n">loc</span><span class="p">.</span><span class="n">y</span><span class="p">()</span><span class="o">+=</span><span class="mi">15</span><span class="p">;</span> <span class="c1">// move to (11,25)</span>
<span class="n">loc</span><span class="o">-=</span><span class="n">point</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span><span class="c1">// move to (10,24)</span>
<span class="o">*</span><span class="n">loc</span><span class="o">=</span><span class="p">(</span><span class="n">loc</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">+</span><span class="n">loc</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">))</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span> <span class="c1">// set pixel (10,24) to the average of (10,23) and (10,25) (grayscale pixels only)</span>
<span class="o">*</span><span class="n">loc</span><span class="o">=</span><span class="p">(</span><span class="n">loc</span><span class="p">[</span><span class="n">above</span><span class="p">]</span><span class="o">+</span><span class="n">loc</span><span class="p">[</span><span class="n">below</span><span class="p">])</span><span class="o">/</span><span class="mi">2</span><span class="p">;</span> <span class="c1">// the same, but faster using cached relative neighbor locations</span>
</pre></div>
</div>
<p>The standard GIL locators are fast and lightweight objects. For example, the
locator for a simple interleaved image consists of one raw pointer to the
pixel location plus one integer for the row size in bytes, for a total of
8 bytes. <code class="docutils literal notranslate"><span class="pre">++loc.x()</span></code> amounts to incrementing a raw pointer (or N pointers
for planar images). Computing 2D offsets is slower as it requires
multiplication and addition. Filters, for example, need to access the same
neighbors for every pixel in the image, in which case the relative positions
can be cached into a raw byte difference using <code class="docutils literal notranslate"><span class="pre">cache_location</span></code>.
In the above example <code class="docutils literal notranslate"><span class="pre">loc[above]</span></code> for simple interleaved images amounts to a
raw array index operator.</p>
<div class="section" id="iterator-over-2d-image">
<h4>Iterator over 2D image</h4>
<p>Sometimes we want to perform the same, location-independent operation
over all pixels of an image. In such a case it is useful to represent
the pixels as a one-dimensional array. GILs <code class="docutils literal notranslate"><span class="pre">iterator_from_2d</span></code> is a
random access traversal iterator that visits all pixels in an image in
the natural memory-friendly order left-to-right inside
top-to-bottom. It takes a locator, the width of the image and the
current X position. This is sufficient information for it to determine
when to do a “carriage return”. Synopsis:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Locator</span><span class="o">&gt;</span> <span class="c1">// Models PixelLocatorConcept</span>
<span class="k">class</span> <span class="nc">iterator_from_2d</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="n">iterator_from_2d</span><span class="p">(</span><span class="k">const</span> <span class="n">Locator</span><span class="o">&amp;</span> <span class="n">loc</span><span class="p">,</span> <span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">width</span><span class="p">);</span>
<span class="n">iterator_from_2d</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">++</span><span class="p">();</span> <span class="c1">// if (++_x&lt;_width) ++_p.x(); else _p+=point_t(-_width,1);</span>
<span class="p">...</span>
<span class="k">private</span><span class="o">:</span>
<span class="kt">int</span> <span class="n">_x</span><span class="p">,</span> <span class="n">_width</span><span class="p">;</span>
<span class="n">Locator</span> <span class="n">_p</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Iterating through the pixels in an image using <code class="docutils literal notranslate"><span class="pre">iterator_from_2d</span></code> is slower
than going through all rows and using the x-iterator at each row. This is
because two comparisons are done per iteration step - one for the end
condition of the loop using the iterators, and one inside
<code class="docutils literal notranslate"><span class="pre">iterator_from_2d::operator++</span></code> to determine whether we are at the end of a
row. For fast operations, such as pixel copy, this second check adds about
15% performance delay (measured for interleaved images on Intel platform).
GIL overrides some STL algorithms, such as <code class="docutils literal notranslate"><span class="pre">std::copy</span></code> and <code class="docutils literal notranslate"><span class="pre">std::fill</span></code>,
when invoked with <code class="docutils literal notranslate"><span class="pre">iterator_from_2d</span></code>-s, to go through each row using their
base x-iterators, and, if the image has no padding (i.e.
<code class="docutils literal notranslate"><span class="pre">iterator_from_2d::is_1d_traversable()</span></code> returns true) to simply iterate
using the x-iterators directly.</p>
</div>
</div>
</div>
<div class="section" id="image-view">
<h2><a class="toc-backref" href="#id24">Image View</a></h2>
<p>An image view is a generalization of STL range concept to multiple dimensions.
Similar to ranges (and iterators), image views are shallow, dont own the
underlying data and dont propagate their constness over the data.
For example, a constant image view cannot be resized, but may allow modifying
the pixels. For pixel-immutable operations, use constant-value image view
(also called non-mutable image view). Most general N-dimensional views satisfy
the following concept:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">RandomAccessNDImageViewConcept</span><span class="o">&lt;</span><span class="n">Regular</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">value_type</span><span class="p">;</span> <span class="c1">// for pixel-based views, the pixel type</span>
<span class="k">typename</span> <span class="n">reference</span><span class="p">;</span> <span class="c1">// result of dereferencing</span>
<span class="k">typename</span> <span class="n">difference_type</span><span class="p">;</span> <span class="c1">// result of operator-(iterator,iterator) (1-dimensional!)</span>
<span class="k">typename</span> <span class="n">const_t</span><span class="p">;</span> <span class="n">where</span> <span class="n">RandomAccessNDImageViewConcept</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;</span><span class="p">;</span> <span class="c1">// same as View, but over immutable values</span>
<span class="k">typename</span> <span class="n">point_t</span><span class="p">;</span> <span class="n">where</span> <span class="n">PointNDConcept</span><span class="o">&lt;</span><span class="n">point_t</span><span class="o">&gt;</span><span class="p">;</span> <span class="c1">// N-dimensional point</span>
<span class="k">typename</span> <span class="n">locator</span><span class="p">;</span> <span class="n">where</span> <span class="n">RandomAccessNDLocatorConcept</span><span class="o">&lt;</span><span class="n">locator</span><span class="o">&gt;</span><span class="p">;</span> <span class="c1">// N-dimensional locator.</span>
<span class="k">typename</span> <span class="n">iterator</span><span class="p">;</span> <span class="n">where</span> <span class="n">RandomAccessTraversalConcept</span><span class="o">&lt;</span><span class="n">iterator</span><span class="o">&gt;</span><span class="p">;</span> <span class="c1">// 1-dimensional iterator over all values</span>
<span class="k">typename</span> <span class="n">reverse_iterator</span><span class="p">;</span> <span class="n">where</span> <span class="n">RandomAccessTraversalConcept</span><span class="o">&lt;</span><span class="n">reverse_iterator</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">size_type</span><span class="p">;</span> <span class="c1">// the return value of size()</span>
<span class="c1">// Equivalent to RandomAccessNDLocatorConcept::axis</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">axis</span> <span class="p">{</span>
<span class="k">typename</span> <span class="n">coord_t</span> <span class="o">=</span> <span class="n">point_t</span><span class="o">::</span><span class="n">axis</span><span class="o">&lt;</span><span class="n">D</span><span class="o">&gt;::</span><span class="n">coord_t</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">iterator</span><span class="p">;</span> <span class="n">where</span> <span class="n">RandomAccessTraversalConcept</span><span class="o">&lt;</span><span class="n">iterator</span><span class="o">&gt;</span><span class="p">;</span> <span class="c1">// iterator along D-th axis.</span>
<span class="n">where</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="n">coord_t</span><span class="p">,</span> <span class="n">iterator</span><span class="o">::</span><span class="n">difference_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">SameType</span><span class="o">&lt;</span><span class="n">iterator</span><span class="o">::</span><span class="n">value_type</span><span class="p">,</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">// Defines the type of a view similar to this type, except it invokes Deref upon dereferencing</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="n">PixelDereferenceAdaptorConcept</span> <span class="n">Deref</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">add_deref</span> <span class="p">{</span>
<span class="k">typename</span> <span class="n">type</span><span class="p">;</span> <span class="n">where</span> <span class="n">RandomAccessNDImageViewConcept</span><span class="o">&lt;</span><span class="n">type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">static</span> <span class="n">type</span> <span class="nf">make</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">v</span><span class="p">,</span> <span class="k">const</span> <span class="n">Deref</span><span class="o">&amp;</span> <span class="n">deref</span><span class="p">);</span>
<span class="p">};</span>
<span class="k">static</span> <span class="k">const</span> <span class="kt">size_t</span> <span class="n">num_dimensions</span> <span class="o">=</span> <span class="n">point_t</span><span class="o">::</span><span class="n">num_dimensions</span><span class="p">;</span>
<span class="c1">// Create from a locator at the top-left corner and dimensions</span>
<span class="n">View</span><span class="o">::</span><span class="n">View</span><span class="p">(</span><span class="k">const</span> <span class="n">locator</span><span class="o">&amp;</span><span class="p">,</span> <span class="k">const</span> <span class="n">point_type</span><span class="o">&amp;</span><span class="p">);</span>
<span class="n">size_type</span> <span class="n">View</span><span class="o">::</span><span class="n">size</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> <span class="c1">// total number of elements</span>
<span class="n">reference</span> <span class="k">operator</span><span class="p">[](</span><span class="n">View</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span> <span class="c1">// 1-dimensional reference</span>
<span class="n">iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">begin</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">end</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">reverse_iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">rbegin</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">reverse_iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">rend</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">at</span><span class="p">(</span><span class="k">const</span> <span class="n">point_t</span><span class="o">&amp;</span><span class="p">);</span>
<span class="n">point_t</span> <span class="n">View</span><span class="o">::</span><span class="n">dimensions</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> <span class="c1">// number of elements along each dimension</span>
<span class="kt">bool</span> <span class="n">View</span><span class="o">::</span><span class="n">is_1d_traversable</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> <span class="c1">// Does an iterator over the first dimension visit each value?</span>
<span class="c1">// iterator along a given dimension starting at a given point</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">&gt;</span> <span class="n">View</span><span class="o">::</span><span class="n">axis</span><span class="o">&lt;</span><span class="n">D</span><span class="o">&gt;::</span><span class="n">iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">axis_iterator</span><span class="p">(</span><span class="k">const</span> <span class="n">point_t</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">reference</span> <span class="nf">operator</span><span class="p">()(</span><span class="n">View</span><span class="p">,</span><span class="k">const</span> <span class="n">point_t</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutableRandomAccessNDImageViewConcept</span><span class="o">&lt;</span><span class="n">RandomAccessNDImageViewConcept</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">Mutable</span><span class="o">&lt;</span><span class="n">reference</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Two-dimensional image views have the following extra requirements:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">RandomAccess2DImageViewConcept</span><span class="o">&lt;</span><span class="n">RandomAccessNDImageViewConcept</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">num_dimensions</span><span class="o">==</span><span class="mi">2</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">x_iterator</span> <span class="o">=</span> <span class="n">axis</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;::</span><span class="n">iterator</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">y_iterator</span> <span class="o">=</span> <span class="n">axis</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;::</span><span class="n">iterator</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">x_coord_t</span> <span class="o">=</span> <span class="n">axis</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;::</span><span class="n">coord_t</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">y_coord_t</span> <span class="o">=</span> <span class="n">axis</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;::</span><span class="n">coord_t</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">xy_locator</span> <span class="o">=</span> <span class="n">locator</span><span class="p">;</span>
<span class="n">x_coord_t</span> <span class="n">View</span><span class="o">::</span><span class="n">width</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_coord_t</span> <span class="n">View</span><span class="o">::</span><span class="n">height</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="c1">// X-navigation</span>
<span class="n">x_iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">x_at</span><span class="p">(</span><span class="k">const</span> <span class="n">point_t</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">x_iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">row_begin</span><span class="p">(</span><span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">x_iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">row_end</span> <span class="p">(</span><span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="c1">// Y-navigation</span>
<span class="n">y_iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">y_at</span><span class="p">(</span><span class="k">const</span> <span class="n">point_t</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">col_begin</span><span class="p">(</span><span class="n">x_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">col_end</span> <span class="p">(</span><span class="n">x_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="c1">// navigating in 2D</span>
<span class="n">xy_locator</span> <span class="n">View</span><span class="o">::</span><span class="n">xy_at</span><span class="p">(</span><span class="k">const</span> <span class="n">point_t</span><span class="o">&amp;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="c1">// (x,y) versions of all methods taking point_t</span>
<span class="n">View</span><span class="o">::</span><span class="n">View</span><span class="p">(</span><span class="n">x_coord_t</span><span class="p">,</span><span class="n">y_coord_t</span><span class="p">,</span><span class="k">const</span> <span class="n">locator</span><span class="o">&amp;</span><span class="p">);</span>
<span class="n">iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">at</span><span class="p">(</span><span class="n">x_coord_t</span><span class="p">,</span><span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">reference</span> <span class="nf">operator</span><span class="p">()(</span><span class="n">View</span><span class="p">,</span><span class="n">x_coord_t</span><span class="p">,</span><span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">xy_locator</span> <span class="n">View</span><span class="o">::</span><span class="n">xy_at</span><span class="p">(</span><span class="n">x_coord_t</span><span class="p">,</span><span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">x_iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">x_at</span><span class="p">(</span><span class="n">x_coord_t</span><span class="p">,</span><span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_iterator</span> <span class="n">View</span><span class="o">::</span><span class="n">y_at</span><span class="p">(</span><span class="n">x_coord_t</span><span class="p">,</span><span class="n">y_coord_t</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutableRandomAccess2DImageViewConcept</span><span class="o">&lt;</span><span class="n">RandomAccess2DImageViewConcept</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="o">:</span> <span class="n">MutableRandomAccessNDImageViewConcept</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;</span> <span class="p">{};</span>
</pre></div>
</div>
<p>Image views that GIL typically uses operate on value types that model
<code class="docutils literal notranslate"><span class="pre">PixelValueConcept</span></code> and have some additional requirements:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">ImageViewConcept</span><span class="o">&lt;</span><span class="n">RandomAccess2DImageViewConcept</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">PixelValueConcept</span><span class="o">&lt;</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">PixelIteratorConcept</span><span class="o">&lt;</span><span class="n">x_iterator</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">PixelIteratorConcept</span><span class="o">&lt;</span><span class="n">y_iterator</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">x_coord_t</span> <span class="o">==</span> <span class="n">y_coord_t</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">coord_t</span> <span class="o">=</span> <span class="n">x_coord_t</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">View</span><span class="o">::</span><span class="n">num_channels</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">concept</span> <span class="n">MutableImageViewConcept</span><span class="o">&lt;</span><span class="n">ImageViewConcept</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="o">:</span> <span class="n">MutableRandomAccess2DImageViewConcept</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;</span>
<span class="p">{};</span>
</pre></div>
</div>
<p>Two image views are compatible if they have compatible pixels and the same
number of dimensions:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">ViewsCompatibleConcept</span><span class="o">&lt;</span><span class="n">ImageViewConcept</span> <span class="n">V1</span><span class="p">,</span> <span class="n">ImageViewConcept</span> <span class="n">V2</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">PixelsCompatibleConcept</span><span class="o">&lt;</span><span class="n">V1</span><span class="o">::</span><span class="n">value_type</span><span class="p">,</span> <span class="n">V2</span><span class="o">::</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">;</span>
<span class="n">where</span> <span class="n">V1</span><span class="o">::</span><span class="n">num_dimensions</span> <span class="o">==</span> <span class="n">V2</span><span class="o">::</span><span class="n">num_dimensions</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Compatible views must also have the same dimensions (i.e. the same width and
height). Many algorithms taking multiple views require that they be pairwise
compatible.</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<ul class="simple">
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access_n_d_image_view_concept.html">RandomAccessNDImageViewConcept&lt;View&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access_n_d_image_view_concept.html">MutableRandomAccessNDImageViewConcept&lt;View&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access2_d_image_view_concept.html">RandomAccess2DImageViewConcept&lt;View&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access2_d_image_view_concept.html">MutableRandomAccess2DImageViewConcept&lt;View&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_image_view_concept.html">ImageViewConcept&lt;View&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_image_view_concept.html">MutableImageViewConcept&lt;View&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_views_compatible_concept.html">ViewsCompatibleConcept&lt;View1,View2&gt;</a></p></li>
</ul>
</div>
<div class="section" id="id12">
<h3>Models</h3>
<p>GIL provides a model for <code class="docutils literal notranslate"><span class="pre">ImageViewConcept</span></code> called <code class="docutils literal notranslate"><span class="pre">image_view</span></code>. It is
templated over a model of <code class="docutils literal notranslate"><span class="pre">PixelLocatorConcept</span></code>. (If instantiated with a
model of <code class="docutils literal notranslate"><span class="pre">MutablePixelLocatorConcept</span></code>, it models
<code class="docutils literal notranslate"><span class="pre">MutableImageViewConcept</span></code>). Synopsis:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Locator models PixelLocatorConcept, could be MutablePixelLocatorConcept</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Locator</span><span class="o">&gt;</span>
<span class="k">class</span> <span class="nc">image_view</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">typedef</span> <span class="n">Locator</span> <span class="n">xy_locator</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">iterator_from_2d</span><span class="o">&lt;</span><span class="n">Locator</span><span class="o">&gt;</span> <span class="n">iterator</span><span class="p">;</span>
<span class="p">...</span>
<span class="k">private</span><span class="o">:</span>
<span class="n">xy_locator</span> <span class="n">_pixels</span><span class="p">;</span> <span class="c1">// 2D pixel locator at the top left corner of the image view range</span>
<span class="n">point_t</span> <span class="n">_dimensions</span><span class="p">;</span> <span class="c1">// width and height</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Image views are lightweight objects. A regular interleaved view is typically
16 bytes long - two integers for the width and height (inside dimensions) one
for the number of bytes between adjacent rows (inside the locator) and one
pointer to the beginning of the pixel block.</p>
</div>
<div class="section" id="id13">
<h3>Algorithms</h3>
<p>GIL provides algorithms constructing views from raw data or other views.</p>
<div class="section" id="creating-views-from-raw-pixels">
<h4>Creating Views from Raw Pixels</h4>
<p>Standard image views can be constructed from raw data of any supported color
space, bit depth, channel ordering or planar vs. interleaved structure.
Interleaved views are constructed using <code class="docutils literal notranslate"><span class="pre">interleaved_view</span></code>, supplying the
image dimensions, number of bytes per row, and a pointer to the first pixel:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Iterator models pixel iterator (e.g. rgb8_ptr_t or rgb8c_ptr_t)</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Iterator</span><span class="o">&gt;</span>
<span class="n">image_view</span><span class="o">&lt;</span><span class="p">...</span><span class="o">&gt;</span> <span class="n">interleaved_view</span><span class="p">(</span><span class="kt">ptrdiff_t</span> <span class="n">width</span><span class="p">,</span> <span class="kt">ptrdiff_t</span> <span class="n">height</span><span class="p">,</span> <span class="n">Iterator</span> <span class="n">pixels</span><span class="p">,</span> <span class="kt">ptrdiff_t</span> <span class="n">rowsize</span><span class="p">)</span>
</pre></div>
</div>
<p>Planar views are defined for every color space and take each plane separately.
Here is the RGB one:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Iterator models channel iterator (e.g. bits8* or bits8 const*)</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Iterator</span><span class="o">&gt;</span>
<span class="n">image_view</span><span class="o">&lt;</span><span class="p">...</span><span class="o">&gt;</span> <span class="n">planar_rgb_view</span><span class="p">(</span>
<span class="kt">ptrdiff_t</span> <span class="n">width</span><span class="p">,</span> <span class="kt">ptrdiff_t</span> <span class="n">height</span><span class="p">,</span>
<span class="n">IC</span> <span class="n">r</span><span class="p">,</span> <span class="n">IC</span> <span class="n">g</span><span class="p">,</span> <span class="n">IC</span> <span class="n">b</span><span class="p">,</span> <span class="kt">ptrdiff_t</span> <span class="n">rowsize</span><span class="p">);</span>
</pre></div>
</div>
<p>Note that the supplied pixel/channel iterators could be constant (read-only),
in which case the returned view is a constant-value (immutable) view.</p>
</div>
<div class="section" id="creating-image-views-from-other-image-views">
<h4>Creating Image Views from Other Image Views</h4>
<p>It is possible to construct one image view from another by changing some
policy of how image data is interpreted. The result could be a view whose type
is derived from the type of the source. GIL uses the following metafunctions
to get the derived types:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Some result view types</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="nl">dynamic_xy_step_type</span> <span class="p">:</span> <span class="k">public</span> <span class="n">dynamic_y_step_type</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span> <span class="p">{};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="nl">dynamic_xy_step_transposed_type</span> <span class="p">:</span> <span class="k">public</span> <span class="n">dynamic_xy_step_type</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">transposed_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span> <span class="p">{};</span>
<span class="c1">// color and bit depth converted view to match pixel type P</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">SrcView</span><span class="p">,</span> <span class="c1">// Models ImageViewConcept</span>
<span class="k">typename</span> <span class="n">DstP</span><span class="p">,</span> <span class="c1">// Models PixelConcept</span>
<span class="k">typename</span> <span class="n">ColorConverter</span><span class="o">=</span><span class="n">gil</span><span class="o">::</span><span class="n">default_color_converter</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">color_converted_view_type</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="c1">// image view adaptor with value type DstP, over SrcView</span>
<span class="p">};</span>
<span class="c1">// single-channel view of the N-th channel of a given view</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">SrcView</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">nth_channel_view_type</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>GIL Provides the following view transformations:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// flipped upside-down, left-to-right, transposed view</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">dynamic_y_step_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">flipped_up_down_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">flipped_left_right_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">dynamic_xy_step_transposed_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">transposed_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">);</span>
<span class="c1">// rotations</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">dynamic_xy_step_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">rotated180_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">dynamic_xy_step_transposed_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">rotated90cw_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">dynamic_xy_step_transposed_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">rotated90ccw_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">);</span>
<span class="c1">// view of an axis-aligned rectangular area within an image</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="n">View</span> <span class="n">subimage_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span>
<span class="k">const</span> <span class="n">View</span><span class="o">::</span><span class="n">point_t</span><span class="o">&amp;</span> <span class="n">top_left</span><span class="p">,</span> <span class="k">const</span> <span class="n">View</span><span class="o">::</span><span class="n">point_t</span><span class="o">&amp;</span> <span class="n">dimensions</span><span class="p">);</span>
<span class="c1">// subsampled view (skipping pixels in X and Y)</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="k">typename</span> <span class="n">dynamic_xy_step_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">subsampled_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span>
<span class="k">const</span> <span class="n">View</span><span class="o">::</span><span class="n">point_t</span><span class="o">&amp;</span> <span class="n">step</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="p">,</span> <span class="k">typename</span> <span class="n">P</span><span class="o">&gt;</span>
<span class="n">color_converted_view_type</span><span class="o">&lt;</span><span class="n">View</span><span class="p">,</span><span class="n">P</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">color_converted_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="p">,</span> <span class="k">typename</span> <span class="n">P</span><span class="p">,</span> <span class="k">typename</span> <span class="n">CCV</span><span class="o">&gt;</span> <span class="c1">// with a custom color converter</span>
<span class="n">color_converted_view_type</span><span class="o">&lt;</span><span class="n">View</span><span class="p">,</span><span class="n">P</span><span class="p">,</span><span class="n">CCV</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">color_converted_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="n">nth_channel_view_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">view_t</span> <span class="n">nth_channel_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">view</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">);</span>
</pre></div>
</div>
<p>The implementations of most of these view factory methods are straightforward.
Here is, for example, how the flip views are implemented. The flip upside-down
view creates a view whose first pixel is the bottom left pixel of the original
view and whose y-step is the negated step of the source.</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="k">typename</span> <span class="n">dynamic_y_step_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">flipped_up_down_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">gil_function_requires</span><span class="o">&lt;</span><span class="n">ImageViewConcept</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">();</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">dynamic_y_step_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">RView</span><span class="p">;</span>
<span class="k">return</span> <span class="nf">RView</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">dimensions</span><span class="p">(),</span><span class="k">typename</span> <span class="n">RView</span><span class="o">::</span><span class="n">xy_locator</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">xy_at</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">src</span><span class="p">.</span><span class="n">height</span><span class="p">()</span><span class="o">-</span><span class="mi">1</span><span class="p">),</span><span class="o">-</span><span class="mi">1</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The call to <code class="docutils literal notranslate"><span class="pre">gil_function_requires</span></code> ensures (at compile time) that the
template parameter is a valid model of <code class="docutils literal notranslate"><span class="pre">ImageViewConcept</span></code>. Using it
generates easier to track compile errors, creates no extra code and has no
run-time performance impact. We are using the <code class="docutils literal notranslate"><span class="pre">boost::concept_check</span> <span class="pre">library</span></code>,
but wrapping it in <code class="docutils literal notranslate"><span class="pre">gil_function_requires</span></code>, which performs the check if the
<code class="docutils literal notranslate"><span class="pre">BOOST_GIL_USE_CONCEPT_CHECK</span></code> is set. It is unset by default, because there
is a significant increase in compile time when using concept checks. We will
skip <code class="docutils literal notranslate"><span class="pre">gil_function_requires</span></code> in the code examples in this guide for the sake
of succinctness.</p>
<p>Image views can be freely composed
(see section <a class="reference internal" href="#useful-metafunctions-and-typedefs"><span class="std std-ref">Useful Metafunctions and Typedefs</span></a> for the
typedefs <code class="docutils literal notranslate"><span class="pre">rgb16_image_t</span></code> and <code class="docutils literal notranslate"><span class="pre">gray16_step_view_t)</span></code>:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">rgb16_image_t</span> <span class="nf">img</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">100</span><span class="p">);</span> <span class="c1">// an RGB interleaved image</span>
<span class="c1">// grayscale view over the green (index 1) channel of img</span>
<span class="n">gray16_step_view_t</span> <span class="n">green</span><span class="o">=</span><span class="n">nth_channel_view</span><span class="p">(</span><span class="n">view</span><span class="p">(</span><span class="n">img</span><span class="p">),</span><span class="mi">1</span><span class="p">);</span>
<span class="c1">// 50x50 view of the green channel of img, upside down and taking every other pixel in X and in Y</span>
<span class="n">gray16_step_view_t</span> <span class="n">ud_fud</span><span class="o">=</span><span class="n">flipped_up_down_view</span><span class="p">(</span><span class="n">subsampled_view</span><span class="p">(</span><span class="n">green</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">));</span>
</pre></div>
</div>
<p>As previously stated, image views are fast, constant-time, shallow views over
the pixel data. The above code does not copy any pixels; it operates on the
pixel data allocated when <code class="docutils literal notranslate"><span class="pre">img</span></code> was created.</p>
</div>
<div class="section" id="stl-style-algorithms-on-image-views">
<h4>STL-Style Algorithms on Image Views</h4>
<p>Image views provide 1D iteration of their pixels via <code class="docutils literal notranslate"><span class="pre">begin()</span></code> and <code class="docutils literal notranslate"><span class="pre">end()</span></code>
methods, which makes it possible to use STL algorithms with them. However,
using nested loops over X and Y is in many cases more efficient.
The algorithms in this section resemble STL algorithms, but they abstract away
the nested loops and take views (as opposed to ranges) as input.</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Equivalents of std::copy and std::uninitialized_copy</span>
<span class="c1">// where ImageViewConcept&lt;V1&gt;, MutableImageViewConcept&lt;V2&gt;, ViewsCompatibleConcept&lt;V1,V2&gt;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V2</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">copy_pixels</span><span class="p">(</span><span class="k">const</span> <span class="n">V1</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V2</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">uninitialized_copy_pixels</span><span class="p">(</span><span class="k">const</span> <span class="n">V1</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">);</span>
<span class="c1">// Equivalents of std::fill and std::uninitialized_fill</span>
<span class="c1">// where MutableImageViewConcept&lt;V&gt;, PixelConcept&lt;Value&gt;, PixelsCompatibleConcept&lt;Value,V::value_type&gt;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Value</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">fill_pixels</span><span class="p">(</span><span class="k">const</span> <span class="n">V</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="n">Value</span><span class="o">&amp;</span> <span class="n">val</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Value</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">uninitialized_fill_pixels</span><span class="p">(</span><span class="k">const</span> <span class="n">V</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="n">Value</span><span class="o">&amp;</span> <span class="n">val</span><span class="p">);</span>
<span class="c1">// Equivalent of std::for_each</span>
<span class="c1">// where ImageViewConcept&lt;V&gt;, boost::UnaryFunctionConcept&lt;F&gt;</span>
<span class="c1">// where PixelsCompatibleConcept&lt;V::reference, F::argument_type&gt;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V</span><span class="p">,</span> <span class="k">typename</span> <span class="n">F</span><span class="o">&gt;</span>
<span class="n">F</span> <span class="n">for_each_pixel</span><span class="p">(</span><span class="k">const</span> <span class="n">V</span><span class="o">&amp;</span> <span class="n">view</span><span class="p">,</span> <span class="n">F</span> <span class="n">fun</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V</span><span class="p">,</span> <span class="k">typename</span> <span class="n">F</span><span class="o">&gt;</span>
<span class="n">F</span> <span class="n">for_each_pixel_position</span><span class="p">(</span><span class="k">const</span> <span class="n">V</span><span class="o">&amp;</span> <span class="n">view</span><span class="p">,</span> <span class="n">F</span> <span class="n">fun</span><span class="p">);</span>
<span class="c1">// Equivalent of std::generate</span>
<span class="c1">// where MutableImageViewConcept&lt;V&gt;, boost::UnaryFunctionConcept&lt;F&gt;</span>
<span class="c1">// where PixelsCompatibleConcept&lt;V::reference, F::argument_type&gt;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V</span><span class="p">,</span> <span class="k">typename</span> <span class="n">F</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">generate_pixels</span><span class="p">(</span><span class="k">const</span> <span class="n">V</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">,</span> <span class="n">F</span> <span class="n">fun</span><span class="p">);</span>
<span class="c1">// Equivalent of std::transform with one source</span>
<span class="c1">// where ImageViewConcept&lt;V1&gt;, MutableImageViewConcept&lt;V2&gt;</span>
<span class="c1">// where boost::UnaryFunctionConcept&lt;F&gt;</span>
<span class="c1">// where PixelsCompatibleConcept&lt;V1::const_reference, F::argument_type&gt;</span>
<span class="c1">// where PixelsCompatibleConcept&lt;F::result_type, V2::reference&gt;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V2</span><span class="p">,</span> <span class="k">typename</span> <span class="n">F</span><span class="o">&gt;</span>
<span class="n">F</span> <span class="n">transform_pixels</span><span class="p">(</span><span class="k">const</span> <span class="n">V1</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">,</span> <span class="n">F</span> <span class="n">fun</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V2</span><span class="p">,</span> <span class="k">typename</span> <span class="n">F</span><span class="o">&gt;</span>
<span class="n">F</span> <span class="n">transform_pixel_positions</span><span class="p">(</span><span class="k">const</span> <span class="n">V1</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">,</span> <span class="n">F</span> <span class="n">fun</span><span class="p">);</span>
<span class="c1">// Equivalent of std::transform with two sources</span>
<span class="c1">// where ImageViewConcept&lt;V1&gt;, ImageViewConcept&lt;V2&gt;, MutableImageViewConcept&lt;V3&gt;</span>
<span class="c1">// where boost::BinaryFunctionConcept&lt;F&gt;</span>
<span class="c1">// where PixelsCompatibleConcept&lt;V1::const_reference, F::first_argument_type&gt;</span>
<span class="c1">// where PixelsCompatibleConcept&lt;V2::const_reference, F::second_argument_type&gt;</span>
<span class="c1">// where PixelsCompatibleConcept&lt;F::result_type, V3::reference&gt;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V2</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V3</span><span class="p">,</span> <span class="k">typename</span> <span class="n">F</span><span class="o">&gt;</span>
<span class="n">F</span> <span class="n">transform_pixels</span><span class="p">(</span><span class="k">const</span> <span class="n">V1</span><span class="o">&amp;</span> <span class="n">src1</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&amp;</span> <span class="n">src2</span><span class="p">,</span> <span class="k">const</span> <span class="n">V3</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">,</span> <span class="n">F</span> <span class="n">fun</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V2</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V3</span><span class="p">,</span> <span class="k">typename</span> <span class="n">F</span><span class="o">&gt;</span>
<span class="n">F</span> <span class="n">transform_pixel_positions</span><span class="p">(</span><span class="k">const</span> <span class="n">V1</span><span class="o">&amp;</span> <span class="n">src1</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&amp;</span> <span class="n">src2</span><span class="p">,</span> <span class="k">const</span> <span class="n">V3</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">,</span> <span class="n">F</span> <span class="n">fun</span><span class="p">);</span>
<span class="c1">// Copies a view into another, color converting the pixels if needed, with the default or user-defined color converter</span>
<span class="c1">// where ImageViewConcept&lt;V1&gt;, MutableImageViewConcept&lt;V2&gt;</span>
<span class="c1">// V1::value_type must be convertible to V2::value_type.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V2</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">copy_and_convert_pixels</span><span class="p">(</span><span class="k">const</span> <span class="n">V1</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V2</span><span class="p">,</span> <span class="k">typename</span> <span class="n">ColorConverter</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">copy_and_convert_pixels</span><span class="p">(</span><span class="k">const</span> <span class="n">V1</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">,</span> <span class="n">ColorConverter</span> <span class="n">ccv</span><span class="p">);</span>
<span class="c1">// Equivalent of std::equal</span>
<span class="c1">// where ImageViewConcept&lt;V1&gt;, ImageViewConcept&lt;V2&gt;, ViewsCompatibleConcept&lt;V1,V2&gt;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">V1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V2</span><span class="o">&gt;</span>
<span class="kt">bool</span> <span class="n">equal_pixels</span><span class="p">(</span><span class="k">const</span> <span class="n">V1</span><span class="o">&amp;</span> <span class="n">view1</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&amp;</span> <span class="n">view2</span><span class="p">);</span>
</pre></div>
</div>
<p>Algorithms that take multiple views require that they have the same
dimensions. <code class="docutils literal notranslate"><span class="pre">for_each_pixel_position</span></code> and <code class="docutils literal notranslate"><span class="pre">transform_pixel_positions</span></code> pass
pixel locators, as opposed to pixel references, to their function objects.
This allows for writing algorithms that use pixel neighbours, as the tutorial
demonstrates.</p>
<p>Most of these algorithms check whether the image views are 1D-traversable.
A 1D-traversable image view has no gaps at the end of the rows.
In other words, if an x_iterator of that view is advanced past the last pixel
in a row it will move to the first pixel of the next row. When image views are
1D-traversable, the algorithms use a single loop and run more efficiently.
If one or more of the input views are not 1D-traversable, the algorithms
fall-back to an X-loop nested inside a Y-loop.</p>
<p>The algorithms typically delegate the work to their corresponding STL
algorithms. For example, <code class="docutils literal notranslate"><span class="pre">copy_pixels</span></code> calls <code class="docutils literal notranslate"><span class="pre">std::copy</span></code> either for each
row, or, when the images are 1D-traversable, once for all pixels.</p>
<p>In addition, overloads are sometimes provided for the STL algorithms.
For example, <code class="docutils literal notranslate"><span class="pre">std::copy</span></code> for planar iterators is overloaded to perform
<code class="docutils literal notranslate"><span class="pre">std::copy</span></code> for each of the planes. <code class="docutils literal notranslate"><span class="pre">std::copy</span></code> over bitwise-copyable
pixels results in <code class="docutils literal notranslate"><span class="pre">std::copy</span></code> over unsigned char, which STL
implements via <code class="docutils literal notranslate"><span class="pre">memmove</span></code>.</p>
<p>As a result <code class="docutils literal notranslate"><span class="pre">copy_pixels</span></code> may result in a single call to <code class="docutils literal notranslate"><span class="pre">memmove</span></code> for
interleaved 1D-traversable views, or one per each plane of planar
1D-traversable views, or one per each row of interleaved non-1D-traversable
images, etc.</p>
<p>GIL also provides some beta-versions of image processing algorithms, such as
resampling and convolution in a numerics extension available on
<a class="reference external" href="http://stlab.adobe.com/gil/download.html">http://stlab.adobe.com/gil/download.html</a>. This code is in early stage of
development and is not optimized for speed</p>
</div>
</div>
</div>
<div class="section" id="image">
<h2><a class="toc-backref" href="#id25">Image</a></h2>
<p>An image is a container that owns the pixels of a given image view
It allocates them in its constructor and deletes them in the destructor.
It has a deep assignment operator and copy constructor. Images are used
rarely, just when data ownership is important. Most STL algorithms operate on
ranges, not containers. Similarly most GIL algorithms operate on image views
(which images provide).</p>
<p>In the most general form images are N-dimensional and satisfy the following
concept:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">RandomAccessNDImageConcept</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">Img</span><span class="o">&gt;</span> <span class="o">:</span> <span class="n">Regular</span><span class="o">&lt;</span><span class="n">Img</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">view_t</span><span class="p">;</span> <span class="n">where</span> <span class="n">MutableRandomAccessNDImageViewConcept</span><span class="o">&lt;</span><span class="n">view_t</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">const_view_t</span> <span class="o">=</span> <span class="n">view_t</span><span class="o">::</span><span class="n">const_t</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">point_t</span> <span class="o">=</span> <span class="n">view_t</span><span class="o">::</span><span class="n">point_t</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">value_type</span> <span class="o">=</span> <span class="n">view_t</span><span class="o">::</span><span class="n">value_type</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">allocator_type</span><span class="p">;</span>
<span class="n">Img</span><span class="o">::</span><span class="n">Img</span><span class="p">(</span><span class="n">point_t</span> <span class="n">dims</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="o">=</span><span class="mi">0</span><span class="p">);</span>
<span class="n">Img</span><span class="o">::</span><span class="n">Img</span><span class="p">(</span><span class="n">point_t</span> <span class="n">dims</span><span class="p">,</span> <span class="n">value_type</span> <span class="n">fill_value</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="p">);</span>
<span class="kt">void</span> <span class="n">Img</span><span class="o">::</span><span class="n">recreate</span><span class="p">(</span><span class="n">point_t</span> <span class="n">new_dims</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="o">=</span><span class="mi">0</span><span class="p">);</span>
<span class="kt">void</span> <span class="n">Img</span><span class="o">::</span><span class="n">recreate</span><span class="p">(</span><span class="n">point_t</span> <span class="n">new_dims</span><span class="p">,</span> <span class="n">value_type</span> <span class="n">fill_value</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="p">);</span>
<span class="k">const</span> <span class="n">point_t</span><span class="o">&amp;</span> <span class="n">Img</span><span class="o">::</span><span class="n">dimensions</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="k">const</span> <span class="n">const_view_t</span><span class="o">&amp;</span> <span class="n">const_view</span><span class="p">(</span><span class="k">const</span> <span class="n">Img</span><span class="o">&amp;</span><span class="p">);</span>
<span class="k">const</span> <span class="n">view_t</span><span class="o">&amp;</span> <span class="n">view</span><span class="p">(</span><span class="n">Img</span><span class="o">&amp;</span><span class="p">);</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Two-dimensional images have additional requirements:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">RandomAccess2DImageConcept</span><span class="o">&lt;</span><span class="n">RandomAccessNDImageConcept</span> <span class="n">Img</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typename</span> <span class="n">x_coord_t</span> <span class="o">=</span> <span class="n">const_view_t</span><span class="o">::</span><span class="n">x_coord_t</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">y_coord_t</span> <span class="o">=</span> <span class="n">const_view_t</span><span class="o">::</span><span class="n">y_coord_t</span><span class="p">;</span>
<span class="n">Img</span><span class="o">::</span><span class="n">Img</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="n">y_coord_t</span> <span class="n">height</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="o">=</span><span class="mi">0</span><span class="p">);</span>
<span class="n">Img</span><span class="o">::</span><span class="n">Img</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="n">y_coord_t</span> <span class="n">height</span><span class="p">,</span> <span class="n">value_type</span> <span class="n">fill_value</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="p">);</span>
<span class="n">x_coord_t</span> <span class="n">Img</span><span class="o">::</span><span class="n">width</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_coord_t</span> <span class="n">Img</span><span class="o">::</span><span class="n">height</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="kt">void</span> <span class="n">Img</span><span class="o">::</span><span class="n">recreate</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="n">y_coord_t</span> <span class="n">height</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="o">=</span><span class="mi">1</span><span class="p">);</span>
<span class="kt">void</span> <span class="n">Img</span><span class="o">::</span><span class="n">recreate</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="n">y_coord_t</span> <span class="n">height</span><span class="p">,</span> <span class="n">value_type</span> <span class="n">fill_value</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="p">);</span>
<span class="p">};</span>
</pre></div>
</div>
<p>GIL images have views that model <code class="docutils literal notranslate"><span class="pre">ImageViewConcept</span></code> and operate on pixels.</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">concept</span> <span class="n">ImageConcept</span><span class="o">&lt;</span><span class="n">RandomAccess2DImageConcept</span> <span class="n">Img</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="n">where</span> <span class="n">MutableImageViewConcept</span><span class="o">&lt;</span><span class="n">view_t</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">typename</span> <span class="n">coord_t</span> <span class="o">=</span> <span class="n">view_t</span><span class="o">::</span><span class="n">coord_t</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Images, unlike locators and image views, dont have mutable set of concepts
because immutable images are not very useful.</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<ul class="simple">
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access_n_d_image_concept.html">RandomAccessNDImageConcept&lt;Image&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access2_d_image_concept.html">RandomAccess2DImageConcept&lt;Image&gt;</a></p></li>
<li><p><a class="reference external" href="reference/structboost_1_1gil_1_1_image_concept.html">ImageConcept&lt;Image&gt;</a></p></li>
</ul>
</div>
<div class="section" id="id14">
<h3>Models</h3>
<p>GIL provides a class, <code class="docutils literal notranslate"><span class="pre">image</span></code>, which is templated over the value type
(the pixel) and models <code class="docutils literal notranslate"><span class="pre">ImageConcept</span></code>:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span> <span class="k">template</span>
<span class="o">&lt;</span>
<span class="k">typename</span> <span class="n">Pixel</span><span class="p">,</span> <span class="c1">// Models PixelValueConcept</span>
<span class="kt">bool</span> <span class="n">IsPlanar</span><span class="p">,</span> <span class="c1">// planar or interleaved image</span>
<span class="k">typename</span> <span class="n">A</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span>
<span class="o">&gt;</span>
<span class="k">class</span> <span class="nc">image</span><span class="p">;</span>
</pre></div>
</div>
<p>The image constructor takes an alignment parameter which allows for
constructing images that are word-aligned or 8-byte aligned. The alignment is
specified in bytes. The default value for alignment is 0, which means there is
no padding at the end of rows. Many operations are faster using such
1D-traversable images, because <code class="docutils literal notranslate"><span class="pre">image_view::x_iterator</span></code> can be used to
traverse the pixels, instead of the more complicated <code class="docutils literal notranslate"><span class="pre">image_view::iterator</span></code>.
Note that when alignment is 0, packed images are aligned to the bit - i.e.
there are no padding bits at the end of rows of packed images.</p>
</div>
</div>
<div class="section" id="run-time-specified-images-and-image-views">
<h2><a class="toc-backref" href="#id26">Run-time specified images and image views</a></h2>
<p>The color space, channel depth, channel ordering, and interleaved/planar
structure of an image are defined by the type of its template argument, which
makes them compile-time bound. Often some of these parameters are available
only at run time. Consider, for example, writing a module that opens the image
at a given file path, rotates it and saves it back in its original color space
and channel depth. How can we possibly write this using our generic image?
What type is the image loading code supposed to return?</p>
<p>GIL dynamic_image extension allows for images, image views or any GIL
constructs to have their parameters defined at run time. Here is an example:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&lt;boost/gil/extension/dynamic_image/dynamic_image_all.hpp&gt;</span><span class="cp"></span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="p">;</span>
<span class="cp">#define ASSERT_SAME(A,B) static_assert(is_same&lt; A,B &gt;::value, &quot;&quot;)</span>
<span class="c1">// Define the set of allowed images</span>
<span class="k">typedef</span> <span class="n">mpl</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">rgb8_image_t</span><span class="p">,</span> <span class="n">cmyk16_planar_image_t</span><span class="o">&gt;</span> <span class="n">my_images_t</span><span class="p">;</span>
<span class="c1">// Create any_image class (or any_image_view) class</span>
<span class="k">typedef</span> <span class="n">any_image</span><span class="o">&lt;</span><span class="n">my_images_t</span><span class="o">&gt;</span> <span class="n">my_any_image_t</span><span class="p">;</span>
<span class="c1">// Associated view types are available (equivalent to the ones in image_t)</span>
<span class="k">typedef</span> <span class="n">any_image_view</span><span class="o">&lt;</span><span class="n">mpl</span><span class="o">::</span><span class="n">vector2</span><span class="o">&lt;</span><span class="n">rgb8_view_t</span><span class="p">,</span> <span class="n">cmyk16_planar_view_t</span> <span class="o">&gt;</span> <span class="o">&gt;</span> <span class="n">AV</span><span class="p">;</span>
<span class="n">ASSERT_SAME</span><span class="p">(</span><span class="n">my_any_image_t</span><span class="o">::</span><span class="n">view_t</span><span class="p">,</span> <span class="n">AV</span><span class="p">);</span>
<span class="k">typedef</span> <span class="n">any_image_view</span><span class="o">&lt;</span><span class="n">mpl</span><span class="o">::</span><span class="n">vector2</span><span class="o">&lt;</span><span class="n">rgb8c_view_t</span><span class="p">,</span> <span class="n">cmyk16c_planar_view_t</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="n">CAV</span><span class="p">;</span>
<span class="n">ASSERT_SAME</span><span class="p">(</span><span class="n">my_any_image_t</span><span class="o">::</span><span class="n">const_view_t</span><span class="p">,</span> <span class="n">CAV</span><span class="p">);</span>
<span class="n">ASSERT_SAME</span><span class="p">(</span><span class="n">my_any_image_t</span><span class="o">::</span><span class="n">const_view_t</span><span class="p">,</span> <span class="n">my_any_image_t</span><span class="o">::</span><span class="n">view_t</span><span class="o">::</span><span class="n">const_t</span><span class="p">);</span>
<span class="k">typedef</span> <span class="n">any_image_view</span><span class="o">&lt;</span><span class="n">mpl</span><span class="o">::</span><span class="n">vector2</span><span class="o">&lt;</span><span class="n">rgb8_step_view_t</span><span class="p">,</span> <span class="n">cmyk16_planar_step_view_t</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="n">SAV</span><span class="p">;</span>
<span class="n">ASSERT_SAME</span><span class="p">(</span><span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o">&lt;</span><span class="n">my_any_image_t</span><span class="o">::</span><span class="n">view_t</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">,</span> <span class="n">SAV</span><span class="p">);</span>
<span class="c1">// Assign it a concrete image at run time:</span>
<span class="n">my_any_image_t</span> <span class="n">myImg</span> <span class="o">=</span> <span class="n">my_any_image_t</span><span class="p">(</span><span class="n">rgb8_image_t</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">100</span><span class="p">));</span>
<span class="c1">// Change it to another at run time. The previous image gets destroyed</span>
<span class="n">myImg</span> <span class="o">=</span> <span class="n">cmyk16_planar_image_t</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span><span class="mi">100</span><span class="p">);</span>
<span class="c1">// Assigning to an image not in the allowed set throws an exception</span>
<span class="n">myImg</span> <span class="o">=</span> <span class="n">gray8_image_t</span><span class="p">();</span> <span class="c1">// will throw std::bad_cast</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">any_image</span></code> and <code class="docutils literal notranslate"><span class="pre">any_image_view</span></code> subclass from GIL <code class="docutils literal notranslate"><span class="pre">variant</span></code> class,
which breaks down the instantiated type into a non-templated underlying base
type and a unique instantiation type identifier. The underlying base instance
is represented as a block of bytes.
The block is large enough to hold the largest of the specified types.</p>
<p>GIL variant is similar to <code class="docutils literal notranslate"><span class="pre">boost::variant</span></code> in spirit (hence we borrow the
name from there) but it differs in several ways from the current boost
implementation. Perhaps the biggest difference is that GIL variant always
takes a single argument, which is a model of MPL Random Access Sequence
enumerating the allowed types. Having a single interface allows GIL variant
to be used easier in generic code. Synopsis:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Types</span><span class="o">&gt;</span> <span class="c1">// models MPL Random Access Container</span>
<span class="k">class</span> <span class="nc">variant</span>
<span class="p">{</span>
<span class="p">...</span> <span class="n">_bits</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">_index</span><span class="p">;</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">typedef</span> <span class="n">Types</span> <span class="n">types_t</span><span class="p">;</span>
<span class="n">variant</span><span class="p">();</span>
<span class="n">variant</span><span class="p">(</span><span class="k">const</span> <span class="n">variant</span><span class="o">&amp;</span> <span class="n">v</span><span class="p">);</span>
<span class="k">virtual</span> <span class="o">~</span><span class="n">variant</span><span class="p">();</span>
<span class="n">variant</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">variant</span><span class="o">&amp;</span> <span class="n">v</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">TS</span><span class="o">&gt;</span> <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="k">const</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">TS</span><span class="o">&gt;&amp;</span> <span class="n">x</span><span class="p">,</span> <span class="k">const</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">TS</span><span class="o">&gt;&amp;</span> <span class="n">y</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">TS</span><span class="o">&gt;</span> <span class="k">friend</span> <span class="kt">bool</span> <span class="k">operator</span><span class="o">!=</span><span class="p">(</span><span class="k">const</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">TS</span><span class="o">&gt;&amp;</span> <span class="n">x</span><span class="p">,</span> <span class="k">const</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">TS</span><span class="o">&gt;&amp;</span> <span class="n">y</span><span class="p">);</span>
<span class="c1">// Construct/assign to type T. Throws std::bad_cast if T is not in Types</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">explicit</span> <span class="n">variant</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">obj</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="n">variant</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">obj</span><span class="p">);</span>
<span class="c1">// Construct/assign by swapping T with its current instance. Only possible if they are swappable</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">explicit</span> <span class="n">variant</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span> <span class="n">obj</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">do_swap</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">move_in</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span> <span class="n">obj</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">static</span> <span class="kt">bool</span> <span class="n">has_type</span><span class="p">();</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">_dynamic_cast</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">_dynamic_cast</span><span class="p">();</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="kt">bool</span> <span class="n">current_type_is</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">UOP</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Types</span><span class="o">&gt;</span>
<span class="n">UOP</span><span class="o">::</span><span class="n">result_type</span> <span class="n">apply_operation</span><span class="p">(</span><span class="n">variant</span><span class="o">&lt;</span><span class="n">Types</span><span class="o">&gt;&amp;</span> <span class="n">v</span><span class="p">,</span> <span class="n">UOP</span> <span class="n">op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">UOP</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Types</span><span class="o">&gt;</span>
<span class="n">UOP</span><span class="o">::</span><span class="n">result_type</span> <span class="n">apply_operation</span><span class="p">(</span><span class="k">const</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">Types</span><span class="o">&gt;&amp;</span> <span class="n">v</span><span class="p">,</span> <span class="n">UOP</span> <span class="n">op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">BOP</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Types1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Types2</span><span class="o">&gt;</span>
<span class="n">BOP</span><span class="o">::</span><span class="n">result_type</span> <span class="n">apply_operation</span><span class="p">(</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">Types1</span><span class="o">&gt;&amp;</span> <span class="n">v1</span><span class="p">,</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">Types2</span><span class="o">&gt;&amp;</span> <span class="n">v2</span><span class="p">,</span> <span class="n">UOP</span> <span class="n">op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">BOP</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Types1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Types2</span><span class="o">&gt;</span>
<span class="n">BOP</span><span class="o">::</span><span class="n">result_type</span> <span class="n">apply_operation</span><span class="p">(</span><span class="k">const</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">Types1</span><span class="o">&gt;&amp;</span> <span class="n">v1</span><span class="p">,</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">Types2</span><span class="o">&gt;&amp;</span> <span class="n">v2</span><span class="p">,</span> <span class="n">UOP</span> <span class="n">op</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">BOP</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Types1</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Types2</span><span class="o">&gt;</span>
<span class="n">BOP</span><span class="o">::</span><span class="n">result_type</span> <span class="n">apply_operation</span><span class="p">(</span><span class="k">const</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">Types1</span><span class="o">&gt;&amp;</span> <span class="n">v1</span><span class="p">,</span> <span class="k">const</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">Types2</span><span class="o">&gt;&amp;</span> <span class="n">v2</span><span class="p">,</span> <span class="n">UOP</span> <span class="n">op</span><span class="p">);</span>
</pre></div>
</div>
<p>GIL <code class="docutils literal notranslate"><span class="pre">any_image_view</span></code> and <code class="docutils literal notranslate"><span class="pre">any_image</span></code> are subclasses of <code class="docutils literal notranslate"><span class="pre">variant</span></code>:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ImageViewTypes</span><span class="o">&gt;</span>
<span class="k">class</span> <span class="nc">any_image_view</span> <span class="o">:</span> <span class="k">public</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">ImageViewTypes</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">const_t</span><span class="p">;</span> <span class="c1">// immutable equivalent of this</span>
<span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">x_coord_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">y_coord_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">point</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span><span class="o">&gt;</span> <span class="n">point_t</span><span class="p">;</span>
<span class="n">any_image_view</span><span class="p">();</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">explicit</span> <span class="n">any_image_view</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">obj</span><span class="p">);</span>
<span class="n">any_image_view</span><span class="p">(</span><span class="k">const</span> <span class="n">any_image_view</span><span class="o">&amp;</span> <span class="n">v</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="n">any_image_view</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">obj</span><span class="p">);</span>
<span class="n">any_image_view</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">any_image_view</span><span class="o">&amp;</span> <span class="n">v</span><span class="p">);</span>
<span class="c1">// parameters of the currently instantiated view</span>
<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">num_channels</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">point_t</span> <span class="nf">dimensions</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">x_coord_t</span> <span class="nf">width</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_coord_t</span> <span class="nf">height</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ImageTypes</span><span class="o">&gt;</span>
<span class="k">class</span> <span class="nc">any_image</span> <span class="o">:</span> <span class="k">public</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">ImageTypes</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="n">variant</span><span class="o">&lt;</span><span class="n">ImageTypes</span><span class="o">&gt;</span> <span class="n">parent_t</span><span class="p">;</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">const_view_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">view_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">x_coord_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">y_coord_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">point</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span><span class="o">&gt;</span> <span class="n">point_t</span><span class="p">;</span>
<span class="n">any_image</span><span class="p">();</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">explicit</span> <span class="n">any_image</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">obj</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">explicit</span> <span class="n">any_image</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span> <span class="n">obj</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">do_swap</span><span class="p">);</span>
<span class="n">any_image</span><span class="p">(</span><span class="k">const</span> <span class="n">any_image</span><span class="o">&amp;</span> <span class="n">v</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="n">any_image</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span><span class="o">&amp;</span> <span class="n">obj</span><span class="p">);</span>
<span class="n">any_image</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">any_image</span><span class="o">&amp;</span> <span class="n">v</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">recreate</span><span class="p">(</span><span class="k">const</span> <span class="n">point_t</span><span class="o">&amp;</span> <span class="n">dims</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">alignment</span><span class="o">=</span><span class="mi">1</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">recreate</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="n">y_coord_t</span> <span class="n">height</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">alignment</span><span class="o">=</span><span class="mi">1</span><span class="p">);</span>
<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">num_channels</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">point_t</span> <span class="nf">dimensions</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">x_coord_t</span> <span class="nf">width</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="n">y_coord_t</span> <span class="nf">height</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Operations are invoked on variants via <code class="docutils literal notranslate"><span class="pre">apply_operation</span></code> passing a
function object to perform the operation. The code for every allowed
type in the variant is instantiated and the appropriate instantiation
is selected via a switch statement. Since image view algorithms
typically have time complexity at least linear on the number of
pixels, the single switch statement of image view variant adds
practically no measurable performance overhead compared to templated
image views.</p>
<p>Variants behave like the underlying type. Their copy constructor will
invoke the copy constructor of the underlying instance. Equality
operator will check if the two instances are of the same type and then
invoke their <code class="docutils literal notranslate"><span class="pre">operator==</span></code>, etc. The default constructor of a variant
will default-construct the first type. That means that
<code class="docutils literal notranslate"><span class="pre">any_image_view</span></code> has shallow default-constructor, copy-constructor,
assignment and equality comparison, whereas <code class="docutils literal notranslate"><span class="pre">any_image</span></code> has deep
ones.</p>
<p>It is important to note that even though <code class="docutils literal notranslate"><span class="pre">any_image_view</span></code> and
<code class="docutils literal notranslate"><span class="pre">any_image</span></code> resemble the static <code class="docutils literal notranslate"><span class="pre">image_view</span></code> and <code class="docutils literal notranslate"><span class="pre">image</span></code>, they
do not model the full requirements of <code class="docutils literal notranslate"><span class="pre">ImageViewConcept</span></code> and
<code class="docutils literal notranslate"><span class="pre">ImageConcept</span></code>. In particular they dont provide access to the
pixels. There is no “any_pixel” or “any_pixel_iterator” in GIL. Such
constructs could be provided via the <code class="docutils literal notranslate"><span class="pre">variant</span></code> mechanism, but doing
so would result in inefficient algorithms, since the type resolution
would have to be performed per pixel. Image-level algorithms should be
implemented via <code class="docutils literal notranslate"><span class="pre">apply_operation</span></code>. That said, many common operations
are shared between the static and dynamic types. In addition, all of
the image view transformations and many STL-like image view algorithms
have overloads operating on <code class="docutils literal notranslate"><span class="pre">any_image_view</span></code>, as illustrated with
<code class="docutils literal notranslate"><span class="pre">copy_pixels</span></code>:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">rgb8_view_t</span> <span class="nf">v1</span><span class="p">(...);</span> <span class="c1">// concrete image view</span>
<span class="n">bgr8_view_t</span> <span class="nf">v2</span><span class="p">(...);</span> <span class="c1">// concrete image view compatible with v1 and of the same size</span>
<span class="n">any_image_view</span><span class="o">&lt;</span><span class="n">Types</span><span class="o">&gt;</span> <span class="n">av</span><span class="p">(...);</span> <span class="c1">// run-time specified image view</span>
<span class="c1">// Copies the pixels from v1 into v2.</span>
<span class="c1">// If the pixels are incompatible triggers compile error</span>
<span class="n">copy_pixels</span><span class="p">(</span><span class="n">v1</span><span class="p">,</span><span class="n">v2</span><span class="p">);</span>
<span class="c1">// The source or destination (or both) may be run-time instantiated.</span>
<span class="c1">// If they happen to be incompatible, throws std::bad_cast</span>
<span class="n">copy_pixels</span><span class="p">(</span><span class="n">v1</span><span class="p">,</span> <span class="n">av</span><span class="p">);</span>
<span class="n">copy_pixels</span><span class="p">(</span><span class="n">av</span><span class="p">,</span> <span class="n">v2</span><span class="p">);</span>
<span class="n">copy_pixels</span><span class="p">(</span><span class="n">av</span><span class="p">,</span> <span class="n">av</span><span class="p">);</span>
</pre></div>
</div>
<p>By having algorithm overloads supporting dynamic constructs, we create
a base upon which it is possible to write algorithms that can work
with either compile-time or runtime images or views. The following
code, for example, uses the GIL I/O extension to turn an image on disk
upside down:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&lt;boost\gil\extension\io\jpeg_dynamic_io.hpp&gt;</span><span class="cp"></span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Image</span><span class="o">&gt;</span> <span class="c1">// Could be rgb8_image_t or any_image&lt;...&gt;</span>
<span class="kt">void</span> <span class="n">save_180rot</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">file_name</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">Image</span> <span class="n">img</span><span class="p">;</span>
<span class="n">jpeg_read_image</span><span class="p">(</span><span class="n">file_name</span><span class="p">,</span> <span class="n">img</span><span class="p">);</span>
<span class="n">jpeg_write_view</span><span class="p">(</span><span class="n">file_name</span><span class="p">,</span> <span class="n">rotated180_view</span><span class="p">(</span><span class="n">view</span><span class="p">(</span><span class="n">img</span><span class="p">)));</span>
<span class="p">}</span>
</pre></div>
</div>
<p>It can be instantiated with either a compile-time or a runtime image
because all functions it uses have overloads taking runtime
constructs. For example, here is how <code class="docutils literal notranslate"><span class="pre">rotated180_view</span></code> is
implemented:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// implementation using templated view</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span>
<span class="k">typename</span> <span class="n">dynamic_xy_step_type</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">rotated180_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">)</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span>
<span class="k">namespace</span> <span class="n">detail</span>
<span class="p">{</span>
<span class="c1">// the function, wrapped inside a function object</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Result</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">rotated180_view_fn</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="n">Result</span> <span class="n">result_type</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="n">result_type</span> <span class="k">operator</span><span class="p">()(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">)</span> <span class="k">const</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">result_type</span><span class="p">(</span><span class="n">rotated180_view</span><span class="p">(</span><span class="n">src</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="c1">// overloading of the function using variant. Takes and returns run-time bound view.</span>
<span class="c1">// The returned view has a dynamic step</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ViewTypes</span><span class="o">&gt;</span> <span class="kr">inline</span> <span class="c1">// Models MPL Random Access Container of models of ImageViewConcept</span>
<span class="k">typename</span> <span class="n">dynamic_xy_step_type</span><span class="o">&lt;</span><span class="n">any_image_view</span><span class="o">&lt;</span><span class="n">ViewTypes</span><span class="o">&gt;</span> <span class="o">&gt;::</span><span class="n">type</span> <span class="n">rotated180_view</span><span class="p">(</span><span class="k">const</span> <span class="n">any_image_view</span><span class="o">&lt;</span><span class="n">ViewTypes</span><span class="o">&gt;&amp;</span> <span class="n">src</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">apply_operation</span><span class="p">(</span><span class="n">src</span><span class="p">,</span><span class="n">detail</span><span class="o">::</span><span class="n">rotated180_view_fn</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">dynamic_xy_step_type</span><span class="o">&lt;</span><span class="n">any_image_view</span><span class="o">&lt;</span><span class="n">ViewTypes</span><span class="o">&gt;</span> <span class="o">&gt;::</span><span class="n">type</span><span class="o">&gt;</span><span class="p">());</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Variants should be used with caution (especially algorithms that take
more than one variant) because they instantiate the algorithm for
every possible model that the variant can take. This can take a toll
on compile time and executable size. Despite these limitations,
<code class="docutils literal notranslate"><span class="pre">variant</span></code> is a powerful technique that allows us to combine the
speed of compile-time resolution with the flexibility of run-time
resolution. It allows us to treat images of different parameters
uniformly as a collection and store them in the same container.</p>
</div>
<div class="section" id="useful-metafunctions-and-typedefs">
<h2><a class="toc-backref" href="#id27">Useful Metafunctions and Typedefs</a></h2>
<p>Flexibility comes at a price. GIL types can be very long and hard to read.
To address this problem, GIL provides typedefs to refer to any standard image,
pixel iterator, pixel locator, pixel reference or pixel value.</p>
<p>They follow this pattern:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="o">*</span><span class="n">ColorSpace</span><span class="o">*</span> <span class="o">+</span> <span class="o">*</span><span class="n">BitDepth</span><span class="o">*</span> <span class="o">+</span> <span class="p">[</span><span class="s">&quot;s|f&quot;</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="s">&quot;c&quot;</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="s">&quot;_planar&quot;</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="s">&quot;_step&quot;</span><span class="p">]</span> <span class="o">+</span> <span class="o">*</span><span class="n">ClassType</span><span class="o">*</span> <span class="o">+</span> <span class="s">&quot;_t&quot;</span>
</pre></div>
</div>
<p>where <em>ColorSpace</em> also indicates the ordering of components.</p>
<p>Examples are <code class="docutils literal notranslate"><span class="pre">rgb</span></code>, <code class="docutils literal notranslate"><span class="pre">bgr</span></code>, <code class="docutils literal notranslate"><span class="pre">cmyk</span></code>, <code class="docutils literal notranslate"><span class="pre">rgba</span></code>. <em>BitDepth</em> can be, for
example, <code class="docutils literal notranslate"><span class="pre">8</span></code>,``16``,``32``. By default the bits are unsigned integral type.
Append <code class="docutils literal notranslate"><span class="pre">s</span></code> to the bit depth to indicate signed integral, or <code class="docutils literal notranslate"><span class="pre">f</span></code> to
indicate floating point. <code class="docutils literal notranslate"><span class="pre">c</span></code> indicates object whose associated pixel
reference is immutable. <code class="docutils literal notranslate"><span class="pre">_planar</span></code> indicates planar organization (as opposed
to interleaved). <code class="docutils literal notranslate"><span class="pre">_step</span></code> indicates the type has a dynamic step and
<em>ClassType</em> is <code class="docutils literal notranslate"><span class="pre">_image</span></code> (image, using a standard allocator), <code class="docutils literal notranslate"><span class="pre">_view</span></code>
(image view), <code class="docutils literal notranslate"><span class="pre">_loc</span></code> (pixel locator), <code class="docutils literal notranslate"><span class="pre">_ptr</span></code> (pixel iterator), <code class="docutils literal notranslate"><span class="pre">_ref</span></code>
(pixel reference), <code class="docutils literal notranslate"><span class="pre">_pixel</span></code> (pixel value).</p>
<p>Here are examples:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">bgr8_image_t</span> <span class="n">i</span><span class="p">;</span> <span class="c1">// 8-bit unsigned (unsigned char) interleaved BGR image</span>
<span class="n">cmyk16_pixel_t</span><span class="p">;</span> <span class="n">x</span><span class="p">;</span> <span class="c1">// 16-bit unsigned (unsigned short) CMYK pixel value;</span>
<span class="n">cmyk16sc_planar_ref_t</span> <span class="nf">p</span><span class="p">(</span><span class="n">x</span><span class="p">);</span> <span class="c1">// const reference to a 16-bit signed integral (signed short) planar CMYK pixel x.</span>
<span class="n">rgb32f_planar_step_ptr_t</span> <span class="n">ii</span><span class="p">;</span> <span class="c1">// step iterator to a floating point 32-bit (float) planar RGB pixel.</span>
</pre></div>
</div>
<p>GIL provides the metafunctions that return the types of standard
homogeneous memory-based GIL constructs given a channel type, a
layout, and whether the construct is planar, has a step along the X
direction, and is mutable:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ChannelValue</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsPlanar</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsMutable</span><span class="o">=</span><span class="nb">true</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">pixel_reference_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Channel</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">pixel_value_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ChannelValue</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsPlanar</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsStep</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsMutable</span><span class="o">=</span><span class="nb">true</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">iterator_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ChannelValue</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsPlanar</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsXStep</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsMutable</span><span class="o">=</span><span class="nb">true</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">locator_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ChannelValue</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsPlanar</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsXStep</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsMutable</span><span class="o">=</span><span class="nb">true</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">view_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ChannelValue</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsPlanar</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">image_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">BitField</span><span class="p">,</span> <span class="k">typename</span> <span class="n">ChannelBitSizeVector</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">packed_image_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">ChannelBitSizeVector</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">bit_aligned_image_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
</pre></div>
</div>
<p>There are also helper metafunctions to construct packed and
bit-aligned images with up to five channels:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">BitField</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size1</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">packed_image1_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">BitField</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size1</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size2</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">packed_image2_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">BitField</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size1</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size2</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size3</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">packed_image3_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">BitField</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size1</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size2</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size3</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size4</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">packed_image4_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">BitField</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size1</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size2</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size3</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size4</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size5</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">packed_image5_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">unsigned</span> <span class="n">Size1</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">bit_aligned_image1_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">unsigned</span> <span class="n">Size1</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size2</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">bit_aligned_image2_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">unsigned</span> <span class="n">Size1</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size2</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size3</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">bit_aligned_image3_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">unsigned</span> <span class="n">Size1</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size2</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size3</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size4</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">bit_aligned_image4_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="kt">unsigned</span> <span class="n">Size1</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size2</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size3</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size4</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">Size5</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Alloc</span><span class="o">=</span><span class="n">std</span><span class="o">::</span><span class="n">allocator</span><span class="o">&lt;</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">&gt;</span> <span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">bit_aligned_image5_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
</pre></div>
</div>
<p>Here <code class="docutils literal notranslate"><span class="pre">ChannelValue</span></code> models <code class="docutils literal notranslate"><span class="pre">ChannelValueConcept</span></code>. We dont need
<code class="docutils literal notranslate"><span class="pre">IsYStep</span></code> because GILs memory-based locator and view already allow
the vertical step to be specified dynamically. Iterators and views can
be constructed from a pixel type:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Pixel</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsPlanar</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsStep</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsMutable</span><span class="o">=</span><span class="nb">true</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">iterator_type_from_pixel</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Pixel</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsPlanar</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsStepX</span><span class="o">=</span><span class="nb">false</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">IsMutable</span><span class="o">=</span><span class="nb">true</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">view_type_from_pixel</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
</pre></div>
</div>
<p>Using a heterogeneous pixel type will result in heterogeneous iterators and
views. Types can also be constructed from horizontal iterator:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">XIterator</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">type_from_x_iterator</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">step_iterator_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">xy_locator_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">view_t</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>There are metafunctions to construct the type of a construct from an existing
type by changing one or more of its properties:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">PixelReference</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">ChannelValue</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">IsPlanar</span><span class="p">,</span> <span class="k">typename</span> <span class="n">IsMutable</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">derived_pixel_reference_type</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="c1">// Models PixelConcept</span>
<span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Iterator</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">ChannelValue</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">IsPlanar</span><span class="p">,</span> <span class="k">typename</span> <span class="n">IsStep</span><span class="p">,</span> <span class="k">typename</span> <span class="n">IsMutable</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">derived_iterator_type</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="c1">// Models PixelIteratorConcept</span>
<span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">ChannelValue</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">IsPlanar</span><span class="p">,</span> <span class="k">typename</span> <span class="n">IsXStep</span><span class="p">,</span> <span class="k">typename</span> <span class="n">IsMutable</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">derived_view_type</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="c1">// Models ImageViewConcept</span>
<span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Image</span><span class="p">,</span>
<span class="k">typename</span> <span class="n">ChannelValue</span><span class="p">,</span> <span class="k">typename</span> <span class="n">Layout</span><span class="p">,</span> <span class="k">typename</span> <span class="n">IsPlanar</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">derived_image_type</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="c1">// Models ImageConcept</span>
<span class="p">};</span>
</pre></div>
</div>
<p>You can replace one or more of its properties and use <code class="docutils literal notranslate"><span class="pre">boost::use_default</span></code>
for the rest. In this case <code class="docutils literal notranslate"><span class="pre">IsPlanar</span></code>, <code class="docutils literal notranslate"><span class="pre">IsStep</span></code> and <code class="docutils literal notranslate"><span class="pre">IsMutable</span></code> are
MPL boolean constants. For example, here is how to create the type of a view
just like <code class="docutils literal notranslate"><span class="pre">View</span></code>, but being grayscale and planar:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">using</span> <span class="n">VT</span> <span class="o">=</span> <span class="k">typename</span> <span class="n">derived_view_type</span><span class="o">&lt;</span><span class="n">View</span><span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">use_default</span><span class="p">,</span> <span class="n">gray_t</span><span class="p">,</span> <span class="n">mpl</span><span class="o">::</span><span class="n">true_</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">;</span>
</pre></div>
</div>
<p>You can get pixel-related types of any pixel-based GIL constructs (pixels,
iterators, locators and views) using the following metafunctions provided by
<code class="docutils literal notranslate"><span class="pre">PixelBasedConcept</span></code>, <code class="docutils literal notranslate"><span class="pre">HomogeneousPixelBasedConcept</span></code> and metafunctions
built on top of them:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">color_space_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">channel_mapping_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">is_planar</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="c1">// Defined by homogeneous constructs</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">channel_type</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">num_channels</span> <span class="p">{</span> <span class="k">typedef</span> <span class="p">...</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span>
</pre></div>
</div>
<p>These are metafunctions, some of which return integral types which can be
evaluated like this:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">static_assert</span><span class="p">(</span><span class="n">is_planar</span><span class="o">&lt;</span><span class="n">rgb8_planar_view_t</span><span class="o">&gt;::</span><span class="n">value</span> <span class="o">==</span> <span class="nb">true</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">);</span>
</pre></div>
</div>
<p>GIL also supports type analysis metafunctions of the form:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">pixel_reference</span><span class="o">/</span><span class="n">iterator</span><span class="o">/</span><span class="n">locator</span><span class="o">/</span><span class="n">view</span><span class="o">/</span><span class="n">image</span><span class="p">]</span> <span class="o">+</span> <span class="s">&quot;_is_&quot;</span> <span class="o">+</span> <span class="p">[</span><span class="n">basic</span><span class="o">/</span><span class="k">mutable</span><span class="o">/</span><span class="n">step</span><span class="p">]</span>
</pre></div>
</div>
<p>For example:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">view_is_mutable</span><span class="o">&lt;</span><span class="n">View</span><span class="o">&gt;::</span><span class="n">value</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>A <em>basic</em> GIL construct is a memory-based construct that uses the built-in GIL
classes and does not have any function object to invoke upon dereferencing.
For example, a simple planar or interleaved, step or non-step RGB image view
is basic, but a color converted view or a virtual view is not.</p>
</div>
<div class="section" id="i-o-extension">
<h2><a class="toc-backref" href="#id28">I/O Extension</a></h2>
<p>GIL I/O extension provides low level image I/O utilities. It supports loading
and saving several image formats, each of which requires linking against the
corresponding library:</p>
<div class="section" id="jpeg">
<h3>JPEG</h3>
<p>To use JPEG files, include the file <code class="docutils literal notranslate"><span class="pre">gil/extension/io/jpeg_io.hpp</span></code>.
If you are using run-time images, you need to include
<code class="docutils literal notranslate"><span class="pre">gil/extension/io/jpeg_dynamic_io.hpp</span></code> instead.
You need to compile and link against libjpeg.lib (available at
<a class="reference external" href="http://www.ijg.org">http://www.ijg.org</a>). You need to have <code class="docutils literal notranslate"><span class="pre">jpeglib.h</span></code> in your include path.</p>
</div>
<div class="section" id="tiff">
<h3>TIFF</h3>
<p>To use TIFF files, include the file <code class="docutils literal notranslate"><span class="pre">gil/extension/io/tiff_io.hpp</span></code>.
If you are using run-time images, you need to include
<code class="docutils literal notranslate"><span class="pre">gil/extension/io/tiff_dynamic_io.hpp</span></code> instead.
You need to compile and link against libtiff.lib (available at
<a class="reference external" href="http://www.libtiff.org">http://www.libtiff.org</a>). You need to have <code class="docutils literal notranslate"><span class="pre">tiffio.h</span></code> in your include path.</p>
</div>
<div class="section" id="png">
<h3>PNG</h3>
<p>To use PNG files, include the file <code class="docutils literal notranslate"><span class="pre">gil/extension/io/png_io.hpp</span></code>.
If you are using run-time images, you need to include
<code class="docutils literal notranslate"><span class="pre">gil/extension/io/png_dynamic_io.hpp</span></code> instead.
You need to compile and link against libpng.lib (available at
<a class="reference external" href="http://wwwlibpng.org">http://wwwlibpng.org</a>).
You need to have <code class="docutils literal notranslate"><span class="pre">png.h</span></code> in your include path.</p>
<p>You dont need to install all these libraries; just the ones you will use.
Here are the I/O APIs for JPEG files (replace “jpeg” with “tiff” or “png” for
the APIs of the other libraries):</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Returns the width and height of the JPEG file at the specified location.</span>
<span class="c1">// Throws std::ios_base::failure if the location does not correspond to a valid JPEG file</span>
<span class="n">point</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span><span class="o">&gt;</span> <span class="n">jpeg_read_dimensions</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">);</span>
<span class="c1">// Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it.</span>
<span class="c1">// Triggers a compile assert if the image color space or channel depth are not supported by the JPEG library or by the I/O extension.</span>
<span class="c1">// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not</span>
<span class="c1">// compatible with the ones specified by Image</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Img</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">jpeg_read_image</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">,</span> <span class="n">Img</span><span class="o">&amp;</span><span class="p">);</span>
<span class="c1">// Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it,</span>
<span class="c1">// color-converting and channel-converting if necessary.</span>
<span class="c1">// Triggers a compile assert if the image color space or channel depth are not supported by the JPEG library or by the I/O extension.</span>
<span class="c1">// Throws std::ios_base::failure if the file is not a valid JPEG file or if it fails to read it.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Img</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">jpeg_read_and_convert_image</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">,</span> <span class="n">Img</span><span class="o">&amp;</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Img</span><span class="p">,</span> <span class="k">typename</span> <span class="n">CCV</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">jpeg_read_and_convert_image</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">,</span> <span class="n">Img</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CCV</span> <span class="n">color_converter</span><span class="p">);</span>
<span class="c1">// Loads the image specified by the given jpeg image file name into the given view.</span>
<span class="c1">// Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension.</span>
<span class="c1">// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not</span>
<span class="c1">// compatible with the ones specified by View, or if its dimensions don&#39;t match the ones of the view.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">jpeg_read_view</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span><span class="p">);</span>
<span class="c1">// Loads the image specified by the given jpeg image file name into the given view and color-converts (and channel-converts) it if necessary.</span>
<span class="c1">// Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension.</span>
<span class="c1">// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its dimensions don&#39;t match the ones of the view.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">jpeg_read_and_convert_view</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span><span class="p">);</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="p">,</span> <span class="k">typename</span> <span class="n">CCV</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">jpeg_read_and_convert_view</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span><span class="p">,</span> <span class="n">CCV</span> <span class="n">color_converter</span><span class="p">);</span>
<span class="c1">// Saves the view to a jpeg file specified by the given jpeg image file name.</span>
<span class="c1">// Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension.</span>
<span class="c1">// Throws std::ios_base::failure if it fails to create the file.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">jpeg_write_view</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">,</span> <span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span><span class="p">);</span>
<span class="c1">// Determines whether the given view type is supported for reading</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">jpeg_read_support</span>
<span class="p">{</span>
<span class="k">static</span> <span class="k">const</span> <span class="kt">bool</span> <span class="n">value</span> <span class="o">=</span> <span class="p">...;</span>
<span class="p">};</span>
<span class="c1">// Determines whether the given view type is supported for writing</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">jpeg_write_support</span>
<span class="p">{</span>
<span class="k">static</span> <span class="k">const</span> <span class="kt">bool</span> <span class="n">value</span> <span class="o">=</span> <span class="p">...;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>If you use the dynamic image extension, make sure to include
<code class="docutils literal notranslate"><span class="pre">&quot;jpeg_dynamic_io.hpp&quot;</span></code> instead of <code class="docutils literal notranslate"><span class="pre">&quot;jpeg_io.hpp&quot;</span></code>. In addition to the
above methods, you have the following overloads dealing with dynamic images:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// Opens the given JPEG file name, selects the first type in Images</span>
<span class="c1">// whose color space and channel are compatible to those of the image</span>
<span class="c1">// file and creates a new image of that type with the dimensions specified</span>
<span class="c1">// by the image file.</span>
<span class="c1">// Throws std::ios_base::failure if none of the types in Images are</span>
<span class="c1">// compatible with the type on disk.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Images</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">jpeg_read_image</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">,</span> <span class="n">any_image</span><span class="o">&lt;</span><span class="n">Images</span><span class="o">&gt;&amp;</span><span class="p">);</span>
<span class="c1">// Saves the currently instantiated view to a jpeg file specified by the given jpeg image file name.</span>
<span class="c1">// Throws std::ios_base::failure if the currently instantiated view type is not supported for writing by the I/O extension</span>
<span class="c1">// or if it fails to create the file.</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Views</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="n">jpeg_write_view</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">,</span> <span class="n">any_image_view</span><span class="o">&lt;</span><span class="n">Views</span><span class="o">&gt;&amp;</span><span class="p">);</span>
</pre></div>
</div>
<p>All of the above methods have overloads taking <code class="docutils literal notranslate"><span class="pre">std::string</span></code> instead of
<code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">const*</span></code></p>
</div>
</div>
<div class="section" id="sample-code">
<h2><a class="toc-backref" href="#id29">Sample Code</a></h2>
<div class="section" id="pixel-level-sample-code">
<h3>Pixel-level Sample Code</h3>
<p>Here are some operations you can do with pixel values, pixel pointers and
pixel references:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">rgb8_pixel_t</span> <span class="nf">p1</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// make a red RGB pixel</span>
<span class="n">bgr8_pixel_t</span> <span class="n">p2</span> <span class="o">=</span> <span class="n">p1</span><span class="p">;</span> <span class="c1">// RGB and BGR are compatible and the channels will be properly mapped.</span>
<span class="n">assert</span><span class="p">(</span><span class="n">p1</span><span class="o">==</span><span class="n">p2</span><span class="p">);</span> <span class="c1">// p2 will also be red.</span>
<span class="n">assert</span><span class="p">(</span><span class="n">p2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">!=</span><span class="n">p1</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span> <span class="c1">// operator[] gives physical channel order (as laid down in memory)</span>
<span class="n">assert</span><span class="p">(</span><span class="n">semantic_at_c</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span><span class="o">==</span><span class="n">semantic_at_c</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">p2</span><span class="p">));</span> <span class="c1">// this is how to compare the two red channels</span>
<span class="n">get_color</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span><span class="n">green_t</span><span class="p">())</span> <span class="o">=</span> <span class="n">get_color</span><span class="p">(</span><span class="n">p2</span><span class="p">,</span><span class="n">blue_t</span><span class="p">());</span> <span class="c1">// channels can also be accessed by name</span>
<span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span><span class="o">*</span> <span class="n">r</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span><span class="o">*</span> <span class="n">g</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">unsigned</span> <span class="kt">char</span><span class="o">*</span> <span class="n">b</span><span class="p">;</span>
<span class="n">rgb8c_planar_ptr_t</span> <span class="nf">ptr</span><span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="n">g</span><span class="p">,</span><span class="n">b</span><span class="p">);</span> <span class="c1">// constructing const planar pointer from const pointers to each plane</span>
<span class="n">rgb8c_planar_ref_t</span> <span class="n">ref</span><span class="o">=*</span><span class="n">ptr</span><span class="p">;</span> <span class="c1">// just like built-in reference, dereferencing a planar pointer returns a planar reference</span>
<span class="n">p2</span><span class="o">=</span><span class="n">ref</span><span class="p">;</span> <span class="n">p2</span><span class="o">=</span><span class="n">p1</span><span class="p">;</span> <span class="n">p2</span><span class="o">=</span><span class="n">ptr</span><span class="p">[</span><span class="mi">7</span><span class="p">];</span> <span class="n">p2</span><span class="o">=</span><span class="n">rgb8_pixel_t</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span> <span class="c1">// planar/interleaved references and values to RGB/BGR can be freely mixed</span>
<span class="c1">//rgb8_planar_ref_t ref2; // compile error: References have no default constructors</span>
<span class="c1">//ref2=*ptr; // compile error: Cannot construct non-const reference by dereferencing const pointer</span>
<span class="c1">//ptr[3]=p1; // compile error: Cannot set the fourth pixel through a const pointer</span>
<span class="c1">//p1 = pixel&lt;float, rgb_layout_t&gt;();// compile error: Incompatible channel depth</span>
<span class="c1">//p1 = pixel&lt;bits8, rgb_layout_t&gt;();// compile error: Incompatible color space (even though it has the same number of channels)</span>
<span class="c1">//p1 = pixel&lt;bits8,rgba_layout_t&gt;();// compile error: Incompatible color space (even though it contains red, green and blue channels)</span>
</pre></div>
</div>
<p>Here is how to use pixels in generic code:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">GrayPixel</span><span class="p">,</span> <span class="k">typename</span> <span class="n">RGBPixel</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">gray_to_rgb</span><span class="p">(</span><span class="k">const</span> <span class="n">GrayPixel</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="n">RGBPixel</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">gil_function_requires</span><span class="o">&lt;</span><span class="n">PixelConcept</span><span class="o">&lt;</span><span class="n">GrayPixel</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">();</span>
<span class="n">gil_function_requires</span><span class="o">&lt;</span><span class="n">MutableHomogeneousPixelConcept</span><span class="o">&lt;</span><span class="n">RGBPixel</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">();</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">color_space_type</span><span class="o">&lt;</span><span class="n">GrayPixel</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">gray_cs_t</span><span class="p">;</span>
<span class="k">static_assert</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">is_same</span><span class="o">&lt;</span><span class="n">gray_cs_t</span><span class="p">,</span><span class="n">gray_t</span><span class="o">&gt;::</span><span class="n">value</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">);</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">color_space_type</span><span class="o">&lt;</span><span class="n">RGBPixel</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">rgb_cs_t</span><span class="p">;</span>
<span class="k">static_assert</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">is_same</span><span class="o">&lt;</span><span class="n">rgb_cs_t</span><span class="p">,</span><span class="n">rgb_t</span><span class="o">&gt;::</span><span class="n">value</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">);</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">channel_type</span><span class="o">&lt;</span><span class="n">GrayPixel</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">gray_channel_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">channel_type</span><span class="o">&lt;</span><span class="n">RGBPixel</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">rgb_channel_t</span><span class="p">;</span>
<span class="n">gray_channel_t</span> <span class="n">gray</span> <span class="o">=</span> <span class="n">get_color</span><span class="p">(</span><span class="n">src</span><span class="p">,</span><span class="n">gray_color_t</span><span class="p">());</span>
<span class="n">static_fill</span><span class="p">(</span><span class="n">dst</span><span class="p">,</span> <span class="n">channel_convert</span><span class="o">&lt;</span><span class="n">rgb_channel_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">gray</span><span class="p">));</span>
<span class="p">}</span>
<span class="c1">// example use patterns:</span>
<span class="c1">// converting gray l-value to RGB and storing at (5,5) in a 16-bit BGR interleaved image:</span>
<span class="n">bgr16_view_t</span> <span class="n">b16</span><span class="p">(...);</span>
<span class="n">gray_to_rgb</span><span class="p">(</span><span class="n">gray8_pixel_t</span><span class="p">(</span><span class="mi">33</span><span class="p">),</span> <span class="n">b16</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span><span class="mi">5</span><span class="p">));</span>
<span class="c1">// storing the first pixel of an 8-bit grayscale image as the 5-th pixel of 32-bit planar RGB image:</span>
<span class="n">rgb32f_planar_view_t</span> <span class="n">rpv32</span><span class="p">;</span>
<span class="n">gray8_view_t</span> <span class="nf">gv8</span><span class="p">(...);</span>
<span class="n">gray_to_rgb</span><span class="p">(</span><span class="o">*</span><span class="n">gv8</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">rpv32</span><span class="p">[</span><span class="mi">5</span><span class="p">]);</span>
</pre></div>
</div>
<p>As the example shows, both the source and the destination can be references or
values, planar or interleaved, as long as they model <code class="docutils literal notranslate"><span class="pre">PixelConcept</span></code> and
<code class="docutils literal notranslate"><span class="pre">MutablePixelConcept</span></code> respectively.</p>
</div>
<div class="section" id="creating-a-copy-of-an-image-with-a-safe-buffer">
<h3>Creating a Copy of an Image with a Safe Buffer</h3>
<p>Suppose we want to convolve an image with multiple kernels, the largest of
which is 2K+1 x 2K+1 pixels. It may be worth creating a margin of K pixels
around the image borders. Here is how to do it:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">SrcView</span><span class="p">,</span> <span class="c1">// Models ImageViewConcept (the source view)</span>
<span class="k">typename</span> <span class="n">DstImage</span><span class="o">&gt;</span> <span class="c1">// Models ImageConcept (the returned image)</span>
<span class="kt">void</span> <span class="n">create_with_margin</span><span class="p">(</span><span class="k">const</span> <span class="n">SrcView</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">,</span> <span class="n">DstImage</span><span class="o">&amp;</span> <span class="n">result</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">gil_function_requires</span><span class="o">&lt;</span><span class="n">ImageViewConcept</span><span class="o">&lt;</span><span class="n">SrcView</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">();</span>
<span class="n">gil_function_requires</span><span class="o">&lt;</span><span class="n">ImageConcept</span><span class="o">&lt;</span><span class="n">DstImage</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">();</span>
<span class="n">gil_function_requires</span><span class="o">&lt;</span><span class="n">ViewsCompatibleConcept</span><span class="o">&lt;</span><span class="n">SrcView</span><span class="p">,</span> <span class="k">typename</span> <span class="n">DstImage</span><span class="o">::</span><span class="n">view_t</span><span class="o">&gt;</span> <span class="o">&gt;</span><span class="p">();</span>
<span class="n">result</span><span class="o">=</span><span class="n">DstImage</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">width</span><span class="p">()</span><span class="o">+</span><span class="mi">2</span><span class="o">*</span><span class="n">k</span><span class="p">,</span> <span class="n">src</span><span class="p">.</span><span class="n">height</span><span class="p">()</span><span class="o">+</span><span class="mi">2</span><span class="o">*</span><span class="n">k</span><span class="p">);</span>
<span class="k">typename</span> <span class="n">DstImage</span><span class="o">::</span><span class="n">view_t</span> <span class="n">centerImg</span><span class="o">=</span><span class="n">subimage_view</span><span class="p">(</span><span class="n">view</span><span class="p">(</span><span class="n">result</span><span class="p">),</span> <span class="n">k</span><span class="p">,</span><span class="n">k</span><span class="p">,</span><span class="n">src</span><span class="p">.</span><span class="n">width</span><span class="p">(),</span><span class="n">src</span><span class="p">.</span><span class="n">height</span><span class="p">());</span>
<span class="n">std</span><span class="o">::</span><span class="n">copy</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">src</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">centerImg</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span>
<span class="p">}</span>
</pre></div>
</div>
<p>We allocated a larger image, then we used <code class="docutils literal notranslate"><span class="pre">subimage_view</span></code> to create a
shallow image of its center area of top left corner at (k,k) and of identical
size as <code class="docutils literal notranslate"><span class="pre">src</span></code>, and finally we copied <code class="docutils literal notranslate"><span class="pre">src</span></code> into that center image. If the
margin needs initialization, we could have done it with <code class="docutils literal notranslate"><span class="pre">fill_pixels</span></code>. Here
is how to simplify this code using the <code class="docutils literal notranslate"><span class="pre">copy_pixels</span></code> algorithm:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">SrcView</span><span class="p">,</span> <span class="k">typename</span> <span class="n">DstImage</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">create_with_margin</span><span class="p">(</span><span class="k">const</span> <span class="n">SrcView</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="kt">int</span> <span class="n">k</span><span class="p">,</span> <span class="n">DstImage</span><span class="o">&amp;</span> <span class="n">result</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">result</span><span class="p">.</span><span class="n">recreate</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">width</span><span class="p">()</span><span class="o">+</span><span class="mi">2</span><span class="o">*</span><span class="n">k</span><span class="p">,</span> <span class="n">src</span><span class="p">.</span><span class="n">height</span><span class="p">()</span><span class="o">+</span><span class="mi">2</span><span class="o">*</span><span class="n">k</span><span class="p">);</span>
<span class="n">copy_pixels</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">subimage_view</span><span class="p">(</span><span class="n">view</span><span class="p">(</span><span class="n">result</span><span class="p">),</span> <span class="n">k</span><span class="p">,</span><span class="n">k</span><span class="p">,</span><span class="n">src</span><span class="p">.</span><span class="n">width</span><span class="p">(),</span><span class="n">src</span><span class="p">.</span><span class="n">height</span><span class="p">()));</span>
<span class="p">}</span>
</pre></div>
</div>
<p>(Note also that <code class="docutils literal notranslate"><span class="pre">image::recreate</span></code> is more efficient than <code class="docutils literal notranslate"><span class="pre">operator=</span></code>, as
the latter will do an unnecessary copy construction). Not only does the above
example work for planar and interleaved images of any color space and pixel
depth; it is also optimized. GIL overrides <code class="docutils literal notranslate"><span class="pre">std::copy</span></code> - when called on two
identical interleaved images with no padding at the end of rows, it simply
does a <code class="docutils literal notranslate"><span class="pre">memmove</span></code>. For planar images it does <code class="docutils literal notranslate"><span class="pre">memmove</span></code> for each channel.
If one of the images has padding, (as in our case) it will try to do
<code class="docutils literal notranslate"><span class="pre">memmove</span></code> for each row. When an image has no padding, it will use its
lightweight horizontal iterator (as opposed to the more complex 1D image
iterator that has to check for the end of rows). It choses the fastest method,
taking into account both static and run-time parameters.</p>
</div>
<div class="section" id="histogram">
<h3>Histogram</h3>
<p>The histogram can be computed by counting the number of pixel values that fall
in each bin. The following method takes a grayscale (one-dimensional) image
view, since only grayscale pixels are convertible to integers:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">GrayView</span><span class="p">,</span> <span class="k">typename</span> <span class="n">R</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">grayimage_histogram</span><span class="p">(</span><span class="k">const</span> <span class="n">GrayView</span><span class="o">&amp;</span> <span class="n">img</span><span class="p">,</span> <span class="n">R</span><span class="o">&amp;</span> <span class="n">hist</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="k">typename</span> <span class="n">GrayView</span><span class="o">::</span><span class="n">iterator</span> <span class="n">it</span><span class="o">=</span><span class="n">img</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span> <span class="n">it</span><span class="o">!=</span><span class="n">img</span><span class="p">.</span><span class="n">end</span><span class="p">();</span> <span class="o">++</span><span class="n">it</span><span class="p">)</span>
<span class="o">++</span><span class="n">hist</span><span class="p">[</span><span class="o">*</span><span class="n">it</span><span class="p">];</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Using <code class="docutils literal notranslate"><span class="pre">boost::lambda</span></code> and GILs <code class="docutils literal notranslate"><span class="pre">for_each_pixel</span></code> algorithm, we can write
this more compactly:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">GrayView</span><span class="p">,</span> <span class="k">typename</span> <span class="n">R</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">grayimage_histogram</span><span class="p">(</span><span class="k">const</span> <span class="n">GrayView</span><span class="o">&amp;</span> <span class="n">v</span><span class="p">,</span> <span class="n">R</span><span class="o">&amp;</span> <span class="n">hist</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">for_each_pixel</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="o">++</span><span class="n">var</span><span class="p">(</span><span class="n">hist</span><span class="p">)[</span><span class="n">_1</span><span class="p">]);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Where <code class="docutils literal notranslate"><span class="pre">for_each_pixel</span></code> invokes <code class="docutils literal notranslate"><span class="pre">std::for_each</span></code> and <code class="docutils literal notranslate"><span class="pre">var</span></code> and <code class="docutils literal notranslate"><span class="pre">_1</span></code> are
<code class="docutils literal notranslate"><span class="pre">boost::lambda</span></code> constructs. To compute the luminosity histogram, we call the
above method using the grayscale view of an image:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">View</span><span class="p">,</span> <span class="k">typename</span> <span class="n">R</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">luminosity_histogram</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">v</span><span class="p">,</span> <span class="n">R</span><span class="o">&amp;</span> <span class="n">hist</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">grayimage_histogram</span><span class="p">(</span><span class="n">color_converted_view</span><span class="o">&lt;</span><span class="n">gray8_pixel_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">v</span><span class="p">),</span><span class="n">hist</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This is how to invoke it:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">hist</span><span class="p">[</span><span class="mi">256</span><span class="p">];</span>
<span class="n">std</span><span class="o">::</span><span class="n">fill</span><span class="p">(</span><span class="n">hist</span><span class="p">,</span><span class="n">hist</span><span class="o">+</span><span class="mi">256</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="n">luminosity_histogram</span><span class="p">(</span><span class="n">my_view</span><span class="p">,</span><span class="n">hist</span><span class="p">);</span>
</pre></div>
</div>
<p>If we want to view the histogram of the second channel of the image in the top
left 100x100 area, we call:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">grayimage_histogram</span><span class="p">(</span><span class="n">nth_channel_view</span><span class="p">(</span><span class="n">subimage_view</span><span class="p">(</span><span class="n">img</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">100</span><span class="p">,</span><span class="mi">100</span><span class="p">),</span><span class="mi">1</span><span class="p">),</span><span class="n">hist</span><span class="p">);</span>
</pre></div>
</div>
<p>No pixels are copied and no extra memory is allocated - the code operates
directly on the source pixels, which could be in any supported color space and
channel depth. They could be either planar or interleaved.</p>
</div>
<div class="section" id="using-image-views">
<h3>Using Image Views</h3>
<p>The following code illustrates the power of using image views:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">jpeg_read_image</span><span class="p">(</span><span class="s">&quot;monkey.jpg&quot;</span><span class="p">,</span> <span class="n">img</span><span class="p">);</span>
<span class="n">step1</span><span class="o">=</span><span class="n">view</span><span class="p">(</span><span class="n">img</span><span class="p">);</span>
<span class="n">step2</span><span class="o">=</span><span class="n">subimage_view</span><span class="p">(</span><span class="n">step1</span><span class="p">,</span> <span class="mi">200</span><span class="p">,</span><span class="mi">300</span><span class="p">,</span> <span class="mi">150</span><span class="p">,</span><span class="mi">150</span><span class="p">);</span>
<span class="n">step3</span><span class="o">=</span><span class="n">color_converted_view</span><span class="o">&lt;</span><span class="n">rgb8_view_t</span><span class="p">,</span><span class="n">gray8_pixel_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">step2</span><span class="p">);</span>
<span class="n">step4</span><span class="o">=</span><span class="n">rotated180_view</span><span class="p">(</span><span class="n">step3</span><span class="p">);</span>
<span class="n">step5</span><span class="o">=</span><span class="n">subsampled_view</span><span class="p">(</span><span class="n">step4</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="n">jpeg_write_view</span><span class="p">(</span><span class="s">&quot;monkey_transform.jpg&quot;</span><span class="p">,</span> <span class="n">step5</span><span class="p">);</span>
</pre></div>
</div>
<p>The intermediate images are shown here:</p>
<img alt="_images/monkey_steps.jpg" src="_images/monkey_steps.jpg" />
<p>Notice that no pixels are ever copied. All the work is done inside
<code class="docutils literal notranslate"><span class="pre">jpeg_write_view</span></code>. If we call our <code class="docutils literal notranslate"><span class="pre">luminosity_histogram</span></code> with
<code class="docutils literal notranslate"><span class="pre">step5</span></code> it will do the right thing.</p>
</div>
</div>
<div class="section" id="extending-the-generic-image-library">
<h2><a class="toc-backref" href="#id30">Extending the Generic Image Library</a></h2>
<p>You can define your own pixel iterators, locators, image views,
images, channel types, color spaces and algorithms. You can make
virtual images that live on the disk, inside a jpeg file, somewhere on
the internet, or even fully-synthetic images such as the Mandelbrot
set. As long as they properly model the corresponding concepts, they
will work with any existing GIL code. Most such extensions require no
changes to the library and can thus be supplied in another module.</p>
<div class="section" id="defining-new-color-spaces">
<h3>Defining New Color Spaces</h3>
<p>Each color space is in a separate file. To add a new color space, just
copy one of the existing ones (like rgb.hpp) and change it
accordingly. If you want color conversion support, you will have to
provide methods to convert between it and the existing color spaces
(see color_convert.h). For convenience you may want to provide useful
typedefs for pixels, pointers, references and images with the new
color space (see typedefs.h).</p>
</div>
<div class="section" id="defining-new-channel-types">
<h3>Defining New Channel Types</h3>
<p>Most of the time you dont need to do anything special to use a new
channel type. You can just use it:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">typedef</span> <span class="n">pixel</span><span class="o">&lt;</span><span class="kt">double</span><span class="p">,</span><span class="n">rgb_layout_t</span><span class="o">&gt;</span> <span class="n">rgb64_pixel_t</span><span class="p">;</span> <span class="c1">// 64 bit RGB pixel</span>
<span class="k">typedef</span> <span class="n">rgb64_pixel</span><span class="o">*</span> <span class="n">rgb64_pixel_ptr_t</span><span class="p">;</span><span class="c1">// pointer to 64-bit interleaved data</span>
<span class="k">typedef</span> <span class="n">image_type</span><span class="o">&lt;</span><span class="kt">double</span><span class="p">,</span><span class="n">rgb_layout_t</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">rgb64_image_t</span><span class="p">;</span> <span class="c1">// 64-bit interleaved image</span>
</pre></div>
</div>
<p>If you want to use your own channel class, you will need to provide a
specialization of <code class="docutils literal notranslate"><span class="pre">channel_traits</span></code> for it (see channel.hpp). If you
want to do conversion between your and existing channel types, you
will need to provide an overload of <code class="docutils literal notranslate"><span class="pre">channel_convert</span></code>.</p>
</div>
<div class="section" id="overloading-color-conversion">
<h3>Overloading Color Conversion</h3>
<p>Suppose you want to provide your own color conversion. For example,
you may want to implement higher quality color conversion using color
profiles. Typically you may want to redefine color conversion only in
some instances and default to GILs color conversion in all other
cases. Here is, for example, how to overload color conversion so that
color conversion to gray inverts the result but everything else
remains the same:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="c1">// make the default use GIL&#39;s default</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">SrcColorSpace</span><span class="p">,</span> <span class="k">typename</span> <span class="n">DstColorSpace</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="nl">my_color_converter_impl</span>
<span class="p">:</span> <span class="k">public</span> <span class="n">default_color_converter_impl</span><span class="o">&lt;</span><span class="n">SrcColorSpace</span><span class="p">,</span><span class="n">DstColorSpace</span><span class="o">&gt;</span> <span class="p">{};</span>
<span class="c1">// provide specializations only for cases you care about</span>
<span class="c1">// (in this case, if the destination is grayscale, invert it)</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">SrcColorSpace</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">my_color_converter_impl</span><span class="o">&lt;</span><span class="n">SrcColorSpace</span><span class="p">,</span><span class="n">gray_t</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">SrcP</span><span class="p">,</span> <span class="k">typename</span> <span class="n">DstP</span><span class="o">&gt;</span> <span class="c1">// Model PixelConcept</span>
<span class="kt">void</span> <span class="k">operator</span><span class="p">()(</span><span class="k">const</span> <span class="n">SrcP</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span> <span class="n">DstP</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">)</span> <span class="k">const</span>
<span class="p">{</span>
<span class="n">default_color_converter_impl</span><span class="o">&lt;</span><span class="n">SrcColorSpace</span><span class="p">,</span><span class="n">gray_t</span><span class="o">&gt;</span><span class="p">()(</span><span class="n">src</span><span class="p">,</span><span class="n">dst</span><span class="p">);</span>
<span class="n">get_color</span><span class="p">(</span><span class="n">dst</span><span class="p">,</span><span class="n">gray_color_t</span><span class="p">())</span><span class="o">=</span><span class="n">channel_invert</span><span class="p">(</span><span class="n">get_color</span><span class="p">(</span><span class="n">dst</span><span class="p">,</span><span class="n">gray_color_t</span><span class="p">()));</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="c1">// create a color converter object that dispatches to your own implementation</span>
<span class="k">struct</span> <span class="n">my_color_converter</span>
<span class="p">{</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">SrcP</span><span class="p">,</span> <span class="k">typename</span> <span class="n">DstP</span><span class="o">&gt;</span> <span class="c1">// Model PixelConcept</span>
<span class="kt">void</span> <span class="k">operator</span><span class="p">()(</span><span class="k">const</span> <span class="n">SrcP</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">,</span><span class="n">DstP</span><span class="o">&amp;</span> <span class="n">dst</span><span class="p">)</span> <span class="k">const</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">color_space_type</span><span class="o">&lt;</span><span class="n">SrcP</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">SrcColorSpace</span><span class="p">;</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">color_space_type</span><span class="o">&lt;</span><span class="n">DstP</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">DstColorSpace</span><span class="p">;</span>
<span class="n">my_color_converter_impl</span><span class="o">&lt;</span><span class="n">SrcColorSpace</span><span class="p">,</span><span class="n">DstColorSpace</span><span class="o">&gt;</span><span class="p">()(</span><span class="n">src</span><span class="p">,</span><span class="n">dst</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
</pre></div>
</div>
<p>GIL color conversion functions take the color converter as an
optional parameter. You can pass your own color converter:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">color_converted_view</span><span class="o">&lt;</span><span class="n">gray8_pixel_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">img_view</span><span class="p">,</span><span class="n">my_color_converter</span><span class="p">());</span>
</pre></div>
</div>
</div>
<div class="section" id="defining-new-image-views">
<h3>Defining New Image Views</h3>
<p>You can provide your own pixel iterators, locators and views,
overriding either the mechanism for getting from one pixel to the next
or doing an arbitrary pixel transformation on dereference. For
example, lets look at the implementation of <code class="docutils literal notranslate"><span class="pre">color_converted_view</span></code>
(an image factory method that, given any image view, returns a new,
otherwise identical view, except that color conversion is performed on
pixel access). First we need to define a model of
<code class="docutils literal notranslate"><span class="pre">PixelDereferenceAdaptorConcept</span></code>; a function object that will be
called when we dereference a pixel iterator. It will call
<code class="docutils literal notranslate"><span class="pre">color_convert</span></code> to convert to the destination pixel type:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">SrcConstRefP</span><span class="p">,</span> <span class="c1">// const reference to the source pixel</span>
<span class="k">typename</span> <span class="n">DstP</span><span class="o">&gt;</span> <span class="c1">// Destination pixel value (models PixelValueConcept)</span>
<span class="k">class</span> <span class="nc">color_convert_deref_fn</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">typedef</span> <span class="n">color_convert_deref_fn</span> <span class="n">const_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">DstP</span> <span class="n">value_type</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">value_type</span> <span class="n">reference</span><span class="p">;</span> <span class="c1">// read-only dereferencing</span>
<span class="k">typedef</span> <span class="k">const</span> <span class="n">value_type</span><span class="o">&amp;</span> <span class="n">const_reference</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">SrcConstRefP</span> <span class="n">argument_type</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">reference</span> <span class="n">result_type</span><span class="p">;</span>
<span class="k">static</span> <span class="kt">bool</span> <span class="k">constexpr</span> <span class="n">is_mutable</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
<span class="n">result_type</span> <span class="nf">operator</span><span class="p">()(</span><span class="n">argument_type</span> <span class="n">srcP</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
<span class="n">result_type</span> <span class="n">dstP</span><span class="p">;</span>
<span class="n">color_convert</span><span class="p">(</span><span class="n">srcP</span><span class="p">,</span><span class="n">dstP</span><span class="p">);</span>
<span class="k">return</span> <span class="n">dstP</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</pre></div>
</div>
<p>We then use the <code class="docutils literal notranslate"><span class="pre">add_deref</span></code> member struct of image views to construct the
type of a view that invokes a given function object (<code class="docutils literal notranslate"><span class="pre">deref_t</span></code>) upon
dereferencing. In our case, it performs color conversion:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">SrcView</span><span class="p">,</span> <span class="k">typename</span> <span class="n">DstP</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">color_converted_view_type</span>
<span class="p">{</span>
<span class="k">private</span><span class="o">:</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">SrcView</span><span class="o">::</span><span class="n">const_t</span><span class="o">::</span><span class="n">reference</span> <span class="n">src_pix_ref</span><span class="p">;</span> <span class="c1">// const reference to pixel in SrcView</span>
<span class="k">typedef</span> <span class="n">color_convert_deref_fn</span><span class="o">&lt;</span><span class="n">src_pix_ref</span><span class="p">,</span> <span class="n">DstP</span><span class="o">&gt;</span> <span class="n">deref_t</span><span class="p">;</span> <span class="c1">// the dereference adaptor that performs color conversion</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">SrcView</span><span class="o">::</span><span class="k">template</span> <span class="n">add_deref</span><span class="o">&lt;</span><span class="n">deref_t</span><span class="o">&gt;</span> <span class="n">add_ref_t</span><span class="p">;</span>
<span class="k">public</span><span class="o">:</span>
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">add_ref_t</span><span class="o">::</span><span class="n">type</span> <span class="n">type</span><span class="p">;</span> <span class="c1">// the color converted view type</span>
<span class="k">static</span> <span class="n">type</span> <span class="nf">make</span><span class="p">(</span><span class="k">const</span> <span class="n">SrcView</span><span class="o">&amp;</span> <span class="n">sv</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">add_ref_t</span><span class="o">::</span><span class="n">make</span><span class="p">(</span><span class="n">sv</span><span class="p">,</span> <span class="n">deref_t</span><span class="p">());</span> <span class="p">}</span>
<span class="p">};</span>
</pre></div>
</div>
<p>Finally our <code class="docutils literal notranslate"><span class="pre">color_converted_view</span></code> code simply creates color-converted view
from the source view:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">DstP</span><span class="p">,</span> <span class="k">typename</span> <span class="n">View</span><span class="o">&gt;</span> <span class="kr">inline</span>
<span class="k">typename</span> <span class="n">color_converted_view_type</span><span class="o">&lt;</span><span class="n">View</span><span class="p">,</span><span class="n">DstP</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">color_convert_view</span><span class="p">(</span><span class="k">const</span> <span class="n">View</span><span class="o">&amp;</span> <span class="n">src</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">color_converted_view_type</span><span class="o">&lt;</span><span class="n">View</span><span class="p">,</span><span class="n">DstP</span><span class="o">&gt;::</span><span class="n">make</span><span class="p">(</span><span class="n">src</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>(The actual color convert view transformation is slightly more
complicated, as it takes an optional color conversion object, which
allows users to specify their own color conversion methods). See the
GIL tutorial for an example of creating a virtual image view that
defines the Mandelbrot set.</p>
</div>
</div>
<div class="section" id="technicalities">
<h2><a class="toc-backref" href="#id31">Technicalities</a></h2>
<div class="section" id="creating-a-reference-proxy">
<h3>Creating a reference proxy</h3>
<p>Sometimes it is necessary to create a proxy class that represents a
reference to a given object. Examples of these are GILs reference to
a planar pixel (<code class="docutils literal notranslate"><span class="pre">planar_pixel_reference</span></code>) and GILs sub-byte channel
references. Writing a reference proxy class can be tricky. One problem
is that the proxy reference is constructed as a temporary object and
returned by value upon dereferencing the iterator:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">struct</span> <span class="n">rgb_planar_pixel_iterator</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="n">my_reference_proxy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="n">reference</span><span class="p">;</span>
<span class="n">reference</span> <span class="k">operator</span><span class="o">*</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">reference</span><span class="p">(</span><span class="n">red</span><span class="p">,</span><span class="n">green</span><span class="p">,</span><span class="n">blue</span><span class="p">);</span> <span class="p">}</span>
<span class="p">};</span>
</pre></div>
</div>
<p>The problem arises when an iterator is dereferenced directly into a
function that takes a mutable pixel:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Pixel</span><span class="o">&gt;</span> <span class="c1">// Models MutablePixelConcept</span>
<span class="kt">void</span> <span class="n">invert_pixel</span><span class="p">(</span><span class="n">Pixel</span><span class="o">&amp;</span> <span class="n">p</span><span class="p">);</span>
<span class="n">rgb_planar_pixel_iterator</span> <span class="n">myIt</span><span class="p">;</span>
<span class="n">invert_pixel</span><span class="p">(</span><span class="o">*</span><span class="n">myIt</span><span class="p">);</span> <span class="c1">// compile error!</span>
</pre></div>
</div>
<p>C++ does not allow for matching a temporary object against a non-constant
reference. The solution is to:</p>
<ul class="simple">
<li><p>Use const qualifier on all members of the reference proxy object:</p></li>
</ul>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="k">struct</span> <span class="n">my_reference_proxy</span>
<span class="p">{</span>
<span class="k">const</span> <span class="n">my_reference_proxy</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">my_reference_proxy</span><span class="o">&amp;</span> <span class="n">p</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="k">const</span> <span class="n">my_reference_proxy</span><span class="o">*</span> <span class="k">operator</span><span class="o">-&gt;</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="k">this</span><span class="p">;</span> <span class="p">}</span>
<span class="p">...</span>
<span class="p">};</span>
</pre></div>
</div>
<ul class="simple">
<li><p>Use different classes to denote mutable and constant reference
(maybe based on the constness of the template parameter)</p></li>
<li><p>Define the reference type of your iterator with const qualifier:</p></li>
</ul>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">struct</span> <span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">rgb_planar_pixel_iterator</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="k">typedef</span> <span class="k">const</span> <span class="n">my_reference_proxy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="n">reference</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>
</div>
<p>A second important issue is providing an overload for <code class="docutils literal notranslate"><span class="pre">swap</span></code> for
your reference class. The default <code class="docutils literal notranslate"><span class="pre">std::swap</span></code> will not work
correctly. You must use a real value type as the temporary. A further
complication is that in some implementations of the STL the <code class="docutils literal notranslate"><span class="pre">swap</span></code>
function is incorrectly called qualified, as <code class="docutils literal notranslate"><span class="pre">std::swap</span></code>. The only
way for these STL algorithms to use your overload is if you define it
in the <code class="docutils literal notranslate"><span class="pre">std</span></code> namespace:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">namespace</span> <span class="n">std</span>
<span class="p">{</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
<span class="kt">void</span> <span class="n">swap</span><span class="p">(</span><span class="n">my_reference_proxy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;&amp;</span> <span class="n">x</span><span class="p">,</span> <span class="n">my_reference_proxy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;&amp;</span> <span class="n">y</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">my_value</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="n">tmp</span><span class="o">=</span><span class="n">x</span><span class="p">;</span>
<span class="n">x</span><span class="o">=</span><span class="n">y</span><span class="p">;</span>
<span class="n">y</span><span class="o">=</span><span class="n">tmp</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Lastly, remember that constructors and copy-constructors of proxy
references are always shallow and assignment operators are deep.</p>
<p>We are grateful to Dave Abrahams, Sean Parent and Alex Stepanov for
suggesting the above solution.</p>
</div>
</div>
<div class="section" id="conclusion">
<h2><a class="toc-backref" href="#id32">Conclusion</a></h2>
<p>The Generic Image Library is designed with the following five goals in
mind:</p>
<dl class="field-list simple">
<dt class="field-odd">Generality</dt>
<dd class="field-odd"><p>Abstracts image representations from algorithms on
images. It allows for writing code once and have it work for any
image type.</p>
</dd>
<dt class="field-even">Performance</dt>
<dd class="field-even"><p>Speed has been instrumental to the design of the
library. The generic algorithms provided in the library are in many
cases comparable in speed to hand-coding the algorithm for a
specific image type.</p>
</dd>
<dt class="field-odd">Flexibility</dt>
<dd class="field-odd"><p>Compile-type parameter resolution results in faster
code, but severely limits code flexibility. The library allows for
any image parameter to be specified at run time, at a minor
performance cost.</p>
</dd>
<dt class="field-even">Extensibility</dt>
<dd class="field-even"><p>Virtually every construct in GIL can be extended - new
channel types, color spaces, layouts, iterators, locators, image
views and images can be provided by modeling the corresponding GIL
concepts.</p>
</dd>
<dt class="field-odd">Compatibility</dt>
<dd class="field-odd"><p>The library is designed as an STL complement. Generic
STL algorithms can be used for pixel manipulation, and they are
specifically targeted for optimization. The library works with
existing raw pixel data from another image library.</p>
</dd>
</dl>
</div>
</div>
<div class="navbar" style="text-align:right;">
<a class="prev" title="Naming Conventions" href="naming.html"><img src="_static/prev.png" alt="prev"/></a>
<a class="next" title="Image Processing" href="image_processing/index.html"><img src="_static/next.png" alt="next"/></a>
</div>
</div>
<div class="footer" role="contentinfo">
Last updated on 2019-09-03 19:09:44.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 2.2.0.
</div>
</body>
</html>