mirror of
https://github.com/boostorg/gil.git
synced 2026-01-24 05:52:13 +00:00
2996 lines
387 KiB
HTML
2996 lines
387 KiB
HTML
|
||
|
||
<!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, GIL’s
|
||
class <code class="docutils literal notranslate"><span class="pre">pixel</span></code> is a model of GIL’s <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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</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">></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">&</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"><</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">></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"><</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="p">{</span> <span class="cm">/* unspecified */</span> <span class="p">};</span>
|
||
<span class="k">template</span><span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="n">concept_map</span> <span class="n">SameType</span><span class="o"><</span><span class="n">T</span><span class="p">,</span> <span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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">&</span> <span class="n">t</span><span class="p">,</span> <span class="n">T</span><span class="o">&</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="o">:</span> <span class="n">DefaultConstructible</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span> <span class="n">CopyConstructible</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span> <span class="n">EqualityComparable</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span> <span class="n">Assignable</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span> <span class="n">Swappable</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="p">{};</span>
|
||
|
||
<span class="k">auto</span> <span class="n">concept</span> <span class="n">Metafunction</span><span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="o">:</span> <span class="n">Regular</span><span class="o"><</span><span class="n">T</span><span class="o">></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"><</span><span class="kt">size_t</span> <span class="n">K</span><span class="o">></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"><</span><span class="n">axis</span><span class="o">></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"><</span><span class="kt">size_t</span> <span class="n">K</span><span class="o">></span> <span class="k">const</span> <span class="k">typename</span> <span class="n">axis</span><span class="o"><</span><span class="n">K</span><span class="o">>::</span><span class="n">type</span><span class="o">&</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"><</span><span class="kt">size_t</span> <span class="n">K</span><span class="o">></span> <span class="k">typename</span> <span class="n">axis</span><span class="o"><</span><span class="n">K</span><span class="o">>::</span><span class="n">type</span><span class="o">&</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="o">:</span> <span class="n">PointNDConcept</span><span class="o"><</span><span class="n">T</span><span class="o">></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"><</span><span class="n">axis</span><span class="o"><</span><span class="mi">0</span><span class="o">>::</span><span class="n">type</span><span class="p">,</span> <span class="n">axis</span><span class="o"><</span><span class="mi">1</span><span class="o">>::</span><span class="n">type</span><span class="o">></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"><</span><span class="mi">0</span><span class="o">>::</span><span class="n">type</span><span class="p">;</span>
|
||
|
||
<span class="k">const</span> <span class="n">value_type</span><span class="o">&</span> <span class="k">operator</span><span class="p">[](</span><span class="k">const</span> <span class="n">T</span><span class="o">&</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">&</span> <span class="k">operator</span><span class="p">[](</span> <span class="n">T</span><span class="o">&</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<T></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="o">:</span> <span class="n">EqualityComparable</span><span class="o"><</span><span class="n">T</span><span class="o">></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<T>::value_type to access it</span>
|
||
<span class="n">where</span> <span class="n">ChannelValueConcept</span><span class="o"><</span><span class="n">value_type</span><span class="o">></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">&</span><span class="p">;</span> <span class="c1">// use channel_traits<T>::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<T>::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">&</span><span class="p">;</span> <span class="c1">// use channel_traits<T>::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<T>::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<T>::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<T>::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<T>::min_value to access it</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="n">concept</span> <span class="n">MutableChannelConcept</span><span class="o"><</span><span class="n">ChannelConcept</span> <span class="n">T</span><span class="o">></span> <span class="o">:</span> <span class="n">Swappable</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span> <span class="n">Assignable</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="p">{};</span>
|
||
|
||
<span class="n">concept</span> <span class="n">ChannelValueConcept</span><span class="o"><</span><span class="n">ChannelConcept</span> <span class="n">T</span><span class="o">></span> <span class="o">:</span> <span class="n">Regular</span><span class="o"><</span><span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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">&</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">&</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"><</span><span class="n">T</span><span class="o">>::</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"><</span><span class="n">T</span><span class="o">>::</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"><</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">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">SameType</span><span class="o"><</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">></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"><</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">></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<T></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_value_concept.html">ChannelValueConcept<T></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_channel_concept.html">MutableChannelConcept<T></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_channels_compatible_concept.html">ChannelsCompatibleConcept<T1,T2></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_convertible_concept.html">ChannelConvertibleConcept<SrcChannel,DstChannel></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"><</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">></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"><</span><span class="kt">int</span> <span class="n">NumBits</span><span class="o">></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"><</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">></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"><</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">></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"><</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">></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"><</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">></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"><</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">></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">&</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">&</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">&</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"><</span><span class="n">channel16_0_5_reference_t</span><span class="o">>::</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"><</span><span class="n">channel16_5_6_reference_t</span><span class="o">>::</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"><</span><span class="n">channel16_11_5_reference_t</span><span class="o">>::</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"><</span><span class="mi">5</span><span class="o">></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"><</span><span class="n">channel16_0_5_reference_t</span><span class="o">>::</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"><</span><span class="n">bits16</span><span class="o">></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. GIL’s channel conversion is a
|
||
linear transformation between the ranges of the source and destination
|
||
channel. It maps precisely the minimum to the minimum and the maximum
|
||
to the maximum. (For example, to convert from uint8_t to uint16_t GIL
|
||
does not do a bit shift because it will not properly match the maximum
|
||
values. Instead GIL multiplies the source by 257).</p>
|
||
<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"><</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">></span>
|
||
<span class="k">typename</span> <span class="n">channel_traits</span><span class="o"><</span><span class="n">DstChannel</span><span class="o">>::</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"><</span><span class="k">typename</span> <span class="n">Channel</span><span class="o">></span>
|
||
<span class="k">typename</span> <span class="n">channel_traits</span><span class="o"><</span><span class="n">Channel</span><span class="o">>::</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"><</span><span class="k">typename</span> <span class="n">Channel</span><span class="o">></span>
|
||
<span class="k">typename</span> <span class="n">channel_traits</span><span class="o"><</span><span class="n">Channel</span><span class="o">>::</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<ColorSpace></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_color_spaces_compatible_concept.html">ColorSpacesCompatibleConcept<ColorSpace1,ColorSpace2></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_channel_mapping_concept.html">ChannelMappingConcept<Mapping></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<2></span></code></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">devicen_t<3></span></code></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">devicen_t<4></span></code></li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">devicen_t<5></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"><</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">></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 GIL’s layout:</p>
|
||
<div class="highlight-c++ notranslate"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o"><</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"><</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"><</span><span class="n">ColorSpace</span><span class="o">>::</span><span class="n">value</span><span class="o">></span> <span class="o">></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"><</span><span class="n">rgba_t</span><span class="o">></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"><</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"><</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">></span> <span class="o">></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"><</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"><</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">></span> <span class="o">></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"><</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"><</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">></span> <span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="o">:</span> <span class="n">CopyConstructible</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span> <span class="n">EqualityComparable</span><span class="o"><</span><span class="n">T</span><span class="o">></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"><</span><span class="kt">int</span> <span class="n">K</span><span class="o">></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"><</span><span class="n">kth_element_type</span><span class="o">></span><span class="p">;</span>
|
||
|
||
<span class="c1">// The result of at_c</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="kt">int</span> <span class="n">K</span><span class="o">></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"><</span><span class="n">kth_element_const_reference_type</span><span class="o">></span><span class="p">;</span>
|
||
|
||
<span class="k">template</span> <span class="o"><</span><span class="kt">int</span> <span class="n">K</span><span class="o">></span> <span class="n">kth_element_const_reference_type</span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="n">K</span><span class="o">>::</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"><</span><span class="n">ColorBaseConcept</span> <span class="n">T2</span><span class="o">></span> <span class="n">where</span> <span class="p">{</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="n">T2</span><span class="o">></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"><</span><span class="n">ColorBaseConcept</span> <span class="n">T2</span><span class="o">></span> <span class="n">where</span> <span class="p">{</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="n">T2</span><span class="o">></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">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">T2</span><span class="o">&</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="n">ColorBaseConcept</span> <span class="n">T2</span><span class="o">></span> <span class="n">where</span> <span class="p">{</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="n">T2</span><span class="o">></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">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">T2</span><span class="o">&</span><span class="p">);</span>
|
||
|
||
<span class="p">};</span>
|
||
|
||
<span class="n">concept</span> <span class="n">MutableColorBaseConcept</span><span class="o"><</span><span class="n">ColorBaseConcept</span> <span class="n">T</span><span class="o">></span> <span class="o">:</span> <span class="n">Assignable</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span> <span class="n">Swappable</span><span class="o"><</span><span class="n">T</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="kt">int</span> <span class="n">K</span><span class="o">></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"><</span><span class="n">kth_element_reference_type</span><span class="o">></span><span class="p">;</span>
|
||
|
||
<span class="k">template</span> <span class="o"><</span><span class="kt">int</span> <span class="n">K</span><span class="o">></span> <span class="n">kth_element_reference_type</span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="n">K</span><span class="o">>::</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"><</span><span class="n">ColorBaseConcept</span> <span class="n">T2</span><span class="o">></span> <span class="n">where</span> <span class="p">{</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o"><</span><span class="n">T</span><span class="p">,</span><span class="n">T2</span><span class="o">></span> <span class="p">}</span>
|
||
<span class="n">T</span><span class="o">&</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">T</span><span class="o">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">T2</span><span class="o">&</span><span class="p">);</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="n">concept</span> <span class="n">ColorBaseValueConcept</span><span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="o">:</span> <span class="n">MutableColorBaseConcept</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span> <span class="n">Regular</span><span class="o"><</span><span class="n">T</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="n">concept</span> <span class="n">HomogeneousColorBaseConcept</span><span class="o"><</span><span class="n">ColorBaseConcept</span> <span class="n">CB</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="c1">// For all K in [0 ... size<C1>::value-1):</span>
|
||
<span class="c1">// where SameType<kth_element_type<K>::type, kth_element_type<K+1>::type>;</span>
|
||
<span class="n">kth_element_const_reference_type</span><span class="o"><</span><span class="mi">0</span><span class="o">>::</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">&</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"><</span><span class="n">MutableColorBaseConcept</span> <span class="n">CB</span><span class="o">></span> <span class="o">:</span> <span class="n">HomogeneousColorBaseConcept</span><span class="o"><</span><span class="n">CB</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">kth_element_reference_type</span><span class="o"><</span><span class="mi">0</span><span class="o">>::</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">&</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="o">:</span> <span class="n">MutableHomogeneousColorBaseConcept</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span> <span class="n">Regular</span><span class="o"><</span><span class="n">T</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="n">concept</span> <span class="n">ColorBasesCompatibleConcept</span><span class="o"><</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">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">SameType</span><span class="o"><</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">></span><span class="p">;</span>
|
||
<span class="c1">// also, for all K in [0 ... size<C1>::value):</span>
|
||
<span class="c1">// where Convertible<kth_semantic_element_type<C1,K>::type, kth_semantic_element_type<C2,K>::type>;</span>
|
||
<span class="c1">// where Convertible<kth_semantic_element_type<C2,K>::type, kth_semantic_element_type<C1,K>::type>;</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<K>(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<K>(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"><</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">></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 GIL’s 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"><</span><span class="k">class</span> <span class="nc">ColorBase</span><span class="o">></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<K>(color_base)</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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"><</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">></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"><</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">></span>
|
||
<span class="k">typename</span> <span class="n">kth_semantic_element_reference_type</span><span class="o"><</span><span class="n">ColorBase</span><span class="p">,</span><span class="n">K</span><span class="o">>::</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">&</span> <span class="n">p</span><span class="p">)</span>
|
||
<span class="k">template</span> <span class="o"><</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">></span>
|
||
<span class="k">typename</span> <span class="n">kth_semantic_element_const_reference_type</span><span class="o"><</span><span class="n">ColorBase</span><span class="p">,</span><span class="n">K</span><span class="o">>::</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">&</span> <span class="n">p</span><span class="p">)</span>
|
||
|
||
<span class="c1">// Returns the type of the return value of get_color<Color>(color_base)</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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"><</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">></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"><</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">></span>
|
||
<span class="k">typename</span> <span class="n">color_reference_t</span><span class="o"><</span><span class="n">Color</span><span class="p">,</span><span class="n">ColorBase</span><span class="o">>::</span><span class="n">type</span> <span class="n">get_color</span><span class="p">(</span><span class="n">ColorBase</span><span class="o">&</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"><</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">></span>
|
||
<span class="k">typename</span> <span class="n">color_const_reference_t</span><span class="o"><</span><span class="n">Color</span><span class="p">,</span><span class="n">ColorBase</span><span class="o">>::</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">&</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"><</span><span class="k">typename</span> <span class="n">ColorBase</span><span class="o">></span> <span class="k">struct</span> <span class="n">element_type</span><span class="p">;</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">ColorBase</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">ColorBase</span><span class="o">></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"><</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">></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">&</span> <span class="n">p1</span><span class="p">,</span> <span class="k">const</span> <span class="n">CB2</span><span class="o">&</span> <span class="n">p2</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">src</span><span class="p">,</span> <span class="n">Dst</span><span class="o">&</span> <span class="n">dst</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></span> <span class="kt">void</span> <span class="n">static_generate</span><span class="p">(</span><span class="n">CB</span><span class="o">&</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"><</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">></span> <span class="n">Op</span> <span class="n">static_transform</span><span class="p">(</span> <span class="n">CB</span><span class="o">&</span><span class="p">,</span><span class="n">Dst</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span><span class="n">Dst</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></span> <span class="n">Op</span> <span class="n">static_transform</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="n">Dst</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="n">Dst</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></span> <span class="n">Op</span> <span class="n">static_transform</span><span class="p">(</span> <span class="n">CB1</span><span class="o">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="n">Dst</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="n">Dst</span><span class="o">&</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"><</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">></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">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span> <span class="n">CB3</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB3</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span> <span class="n">CB3</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB3</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span> <span class="n">CB3</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB3</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span> <span class="n">CB3</span><span class="o">&</span><span class="p">,</span><span class="n">Op</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB2</span><span class="o">&</span><span class="p">,</span><span class="k">const</span> <span class="n">CB3</span><span class="o">&</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"><</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">></span> <span class="kt">void</span> <span class="n">static_fill</span><span class="p">(</span><span class="n">HCB</span><span class="o">&</span> <span class="n">p</span><span class="p">,</span> <span class="k">const</span> <span class="n">Element</span><span class="o">&</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"><</span><span class="k">typename</span> <span class="n">HCB</span><span class="o">></span> <span class="k">typename</span> <span class="n">element_const_reference_type</span><span class="o"><</span><span class="n">HCB</span><span class="o">>::</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">&</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">HCB</span><span class="o">></span> <span class="k">typename</span> <span class="n">element_reference_type</span><span class="o"><</span><span class="n">HCB</span><span class="o">>::</span><span class="n">type</span> <span class="n">static_min</span><span class="p">(</span> <span class="n">HCB</span><span class="o">&</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">HCB</span><span class="o">></span> <span class="k">typename</span> <span class="n">element_const_reference_type</span><span class="o"><</span><span class="n">HCB</span><span class="o">>::</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">&</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">HCB</span><span class="o">></span> <span class="k">typename</span> <span class="n">element_reference_type</span><span class="o"><</span><span class="n">HCB</span><span class="o">>::</span><span class="n">type</span> <span class="n">static_max</span><span class="p">(</span> <span class="n">HCB</span><span class="o">&</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"><</span><span class="kt">int</span> <span class="n">K</span><span class="o">></span> <span class="k">struct</span> <span class="n">element_recursion</span>
|
||
<span class="p">{</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">p1</span><span class="p">,</span> <span class="k">const</span> <span class="n">P2</span><span class="o">&</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"><</span><span class="n">K</span><span class="o">-</span><span class="mi">1</span><span class="o">>::</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">&&</span>
|
||
<span class="n">semantic_at_c</span><span class="o"><</span><span class="n">K</span><span class="o">-</span><span class="mi">1</span><span class="o">></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"><</span><span class="n">N</span><span class="o">-</span><span class="mi">1</span><span class="o">></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"><></span> <span class="k">struct</span> <span class="n">element_recursion</span><span class="o"><</span><span class="mi">0</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">P2</span><span class="o">&</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"><</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">></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">&</span> <span class="n">p1</span><span class="p">,</span> <span class="k">const</span> <span class="n">P2</span><span class="o">&</span> <span class="n">p2</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">gil_function_requires</span><span class="o"><</span><span class="n">ColorSpacesCompatibleConcept</span><span class="o"><</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">></span> <span class="o">></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"><</span><span class="n">size</span><span class="o"><</span><span class="n">P1</span><span class="o">>::</span><span class="n">value</span><span class="o">>::</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">typename</span> <span class="n">color_space_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">Metafunction</span><span class="o"><</span><span class="n">color_space_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">ColorSpaceConcept</span><span class="o"><</span><span class="n">color_space_type</span><span class="o"><</span><span class="n">T</span><span class="o">>::</span><span class="n">type</span><span class="o">></span><span class="p">;</span>
|
||
<span class="k">typename</span> <span class="n">channel_mapping_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">Metafunction</span><span class="o"><</span><span class="n">channel_mapping_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">ChannelMappingConcept</span><span class="o"><</span><span class="n">channel_mapping_type</span><span class="o"><</span><span class="n">T</span><span class="o">>::</span><span class="n">type</span><span class="o">></span><span class="p">;</span>
|
||
<span class="k">typename</span> <span class="n">is_planar</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">Metafunction</span><span class="o"><</span><span class="n">is_planar</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">SameType</span><span class="o"><</span><span class="n">is_planar</span><span class="o"><</span><span class="n">T</span><span class="o">>::</span><span class="n">type</span><span class="p">,</span> <span class="kt">bool</span><span class="o">></span><span class="p">;</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="n">concept</span> <span class="n">HomogeneousPixelBasedConcept</span><span class="o"><</span><span class="n">PixelBasedConcept</span> <span class="n">T</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">typename</span> <span class="n">channel_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">Metafunction</span><span class="o"><</span><span class="n">channel_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">ChannelConcept</span><span class="o"><</span><span class="n">channel_type</span><span class="o"><</span><span class="n">T</span><span class="o">>::</span><span class="n">type</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">P</span><span class="o">></span> <span class="o">:</span> <span class="n">ColorBaseConcept</span><span class="o"><</span><span class="n">P</span><span class="o">></span><span class="p">,</span> <span class="n">PixelBasedConcept</span><span class="o"><</span><span class="n">P</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">is_pixel</span><span class="o"><</span><span class="n">P</span><span class="o">>::</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<P>::value-1]:</span>
|
||
<span class="c1">// ChannelConcept<kth_element_type<K> >;</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"><</span><span class="n">value_type</span><span class="o">></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"><</span><span class="n">reference</span><span class="o">></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"><</span><span class="n">const_reference</span><span class="o">></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"><</span><span class="n">PixelConcept</span> <span class="n">P2</span><span class="o">></span> <span class="n">where</span> <span class="p">{</span> <span class="n">PixelConcept</span><span class="o"><</span><span class="n">P</span><span class="p">,</span><span class="n">P2</span><span class="o">></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"><</span><span class="n">PixelConcept</span> <span class="n">P2</span><span class="o">></span> <span class="n">where</span> <span class="p">{</span> <span class="n">PixelConcept</span><span class="o"><</span><span class="n">P</span><span class="p">,</span><span class="n">P2</span><span class="o">></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">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">P2</span><span class="o">&</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="n">PixelConcept</span> <span class="n">P2</span><span class="o">></span> <span class="n">where</span> <span class="p">{</span> <span class="n">PixelConcept</span><span class="o"><</span><span class="n">P</span><span class="p">,</span><span class="n">P2</span><span class="o">></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">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">P2</span><span class="o">&</span><span class="p">);</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="n">concept</span> <span class="n">MutablePixelConcept</span><span class="o"><</span><span class="k">typename</span> <span class="n">P</span><span class="o">></span> <span class="o">:</span> <span class="n">PixelConcept</span><span class="o"><</span><span class="n">P</span><span class="o">></span><span class="p">,</span> <span class="n">MutableColorBaseConcept</span><span class="o"><</span><span class="n">P</span><span class="o">></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"><</span><span class="n">PixelConcept</span> <span class="n">P</span><span class="o">></span> <span class="o">:</span> <span class="n">HomogeneousColorBaseConcept</span><span class="o"><</span><span class="n">P</span><span class="o">></span><span class="p">,</span> <span class="n">HomogeneousPixelBasedConcept</span><span class="o"><</span><span class="n">P</span><span class="o">></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"><</span><span class="n">P</span><span class="o">>::</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"><</span><span class="n">MutablePixelConcept</span> <span class="n">P</span><span class="o">></span> <span class="o">:</span> <span class="n">MutableHomogeneousColorBaseConcept</span><span class="o"><</span><span class="n">P</span><span class="o">></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"><</span><span class="n">P</span><span class="o">>::</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"><</span><span class="k">typename</span> <span class="n">P</span><span class="o">></span> <span class="o">:</span> <span class="n">PixelConcept</span><span class="o"><</span><span class="n">P</span><span class="o">></span><span class="p">,</span> <span class="n">Regular</span><span class="o"><</span><span class="n">P</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">SameType</span><span class="o"><</span><span class="n">value_type</span><span class="p">,</span><span class="n">P</span><span class="o">></span><span class="p">;</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="n">concept</span> <span class="n">PixelsCompatibleConcept</span><span class="o"><</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">></span> <span class="o">:</span> <span class="n">ColorBasesCompatibleConcept</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="p">{</span>
|
||
<span class="c1">// where for each K [0..size<P1>::value):</span>
|
||
<span class="c1">// ChannelsCompatibleConcept<kth_semantic_element_type<P1,K>::type, kth_semantic_element_type<P2,K>::type>;</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"><</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">></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">&</span><span class="p">,</span> <span class="n">DstPixel</span><span class="o">&</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<P></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_concept.html">PixelConcept<Pixel></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_pixel_concept.html">MutablePixelConcept<Pixel></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_value_concept.html">PixelValueConcept<Pixel></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_homogeneous_pixel_based_concept.html">HomogeneousPixelConcept<Pixel></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_homogeneous_pixel_concept.html">MutableHomogeneousPixelConcept<Pixel></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_homogeneous_pixel_value_concept.html">HomogeneousPixelValueConcept<Pixel></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixels_compatible_concept.html">PixelsCompatibleConcept<Pixel1, Pixel2></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_convertible_concept.html">PixelConvertibleConcept<SrcPixel, DstPixel></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"><</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">></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"><</span><span class="n">bits8</span><span class="p">,</span> <span class="n">rgb_layout_t</span><span class="o">></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"><</span><span class="n">bits8</span><span class="p">,</span> <span class="n">bgr_layout_t</span><span class="o">></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"><</span><span class="mi">0</span><span class="o">></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"><</span><span class="mi">0</span><span class="o">></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"><</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">></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"><</span> <span class="n">bits8</span><span class="o">&</span><span class="p">,</span><span class="n">rgb_t</span><span class="o">></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"><</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">></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"><</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"><</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">></span><span class="p">,</span> <span class="n">rgb_layout_t</span><span class="o">>::</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"><</span><span class="n">PixelValueConcept</span><span class="o"><</span><span class="n">rgb565_pixel_t</span><span class="o">></span> <span class="o">></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"><</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"><</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">></span><span class="p">,</span> <span class="n">bgr_layout_t</span><span class="o">>::</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"><</span><span class="n">PixelValueConcept</span><span class="o"><</span><span class="n">bgr556_pixel_t</span><span class="o">></span> <span class="o">></span><span class="p">();</span>
|
||
|
||
<span class="c1">// rgb565 is compatible with bgr556.</span>
|
||
<span class="n">function_requires</span><span class="o"><</span><span class="n">PixelsCompatibleConcept</span><span class="o"><</span><span class="n">rgb565_pixel_t</span><span class="p">,</span><span class="n">bgr556_pixel_t</span><span class="o">></span> <span class="o">></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"><</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"><</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">></span><span class="p">,</span> <span class="n">bgr_layout_t</span><span class="p">,</span> <span class="nb">true</span><span class="o">></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"><</span><span class="n">bgr232_ref_t</span><span class="o">></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"><</span><span class="n">bgr232_ptr_t</span><span class="o">>::</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">&</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"><</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"><</span><span class="mi">0</span><span class="o">></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"><</span><span class="mi">0</span><span class="o">></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"><</span><span class="n">red_t</span><span class="o">></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"><</span><span class="n">red_t</span><span class="o">></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'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"><</span><span class="n">rgb8_pixel_t</span><span class="o">>::</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"><</span><span class="n">channel_type</span><span class="o"><</span><span class="n">rgb8_pixel_t</span><span class="o">>::</span><span class="n">type</span><span class="p">,</span> <span class="n">bits8</span><span class="o">></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"><</span><span class="n">color_space_type</span><span class="o"><</span><span class="n">bgr8_pixel_t</span><span class="o">>::</span><span class="n">type</span><span class="p">,</span> <span class="n">rgb_t</span><span class="o">></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"><</span><span class="n">channel_mapping_type</span><span class="o"><</span><span class="n">bgr8_pixel_t</span><span class="o">>::</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"><</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">></span> <span class="o">></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"><</span><span class="n">red_t</span><span class="o">></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"><</span><span class="n">red_t</span><span class="o">></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 & 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"><</span><span class="n">rgb565_channel0_t</span><span class="o">></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"><</span><span class="n">rgb565_channel1_t</span><span class="o">></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"><</span><span class="n">rgb565_channel2_t</span><span class="o">></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"><</span><span class="n">RandomAccessTraversalIteratorConcept</span> <span class="n">Iterator</span><span class="o">></span> <span class="o">:</span> <span class="n">PixelBasedConcept</span><span class="o"><</span><span class="n">Iterator</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">PixelValueConcept</span><span class="o"><</span><span class="n">value_type</span><span class="o">></span><span class="p">;</span>
|
||
<span class="k">typename</span> <span class="n">const_iterator_type</span><span class="o"><</span><span class="n">It</span><span class="o">>::</span><span class="n">type</span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">PixelIteratorConcept</span><span class="o"><</span><span class="n">const_iterator_type</span><span class="o"><</span><span class="n">It</span><span class="o">>::</span><span class="n">type</span><span class="o">></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"><</span><span class="n">It</span><span class="o">>::</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"><</span><span class="n">It</span><span class="o">>::</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"><</span><span class="k">typename</span> <span class="n">Iterator</span><span class="o">></span>
|
||
<span class="n">concept</span> <span class="nl">MutablePixelIteratorConcept</span> <span class="p">:</span> <span class="n">PixelIteratorConcept</span><span class="o"><</span><span class="n">Iterator</span><span class="o">></span><span class="p">,</span> <span class="n">MutableRandomAccessIteratorConcept</span><span class="o"><</span><span class="n">Iterator</span><span class="o">></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<Iterator></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_pixel_iterator_concept.html">MutablePixelIteratorConcept<Iterator></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<ChannelValue,Layout>*</span></code>, is GIL’s
|
||
model for pixel iterator over interleaved homogeneous pixels.
|
||
Similarly, <code class="docutils literal notranslate"><span class="pre">packed_pixel<PixelData,ChannelRefVec,Layout>*</span></code> is GIL’s
|
||
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"><</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">></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"><</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">></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"><</span> <span class="n">bits8</span><span class="o">*</span><span class="p">,</span> <span class="n">rgb_t</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</span><span class="n">T</span><span class="p">,</span><span class="n">T</span><span class="o">></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"><</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">></span>
|
||
<span class="n">planar_pixel_iterator</span><span class="o"><</span><span class="n">ChannelPtr</span><span class="p">,</span><span class="n">ColorSpace</span><span class="o">>&</span>
|
||
<span class="n">planar_pixel_iterator</span><span class="o"><</span><span class="n">ChannelPtr</span><span class="p">,</span><span class="n">ColorSpace</span><span class="o">>::</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"><</span><span class="n">ChannelPtr</span><span class="o">></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"><</span><span class="n">RandomAccessTraversalIteratorConcept</span> <span class="n">Iterator</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">SameType</span><span class="o"><</span><span class="n">is_iterator_adaptor</span><span class="o"><</span><span class="n">Iterator</span><span class="o">>::</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">></span><span class="p">;</span>
|
||
|
||
<span class="k">typename</span> <span class="n">iterator_adaptor_get_base</span><span class="o"><</span><span class="n">Iterator</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">Metafunction</span><span class="o"><</span><span class="n">iterator_adaptor_get_base</span><span class="o"><</span><span class="n">Iterator</span><span class="o">></span> <span class="o">></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"><</span><span class="n">iterator_adaptor_get_base</span><span class="o"><</span><span class="n">Iterator</span><span class="o">>::</span><span class="n">type</span><span class="o">></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"><</span><span class="n">Iterator</span><span class="p">,</span><span class="n">another_iterator</span><span class="o">>::</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"><</span><span class="n">another_iterator</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">IteratorAdaptorConcept</span><span class="o"><</span><span class="n">iterator_adaptor_rebind</span><span class="o"><</span><span class="n">Iterator</span><span class="p">,</span><span class="n">another_iterator</span><span class="o">>::</span><span class="n">type</span><span class="o">></span><span class="p">;</span>
|
||
|
||
<span class="k">const</span> <span class="n">iterator_adaptor_get_base</span><span class="o"><</span><span class="n">Iterator</span><span class="o">>::</span><span class="n">type</span><span class="o">&</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"><</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">></span>
|
||
<span class="n">concept</span> <span class="nl">MutableIteratorAdaptorConcept</span> <span class="p">:</span> <span class="n">IteratorAdaptorConcept</span><span class="o"><</span><span class="n">Iterator</span><span class="o">></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<Iterator></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_iterator_adaptor_concept.html">MutableIteratorAdaptorConcept<Iterator></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<Iterator></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<Iterator,Fn></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"><</span><span class="n">boost</span><span class="o">::</span><span class="n">UnaryFunctionConcept</span> <span class="n">D</span><span class="o">></span>
|
||
<span class="n">concept</span> <span class="nl">PixelDereferenceAdaptorConcept</span> <span class="p">:</span> <span class="n">DefaultConstructibleConcept</span><span class="o"><</span><span class="n">D</span><span class="o">></span><span class="p">,</span> <span class="n">CopyConstructibleConcept</span><span class="o"><</span><span class="n">D</span><span class="o">></span><span class="p">,</span> <span class="n">AssignableConcept</span><span class="o"><</span><span class="n">D</span><span class="o">></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"><</span><span class="n">const_t</span><span class="o">></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"><</span><span class="n">value_type</span><span class="o">></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"><</span><span class="n">remove_reference</span><span class="o"><</span><span class="n">reference</span><span class="o">>::</span><span class="n">type</span><span class="o">></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"><</span><span class="n">value_type</span><span class="p">,</span> <span class="n">result_type</span><span class="o">></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<Iterator,Fn></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"><</span><span class="n">boost_concepts</span><span class="o">::</span><span class="n">ForwardTraversalConcept</span> <span class="n">Iterator</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="n">Integral</span> <span class="n">D</span><span class="o">></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"><</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">></span> <span class="o">:</span> <span class="n">StepIteratorConcept</span><span class="o"><</span><span class="n">Iterator</span><span class="o">></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"><</span><span class="n">boost_concepts</span><span class="o">::</span><span class="n">RandomAccessTraversalConcept</span> <span class="n">Iterator</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">typename</span> <span class="n">byte_to_memunit</span><span class="o"><</span><span class="n">Iterator</span><span class="o">></span><span class="p">;</span> <span class="n">where</span> <span class="n">metafunction</span><span class="o"><</span><span class="n">byte_to_memunit</span><span class="o"><</span><span class="n">Iterator</span><span class="o">></span> <span class="o">></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">&</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">&</span> <span class="p">,</span> <span class="k">const</span> <span class="n">Iterator</span><span class="o">&</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">&</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">&</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">&</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">Metafunction</span><span class="o"><</span><span class="n">dynamic_x_step_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="o">></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<Iterator></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_step_iterator_concept.html">MutableStepIteratorConcept<Iterator></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_memory_based_iterator_concept.html">MemoryBasedIteratorConcept<Iterator></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_has_dynamic_x_step_type_concept.html">HasDynamicXStepTypeConcept<T></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. GIL’s 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"><</span><span class="k">typename</span> <span class="n">I</span><span class="o">></span> <span class="c1">// Models MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept</span>
|
||
<span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o"><</span><span class="n">I</span><span class="o">>::</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">&</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 don’t satisfy all the requirements of iterators. For
|
||
example, they don’t 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"><</span><span class="n">Regular</span> <span class="n">Loc</span><span class="o">></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"><</span><span class="n">difference_type</span><span class="o">></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"><</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">></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"><</span><span class="n">D</span><span class="o">>::</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"><</span><span class="n">iterator</span><span class="o">></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"><</span><span class="n">PixelDereferenceAdaptorConcept</span> <span class="n">Deref</span><span class="o">></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"><</span><span class="n">type</span><span class="o">></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">&</span> <span class="n">loc</span><span class="p">,</span> <span class="k">const</span> <span class="n">Deref</span><span class="o">&</span> <span class="n">deref</span><span class="p">);</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="n">Loc</span><span class="o">&</span> <span class="k">operator</span><span class="o">+=</span><span class="p">(</span><span class="n">Loc</span><span class="o">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&</span><span class="p">);</span>
|
||
<span class="n">Loc</span><span class="o">&</span> <span class="k">operator</span><span class="o">-=</span><span class="p">(</span><span class="n">Loc</span><span class="o">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&</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">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&</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">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&</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">&</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">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">difference_type</span><span class="o">&</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">&</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">&</span><span class="p">,</span><span class="k">const</span> <span class="n">cached_location_t</span><span class="o">&</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"><</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">></span> <span class="n">axis</span><span class="o"><</span><span class="n">D</span><span class="o">>::</span><span class="n">iterator</span><span class="o">&</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"><</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">></span> <span class="n">axis</span><span class="o"><</span><span class="n">D</span><span class="o">>::</span><span class="n">iterator</span> <span class="k">const</span><span class="o">&</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"><</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">></span> <span class="n">axis</span><span class="o"><</span><span class="n">D</span><span class="o">>::</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">&</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"><</span><span class="k">typename</span> <span class="n">Loc</span><span class="o">></span>
|
||
<span class="n">concept</span> <span class="nl">MutableRandomAccessNDLocatorConcept</span> <span class="p">:</span> <span class="n">RandomAccessNDLocatorConcept</span><span class="o"><</span><span class="n">Loc</span><span class="o">></span> <span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">Mutable</span><span class="o"><</span><span class="n">reference</span><span class="o">></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"><</span><span class="n">RandomAccessNDLocatorConcept</span> <span class="n">Loc</span><span class="o">></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"><</span><span class="n">point_t</span><span class="o">></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"><</span><span class="mi">0</span><span class="o">>::</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"><</span><span class="mi">1</span><span class="o">>::</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"><</span><span class="mi">0</span><span class="o">>::</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"><</span><span class="mi">1</span><span class="o">>::</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& 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& loc, x_coord_t, y_coord_t, bool transposed=false);</span>
|
||
|
||
<span class="n">x_iterator</span><span class="o">&</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">&</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">&</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">&</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">&</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">&</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">&</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">&</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">&</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"><</span><span class="n">RandomAccess2DLocatorConcept</span> <span class="n">Loc</span><span class="o">></span> <span class="o">:</span> <span class="n">MutableRandomAccessNDLocatorConcept</span><span class="o"><</span><span class="n">Loc</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">typename</span> <span class="n">dynamic_y_step_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">Metafunction</span><span class="o"><</span><span class="n">dynamic_y_step_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">typename</span> <span class="n">transposed_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">Metafunction</span><span class="o"><</span><span class="n">transposed_type</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="o">></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"><</span><span class="n">RandomAccess2DLocatorConcept</span> <span class="n">Loc</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">PixelValueConcept</span><span class="o"><</span><span class="n">value_type</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">PixelIteratorConcept</span><span class="o"><</span><span class="n">x_iterator</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">PixelIteratorConcept</span><span class="o"><</span><span class="n">y_iterator</span><span class="o">></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"><</span><span class="n">PixelLocatorConcept</span> <span class="n">Loc</span><span class="o">></span> <span class="o">:</span> <span class="n">MutableRandomAccess2DLocatorConcept</span><span class="o"><</span><span class="n">Loc</span><span class="o">></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<T></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_has_transposed_type_concept.html">HasTransposedTypeConcept<T></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access_n_d_locator_concept.html">RandomAccessNDLocatorConcept<Locator></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access_n_d_locator_concept.html">MutableRandomAccessNDLocatorConcept<Locator></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access2_d_locator_concept.html">RandomAccess2DLocatorConcept<Locator></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access2_d_locator_concept.html">MutableRandomAccess2DLocatorConcept<Locator></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_pixel_locator_concept.html">PixelLocatorConcept<Locator></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_pixel_locator_concept.html">MutablePixelLocatorConcept<Locator></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"><</span><span class="k">typename</span> <span class="n">StepIterator</span><span class="o">></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<T,C>*</span></code> - for interleaved images</li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">planar_pixel_iterator<T*,C></span></code> - for planar images</li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">memory_based_step_iterator<pixel<T,C>*></span></code> - for interleaved images with
|
||
non-standard step)</li>
|
||
<li><code class="docutils literal notranslate"><span class="pre">memory_based_step_iterator<planar_pixel_iterator<T*,C></span> <span class="pre">></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<XIterator></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<memory_based_step_iterator<XIterator></span> <span class="pre">></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"><</span><span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span><span class="o">></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. GIL’s <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"><</span><span class="k">typename</span> <span class="n">Locator</span><span class="o">></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">&</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">&</span> <span class="k">operator</span><span class="o">++</span><span class="p">();</span> <span class="c1">// if (++_x<_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, don’t own the underlying data and don’t 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"><</span><span class="n">Regular</span> <span class="n">View</span><span class="o">></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"><</span><span class="n">View</span><span class="o">></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"><</span><span class="n">point_t</span><span class="o">></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"><</span><span class="n">locator</span><span class="o">></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"><</span><span class="n">iterator</span><span class="o">></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"><</span><span class="n">reverse_iterator</span><span class="o">></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"><</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">></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"><</span><span class="n">D</span><span class="o">>::</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"><</span><span class="n">iterator</span><span class="o">></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"><</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">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">SameType</span><span class="o"><</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">></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"><</span><span class="n">PixelDereferenceAdaptorConcept</span> <span class="n">Deref</span><span class="o">></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"><</span><span class="n">type</span><span class="o">></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">&</span> <span class="n">v</span><span class="p">,</span> <span class="k">const</span> <span class="n">Deref</span><span class="o">&</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">&</span><span class="p">,</span> <span class="k">const</span> <span class="n">point_type</span><span class="o">&</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">&</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">&</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"><</span><span class="kt">size_t</span> <span class="n">D</span><span class="o">></span> <span class="n">View</span><span class="o">::</span><span class="n">axis</span><span class="o"><</span><span class="n">D</span><span class="o">>::</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">&</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">&</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"><</span><span class="n">RandomAccessNDImageViewConcept</span> <span class="n">View</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">Mutable</span><span class="o"><</span><span class="n">reference</span><span class="o">></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"><</span><span class="n">RandomAccessNDImageViewConcept</span> <span class="n">View</span><span class="o">></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"><</span><span class="mi">0</span><span class="o">>::</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"><</span><span class="mi">1</span><span class="o">>::</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"><</span><span class="mi">0</span><span class="o">>::</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"><</span><span class="mi">1</span><span class="o">>::</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">&</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">&</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">&</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">&</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"><</span><span class="n">RandomAccess2DImageViewConcept</span> <span class="n">View</span><span class="o">></span>
|
||
<span class="o">:</span> <span class="n">MutableRandomAccessNDImageViewConcept</span><span class="o"><</span><span class="n">View</span><span class="o">></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"><</span><span class="n">RandomAccess2DImageViewConcept</span> <span class="n">View</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">PixelValueConcept</span><span class="o"><</span><span class="n">value_type</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">PixelIteratorConcept</span><span class="o"><</span><span class="n">x_iterator</span><span class="o">></span><span class="p">;</span>
|
||
<span class="n">where</span> <span class="n">PixelIteratorConcept</span><span class="o"><</span><span class="n">y_iterator</span><span class="o">></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"><</span><span class="n">ImageViewConcept</span> <span class="n">View</span><span class="o">></span> <span class="o">:</span> <span class="n">MutableRandomAccess2DImageViewConcept</span><span class="o"><</span><span class="n">View</span><span class="o">></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"><</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">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">PixelsCompatibleConcept</span><span class="o"><</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">></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<View></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access_n_d_image_view_concept.html">MutableRandomAccessNDImageViewConcept<View></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access2_d_image_view_concept.html">RandomAccess2DImageViewConcept<View></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_random_access2_d_image_view_concept.html">MutableRandomAccess2DImageViewConcept<View></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_image_view_concept.html">ImageViewConcept<View></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_mutable_image_view_concept.html">MutableImageViewConcept<View></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_views_compatible_concept.html">ViewsCompatibleConcept<View1,View2></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"><</span><span class="k">typename</span> <span class="n">Locator</span><span class="o">></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"><</span><span class="n">Locator</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">Iterator</span><span class="o">></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"><</span><span class="p">...</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">IC</span><span class="o">></span> <span class="c1">// Models channel iterator (like bits8* or const bits8*)</span>
|
||
<span class="n">image_view</span><span class="o"><</span><span class="p">...</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</span><span class="n">type</span><span class="o">></span> <span class="p">{};</span>
|
||
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">transposed_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</span><span class="n">type</span><span class="o">></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"><</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">></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"><</span><span class="k">typename</span> <span class="n">SrcView</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span> <span class="k">typename</span> <span class="n">dynamic_y_step_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</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">&</span> <span class="n">src</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span> <span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</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">&</span> <span class="n">src</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span> <span class="k">typename</span> <span class="n">dynamic_xy_step_transposed_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</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">&</span> <span class="n">src</span><span class="p">);</span>
|
||
|
||
<span class="c1">// rotations</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span> <span class="k">typename</span> <span class="n">dynamic_xy_step_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</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">&</span> <span class="n">src</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span> <span class="k">typename</span> <span class="n">dynamic_xy_step_transposed_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</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">&</span> <span class="n">src</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span> <span class="k">typename</span> <span class="n">dynamic_xy_step_transposed_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</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">&</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"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></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">&</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">&</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">&</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"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span> <span class="k">typename</span> <span class="n">dynamic_xy_step_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</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">&</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">&</span> <span class="n">step</span><span class="p">);</span>
|
||
|
||
<span class="k">template</span> <span class="o"><</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">></span>
|
||
<span class="n">color_converted_view_type</span><span class="o"><</span><span class="n">View</span><span class="p">,</span><span class="n">P</span><span class="o">>::</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">&</span> <span class="n">src</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></span> <span class="c1">// with a custom color converter</span>
|
||
<span class="n">color_converted_view_type</span><span class="o"><</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">>::</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">&</span> <span class="n">src</span><span class="p">);</span>
|
||
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span>
|
||
<span class="n">nth_channel_view_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</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">&</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"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span>
|
||
<span class="k">typename</span> <span class="n">dynamic_y_step_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</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">&</span> <span class="n">src</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">gil_function_requires</span><span class="o"><</span><span class="n">ImageViewConcept</span><span class="o"><</span><span class="n">View</span><span class="o">></span> <span class="o">></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"><</span><span class="n">View</span><span class="o">>::</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<V1>, MutableImageViewConcept<V2>, ViewsCompatibleConcept<V1,V2></span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&</span> <span class="n">dst</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&</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<V>, PixelConcept<Value>, PixelsCompatibleConcept<Value,V::value_type></span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="n">Value</span><span class="o">&</span> <span class="n">val</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">dst</span><span class="p">,</span> <span class="k">const</span> <span class="n">Value</span><span class="o">&</span> <span class="n">val</span><span class="p">);</span>
|
||
|
||
<span class="c1">// Equivalent of std::for_each</span>
|
||
<span class="c1">// where ImageViewConcept<V>, boost::UnaryFunctionConcept<F></span>
|
||
<span class="c1">// where PixelsCompatibleConcept<V::reference, F::argument_type></span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</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"><</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">></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">&</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<V>, boost::UnaryFunctionConcept<F></span>
|
||
<span class="c1">// where PixelsCompatibleConcept<V::reference, F::argument_type></span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</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<V1>, MutableImageViewConcept<V2></span>
|
||
<span class="c1">// where boost::UnaryFunctionConcept<F></span>
|
||
<span class="c1">// where PixelsCompatibleConcept<V1::const_reference, F::argument_type></span>
|
||
<span class="c1">// where PixelsCompatibleConcept<F::result_type, V2::reference></span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&</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"><</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">></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">&</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&</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<V1>, ImageViewConcept<V2>, MutableImageViewConcept<V3></span>
|
||
<span class="c1">// where boost::BinaryFunctionConcept<F></span>
|
||
<span class="c1">// where PixelsCompatibleConcept<V1::const_reference, F::first_argument_type></span>
|
||
<span class="c1">// where PixelsCompatibleConcept<V2::const_reference, F::second_argument_type></span>
|
||
<span class="c1">// where PixelsCompatibleConcept<F::result_type, V3::reference></span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">src1</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&</span> <span class="n">src2</span><span class="p">,</span> <span class="k">const</span> <span class="n">V3</span><span class="o">&</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"><</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">></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">&</span> <span class="n">src1</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&</span> <span class="n">src2</span><span class="p">,</span> <span class="k">const</span> <span class="n">V3</span><span class="o">&</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<V1>, MutableImageViewConcept<V2></span>
|
||
<span class="c1">// V1::value_type must be convertible to V2::value_type.</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&</span> <span class="n">dst</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">src</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&</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<V1>, ImageViewConcept<V2>, ViewsCompatibleConcept<V1,V2></span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">view1</span><span class="p">,</span> <span class="k">const</span> <span class="n">V2</span><span class="o">&</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"><</span><span class="k">typename</span> <span class="n">Img</span><span class="o">></span> <span class="o">:</span> <span class="n">Regular</span><span class="o"><</span><span class="n">Img</span><span class="o">></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"><</span><span class="n">view_t</span><span class="o">></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">&</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">&</span> <span class="n">const_view</span><span class="p">(</span><span class="k">const</span> <span class="n">Img</span><span class="o">&</span><span class="p">);</span>
|
||
<span class="k">const</span> <span class="n">view_t</span><span class="o">&</span> <span class="n">view</span><span class="p">(</span><span class="n">Img</span><span class="o">&</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"><</span><span class="n">RandomAccessNDImageConcept</span> <span class="n">Img</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">typename</span> <span class="n">x_coord_t</span> <span class="o">=</span> <span class="n">const_view_t</span><span class="o">::</span><span class="n">x_coord_t</span><span class="p">;</span>
|
||
<span class="k">typename</span> <span class="n">y_coord_t</span> <span class="o">=</span> <span class="n">const_view_t</span><span class="o">::</span><span class="n">y_coord_t</span><span class="p">;</span>
|
||
|
||
<span class="n">Img</span><span class="o">::</span><span class="n">Img</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="n">y_coord_t</span> <span class="n">height</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="o">=</span><span class="mi">0</span><span class="p">);</span>
|
||
<span class="n">Img</span><span class="o">::</span><span class="n">Img</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="n">y_coord_t</span> <span class="n">height</span><span class="p">,</span> <span class="n">value_type</span> <span class="n">fill_value</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="p">);</span>
|
||
|
||
<span class="n">x_coord_t</span> <span class="n">Img</span><span class="o">::</span><span class="n">width</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
|
||
<span class="n">y_coord_t</span> <span class="n">Img</span><span class="o">::</span><span class="n">height</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
|
||
|
||
<span class="kt">void</span> <span class="n">Img</span><span class="o">::</span><span class="n">recreate</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="n">y_coord_t</span> <span class="n">height</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="o">=</span><span class="mi">1</span><span class="p">);</span>
|
||
<span class="kt">void</span> <span class="n">Img</span><span class="o">::</span><span class="n">recreate</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="n">y_coord_t</span> <span class="n">height</span><span class="p">,</span> <span class="n">value_type</span> <span class="n">fill_value</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">alignment</span><span class="p">);</span>
|
||
<span class="p">};</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>GIL’s 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"><</span><span class="n">RandomAccess2DImageConcept</span> <span class="n">Img</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="n">where</span> <span class="n">MutableImageViewConcept</span><span class="o"><</span><span class="n">view_t</span><span class="o">></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, don’t 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<Image></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_random_access2_d_image_concept.html">RandomAccess2DImageConcept<Image></a></li>
|
||
<li><a class="reference external" href="reference/structboost_1_1gil_1_1_image_concept.html">ImageConcept<Image></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 <typename Pixel, \\ Models PixelValueConcept
|
||
bool IsPlanar, \\ planar or interleaved image
|
||
typename A=std::allocator<unsigned char> >
|
||
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>GIL’s 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"><boost/gil/extension/dynamic_image/dynamic_image_all.hpp></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< A,B >::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"><</span><span class="n">rgb8_image_t</span><span class="p">,</span> <span class="n">cmyk16_planar_image_t</span><span class="o">></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"><</span><span class="n">my_images_t</span><span class="o">></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"><</span><span class="n">mpl</span><span class="o">::</span><span class="n">vector2</span><span class="o"><</span><span class="n">rgb8_view_t</span><span class="p">,</span> <span class="n">cmyk16_planar_view_t</span> <span class="o">></span> <span class="o">></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"><</span><span class="n">mpl</span><span class="o">::</span><span class="n">vector2</span><span class="o"><</span><span class="n">rgb8c_view_t</span><span class="p">,</span> <span class="n">cmyk16c_planar_view_t</span><span class="o">></span> <span class="o">></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"><</span><span class="n">mpl</span><span class="o">::</span><span class="n">vector2</span><span class="o"><</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">></span> <span class="o">></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"><</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">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 GIL’s <code class="docutils literal notranslate"><span class="pre">variant</span></code>
|
||
class, which breaks down the instantiated type into a non-templated
|
||
underlying base type and a unique instantiation type identifier. The
|
||
underlying base instance is represented as a block of bytes. The block
|
||
is large enough to hold the largest of the specified types.</p>
|
||
<p>GIL’s variant is similar to <code class="docutils literal notranslate"><span class="pre">boost::variant</span></code> in spirit (hence we
|
||
borrow the name from there) but it differs in several ways from the
|
||
current boost implementation. Perhaps the biggest difference is that
|
||
GIL’s variant always takes a single argument, which is a model of MPL
|
||
Random Access Sequence enumerating the allowed types. Having a single
|
||
interface allows GIL’s 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"><</span><span class="k">typename</span> <span class="n">Types</span><span class="o">></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">&</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">&</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">&</span> <span class="n">v</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">TS</span><span class="o">></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"><</span><span class="n">TS</span><span class="o">>&</span> <span class="n">x</span><span class="p">,</span> <span class="k">const</span> <span class="n">variant</span><span class="o"><</span><span class="n">TS</span><span class="o">>&</span> <span class="n">y</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">TS</span><span class="o">></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"><</span><span class="n">TS</span><span class="o">>&</span> <span class="n">x</span><span class="p">,</span> <span class="k">const</span> <span class="n">variant</span><span class="o"><</span><span class="n">TS</span><span class="o">>&</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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">&</span> <span class="n">obj</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="n">variant</span><span class="o">&</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">&</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="k">explicit</span> <span class="n">variant</span><span class="p">(</span><span class="n">T</span><span class="o">&</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="kt">void</span> <span class="n">move_in</span><span class="p">(</span><span class="n">T</span><span class="o">&</span> <span class="n">obj</span><span class="p">);</span>
|
||
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="k">const</span> <span class="n">T</span><span class="o">&</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="n">T</span><span class="o">&</span> <span class="n">_dynamic_cast</span><span class="p">();</span>
|
||
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</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">></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"><</span><span class="n">Types</span><span class="o">>&</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"><</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">></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"><</span><span class="n">Types</span><span class="o">>&</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"><</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">></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"><</span><span class="n">Types1</span><span class="o">>&</span> <span class="n">v1</span><span class="p">,</span> <span class="n">variant</span><span class="o"><</span><span class="n">Types2</span><span class="o">>&</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"><</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">></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"><</span><span class="n">Types1</span><span class="o">>&</span> <span class="n">v1</span><span class="p">,</span> <span class="n">variant</span><span class="o"><</span><span class="n">Types2</span><span class="o">>&</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"><</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">></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"><</span><span class="n">Types1</span><span class="o">>&</span> <span class="n">v1</span><span class="p">,</span> <span class="k">const</span> <span class="n">variant</span><span class="o"><</span><span class="n">Types2</span><span class="o">>&</span> <span class="n">v2</span><span class="p">,</span> <span class="n">UOP</span> <span class="n">op</span><span class="p">);</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>GIL’s <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"><</span><span class="k">typename</span> <span class="n">ImageViewTypes</span><span class="o">></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"><</span><span class="n">ImageViewTypes</span><span class="o">></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"><</span><span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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">&</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">&</span> <span class="n">v</span><span class="p">);</span>
|
||
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="n">any_image_view</span><span class="o">&</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">&</span> <span class="n">obj</span><span class="p">);</span>
|
||
<span class="n">any_image_view</span><span class="o">&</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">&</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"><</span><span class="k">typename</span> <span class="n">ImageTypes</span><span class="o">></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"><</span><span class="n">ImageTypes</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">typedef</span> <span class="n">variant</span><span class="o"><</span><span class="n">ImageTypes</span><span class="o">></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"><</span><span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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">&</span> <span class="n">obj</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="k">explicit</span> <span class="n">any_image</span><span class="p">(</span><span class="n">T</span><span class="o">&</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">&</span> <span class="n">v</span><span class="p">);</span>
|
||
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></span> <span class="n">any_image</span><span class="o">&</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">&</span> <span class="n">obj</span><span class="p">);</span>
|
||
<span class="n">any_image</span><span class="o">&</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">&</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">&</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 don’t 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"><</span><span class="n">Types</span><span class="o">></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"><boost\gil\extension\io\jpeg_dynamic_io.hpp></span><span class="cp"></span>
|
||
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">Image</span><span class="o">></span> <span class="c1">// Could be rgb8_image_t or any_image<...></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">&</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"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span>
|
||
<span class="k">typename</span> <span class="n">dynamic_xy_step_type</span><span class="o"><</span><span class="n">View</span><span class="o">>::</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">&</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"><</span><span class="k">typename</span> <span class="n">Result</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></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">&</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"><</span><span class="k">typename</span> <span class="n">ViewTypes</span><span class="o">></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"><</span><span class="n">any_image_view</span><span class="o"><</span><span class="n">ViewTypes</span><span class="o">></span> <span class="o">>::</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"><</span><span class="n">ViewTypes</span><span class="o">>&</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"><</span><span class="k">typename</span> <span class="n">dynamic_xy_step_type</span><span class="o"><</span><span class="n">any_image_view</span><span class="o"><</span><span class="n">ViewTypes</span><span class="o">></span> <span class="o">>::</span><span class="n">type</span><span class="o">></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"><</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">></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"><</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">></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"><</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">></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"><</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">></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"><</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">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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"><</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"><</span><span class="kt">unsigned</span> <span class="kt">char</span><span class="o">></span> <span class="o">></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 don’t need
|
||
<code class="docutils literal notranslate"><span class="pre">IsYStep</span></code> because GIL’s 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"><</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">></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"><</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">></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"><</span><span class="k">typename</span> <span class="n">XIterator</span><span class="o">></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"><</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">></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"><</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">></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"><</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">></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"><</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">></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"><</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">>::</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</span><span class="n">rgb8_planar_view_t</span><span class="o">>::</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"><</span><span class="n">View</span><span class="o">>::</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>GIL’s 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 don’t 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"><</span><span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">Img</span><span class="o">></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">&</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"><</span><span class="k">typename</span> <span class="n">Img</span><span class="o">></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">&</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</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't match the ones of the view.</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></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">&</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't match the ones of the view.</span>
|
||
<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></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">&</span><span class="p">);</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</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"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></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">&</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"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></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">"jpeg_dynamic_io.hpp"</span></code> instead of <code class="docutils literal notranslate"><span class="pre">"jpeg_io.hpp"</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"><</span><span class="k">typename</span> <span class="n">Images</span><span class="o">></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"><</span><span class="n">Images</span><span class="o">>&</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"><</span><span class="k">typename</span> <span class="n">Views</span><span class="o">></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"><</span><span class="n">Views</span><span class="o">>&</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"><</span><span class="mi">0</span><span class="o">></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"><</span><span class="mi">0</span><span class="o">></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<float, rgb_layout_t>();// compile error: Incompatible channel depth</span>
|
||
<span class="c1">//p1 = pixel<bits8, rgb_layout_t>();// compile error: Incompatible color space (even though it has the same number of channels)</span>
|
||
<span class="c1">//p1 = pixel<bits8,rgba_layout_t>();// 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"><</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">></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">&</span> <span class="n">src</span><span class="p">,</span> <span class="n">RGBPixel</span><span class="o">&</span> <span class="n">dst</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">gil_function_requires</span><span class="o"><</span><span class="n">PixelConcept</span><span class="o"><</span><span class="n">GrayPixel</span><span class="o">></span> <span class="o">></span><span class="p">();</span>
|
||
<span class="n">gil_function_requires</span><span class="o"><</span><span class="n">MutableHomogeneousPixelConcept</span><span class="o"><</span><span class="n">RGBPixel</span><span class="o">></span> <span class="o">></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"><</span><span class="n">GrayPixel</span><span class="o">>::</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"><</span><span class="n">gray_cs_t</span><span class="p">,</span><span class="n">gray_t</span><span class="o">>::</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"><</span><span class="n">RGBPixel</span><span class="o">>::</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"><</span><span class="n">rgb_cs_t</span><span class="p">,</span><span class="n">rgb_t</span><span class="o">>::</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"><</span><span class="n">GrayPixel</span><span class="o">>::</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"><</span><span class="n">RGBPixel</span><span class="o">>::</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"><</span><span class="n">rgb_channel_t</span><span class="o">></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"><</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">></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">&</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">&</span> <span class="n">result</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">gil_function_requires</span><span class="o"><</span><span class="n">ImageViewConcept</span><span class="o"><</span><span class="n">SrcView</span><span class="o">></span> <span class="o">></span><span class="p">();</span>
|
||
<span class="n">gil_function_requires</span><span class="o"><</span><span class="n">ImageConcept</span><span class="o"><</span><span class="n">DstImage</span><span class="o">></span> <span class="o">></span><span class="p">();</span>
|
||
<span class="n">gil_function_requires</span><span class="o"><</span><span class="n">ViewsCompatibleConcept</span><span class="o"><</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">></span> <span class="o">></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"><</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">></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">&</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">&</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"><</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">></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">&</span> <span class="n">img</span><span class="p">,</span> <span class="n">R</span><span class="o">&</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 GIL’s <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"><</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">></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">&</span> <span class="n">v</span><span class="p">,</span> <span class="n">R</span><span class="o">&</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"><</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">></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">&</span> <span class="n">v</span><span class="p">,</span> <span class="n">R</span><span class="o">&</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"><</span><span class="n">gray8_pixel_t</span><span class="o">></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">"monkey.jpg"</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"><</span><span class="n">rgb8_view_t</span><span class="p">,</span><span class="n">gray8_pixel_t</span><span class="o">></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">"monkey_transform.jpg"</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 don’t 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"><</span><span class="kt">double</span><span class="p">,</span><span class="n">rgb_layout_t</span><span class="o">></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"><</span><span class="kt">double</span><span class="p">,</span><span class="n">rgb_layout_t</span><span class="o">>::</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 GIL’s 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's default</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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"><</span><span class="n">SrcColorSpace</span><span class="p">,</span><span class="n">DstColorSpace</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">SrcColorSpace</span><span class="o">></span>
|
||
<span class="k">struct</span> <span class="n">my_color_converter_impl</span><span class="o"><</span><span class="n">SrcColorSpace</span><span class="p">,</span><span class="n">gray_t</span><span class="o">></span>
|
||
<span class="p">{</span>
|
||
<span class="k">template</span> <span class="o"><</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">></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">&</span> <span class="n">src</span><span class="p">,</span> <span class="n">DstP</span><span class="o">&</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"><</span><span class="n">SrcColorSpace</span><span class="p">,</span><span class="n">gray_t</span><span class="o">></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"><</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">></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">&</span> <span class="n">src</span><span class="p">,</span><span class="n">DstP</span><span class="o">&</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"><</span><span class="n">SrcP</span><span class="o">>::</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"><</span><span class="n">DstP</span><span class="o">>::</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"><</span><span class="n">SrcColorSpace</span><span class="p">,</span><span class="n">DstColorSpace</span><span class="o">></span><span class="p">()(</span><span class="n">src</span><span class="p">,</span><span class="n">dst</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
<span class="p">};</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>GIL’s 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"><</span><span class="n">gray8_pixel_t</span><span class="o">></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, let’s 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"><</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">></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">&</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"><</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">></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"><</span><span class="n">src_pix_ref</span><span class="p">,</span> <span class="n">DstP</span><span class="o">></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"><</span><span class="n">deref_t</span><span class="o">></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">&</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"><</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">></span> <span class="kr">inline</span>
|
||
<span class="k">typename</span> <span class="n">color_converted_view_type</span><span class="o"><</span><span class="n">View</span><span class="p">,</span><span class="n">DstP</span><span class="o">>::</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">&</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"><</span><span class="n">View</span><span class="p">,</span><span class="n">DstP</span><span class="o">>::</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 GIL’s reference to
|
||
a planar pixel (<code class="docutils literal notranslate"><span class="pre">planar_pixel_reference</span></code>) and GIL’s 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"><</span><span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">Pixel</span><span class="o">></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">&</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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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">&</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">&</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">-></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"><</span><span class="n">rgb_planar_pixel_iterator</span><span class="o">></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"><</span><span class="n">T</span><span class="o">></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"><</span><span class="k">typename</span> <span class="n">T</span><span class="o">></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"><</span><span class="n">T</span><span class="o">>&</span> <span class="n">x</span><span class="p">,</span> <span class="n">my_reference_proxy</span><span class="o"><</span><span class="n">T</span><span class="o">>&</span> <span class="n">y</span><span class="p">)</span>
|
||
<span class="p">{</span>
|
||
<span class="n">my_value</span><span class="o"><</span><span class="n">T</span><span class="o">></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> |