mirror of
https://github.com/boostorg/gil.git
synced 2026-01-25 18:22:16 +00:00
2555 lines
378 KiB
HTML
2555 lines
378 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>
|
|
<p>This document describes the design of the Generic Image Library, a C++ image-processing library that abstracts image representation from algorithms on images.
|
|
It covers more than you need to know for a causal use of GIL. You can find a quick, jump-start GIL tutorial on the main GIL page at <a class="reference external" href="http://stlab.adobe.com/gil">http://stlab.adobe.com/gil</a></p>
|
|
<div class="contents local topic" id="contents">
|
|
<ul class="simple">
|
|
<li><a class="reference internal" href="#overview" id="id1">Overview</a></li>
|
|
<li><a class="reference internal" href="#about-concepts" id="id2">About Concepts</a></li>
|
|
<li><a class="reference internal" href="#point" id="id3">Point</a></li>
|
|
<li><a class="reference internal" href="#channel" id="id4">Channel</a></li>
|
|
<li><a class="reference internal" href="#color-space-and-layout" id="id5">Color Space and Layout</a></li>
|
|
<li><a class="reference internal" href="#color-base" id="id6">Color Base</a></li>
|
|
<li><a class="reference internal" href="#pixel" id="id7">Pixel</a></li>
|
|
<li><a class="reference internal" href="#pixel-iterator" id="id8">Pixel Iterator</a><ul>
|
|
<li><a class="reference internal" href="#fundamental-iterator" id="id9">Fundamental Iterator</a></li>
|
|
<li><a class="reference internal" href="#iterator-adaptor" id="id10">Iterator Adaptor</a></li>
|
|
<li><a class="reference internal" href="#pixel-dereference-adaptor" id="id11">Pixel Dereference Adaptor</a></li>
|
|
<li><a class="reference internal" href="#step-iterator" id="id12">Step Iterator</a></li>
|
|
<li><a class="reference internal" href="#pixel-locator" id="id13">Pixel Locator</a></li>
|
|
<li><a class="reference internal" href="#iterator-over-2d-image" id="id14">Iterator over 2D image</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="reference internal" href="#image-view" id="id15">Image View</a><ul>
|
|
<li><a class="reference internal" href="#creating-views-from-raw-pixels" id="id16">Creating Views from Raw Pixels</a></li>
|
|
<li><a class="reference internal" href="#creating-image-views-from-other-image-views" id="id17">Creating Image Views from Other Image Views</a></li>
|
|
<li><a class="reference internal" href="#stl-style-algorithms-on-image-views" id="id18">STL-Style Algorithms on Image Views</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="reference internal" href="#image" id="id19">Image</a></li>
|
|
<li><a class="reference internal" href="#run-time-specified-images-and-image-views" id="id20">Run-time specified images and image views</a></li>
|
|
<li><a class="reference internal" href="#useful-metafunctions-and-typedefs" id="id21">Useful Metafunctions and Typedefs</a></li>
|
|
<li><a class="reference internal" href="#i-o-extension" id="id22">I/O Extension</a></li>
|
|
<li><a class="reference internal" href="#sample-code" id="id23">Sample Code</a><ul>
|
|
<li><a class="reference internal" href="#pixel-level-sample-code" id="id24">Pixel-level Sample Code</a></li>
|
|
<li><a class="reference internal" href="#creating-a-copy-of-an-image-with-a-safe-buffer" id="id25">Creating a Copy of an Image with a Safe Buffer</a></li>
|
|
<li><a class="reference internal" href="#histogram" id="id26">Histogram</a></li>
|
|
<li><a class="reference internal" href="#using-image-views" id="id27">Using Image Views</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="reference internal" href="#extending-the-generic-image-library" id="id28">Extending the Generic Image Library</a><ul>
|
|
<li><a class="reference internal" href="#defining-new-color-spaces" id="id29">Defining New Color Spaces</a></li>
|
|
<li><a class="reference internal" href="#defining-new-channel-types" id="id30">Defining New Channel Types</a></li>
|
|
<li><a class="reference internal" href="#overloading-color-conversion" id="id31">Overloading Color Conversion</a></li>
|
|
<li><a class="reference internal" href="#defining-new-image-views" id="id32">Defining New Image Views</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="reference internal" href="#technicalities" id="id33">Technicalities</a><ul>
|
|
<li><a class="reference internal" href="#creating-a-reference-proxy" id="id34">Creating a reference proxy</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a class="reference internal" href="#conclusion" id="id35">Conclusion</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="section" id="overview">
|
|
<h2><a class="toc-backref" href="#id1">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:
|
|
- Structure (planar vs. interleaved)
|
|
- Color space and presence of alpha (RGB, RGBA, CMYK, etc.)
|
|
- Channel depth (8-bit, 16-bit, etc.)
|
|
- Order of channels (RGB vs. BGR, etc.)
|
|
- Row alignment policy (no alignment, word-alignment, etc.)</p>
|
|
<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="#id2">About Concepts</a></h2>
|
|
<p>All constructs in GIL are models of GIL concepts. A em concept 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 <tt class="docutils literal"><span class="pre">pixel</span></tt> is a model of GIL’s <tt class="docutils literal"><span class="pre">PixelConcept</span></tt>. The user may substitute the pixel class with one of their own, and, as long as
|
|
it satisfies the requirements of <tt class="docutils literal"><span class="pre">PixelConcept</span></tt>, 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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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="#id3">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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">PointNDConcept</span></tt> in which both dimensions are of the same type:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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>
|
|
<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" colspan="2">Related Concepts:</th></tr>
|
|
<tr class="field-odd field"><td> </td><td class="field-body"><ul class="first simple">
|
|
<li><tt class="docutils literal"><span class="pre">PointNDConcept</span></tt></li>
|
|
<li><tt class="docutils literal"><span class="pre">Point2DConcept</span></tt></li>
|
|
</ul>
|
|
</td>
|
|
</tr>
|
|
<tr class="field-even field"><th class="field-name">Models:</th><td class="field-body"><p class="first last">GIL provides a model of <tt class="docutils literal"><span class="pre">Point2DConcept</span></tt>, <tt class="docutils literal"><span class="pre">point2<T></span></tt> where <tt class="docutils literal"><span class="pre">T</span></tt> is the coordinate type.</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="section" id="channel">
|
|
<h2><a class="toc-backref" href="#id4">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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">channel_traits</span></tt> with the following default implementation:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">ChannelConcept</span></tt> and <tt class="docutils literal"><span class="pre">MutableChannelConcept</span></tt> do not require a default constructor. Channels that also
|
|
support default construction (and thus are regular types) model <tt class="docutils literal"><span class="pre">ChannelValueConcept</span></tt>. 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 <tt class="docutils literal"><span class="pre">ChannelConcept</span></tt>, 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>
|
|
<p><b>Related Concepts:</b></p>
|
|
<ul class="simple">
|
|
<li>ChannelConcept<T></li>
|
|
<li>ChannelValueConcept<T></li>
|
|
<li>MutableChannelConcept<T></li>
|
|
<li>ChannelsCompatibleConcept<T1,T2></li>
|
|
<li>ChannelConvertibleConcept<SrcChannel,DstChannel></li>
|
|
</ul>
|
|
<p><b>Models:</b></p>
|
|
<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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">std::numeric_limits</span></tt>. Sometimes the physical range is not appropriate. GIL provides <tt class="docutils literal"><span class="pre">scoped_channel_value</span></tt>, 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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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>
|
|
<p><b>Algorithms:</b></p>
|
|
<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++"><div class="highlight"><pre><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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><span class="n">channel1</span> <span class="o">=</span> <span class="n">channel_traits</span><span class="o"><</span><span class="kt">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++"><div class="highlight"><pre><span class="c1">// Converts a source channel value into a destination channel. Linearly maps the value of the source</span>
|
|
<span class="c1">// 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 class="section" id="color-space-and-layout">
|
|
<h2><a class="toc-backref" href="#id5">Color Space and Layout</a></h2>
|
|
<p>A color space captures the set and interpretation of channels comprising a pixel. It is an MPL random access sequence containing the types
|
|
of all elements in the color space. Two color spaces are considered <em>compatible</em> if they are equal (i.e. have the same set of colors in the same order).</p>
|
|
<p><b>Related Concepts:</b></p>
|
|
<ul class="simple">
|
|
<li>ColorSpaceConcept<ColorSpace></li>
|
|
<li>ColorSpacesCompatibleConcept<ColorSpace1,ColorSpace2></li>
|
|
<li>ChannelMappingConcept<Mapping></li>
|
|
</ul>
|
|
<p><b>Models:</b></p>
|
|
<p>GIL currently provides the following color spaces: <tt class="docutils literal"><span class="pre">gray_t</span></tt>, <tt class="docutils literal"><span class="pre">rgb_t</span></tt>, <tt class="docutils literal"><span class="pre">rgba_t</span></tt>, and <tt class="docutils literal"><span class="pre">cmyk_t</span></tt>. It also provides unnamed
|
|
N-channel color spaces of two to five channels, <tt class="docutils literal"><span class="pre">devicen_t<2></span></tt>,
|
|
<tt class="docutils literal"><span class="pre">devicen_t<3></span></tt>, <tt class="docutils literal"><span class="pre">devicen_t<4></span></tt>, <tt class="docutils literal"><span class="pre">devicen_t<5></span></tt>. Besides the standard layouts, it provides <tt class="docutils literal"><span class="pre">bgr_layout_t</span></tt>, <tt class="docutils literal"><span class="pre">bgra_layout_t</span></tt>, <tt class="docutils literal"><span class="pre">abgr_layout_t</span></tt>
|
|
and <tt class="docutils literal"><span class="pre">argb_layout_t</span></tt>.</p>
|
|
<p>As an example, here is how GIL defines the RGBA color space:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><span class="k">struct</span> <span class="kt">red_t</span><span class="p">{};</span>
|
|
<span class="k">struct</span> <span class="kt">green_t</span><span class="p">{};</span>
|
|
<span class="k">struct</span> <span class="kt">blue_t</span><span class="p">{};</span>
|
|
<span class="k">struct</span> <span class="kt">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="kt">red_t</span><span class="p">,</span><span class="kt">green_t</span><span class="p">,</span><span class="kt">blue_t</span><span class="p">,</span><span class="kt">alpha_t</span><span class="o">></span> <span class="kt">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, <tt class="docutils literal"><span class="pre">red_t</span></tt> is the first semantic channel of <tt class="docutils literal"><span class="pre">rgba_t</span></tt>.
|
|
While there is a unique semantic ordering of the channels in a color space, channels may vary in their physical ordering in memory. The mapping of channels is
|
|
specified by <tt class="docutils literal"><span class="pre">ChannelMappingConcept</span></tt>, which is an MPL random access sequence of integral types. A color space and its associated mapping are often used together.
|
|
Thus they are grouped in GIL’s layout:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">color_space_t</span><span class="p">;</span>
|
|
<span class="k">typedef</span> <span class="n">ChannelMapping</span> <span class="kt">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++"><div class="highlight"><pre><span class="k">typedef</span> <span class="n">layout</span><span class="o"><</span><span class="kt">rgba_t</span><span class="o">></span> <span class="kt">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="kt">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="kt">bgra_layout_t</span><span class="p">;</span>
|
|
<span class="k">typedef</span> <span class="n">layout</span><span class="o"><</span><span class="kt">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="kt">argb_layout_t</span><span class="p">;</span>
|
|
<span class="k">typedef</span> <span class="n">layout</span><span class="o"><</span><span class="kt">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="kt">abgr_layout_t</span><span class="p">;</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="color-base">
|
|
<h2><a class="toc-backref" href="#id6">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++"><div class="highlight"><pre><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="kt">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="kt">layout_t</span><span class="o">::</span><span class="kt">color_space_t</span><span class="p">,</span> <span class="n">C2</span><span class="o">::</span><span class="kt">layout_t</span><span class="o">::</span><span class="kt">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 <tt class="docutils literal"><span class="pre">ColorBaseConcept</span></tt> are required to provide the <tt class="docutils literal"><span class="pre">at_c<K>(ColorBase)</span></tt> function, which allows for accessing the elements based on their
|
|
physical order. GIL provides a <tt class="docutils literal"><span class="pre">semantic_at_c<K>(ColorBase)</span></tt> 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>
|
|
<p><b>Models:</b></p>
|
|
<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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">ColorBaseConcept</span></tt> is <tt class="docutils literal"><span class="pre">packed_pixel</span></tt> - it is a pixel whose channels are bit ranges. See the ref PixelSectionDG
|
|
section for more.</p>
|
|
<p><b>Algorithms:</b></p>
|
|
<p>GIL provides the following functions and metafunctions operating on color bases:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">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="kt">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="kt">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="kt">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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">static_equal</span></tt>:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">layout_t</span><span class="o">::</span><span class="kt">color_space_t</span><span class="p">,</span><span class="n">P2</span><span class="o">::</span><span class="kt">layout_t</span><span class="o">::</span><span class="kt">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 <tt class="docutils literal"><span class="pre">operator==</span></tt> 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 class="section" id="pixel">
|
|
<h2><a class="toc-backref" href="#id7">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 <tt class="docutils literal"><span class="pre">ChannelConcept</span></tt>.
|
|
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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">PixelConcept</span></tt> and <tt class="docutils literal"><span class="pre">PixelValueConcept</span></tt> is analogous to that for channels and color bases - pixel reference proxies model both,
|
|
but only pixel values model the latter.</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" colspan="2">Related Concepts:</th></tr>
|
|
<tr class="field-odd field"><td> </td><td class="field-body"></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<ul class="simple">
|
|
<li>PixelBasedConcept</li>
|
|
<li>PixelConcept</li>
|
|
<li>MutablePixelConcept</li>
|
|
<li>PixelValueConcept</li>
|
|
<li>HomogeneousPixelConcept</li>
|
|
<li>MutableHomogeneousPixelConcept</li>
|
|
<li>HomogeneousPixelValueConcept</li>
|
|
<li>PixelsCompatibleConcept</li>
|
|
<li>PixelConvertibleConcept</li>
|
|
</ul>
|
|
<p>The most commonly used pixel is a homogeneous pixel whose values are together in memory.
|
|
For this purpose GIL provides the struct <tt class="docutils literal"><span class="pre">pixel</span></tt>, templated over the channel value and layout:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">rgb_layout_t</span><span class="o">></span> <span class="kt">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="kt">bgr_layout_t</span><span class="o">></span> <span class="kt">bgr8_pixel_t</span><span class="p">;</span>
|
|
|
|
<span class="kt">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="kt">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 (<tt class="docutils literal"><span class="pre">pixel</span></tt>) with interleaved pixels, their
|
|
reference type is a proxy class containing references to each of the channels. This is implemented with the struct <tt class="docutils literal"><span class="pre">planar_pixel_reference</span></tt>:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">rgb_t</span><span class="o">></span> <span class="kt">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="kt">rgb_t</span><span class="o">></span> <span class="kt">rgb8c_planar_ref_t</span><span class="p">;</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>Note that, unlike the <tt class="docutils literal"><span class="pre">pixel</span></tt> 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++"><div class="highlight"><pre><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="kt">rgb_layout_t</span><span class="o">>::</span><span class="n">type</span> <span class="kt">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="kt">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="kt">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="kt">bgr_layout_t</span><span class="o">>::</span><span class="n">type</span> <span class="kt">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="kt">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="kt">rgb565_pixel_t</span><span class="p">,</span><span class="kt">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++"><div class="highlight"><pre><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="kt">bgr_layout_t</span><span class="p">,</span> <span class="nb">true</span><span class="o">></span> <span class="kt">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="kt">bgr232_ref_t</span><span class="o">></span> <span class="kt">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="kt">bgr232_ptr_t</span><span class="o">>::</span><span class="n">value_type</span> <span class="kt">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="kt">bgr232_pixel_t</span><span class="p">)</span><span class="o">==</span><span class="mi">1</span><span class="p">));</span>
|
|
|
|
<span class="kt">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="kt">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>
|
|
<p><b>Algorithms:</b></p>
|
|
<p>Since pixels model <tt class="docutils literal"><span class="pre">ColorBaseConcept</span></tt> and <tt class="docutils literal"><span class="pre">PixelBasedConcept</span></tt> all algorithms and metafunctions of color bases can work with them as well:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">bgr8_pixel_t</span><span class="o">>::</span><span class="n">type</span><span class="p">,</span> <span class="kt">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="kt">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="kt">rgb8_pixel_t</span><span class="p">)</span><span class="o">==</span><span class="mi">3</span><span class="p">);</span>
|
|
|
|
<span class="kt">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="kt">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="kt">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="kt">rgb565_pixel_t</span> <span class="n">r565</span><span class="p">;</span>
|
|
<span class="kt">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="kt">red_t</span><span class="p">())</span> <span class="o">=</span> <span class="n">channel_convert</span><span class="o"><</span><span class="kt">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="kt">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="kt">green_t</span><span class="p">())</span> <span class="o">=</span> <span class="n">channel_convert</span><span class="o"><</span><span class="kt">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="kt">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="kt">blue_t</span><span class="p">())</span> <span class="o">=</span> <span class="n">channel_convert</span><span class="o"><</span><span class="kt">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="kt">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="kt">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 <tt class="docutils literal"><span class="pre">color_convert</span></tt> algorithm to convert between pixels of different color spaces and channel types:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><span class="kt">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="kt">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 class="section" id="pixel-iterator">
|
|
<h2><a class="toc-backref" href="#id8">Pixel Iterator</a></h2>
|
|
<div class="section" id="fundamental-iterator">
|
|
<h3><a class="toc-backref" href="#id9">Fundamental Iterator</a></h3>
|
|
<p>Pixel iterators are random traversal iterators whose <tt class="docutils literal"><span class="pre">value_type</span> <span class="pre">models</span></tt> <tt class="docutils literal"><span class="pre">PixelValueConcept</span></tt>.
|
|
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++"><div class="highlight"><pre><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="n">MutablePixelIteratorConcept</span> <span class="o">:</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>
|
|
<p><b>Related Concepts:</b></p>
|
|
<ul class="simple">
|
|
<li>PixelIteratorConcept<Iterator></li>
|
|
<li>MutablePixelIteratorConcept<Iterator></li>
|
|
</ul>
|
|
<p><b>Models:</b></p>
|
|
<p>A built-in pointer to pixel, <tt class="docutils literal"><span class="pre">pixel<ChannelValue,Layout>*</span></tt>, is GIL’s model for pixel iterator over interleaved homogeneous pixels.
|
|
Similarly, <tt class="docutils literal"><span class="pre">packed_pixel<PixelData,ChannelRefVec,Layout>*</span></tt> is GIL’s model for an iterator over interleaved packed pixels.</p>
|
|
<p>For planar homogeneous pixels, GIL provides the class <tt class="docutils literal"><span class="pre">planar_pixel_iterator</span></tt>, 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++"><div class="highlight"><pre><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="kt">rgb_t</span><span class="o">></span> <span class="kt">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="kt">rgb_t</span><span class="o">></span> <span class="kt">rgb8_planar_ptr_t</span><span class="p">;</span>
|
|
</pre></div>
|
|
</div>
|
|
<p><tt class="docutils literal"><span class="pre">planar_pixel_iterator</span></tt> also models <tt class="docutils literal"><span class="pre">HomogeneousColorBaseConcept</span></tt> (it subclasses from <tt class="docutils literal"><span class="pre">homogeneous_color_base</span></tt>) 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 p operator++ of planar iterators approximately
|
|
like this:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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">inc</span> <span class="o">:</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 <tt class="docutils literal"><span class="pre">static_transform</span></tt> uses compile-time recursion, incrementing an instance of <tt class="docutils literal"><span class="pre">rgb8_planar_ptr_t</span></tt> amounts to three pointer increments.
|
|
GIL also uses the class <tt class="docutils literal"><span class="pre">bit_aligned_pixel_iterator</span></tt> 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 class="section" id="iterator-adaptor">
|
|
<h3><a class="toc-backref" href="#id10">Iterator Adaptor</a></h3>
|
|
<p>Iterator adaptor is an iterator that wraps around another iterator. Its <tt class="docutils literal"><span class="pre">is_iterator_adaptor</span></tt> 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++"><div class="highlight"><pre><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="n">MutableIteratorAdaptorConcept</span> <span class="o">:</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>
|
|
<p><b>Related Concepts:</b></p>
|
|
<ul class="simple">
|
|
<li>IteratorAdaptorConcept<Iterator></li>
|
|
<li>MutableIteratorAdaptorConcept<Iterator></li>
|
|
</ul>
|
|
<p><b>Models:</b></p>
|
|
<p>GIL provides several models of <tt class="docutils literal"><span class="pre">IteratorAdaptorConcept</span></tt>:
|
|
- <tt class="docutils literal"><span class="pre">memory_based_step_iterator<Iterator></span></tt>: An iterator adaptor that changes the fundamental step of the base iterator (see ref StepIteratorDG)
|
|
- <tt class="docutils literal"><span class="pre">dereference_iterator_adaptor<Iterator,Fn></span></tt>: An iterator that applies a unary function <tt class="docutils literal"><span class="pre">Fn</span></tt> 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 ref ImageViewFrowImageViewDG for more. The unary function <tt class="docutils literal"><span class="pre">Fn</span></tt> must model <tt class="docutils literal"><span class="pre">PixelDereferenceAdaptorConcept</span></tt> (see below).</p>
|
|
</div>
|
|
<div class="section" id="pixel-dereference-adaptor">
|
|
<h3><a class="toc-backref" href="#id11">Pixel Dereference Adaptor</a></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 <tt class="docutils literal"><span class="pre">PixelConcept</span></tt>) and the result type must be convertible to <tt class="docutils literal"><span class="pre">PixelConcept</span></tt></p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="n">PixelDereferenceAdaptorConcept</span> <span class="o">:</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="kt">const_t</span><span class="p">;</span> <span class="n">where</span> <span class="n">PixelDereferenceAdaptorConcept</span><span class="o"><</span><span class="kt">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>
|
|
<p><b>Models:</b></p>
|
|
<p>GIL provides several models of <tt class="docutils literal"><span class="pre">PixelDereferenceAdaptorConcept</span></tt>:
|
|
- <tt class="docutils literal"><span class="pre">color_convert_deref_fn</span></tt>: a function object that performs color conversion
|
|
- <tt class="docutils literal"><span class="pre">detail::nth_channel_deref_fn</span></tt>: a function object that returns a grayscale pixel corresponding to the n-th channel of a given pixel
|
|
- <tt class="docutils literal"><span class="pre">deref_compose</span></tt>: a function object that composes two models of <tt class="docutils literal"><span class="pre">PixelDereferenceAdaptorConcept</span></tt>. Similar to <tt class="docutils literal"><span class="pre">std::unary_compose</span></tt>, except it needs to pull the additional typedefs required by <tt class="docutils literal"><span class="pre">PixelDereferenceAdaptorConcept</span></tt></p>
|
|
<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. <tt class="docutils literal"><span class="pre">dereference_iterator_adaptor<Iterator,Fn></span></tt> is an iterator wrapper over a pixel iterator <tt class="docutils literal"><span class="pre">Iterator</span></tt> that invokes the given dereference
|
|
iterator adaptor <tt class="docutils literal"><span class="pre">Fn</span></tt> upon dereferencing.</p>
|
|
</div>
|
|
<div class="section" id="step-iterator">
|
|
<h3><a class="toc-backref" href="#id12">Step Iterator</a></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:
|
|
- a single-channel view of the red channel of an RGB interleaved image
|
|
- left-to-right flipped image (step = -fundamental_step)
|
|
- subsampled view, taking every N-th pixel (step = N*fundamental_step)
|
|
- traversal in vertical direction (step = number of bytes per row)
|
|
- any combination of the above (steps are multiplied)</p>
|
|
<p>Step iterators are forward traversal iterators that allow changing the step between adjacent values:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">value_type</span> <span class="pre">models</span></tt> <tt class="docutils literal"><span class="pre">PixelValueConcept</span></tt>. 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.
|
|
<tt class="docutils literal"><span class="pre">memunit_advanced</span></tt> and <tt class="docutils literal"><span class="pre">memunit_advanced_ref</span></tt> have a default implementation but some iterators may supply a more efficient version:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">HasDynamicXStepTypeConcept</span></tt>.</p>
|
|
<p><b>Related Concepts:</b></p>
|
|
<ul class="simple">
|
|
<li>StepIteratorConcept<Iterator></li>
|
|
<li>MutableStepIteratorConcept<Iterator></li>
|
|
<li>MemoryBasedIteratorConcept<Iterator></li>
|
|
<li>HasDynamicXStepTypeConcept<T></li>
|
|
</ul>
|
|
<p><b>Models:</b></p>
|
|
<p>All standard memory-based iterators GIL currently provides model <tt class="docutils literal"><span class="pre">MemoryBasedIteratorConcept</span></tt>.
|
|
GIL provides the class <tt class="docutils literal"><span class="pre">memory_based_step_iterator</span></tt> which models <tt class="docutils literal"><span class="pre">PixelIteratorConcept</span></tt>, <tt class="docutils literal"><span class="pre">StepIteratorConcept</span></tt>, and <tt class="docutils literal"><span class="pre">MemoryBasedIteratorConcept</span></tt>.
|
|
It takes the base iterator as a template parameter (which must model <tt class="docutils literal"><span class="pre">PixelIteratorConcept</span></tt> and <tt class="docutils literal"><span class="pre">MemoryBasedIteratorConcept</span></tt>)
|
|
and allows changing the step dynamically. GIL’s implementation contains the base iterator and a <tt class="docutils literal"><span class="pre">ptrdiff_t</span></tt> 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++"><div class="highlight"><pre><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, <tt class="docutils literal"><span class="pre">position_iterator</span></tt>. 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 <tt class="docutils literal"><span class="pre">PixelIteratorConcept</span></tt> and <tt class="docutils literal"><span class="pre">StepIteratorConcept</span></tt> but
|
|
not <tt class="docutils literal"><span class="pre">MemoryBasedIteratorConcept</span></tt>.</p>
|
|
</div>
|
|
<div class="section" id="pixel-locator">
|
|
<h3><a class="toc-backref" href="#id13">Pixel Locator</a></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++"><div class="highlight"><pre><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="kt">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="kt">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="kt">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="kt">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="kt">coord_t</span> <span class="o">=</span> <span class="kt">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="kt">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="kt">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="kt">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="n">MutableRandomAccessNDLocatorConcept</span> <span class="o">:</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++"><div class="highlight"><pre><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="kt">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="kt">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="kt">coord_t</span><span class="p">;</span>
|
|
<span class="k">typename</span> <span class="kt">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="kt">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="kt">x_coord_t</span><span class="p">,</span> <span class="kt">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="kt">x_coord_t</span><span class="p">,</span> <span class="kt">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="kt">x_coord_t</span><span class="p">,</span> <span class="kt">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="kt">x_coord_t</span><span class="p">,</span> <span class="kt">y_coord_t</span><span class="p">);</span>
|
|
<span class="kt">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="kt">x_coord_t</span><span class="p">,</span> <span class="kt">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="kt">x_coord_t</span> <span class="n">width</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
|
|
<span class="kt">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="kt">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 p HasDynamicXStepTypeConcept:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">HasDynamicYStepTypeConcept</span></tt>.</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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">HasTransposedTypeConcept</span></tt>.</p>
|
|
<p>The locators GIL uses operate over models of <tt class="docutils literal"><span class="pre">PixelConcept</span></tt> and their x and y dimension types are the same. They model the following concept:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">x_coord_t</span> <span class="o">==</span> <span class="kt">y_coord_t</span><span class="p">;</span>
|
|
|
|
<span class="k">typename</span> <span class="kt">coord_t</span> <span class="o">=</span> <span class="kt">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>
|
|
<p><b>Related Concepts:</b></p>
|
|
<ul class="simple">
|
|
<li>HasDynamicYStepTypeConcept<T></li>
|
|
<li>HasTransposedTypeConcept<T></li>
|
|
<li>RandomAccessNDLocatorConcept<Locator></li>
|
|
<li>MutableRandomAccessNDLocatorConcept<Locator></li>
|
|
<li>RandomAccess2DLocatorConcept<Locator></li>
|
|
<li>MutableRandomAccess2DLocatorConcept<Locator></li>
|
|
<li>PixelLocatorConcept<Locator></li>
|
|
<li>MutablePixelLocatorConcept<Locator></li>
|
|
</ul>
|
|
<p><b>Models:</b></p>
|
|
<p>GIL provides two models of <tt class="docutils literal"><span class="pre">PixelLocatorConcept</span></tt> - a memory-based locator, <tt class="docutils literal"><span class="pre">memory_based_2d_locator</span></tt> and a virtual locator <tt class="docutils literal"><span class="pre">virtual_2d_locator</span></tt>.</p>
|
|
<p><tt class="docutils literal"><span class="pre">memory_based_2d_locator</span></tt> is a locator over planar or interleaved images that have their pixels in memory.
|
|
It takes a model of <tt class="docutils literal"><span class="pre">StepIteratorConcept</span></tt> over pixels as a template parameter. (When instantiated with a model of <tt class="docutils literal"><span class="pre">MutableStepIteratorConcept</span></tt>,
|
|
it models <tt class="docutils literal"><span class="pre">MutablePixelLocatorConcept</span></tt>).</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">StepIterator</span></tt> must be the number of memory units (bytes or bits) per row (thus it must be memunit advanceable). The class <tt class="docutils literal"><span class="pre">memory_based_2d_locator</span></tt> is a
|
|
wrapper around <tt class="docutils literal"><span class="pre">StepIterator</span></tt> 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:
|
|
- <tt class="docutils literal"><span class="pre">pixel<T,C>*</span></tt> (for interleaved images)
|
|
- <tt class="docutils literal"><span class="pre">planar_pixel_iterator<T*,C></span></tt> (for planar images)
|
|
- <tt class="docutils literal"><span class="pre">memory_based_step_iterator<pixel<T,C>*></span></tt> (for interleaved images with non-standard step)
|
|
- <tt class="docutils literal"><span class="pre">memory_based_step_iterator<planar_pixel_iterator<T*,C></span> <span class="pre">></span></tt> (for planar images with non-standard step)</p>
|
|
<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 <tt class="docutils literal"><span class="pre">XIterator</span></tt>, we could choose the <tt class="docutils literal"><span class="pre">y-iterator</span></tt>, the iterator that moves along a column, as
|
|
<tt class="docutils literal"><span class="pre">memory_based_step_iterator<XIterator></span></tt> 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 <tt class="docutils literal"><span class="pre">memory_based_2d_locator<memory_based_step_iterator<XIterator></span> <span class="pre">></span></tt> to obtain a 2D pixel locator, as the diagram indicates:
|
|
.. image:: step_iterator.gif</p>
|
|
<p><tt class="docutils literal"><span class="pre">virtual_2d_locator</span></tt> 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 <tt class="docutils literal"><span class="pre">pixel_2d_locator_base</span></tt>, a base class that provides most of the interface required
|
|
by <tt class="docutils literal"><span class="pre">PixelLocatorConcept</span></tt>. Users may find this base class useful if they need to provide other models of <tt class="docutils literal"><span class="pre">PixelLocatorConcept</span></tt>.</p>
|
|
<p>Here is some sample code using locators:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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">point2</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. <tt class="docutils literal"><span class="pre">++loc.x()</span></tt> 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 <tt class="docutils literal"><span class="pre">cache_location</span></tt>. In the above example <tt class="docutils literal"><span class="pre">loc[above]</span></tt> for simple interleaved images amounts to a raw array
|
|
index operator.</p>
|
|
</div>
|
|
<div class="section" id="iterator-over-2d-image">
|
|
<h3><a class="toc-backref" href="#id14">Iterator over 2D image</a></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 <tt class="docutils literal"><span class="pre">iterator_from_2d</span></tt> 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++"><div class="highlight"><pre><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="nl">public:</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="nl">private:</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 <tt class="docutils literal"><span class="pre">iterator_from_2d</span></tt> 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
|
|
<tt class="docutils literal"><span class="pre">iterator_from_2d::operator++</span></tt> 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 std::copy and
|
|
<tt class="docutils literal"><span class="pre">std::fill</span></tt>, when invoked with <tt class="docutils literal"><span class="pre">iterator_from_2d</span></tt>-s, to go through each row using their base x-iterators, and, if the image has no padding
|
|
(i.e. <tt class="docutils literal"><span class="pre">iterator_from_2d::is_1d_traversable()</span></tt> 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="#id15">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++"><div class="highlight"><pre><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="kt">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="kt">point_t</span><span class="p">;</span> <span class="n">where</span> <span class="n">PointNDConcept</span><span class="o"><</span><span class="kt">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="kt">coord_t</span> <span class="o">=</span> <span class="kt">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="kt">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="kt">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="kt">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="kt">point_t</span><span class="o">&</span><span class="p">);</span>
|
|
<span class="kt">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="kt">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="k">operator</span><span class="p">()(</span><span class="n">View</span><span class="p">,</span><span class="k">const</span> <span class="kt">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++"><div class="highlight"><pre><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="kt">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="kt">coord_t</span><span class="p">;</span>
|
|
<span class="k">typename</span> <span class="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">x_coord_t</span><span class="p">,</span><span class="kt">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="kt">x_coord_t</span><span class="p">,</span><span class="kt">y_coord_t</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="n">View</span><span class="p">,</span><span class="kt">x_coord_t</span><span class="p">,</span><span class="kt">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="kt">x_coord_t</span><span class="p">,</span><span class="kt">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="kt">x_coord_t</span><span class="p">,</span><span class="kt">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="kt">x_coord_t</span><span class="p">,</span><span class="kt">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 <tt class="docutils literal"><span class="pre">PixelValueConcept</span></tt> and have some additional requirements:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">x_coord_t</span> <span class="o">==</span> <span class="kt">y_coord_t</span><span class="p">;</span>
|
|
|
|
<span class="k">typename</span> <span class="kt">coord_t</span> <span class="o">=</span> <span class="kt">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++"><div class="highlight"><pre><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>
|
|
<p><b>Related Concepts:</b></p>
|
|
<ul class="simple">
|
|
<li>RandomAccessNDImageViewConcept<View></li>
|
|
<li>MutableRandomAccessNDImageViewConcept<View></li>
|
|
<li>RandomAccess2DImageViewConcept<View></li>
|
|
<li>MutableRandomAccess2DImageViewConcept<View></li>
|
|
<li>ImageViewConcept<View></li>
|
|
<li>MutableImageViewConcept<View></li>
|
|
<li>ViewsCompatibleConcept<View1,View2></li>
|
|
</ul>
|
|
<p><b>Models:</b></p>
|
|
<p>GIL provides a model for <tt class="docutils literal"><span class="pre">ImageViewConcept</span></tt> called <tt class="docutils literal"><span class="pre">image_view</span></tt>. It is templated over a model of <tt class="docutils literal"><span class="pre">PixelLocatorConcept</span></tt>.
|
|
(If instantiated with a model of <tt class="docutils literal"><span class="pre">MutablePixelLocatorConcept</span></tt>, it models <tt class="docutils literal"><span class="pre">MutableImageViewConcept</span></tt>). Synopsis:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="nl">public:</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="nl">private:</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="kt">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 class="section" id="creating-views-from-raw-pixels">
|
|
<h3><a class="toc-backref" href="#id16">Creating Views from Raw Pixels</a></h3>
|
|
<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 <tt class="docutils literal"><span class="pre">interleaved_view</span></tt>, supplying the image dimensions, number of bytes per row, and a
|
|
pointer to the first pixel:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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">
|
|
<h3><a class="toc-backref" href="#id17">Creating Image Views from Other Image Views</a></h3>
|
|
<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++"><div class="highlight"><pre><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="n">dynamic_xy_step_type</span> <span class="o">:</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="n">dynamic_xy_step_transposed_type</span> <span class="o">:</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++"><div class="highlight"><pre><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="kt">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="kt">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="kt">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="kt">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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">gil_function_requires</span></tt> ensures (at compile time) that the template parameter is a valid model of <tt class="docutils literal"><span class="pre">ImageViewConcept</span></tt>. Using it
|
|
generates easier to track compile errors, creates no extra code and has no run-time performance impact.
|
|
We are using the <tt class="docutils literal"><span class="pre">boost::concept_check</span> <span class="pre">library</span></tt>, but wrapping it in <tt class="docutils literal"><span class="pre">gil_function_requires</span></tt>, which performs the check if the <tt class="docutils literal"><span class="pre">BOOST_GIL_USE_CONCEPT_CHECK</span></tt>
|
|
is set. It is unset by default, because there is a significant increase in compile time when using concept checks. We will skip <tt class="docutils literal"><span class="pre">gil_function_requires</span></tt>
|
|
in the code examples in this guide for the sake of succinctness.</p>
|
|
<p>Image views can be freely composed (see section ref MetafunctionsDG for the typedefs <tt class="docutils literal"><span class="pre">rgb16_image_t</span></tt> and <tt class="docutils literal"><span class="pre">gray16_step_view_t)</span></tt>:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><span class="kt">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="kt">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="kt">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 <tt class="docutils literal"><span class="pre">img</span></tt> was created.</p>
|
|
</div>
|
|
<div class="section" id="stl-style-algorithms-on-image-views">
|
|
<h3><a class="toc-backref" href="#id18">STL-Style Algorithms on Image Views</a></h3>
|
|
<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++"><div class="highlight"><pre><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.
|
|
<tt class="docutils literal"><span class="pre">for_each_pixel_position</span></tt> and <tt class="docutils literal"><span class="pre">transform_pixel_positions</span></tt> 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, <tt class="docutils literal"><span class="pre">copy_pixels</span></tt> calls <tt class="docutils literal"><span class="pre">std::copy</span></tt> 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, <tt class="docutils literal"><span class="pre">std::copy</span></tt> for planar iterators is overloaded to perform
|
|
<tt class="docutils literal"><span class="pre">std::copy</span></tt> for each of the planes. <tt class="docutils literal"><span class="pre">std::copy</span></tt> over bitwise-copyable pixels results in <tt class="docutils literal"><span class="pre">std::copy</span></tt> over unsigned char, which STL typically
|
|
implements via p memmove.</p>
|
|
<p>As a result <tt class="docutils literal"><span class="pre">copy_pixels</span></tt> may result in a single call to <tt class="docutils literal"><span class="pre">memmove</span></tt> 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 class="section" id="image">
|
|
<h2><a class="toc-backref" href="#id19">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++"><div class="highlight"><pre><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="kt">view_t</span><span class="p">;</span> <span class="n">where</span> <span class="n">MutableRandomAccessNDImageViewConcept</span><span class="o"><</span><span class="kt">view_t</span><span class="o">></span><span class="p">;</span>
|
|
<span class="k">typename</span> <span class="kt">const_view_t</span> <span class="o">=</span> <span class="kt">view_t</span><span class="o">::</span><span class="kt">const_t</span><span class="p">;</span>
|
|
<span class="k">typename</span> <span class="kt">point_t</span> <span class="o">=</span> <span class="kt">view_t</span><span class="o">::</span><span class="kt">point_t</span><span class="p">;</span>
|
|
<span class="k">typename</span> <span class="n">value_type</span> <span class="o">=</span> <span class="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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++"><div class="highlight"><pre><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="kt">x_coord_t</span> <span class="o">=</span> <span class="kt">const_view_t</span><span class="o">::</span><span class="kt">x_coord_t</span><span class="p">;</span>
|
|
<span class="k">typename</span> <span class="kt">y_coord_t</span> <span class="o">=</span> <span class="kt">const_view_t</span><span class="o">::</span><span class="kt">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="kt">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="kt">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="kt">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="kt">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="kt">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="kt">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="kt">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="kt">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="kt">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="kt">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 <tt class="docutils literal"><span class="pre">ImageViewConcept</span></tt> and operate on pixels.:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">view_t</span><span class="o">></span><span class="p">;</span>
|
|
<span class="k">typename</span> <span class="kt">coord_t</span> <span class="o">=</span> <span class="kt">view_t</span><span class="o">::</span><span class="kt">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>
|
|
<p><b>Related Concepts:</b></p>
|
|
<ul class="simple">
|
|
<li>RandomAccessNDImageConcept<Image></li>
|
|
<li>RandomAccess2DImageConcept<Image></li>
|
|
<li>ImageConcept<Image></li>
|
|
</ul>
|
|
<p><b>Models:</b></p>
|
|
<p>GIL provides a class, <tt class="docutils literal"><span class="pre">image</span></tt>, which is templated over the value type (the pixel) and models <tt class="docutils literal"><span class="pre">ImageConcept</span></tt>:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre>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 <tt class="docutils literal"><span class="pre">image_view::x_iterator</span></tt> can be used to traverse the pixels, instead of the more complicated
|
|
<tt class="docutils literal"><span class="pre">image_view::iterator</span></tt>. 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 class="section" id="run-time-specified-images-and-image-views">
|
|
<h2><a class="toc-backref" href="#id20">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++"><div class="highlight"><pre><span class="cp">#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp></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="kt">rgb8_image_t</span><span class="p">,</span> <span class="kt">cmyk16_planar_image_t</span><span class="o">></span> <span class="kt">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="kt">my_images_t</span><span class="o">></span> <span class="kt">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="kt">rgb8_view_t</span><span class="p">,</span> <span class="kt">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="kt">my_any_image_t</span><span class="o">::</span><span class="kt">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="kt">rgb8c_view_t</span><span class="p">,</span> <span class="kt">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="kt">my_any_image_t</span><span class="o">::</span><span class="kt">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="kt">my_any_image_t</span><span class="o">::</span><span class="kt">const_view_t</span><span class="p">,</span> <span class="kt">my_any_image_t</span><span class="o">::</span><span class="kt">view_t</span><span class="o">::</span><span class="kt">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="kt">rgb8_step_view_t</span><span class="p">,</span> <span class="kt">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="kt">my_any_image_t</span><span class="o">::</span><span class="kt">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="kt">my_any_image_t</span> <span class="n">myImg</span> <span class="o">=</span> <span class="kt">my_any_image_t</span><span class="p">(</span><span class="kt">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="kt">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="kt">gray8_image_t</span><span class="p">();</span> <span class="c1">// will throw std::bad_cast</span>
|
|
</pre></div>
|
|
</div>
|
|
<p><tt class="docutils literal"><span class="pre">any_image</span></tt> and <tt class="docutils literal"><span class="pre">any_image_view</span></tt> subclass from GIL’s <tt class="docutils literal"><span class="pre">variant</span></tt> 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 <tt class="docutils literal"><span class="pre">boost::variant</span></tt> 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++"><div class="highlight"><pre><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="nl">public:</span>
|
|
<span class="k">typedef</span> <span class="n">Types</span> <span class="kt">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 <tt class="docutils literal"><span class="pre">any_image_view</span></tt> and <tt class="docutils literal"><span class="pre">any_image</span></tt> are subclasses of <tt class="docutils literal"><span class="pre">variant</span></tt>:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="nl">public:</span>
|
|
<span class="k">typedef</span> <span class="p">...</span> <span class="kt">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="kt">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="kt">y_coord_t</span><span class="p">;</span>
|
|
<span class="k">typedef</span> <span class="n">point2</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="kt">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="kt">point_t</span> <span class="n">dimensions</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
|
|
<span class="kt">x_coord_t</span> <span class="n">width</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
|
|
<span class="kt">y_coord_t</span> <span class="n">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="kt">parent_t</span><span class="p">;</span>
|
|
<span class="nl">public:</span>
|
|
<span class="k">typedef</span> <span class="p">...</span> <span class="kt">const_view_t</span><span class="p">;</span>
|
|
<span class="k">typedef</span> <span class="p">...</span> <span class="kt">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="kt">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="kt">y_coord_t</span><span class="p">;</span>
|
|
<span class="k">typedef</span> <span class="n">point2</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="kt">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="kt">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="kt">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="kt">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="kt">point_t</span> <span class="n">dimensions</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
|
|
<span class="kt">x_coord_t</span> <span class="n">width</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
|
|
<span class="kt">y_coord_t</span> <span class="n">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 <tt class="docutils literal"><span class="pre">apply_operation</span></tt> 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 <tt class="docutils literal"><span class="pre">any_image_view</span></tt> has shallow default-constructor, copy-constructor, assignment and equality comparison, whereas <tt class="docutils literal"><span class="pre">any_image</span></tt>
|
|
has deep ones.</p>
|
|
<p>It is important to note that even though <tt class="docutils literal"><span class="pre">any_image_view</span></tt> and <tt class="docutils literal"><span class="pre">any_image</span></tt> resemble the static <tt class="docutils literal"><span class="pre">image_view</span></tt> and <tt class="docutils literal"><span class="pre">image</span></tt>, they do not model the full
|
|
requirements of <tt class="docutils literal"><span class="pre">ImageViewConcept</span></tt> and <tt class="docutils literal"><span class="pre">ImageConcept</span></tt>. 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 <tt class="docutils literal"><span class="pre">variant</span></tt> 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 <tt class="docutils literal"><span class="pre">apply_operation</span></tt>. 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 <tt class="docutils literal"><span class="pre">any_image_view</span></tt>, as illustrated with <tt class="docutils literal"><span class="pre">copy_pixels</span></tt>:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><span class="kt">rgb8_view_t</span> <span class="nf">v1</span><span class="p">(...);</span> <span class="c1">// concrete image view</span>
|
|
<span class="kt">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++"><div class="highlight"><pre><span class="cp">#include <boost\gil\extension\io\jpeg_dynamic_io.hpp></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 <tt class="docutils literal"><span class="pre">rotated180_view</span></tt> is implemented:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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, <tt class="docutils literal"><span class="pre">variant</span></tt> 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="#id21">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>
|
|
<p><em>ColorSpace</em> + <em>BitDepth</em> + [“s|f”] + [“c”] + [“_planar”] + [“_step”] + <em>ClassType</em> + “_t”</p>
|
|
<p>where <em>ColorSpace</em> also indicates the ordering of components. Examples are <tt class="docutils literal"><span class="pre">rgb</span></tt>, <tt class="docutils literal"><span class="pre">bgr</span></tt>, <tt class="docutils literal"><span class="pre">cmyk</span></tt>, <tt class="docutils literal"><span class="pre">rgba</span></tt>. <em>BitDepth</em> can be,
|
|
for example, <tt class="docutils literal"><span class="pre">8</span></tt>,``16``,``32``. By default the bits are unsigned integral type. Append <tt class="docutils literal"><span class="pre">s</span></tt> to the bit depth to indicate signed
|
|
integral, or <tt class="docutils literal"><span class="pre">f</span></tt> to indicate floating point. <tt class="docutils literal"><span class="pre">c</span></tt> indicates object whose associated pixel reference is immutable. <tt class="docutils literal"><span class="pre">_planar</span></tt>
|
|
indicates planar organization (as opposed to interleaved). <tt class="docutils literal"><span class="pre">_step</span></tt> indicates the type has a dynamic step and <em>ClassType</em> is <tt class="docutils literal"><span class="pre">_image</span></tt>
|
|
(image, using a standard allocator), <tt class="docutils literal"><span class="pre">_view</span></tt> (image view), <tt class="docutils literal"><span class="pre">_loc</span></tt> (pixel locator), <tt class="docutils literal"><span class="pre">_ptr</span></tt> (pixel iterator), <tt class="docutils literal"><span class="pre">_ref</span></tt>
|
|
(pixel reference), <tt class="docutils literal"><span class="pre">_pixel</span></tt> (pixel value). Here are examples:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><span class="kt">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="kt">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="kt">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="kt">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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">ChannelValue</span></tt> models <tt class="docutils literal"><span class="pre">ChannelValueConcept</span></tt>. We don’t need <tt class="docutils literal"><span class="pre">IsYStep</span></tt> 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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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="kt">step_iterator_t</span><span class="p">;</span>
|
|
<span class="k">typedef</span> <span class="p">...</span> <span class="kt">xy_locator_t</span><span class="p">;</span>
|
|
<span class="k">typedef</span> <span class="p">...</span> <span class="kt">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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">boost::use_default</span></tt> for the rest. In this case <tt class="docutils literal"><span class="pre">IsPlanar</span></tt>, <tt class="docutils literal"><span class="pre">IsStep</span></tt> and <tt class="docutils literal"><span class="pre">IsMutable</span></tt>
|
|
are MPL boolean constants. For example, here is how to create the type of a view just like <tt class="docutils literal"><span class="pre">View</span></tt>, but being grayscale and planar:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><span class="n">BOOST_STATIC_ASSERT</span><span class="p">(</span><span class="n">is_planar</span><span class="o"><</span><span class="kt">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] + p “_is_” + [basic/mutable/step]. For example:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="#id22">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 <tt>gil/extension/io/jpeg_io.hpp</tt>. If you are using run-time images,
|
|
you need to include <tt>gil/extension/io/jpeg_dynamic_io.hpp</tt> 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 <tt>jpeglib.h</tt> 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 <tt>gil/extension/io/tiff_io.hpp</tt>. If you are using run-time images,
|
|
you need to include <tt>gil/extension/io/tiff_dynamic_io.hpp</tt> 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 <tt>tiffio.h</tt> 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 <tt>gil/extension/io/png_io.hpp</tt>. If you are using run-time images,
|
|
you need to include <tt>gil/extension/io/png_dynamic_io.hpp</tt> 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 <tt>png.h</tt> 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++"><div class="highlight"><pre><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">point2</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 <tt class="docutils literal"><span class="pre">"jpeg_dynamic_io.hpp"</span></tt> instead of <tt class="docutils literal"><span class="pre">"jpeg_io.hpp"</span></tt>.
|
|
In addition to the above methods, you have the following overloads dealing with dynamic images:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">std::string</span></tt> instead of <tt class="docutils literal"><span class="pre">const</span> <span class="pre">char*</span></tt></p>
|
|
</div>
|
|
<div class="section" id="sample-code">
|
|
<h2><a class="toc-backref" href="#id23">Sample Code</a></h2>
|
|
<div class="section" id="pixel-level-sample-code">
|
|
<h3><a class="toc-backref" href="#id24">Pixel-level Sample Code</a></h3>
|
|
<p>Here are some operations you can do with pixel values, pointers and references:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><span class="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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="kt">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++"><div class="highlight"><pre><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="kt">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="kt">gray_cs_t</span><span class="p">,</span><span class="kt">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="kt">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="kt">rgb_cs_t</span><span class="p">,</span><span class="kt">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="kt">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="kt">rgb_channel_t</span><span class="p">;</span>
|
|
|
|
<span class="kt">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="kt">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="kt">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="kt">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="kt">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="kt">rgb32f_planar_view_t</span> <span class="n">rpv32</span><span class="p">;</span>
|
|
<span class="kt">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 <tt class="docutils literal"><span class="pre">PixelConcept</span></tt>
|
|
and <tt class="docutils literal"><span class="pre">MutablePixelConcept</span></tt> respectively.</p>
|
|
</div>
|
|
<div class="section" id="creating-a-copy-of-an-image-with-a-safe-buffer">
|
|
<h3><a class="toc-backref" href="#id25">Creating a Copy of an Image with a Safe Buffer</a></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++"><div class="highlight"><pre><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="kt">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="kt">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 <tt class="docutils literal"><span class="pre">subimage_view</span></tt> to create a shallow image of
|
|
its center area of top left corner at (k,k) and of identical size as <tt class="docutils literal"><span class="pre">src</span></tt>, and finally we copied <tt class="docutils literal"><span class="pre">src</span></tt> into that center image. If the margin
|
|
needs initialization, we could have done it with <tt class="docutils literal"><span class="pre">fill_pixels</span></tt>. Here is how to simplify this code using
|
|
the <tt class="docutils literal"><span class="pre">copy_pixels</span></tt> algorithm:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">image::recreate</span></tt> is more efficient than <tt class="docutils literal"><span class="pre">operator=</span></tt>, 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 <tt class="docutils literal"><span class="pre">std::copy</span></tt> - when called on two identical interleaved images with no padding at the end of rows, it
|
|
simply does a <tt class="docutils literal"><span class="pre">memmove</span></tt>. For planar images it does <tt class="docutils literal"><span class="pre">memmove</span></tt> for each channel. If one of the images has padding, (as in
|
|
our case) it will try to do <tt class="docutils literal"><span class="pre">memmove</span></tt> 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><a class="toc-backref" href="#id26">Histogram</a></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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">boost::lambda</span></tt> and GIL’s <tt class="docutils literal"><span class="pre">for_each_pixel</span></tt> algorithm, we can write this more compactly:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">for_each_pixel</span></tt> invokes <tt class="docutils literal"><span class="pre">std::for_each</span></tt> and <tt class="docutils literal"><span class="pre">var</span></tt> and <tt class="docutils literal"><span class="pre">_1</span></tt> are <tt class="docutils literal"><span class="pre">boost::lambda</span></tt> constructs.
|
|
To compute the luminosity histogram, we call the above method using the grayscale view of an image:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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><a class="toc-backref" href="#id27">Using Image Views</a></h3>
|
|
<p>The following code illustrates the power of using image views:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="kt">rgb8_view_t</span><span class="p">,</span><span class="kt">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 <tt class="docutils literal"><span class="pre">jpeg_write_view</span></tt>.
|
|
If we call our <tt class="docutils literal"><span class="pre">luminosity_histogram</span></tt> with <tt class="docutils literal"><span class="pre">step5</span></tt> it will do the right thing.</p>
|
|
</div>
|
|
</div>
|
|
<div class="section" id="extending-the-generic-image-library">
|
|
<h2><a class="toc-backref" href="#id28">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><a class="toc-backref" href="#id29">Defining New Color Spaces</a></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><a class="toc-backref" href="#id30">Defining New Channel Types</a></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++"><div class="highlight"><pre><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="kt">rgb_layout_t</span><span class="o">></span> <span class="kt">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="kt">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="kt">rgb_layout_t</span><span class="o">>::</span><span class="n">type</span> <span class="kt">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 <tt class="docutils literal"><span class="pre">channel_traits</span></tt> 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 <tt class="docutils literal"><span class="pre">channel_convert</span></tt>.</p>
|
|
</div>
|
|
<div class="section" id="overloading-color-conversion">
|
|
<h3><a class="toc-backref" href="#id31">Overloading Color Conversion</a></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++"><div class="highlight"><pre><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="n">my_color_converter_impl</span>
|
|
<span class="o">:</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="kt">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="kt">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="kt">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="kt">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++"><div class="highlight"><pre><span class="n">color_converted_view</span><span class="o"><</span><span class="kt">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><a class="toc-backref" href="#id32">Defining New Image Views</a></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 <tt class="docutils literal"><span class="pre">color_converted_view</span></tt> (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 <tt class="docutils literal"><span class="pre">PixelDereferenceAdaptorConcept</span></tt>; a function object that will be called when we dereference a pixel iterator.
|
|
It will call <tt class="docutils literal"><span class="pre">color_convert</span></tt> to convert to the destination pixel type:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="nl">public:</span>
|
|
<span class="k">typedef</span> <span class="n">color_convert_deref_fn</span> <span class="kt">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="k">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 <tt class="docutils literal"><span class="pre">add_deref</span></tt> member struct of image views to construct the type of a view that invokes a given function object (<tt class="docutils literal"><span class="pre">deref_t</span></tt>) upon
|
|
dereferencing. In our case, it performs color conversion:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="nl">private:</span>
|
|
<span class="k">typedef</span> <span class="k">typename</span> <span class="n">SrcView</span><span class="o">::</span><span class="kt">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="kt">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="kt">deref_t</span><span class="o">></span> <span class="kt">add_ref_t</span><span class="p">;</span>
|
|
<span class="nl">public:</span>
|
|
<span class="k">typedef</span> <span class="k">typename</span> <span class="kt">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="kt">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="kt">deref_t</span><span class="p">());</span> <span class="p">}</span>
|
|
<span class="p">};</span>
|
|
</pre></div>
|
|
</div>
|
|
<p>Finally our <tt class="docutils literal"><span class="pre">color_converted_view</span></tt> code simply creates color-converted view from the source view:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="#id33">Technicalities</a></h2>
|
|
<div class="section" id="creating-a-reference-proxy">
|
|
<h3><a class="toc-backref" href="#id34">Creating a reference proxy</a></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 (<tt class="docutils literal"><span class="pre">planar_pixel_reference</span></tt>) 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++"><div class="highlight"><pre><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++"><div class="highlight"><pre><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:
|
|
- Use const qualifier on all members of the reference proxy object:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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>
|
|
<ul>
|
|
<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++"><div class="highlight"><pre><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 <tt class="docutils literal"><span class="pre">swap</span></tt> for your reference class. The default <tt class="docutils literal"><span class="pre">std::swap</span></tt> 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 <tt class="docutils literal"><span class="pre">swap</span></tt> function is incorrectly called qualified, as <tt class="docutils literal"><span class="pre">std::swap</span></tt>.
|
|
The only way for these STL algorithms to use your overload is if you define it in the <tt class="docutils literal"><span class="pre">std</span></tt> namespace:</p>
|
|
<div class="highlight-c++"><div class="highlight"><pre><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="#id35">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> |