2
0
mirror of https://github.com/boostorg/gil.git synced 2026-01-24 05:52:13 +00:00
Files
gil/develop/doc/html/design_guide.html

2996 lines
387 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 1.0 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: '1.0',
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>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="top" title="Boost.GIL 1.0 documentation" href="index.html" />
<link rel="prev" title="Numeric extension" href="numeric.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="Numeric extension" href="numeric.html"><img src="_static/prev.png" alt="prev"/></a>
</div>
<div class="section" id="design-guide">
<h1>Design Guide</h1>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#overview" id="id15">Overview</a></li>
<li><a class="reference internal" href="#about-concepts" id="id16">About Concepts</a></li>
<li><a class="reference internal" href="#point" id="id17">Point</a></li>
<li><a class="reference internal" href="#channel" id="id18">Channel</a></li>
<li><a class="reference internal" href="#color-space-and-layout" id="id19">Color Space and Layout</a></li>
<li><a class="reference internal" href="#color-base" id="id20">Color Base</a></li>
<li><a class="reference internal" href="#pixel" id="id21">Pixel</a></li>
<li><a class="reference internal" href="#pixel-iterator" id="id22">Pixel Iterator</a></li>
<li><a class="reference internal" href="#image-view" id="id23">Image View</a></li>
<li><a class="reference internal" href="#image" id="id24">Image</a></li>
<li><a class="reference internal" href="#run-time-specified-images-and-image-views" id="id25">Run-time specified images and image views</a></li>
<li><a class="reference internal" href="#useful-metafunctions-and-typedefs" id="id26">Useful Metafunctions and Typedefs</a></li>
<li><a class="reference internal" href="#i-o-extension" id="id27">I/O Extension</a></li>
<li><a class="reference internal" href="#sample-code" id="id28">Sample Code</a></li>
<li><a class="reference internal" href="#extending-the-generic-image-library" id="id29">Extending the Generic Image Library</a></li>
<li><a class="reference internal" href="#technicalities" id="id30">Technicalities</a></li>
<li><a class="reference internal" href="#conclusion" id="id31">Conclusion</a></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>Structure (planar vs. interleaved)</li>
<li>Color space and presence of alpha (RGB, RGBA, CMYK, etc.)</li>
<li>Channel depth (8-bit, 16-bit, etc.)</li>
<li>Order of channels (RGB vs. BGR, etc.)</li>
<li>Row alignment policy (no alignment, word-alignment, etc.)</li>
</ul>
<p>It also supports user-defined models of images, and images whose
parameters are specified at run-time. GIL abstracts image
representation from algorithms applied on images and allows us to
write the algorithm once and have it work on any of the above image
variations while generating code that is comparable in speed to that
of hand-writing the algorithm for a specific image type.</p>
<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, GILs
class <code class="docutils literal notranslate"><span class="pre">pixel</span></code> is a model of GILs <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 here:
<a class="reference external" href="http://www.generic-programming.org/languages/conceptcpp/">http://www.generic-programming.org/languages/conceptcpp/</a></p>
<p>In this document we will use a syntax for defining concepts that is
described in a proposal for a Concepts extension to C++0x specified
here:
<a class="reference external" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf</a></p>
<p>Here are some common concepts that will be used in GIL. Most of them
are defined here:
<a class="reference external" href="http://www.generic-programming.org/languages/conceptcpp/concept_web.php">http://www.generic-programming.org/languages/conceptcpp/concept_web.php</a></p>
<div class="highlight-c++ 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-c++ 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-c++ 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-c++ 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="first admonition-title">See also</p>
<ul class="last simple">
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_point_n_d_concept.html">PointNDConcept</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_point2_d_concept.html">Point2DConcept</a></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-c++ 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-c++ 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-c++ 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-c++ 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="first admonition-title">See also</p>
<ul class="last simple">
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_concept.html">ChannelConcept&lt;T&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_value_concept.html">ChannelValueConcept&lt;T&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_channel_concept.html">MutableChannelConcept&lt;T&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_channels_compatible_concept.html">ChannelsCompatibleConcept&lt;T1,T2&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_convertible_concept.html">ChannelConvertibleConcept&lt;SrcChannel,DstChannel&gt;</a></li>
</ul>
</div>
<div class="section" id="id1">
<h3>Models</h3>
<p>All built-in integral and floating point types are valid channels. GIL
provides standard type aliases for some integral channels:</p>
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">typedef</span> <span class="n">boost</span><span class="o">::</span><span class="kt">uint8_t</span> <span class="n">bits8</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">boost</span><span class="o">::</span><span class="kt">uint16_t</span> <span class="n">bits16</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">boost</span><span class="o">::</span><span class="kt">uint32_t</span> <span class="n">bits32</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">boost</span><span class="o">::</span><span class="kt">int8_t</span> <span class="n">bits8s</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">boost</span><span class="o">::</span><span class="kt">int16_t</span> <span class="n">bits16s</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">boost</span><span class="o">::</span><span class="kt">int32_t</span> <span class="n">bits32s</span><span class="p">;</span>
</pre></div>
</div>
<p>The minimum and maximum values of a channel modeled by a built-in type
correspond to the minimum and maximum physical range of the built-in
type, as specified by its <code 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 [0..1] floating
point channel type as follows:</p>
<div class="highlight-c++ 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-c++ 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-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">typedef</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="n">channel16_0_5_reference_t</span><span class="p">;</span>
<span class="k">typedef</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="n">channel16_5_6_reference_t</span><span class="p">;</span>
<span class="k">typedef</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="n">channel16_11_5_reference_t</span><span class="p">;</span>
<span class="n">boost</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-c++ 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">//channel_6bit = channel2; // compile error: Assignment between incompatible channels.</span>
</pre></div>
</div>
<p>All channel models provided by GIL are pairwise convertible:</p>
<div class="highlight-c++ 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-c++ 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="first admonition-title">See also</p>
<ul class="last simple">
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_color_space_concept.html">ColorSpaceConcept&lt;ColorSpace&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_color_spaces_compatible_concept.html">ColorSpacesCompatibleConcept&lt;ColorSpace1,ColorSpace2&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_mapping_concept.html">ChannelMappingConcept&lt;Mapping&gt;</a></li>
</ul>
</div>
<div class="section" id="id2">
<h3>Models</h3>
<p>GIL currently provides the following color spaces:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">gray_t</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">rgb_t</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">rgba_t</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">cmyk_t</span></code></li>
</ul>
<p>It also provides unnamed N-channel color spaces of two to five channels:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">devicen_t&lt;2&gt;</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">devicen_t&lt;3&gt;</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">devicen_t&lt;4&gt;</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">devicen_t&lt;5&gt;</span></code></li>
</ul>
<p>Besides the standard layouts, it also provides:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">bgr_layout_t</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">bgra_layout_t</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">abgr_layout_t</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">argb_layout_t</span></code></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="k">struct</span> <span class="n">red_t</span><span class="p">{};</span>
<span class="k">struct</span> <span class="n">green_t</span><span class="p">{};</span>
<span class="k">struct</span> <span class="n">blue_t</span><span class="p">{};</span>
<span class="k">struct</span> <span class="n">alpha_t</span><span class="p">{};</span>
<span class="k">typedef</span> <span class="n">mpl</span><span class="o">::</span><span class="n">vector4</span><span class="o">&lt;</span><span class="n">red_t</span><span class="p">,</span><span class="n">green_t</span><span class="p">,</span><span class="n">blue_t</span><span class="p">,</span><span class="n">alpha_t</span><span class="o">&gt;</span> <span class="n">rgba_t</span><span class="p">;</span>
</pre></div>
</div>
<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-c++ 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">typedef</span> <span class="n">ColorSpace</span> <span class="n">color_space_t</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">ChannelMapping</span> <span class="n">channel_mapping_t</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-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">typedef</span> <span class="n">layout</span><span class="o">&lt;</span><span class="n">rgba_t</span><span class="o">&gt;</span> <span class="n">rgba_layout_t</span><span class="p">;</span> <span class="c1">// default ordering is 0,1,2,3...</span>
<span class="k">typedef</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;</span> <span class="o">&gt;</span> <span class="n">bgra_layout_t</span><span class="p">;</span>
<span class="k">typedef</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;</span> <span class="o">&gt;</span> <span class="n">argb_layout_t</span><span class="p">;</span>
<span class="k">typedef</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;</span> <span class="o">&gt;</span> <span class="n">abgr_layout_t</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-c++ 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 {red_t,
green_t, blue_t}. For a color base with a BGR layout, the first
element in physical ordering is the blue element, whereas the first
semantic element is the red one. Models of <code 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-c++ 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. 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-c++ 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-c++ 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. For example, here is the implementation of <code class="docutils literal notranslate"><span class="pre">static_equal</span></code>:</p>
<div class="highlight-c++ 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-c++ 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-c++ 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">type</span><span class="o">::</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-c++ 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="first admonition-title">See also</p>
<ul class="last simple">
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_based_concept.html">PixelBasedConcept&lt;P&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_concept.html">PixelConcept&lt;Pixel&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_pixel_concept.html">MutablePixelConcept&lt;Pixel&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_value_concept.html">PixelValueConcept&lt;Pixel&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_homogeneous_pixel_based_concept.html">HomogeneousPixelConcept&lt;Pixel&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_homogeneous_pixel_concept.html">MutableHomogeneousPixelConcept&lt;Pixel&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_homogeneous_pixel_value_concept.html">HomogeneousPixelValueConcept&lt;Pixel&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixels_compatible_concept.html">PixelsCompatibleConcept&lt;Pixel1, Pixel2&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_convertible_concept.html">PixelConvertibleConcept&lt;SrcPixel, DstPixel&gt;</a></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-c++ 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-c++ 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-c++ 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="n">BOOST_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="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-c++ 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="n">BOOST_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="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-c++ 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-c++ 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>
<div class="section" id="fundamental-iterator">
<h3>Fundamental Iterator</h3>
<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>. 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-c++ 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">type</span><span class="o">::</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">type</span><span class="o">::</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="first admonition-title">See also</p>
<ul class="last simple">
<li><a class="reference external" href="reference/group___pixel_iterator_concept_pixel_iterator.html">PixelIteratorConcept&lt;Iterator&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_pixel_iterator_concept.html">MutablePixelIteratorConcept&lt;Iterator&gt;</a></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 GILs
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 GILs
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-c++ 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-c++ 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-c++ 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="first admonition-title">See also</p>
<ul class="last simple">
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_iterator_adaptor_concept.html">IteratorAdaptorConcept&lt;Iterator&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_iterator_adaptor_concept.html">MutableIteratorAdaptorConcept&lt;Iterator&gt;</a></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><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>)</li>
<li><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).</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-c++ 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><code class="docutils literal notranslate"><span class="pre">color_convert_deref_fn</span></code>: a function object that performs color
conversion</li>
<li><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</li>
<li><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></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>a single-channel view of the red channel of an RGB interleaved image</li>
<li>left-to-right flipped image (step = -fundamental_step)</li>
<li>subsampled view, taking every N-th pixel (step = N*fundamental_step)</li>
<li>traversal in vertical direction (step = number of bytes per row)</li>
<li>any combination of the above (steps are multiplied)</li>
</ul>
<p>Step iterators are forward traversal iterators that allow changing the
step between adjacent values:</p>
<div class="highlight-c++ 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
MemoryBasedIteratorConcept. 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-c++ 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-c++ 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="first admonition-title">See also</p>
<ul class="last simple">
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_step_iterator_concept.html">StepIteratorConcept&lt;Iterator&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_step_iterator_concept.html">MutableStepIteratorConcept&lt;Iterator&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_memory_based_iterator_concept.html">MemoryBasedIteratorConcept&lt;Iterator&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_has_dynamic_x_step_type_concept.html">HasDynamicXStepTypeConcept&lt;T&gt;</a></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. GILs 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-c++ 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">I</span><span class="o">&gt;</span> <span class="c1">// Models MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept</span>
<span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o">&lt;</span><span class="n">I</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">make_step_iterator</span><span class="p">(</span><span class="k">const</span> <span class="n">I</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 class="section" id="pixel-locator">
<h3>Pixel Locator</h3>
<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-c++ 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-c++ 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 also
vertically. This gives rise to the Y equivalent of
HasDynamicXStepTypeConcept:</p>
<div class="highlight-c++ 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-c++ 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-c++ 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="first admonition-title">See also</p>
<ul class="last simple">
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_has_dynamic_y_step_type_concept.html">HasDynamicYStepTypeConcept&lt;T&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_has_transposed_type_concept.html">HasTransposedTypeConcept&lt;T&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access_n_d_locator_concept.html">RandomAccessNDLocatorConcept&lt;Locator&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access_n_d_locator_concept.html">MutableRandomAccessNDLocatorConcept&lt;Locator&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access2_d_locator_concept.html">RandomAccess2DLocatorConcept&lt;Locator&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access2_d_locator_concept.html">MutableRandomAccess2DLocatorConcept&lt;Locator&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_locator_concept.html">PixelLocatorConcept&lt;Locator&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_pixel_locator_concept.html">MutablePixelLocatorConcept&lt;Locator&gt;</a></li>
</ul>
</div>
<div class="section" id="id11">
<h4>Models</h4>
<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><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-c++ 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">StepIterator</span><span class="o">&gt;</span> <span class="c1">// Models StepIteratorConcept, MemoryBasedIteratorConcept</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 and step iterators 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><code class="docutils literal notranslate"><span class="pre">pixel&lt;T,C&gt;*</span></code> - for interleaved images</li>
<li><code class="docutils literal notranslate"><span class="pre">planar_pixel_iterator&lt;T*,C&gt;</span></code> - for planar images</li>
<li><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)</li>
<li><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</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><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-c++ 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>
</div>
<div class="section" id="iterator-over-2d-image">
<h3>Iterator over 2D image</h3>
<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-c++ 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</p>
<blockquote>
<div><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</div></blockquote>
<p><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 class="section" id="image-view">
<h2><a class="toc-backref" href="#id23">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-c++ 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-c++ 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-c++ 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-c++ 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="first admonition-title">See also</p>
<ul class="last simple">
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access_n_d_image_view_concept.html">RandomAccessNDImageViewConcept&lt;View&gt;</a></li>
<li><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></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access2_d_image_view_concept.html">RandomAccess2DImageViewConcept&lt;View&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access2_d_image_view_concept.html">MutableRandomAccess2DImageViewConcept&lt;View&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_image_view_concept.html">ImageViewConcept&lt;View&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_image_view_concept.html">MutableImageViewConcept&lt;View&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_views_compatible_concept.html">ViewsCompatibleConcept&lt;View1,View2&gt;</a></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-c++ 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 (could be MutablePixelLocatorConcept)</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>
<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-c++ 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">Iterator</span><span class="o">&gt;</span> <span class="c1">// Models pixel iterator (like rgb8_ptr_t or rgb8c_ptr_t)</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-c++ 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">IC</span><span class="o">&gt;</span> <span class="c1">// Models channel iterator (like bits8* or const bits8*)</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-c++ 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-c++ 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-c++ 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-c++ 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 begin() and end()
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-c++ 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 neighbors, 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 typically 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="#id24">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-c++ 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-c++ 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>GILs images have views that model <code class="docutils literal notranslate"><span class="pre">ImageViewConcept</span></code> and
operate on pixels.:</p>
<div class="highlight-c++ 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="first admonition-title">See also</p>
<ul class="last simple">
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access_n_d_image_concept.html">RandomAccessNDImageConcept&lt;Image&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access2_d_image_concept.html">RandomAccess2DImageConcept&lt;Image&gt;</a></li>
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_image_concept.html">ImageConcept&lt;Image&gt;</a></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-c++ notranslate"><div class="highlight"><pre><span></span>template &lt;typename Pixel, \\ Models PixelValueConcept
bool IsPlanar, \\ planar or interleaved image
typename A=std::allocator&lt;unsigned char&gt; &gt;
class image;
</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="#id25">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>GILs 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-c++ 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) BOOST_STATIC_ASSERT((is_same&lt; A,B &gt;::value))</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><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 GILs <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>GILs 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
GILs variant always takes a single argument, which is a model of MPL
Random Access Sequence enumerating the allowed types. Having a single
interface allows GILs variant to be used easier in generic
code. Synopsis:</p>
<div class="highlight-c++ 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>GILs <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-c++ 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 operator==, 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-c++ 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-c++ 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-c++ 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="#id26">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. They follow this pattern:</p>
<dl class="docutils">
<dt><em>ColorSpace</em> + <em>BitDepth</em> + [“s|f”] + [“c”] + [“_planar”] +</dt>
<dd>[“_step”] + <em>ClassType</em> + “_t”</dd>
</dl>
<p>where <em>ColorSpace</em> also indicates the ordering of components. 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). Here are examples:</p>
<div class="highlight-c++ 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-c++ 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-c++ 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-c++ 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-c++ 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-c++ 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-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">typedef</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="n">VT</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 PixelBasedConcept,
HomogeneousPixelBasedConcept and metafunctions built on top of them:</p>
<div class="highlight-c++ 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-c++ notranslate"><div class="highlight"><pre><span></span><span class="n">BOOST_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>
</pre></div>
</div>
<p>GIL also supports type analysis metafunctions of the form:
[pixel_reference/iterator/locator/view/image] + “_is_” +
[basic/mutable/step]. For example:</p>
<div class="highlight-c++ 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="#id27">I/O Extension</a></h2>
<p>GILs 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>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field-odd field"><th class="field-name">JPEG:</th><td class="field-body">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.</td>
</tr>
<tr class="field-even field"><th class="field-name">TIFF:</th><td class="field-body">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.</td>
</tr>
<tr class="field-odd field"><th class="field-name">PNG:</th><td class="field-body">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.</td>
</tr>
</tbody>
</table>
<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-c++ 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-c++ notranslate"><div class="highlight"><pre><span></span><span class="c1">// Opens the given JPEG file name, selects the first type in Images whose color space and channel are compatible to those of the image file</span>
<span class="c1">// and creates a new image of that type with the dimensions specified by the image file.</span>
<span class="c1">// Throws std::ios_base::failure if none of the types in Images are 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">const</span> <span class="pre">char*</span></code></p>
</div>
<div class="section" id="sample-code">
<h2><a class="toc-backref" href="#id28">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,
pointers and references:</p>
<div class="highlight-c++ 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-c++ 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="n">BOOST_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="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="n">BOOST_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="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-c++ 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-c++ 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-c++ 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-c++ 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-c++ 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-c++ 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-c++ 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-c++ 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="#id29">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-c++ 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-c++ 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>GILs color conversion functions take the color converter as an
optional parameter. You can pass your own color converter:</p>
<div class="highlight-c++ 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-c++ 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="n">BOOST_STATIC_CONSTANT</span><span class="p">(</span><span class="kt">bool</span><span class="p">,</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-c++ 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-c++ 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="#id30">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-c++ 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-c++ 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>
<li><p class="first">Use const qualifier on all members of the reference proxy object:</p>
<div class="highlight-c++ 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>
</li>
<li><p class="first">Use different classes to denote mutable and constant reference
(maybe based on the constness of the template parameter)</p>
</li>
<li><p class="first">Define the reference type of your iterator with const qualifier:</p>
<div class="highlight-c++ 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>
</li>
</ul>
<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-c++ 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="#id31">Conclusion</a></h2>
<p>The Generic Image Library is designed with the following five goals in
mind:</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field-odd field"><th class="field-name">Generality:</th><td class="field-body">Abstracts image representations from algorithms on
images. It allows for writing code once and have it work for any
image type.</td>
</tr>
<tr class="field-even field"><th class="field-name">Performance:</th><td class="field-body">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.</td>
</tr>
<tr class="field-odd field"><th class="field-name">Flexibility:</th><td class="field-body">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.</td>
</tr>
<tr class="field-even field"><th class="field-name">Extensibility:</th><td class="field-body">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.</td>
</tr>
<tr class="field-odd field"><th class="field-name">Compatibility:</th><td class="field-body">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.</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="navbar" style="text-align:right;">
<a class="prev" title="Numeric extension" href="numeric.html"><img src="_static/prev.png" alt="prev"/></a>
</div>
</div>
</body>
</html>