1 2 3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 4 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 5<html xmlns="http://www.w3.org/1999/xhtml"> 6 <head> 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 8 9 <title>Dynamic images and image views - Boost.GIL documentation</title> 10 <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> 11 <link rel="stylesheet" href="../_static/style.css" type="text/css" /> 12 <script type="text/javascript"> 13 var DOCUMENTATION_OPTIONS = { 14 URL_ROOT: '../', 15 VERSION: '', 16 COLLAPSE_MODINDEX: false, 17 FILE_SUFFIX: '.html' 18 }; 19 </script> 20 <script type="text/javascript" src="../_static/jquery.js"></script> 21 <script type="text/javascript" src="../_static/underscore.js"></script> 22 <script type="text/javascript" src="../_static/doctools.js"></script> 23 <link rel="index" title="Index" href="../genindex.html" /> 24 <link rel="search" title="Search" href="../search.html" /> 25 <link rel="top" title="Boost.GIL documentation" href="../index.html" /> 26 <link rel="up" title="Design Guide" href="index.html" /> 27 <link rel="next" title="Metafunctions" href="metafunctions.html" /> 28 <link rel="prev" title="Image" href="image.html" /> 29 </head> 30 <body> 31 <div class="header"> 32 <table border="0" cellpadding="7" cellspacing="0" width="100%" summary= 33 "header"> 34 <tr> 35 <td valign="top" width="300"> 36 <h3><a href="../index.html"><img 37 alt="C++ Boost" src="../_static/gil.png" border="0"></a></h3> 38 </td> 39 40 <td > 41 <h1 align="center"><a href="../index.html"></a></h1> 42 </td> 43 <td> 44 <div id="searchbox" style="display: none"> 45 <form class="search" action="../search.html" method="get"> 46 <input type="text" name="q" size="18" /> 47 <input type="submit" value="Search" /> 48 <input type="hidden" name="check_keywords" value="yes" /> 49 <input type="hidden" name="area" value="default" /> 50 </form> 51 </div> 52 <script type="text/javascript">$('#searchbox').show(0);</script> 53 </td> 54 </tr> 55 </table> 56 </div> 57 <hr/> 58 <div class="content"> 59 <div class="navbar" style="text-align:right;"> 60 61 62 <a class="prev" title="Image" href="image.html"><img src="../_static/prev.png" alt="prev"/></a> 63 <a class="up" title="Design Guide" href="index.html"><img src="../_static/up.png" alt="up"/></a> 64 <a class="next" title="Metafunctions" href="metafunctions.html"><img src="../_static/next.png" alt="next"/></a> 65 66 </div> 67 68 <div class="section" id="dynamic-images-and-image-views"> 69<h1>Dynamic images and image views</h1> 70<p>The GIL extension called <code class="docutils literal"><span class="pre">dynamic_image</span></code> allows for images, image views 71or any GIL constructs to have their parameters defined at run time.</p> 72<p>The color space, channel depth, channel ordering, and interleaved/planar 73structure of an image are defined by the type of its template argument, which 74makes them compile-time bound. Often some of these parameters are available 75only at run time. Consider, for example, writing a module that opens the image 76at a given file path, rotates it and saves it back in its original color space 77and channel depth. How can we possibly write this using our generic image? 78What type is the image loading code supposed to return?</p> 79<p>Here is an example:</p> 80<div class="highlight-cpp"><div class="highlight"><pre><span class="cp">#include</span> <span class="cpf"><boost/gil/extension/dynamic_image/dynamic_image_all.hpp></span><span class="cp"></span> 81<span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="p">;</span> 82 83<span class="cp">#define ASSERT_SAME(A,B) static_assert(is_same< A,B >::value, "")</span> 84 85<span class="c1">// Create any_image class (or any_image_view) class with a set of allowed images</span> 86<span class="k">typedef</span> <span class="n">any_image</span><span class="o"><</span><span class="n">rgb8_image_t</span><span class="p">,</span> <span class="n">cmyk16_planar_image_t</span><span class="o">></span> <span class="n">my_any_image_t</span><span class="p">;</span> 87 88<span class="c1">// Associated view types are available (equivalent to the ones in image_t)</span> 89<span class="k">typedef</span> <span class="n">any_image_view</span><span class="o"><</span><span class="n">rgb8_view_t</span><span class="p">,</span> <span class="n">cmyk16_planar_view_t</span><span class="o">></span> <span class="n">AV</span><span class="p">;</span> 90<span class="n">ASSERT_SAME</span><span class="p">(</span><span class="n">my_any_image_t</span><span class="o">::</span><span class="n">view_t</span><span class="p">,</span> <span class="n">AV</span><span class="p">);</span> 91 92<span class="k">typedef</span> <span class="n">any_image_view</span><span class="o"><</span><span class="n">rgb8c_view_t</span><span class="p">,</span> <span class="n">cmyk16c_planar_view_t</span><span class="o">>></span> <span class="n">CAV</span><span class="p">;</span> 93<span class="n">ASSERT_SAME</span><span class="p">(</span><span class="n">my_any_image_t</span><span class="o">::</span><span class="n">const_view_t</span><span class="p">,</span> <span class="n">CAV</span><span class="p">);</span> 94<span class="n">ASSERT_SAME</span><span class="p">(</span><span class="n">my_any_image_t</span><span class="o">::</span><span class="n">const_view_t</span><span class="p">,</span> <span class="n">my_any_image_t</span><span class="o">::</span><span class="n">view_t</span><span class="o">::</span><span class="n">const_t</span><span class="p">);</span> 95 96<span class="k">typedef</span> <span class="n">any_image_view</span><span class="o"><</span><span class="n">rgb8_step_view_t</span><span class="p">,</span> <span class="n">cmyk16_planar_step_view_t</span><span class="o">></span> <span class="n">SAV</span><span class="p">;</span> 97<span class="n">ASSERT_SAME</span><span class="p">(</span><span class="k">typename</span> <span class="n">dynamic_x_step_type</span><span class="o"><</span><span class="n">my_any_image_t</span><span class="o">::</span><span class="n">view_t</span><span class="o">>::</span><span class="n">type</span><span class="p">,</span> <span class="n">SAV</span><span class="p">);</span> 98 99<span class="c1">// Assign it a concrete image at run time:</span> 100<span class="n">my_any_image_t</span> <span class="n">myImg</span> <span class="o">=</span> <span class="n">my_any_image_t</span><span class="p">(</span><span class="n">rgb8_image_t</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">100</span><span class="p">));</span> 101 102<span class="c1">// Change it to another at run time. The previous image gets destroyed</span> 103<span class="n">myImg</span> <span class="o">=</span> <span class="n">cmyk16_planar_image_t</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span><span class="mi">100</span><span class="p">);</span> 104 105<span class="c1">// Assigning to an image not in the allowed set throws an exception</span> 106<span class="n">myImg</span> <span class="o">=</span> <span class="n">gray8_image_t</span><span class="p">();</span> <span class="c1">// will throw std::bad_cast</span> 107</pre></div> 108</div> 109<p>The <code class="docutils literal"><span class="pre">any_image</span></code> and <code class="docutils literal"><span class="pre">any_image_view</span></code> subclass from Boost.Variant2 <code class="docutils literal"><span class="pre">variant</span></code> class, 110a never valueless variant type, compatible with <code class="docutils literal"><span class="pre">std::variant</span></code> in C++17.</p> 111<p>GIL <code class="docutils literal"><span class="pre">any_image_view</span></code> and <code class="docutils literal"><span class="pre">any_image</span></code> are subclasses of <code class="docutils literal"><span class="pre">variant</span></code>:</p> 112<div class="highlight-cpp"><div class="highlight"><pre><span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="p">...</span><span class="n">ImageViewTypes</span><span class="o">></span> 113<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="p">...</span><span class="o">></span> 114<span class="p">{</span> 115<span class="k">public</span><span class="o">:</span> 116 <span class="k">typedef</span> <span class="p">...</span> <span class="n">const_t</span><span class="p">;</span> <span class="c1">// immutable equivalent of this</span> 117 <span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">x_coord_t</span><span class="p">;</span> 118 <span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">y_coord_t</span><span class="p">;</span> 119 <span class="k">typedef</span> <span class="n">point</span><span class="o"><</span><span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span><span class="o">></span> <span class="n">point_t</span><span class="p">;</span> 120 <span class="k">using</span> <span class="n">size_type</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="p">;</span> 121 122 <span class="n">any_image_view</span><span class="p">();</span> 123 <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> 124 <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> 125 126 <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> 127 <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> 128 129 <span class="c1">// parameters of the currently instantiated view</span> 130 <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> 131 <span class="n">point_t</span> <span class="nf">dimensions</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> 132 <span class="n">size_type</span> <span class="nf">size</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> 133 <span class="n">x_coord_t</span> <span class="nf">width</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> 134 <span class="n">y_coord_t</span> <span class="nf">height</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> 135<span class="p">};</span> 136 137<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="p">...</span><span class="n">ImageTypes</span><span class="o">></span> 138<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="p">...</span><span class="o">></span> 139<span class="p">{</span> 140<span class="k">public</span><span class="o">:</span> 141 <span class="k">typedef</span> <span class="p">...</span> <span class="n">const_view_t</span><span class="p">;</span> 142 <span class="k">typedef</span> <span class="p">...</span> <span class="n">view_t</span><span class="p">;</span> 143 <span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">x_coord_t</span><span class="p">;</span> 144 <span class="k">typedef</span> <span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span> <span class="n">y_coord_t</span><span class="p">;</span> 145 <span class="k">typedef</span> <span class="n">point</span><span class="o"><</span><span class="n">std</span><span class="o">::</span><span class="kt">ptrdiff_t</span><span class="o">></span> <span class="n">point_t</span><span class="p">;</span> 146 147 <span class="n">any_image</span><span class="p">();</span> 148 <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> 149 <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> 150 <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> 151 152 <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> 153 <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> 154 155 <span class="kt">void</span> <span class="nf">recreate</span><span class="p">(</span><span class="k">const</span> <span class="n">point_t</span><span class="o">&</span> <span class="n">dims</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">alignment</span><span class="o">=</span><span class="mi">1</span><span class="p">);</span> 156 <span class="kt">void</span> <span class="nf">recreate</span><span class="p">(</span><span class="n">x_coord_t</span> <span class="n">width</span><span class="p">,</span> <span class="n">y_coord_t</span> <span class="n">height</span><span class="p">,</span> <span class="kt">unsigned</span> <span class="n">alignment</span><span class="o">=</span><span class="mi">1</span><span class="p">);</span> 157 158 <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> 159 <span class="n">point_t</span> <span class="nf">dimensions</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> 160 <span class="n">x_coord_t</span> <span class="nf">width</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> 161 <span class="n">y_coord_t</span> <span class="nf">height</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> 162<span class="p">};</span> 163</pre></div> 164</div> 165<p>Operations are invoked on variants via <code class="docutils literal"><span class="pre">apply_operation</span></code> passing a 166function object to perform the operation. The code for every allowed 167type in the variant is instantiated and the appropriate instantiation 168is selected via a switch statement. Since image view algorithms 169typically have time complexity at least linear on the number of 170pixels, the single switch statement of image view variant adds 171practically no measurable performance overhead compared to templated 172image views.</p> 173<p>Variants behave like the underlying type. Their copy constructor will 174invoke the copy constructor of the underlying instance. Equality 175operator will check if the two instances are of the same type and then 176invoke their <code class="docutils literal"><span class="pre">operator==</span></code>, etc. The default constructor of a variant 177will default-construct the first type. That means that 178<code class="docutils literal"><span class="pre">any_image_view</span></code> has shallow default-constructor, copy-constructor, 179assignment and equality comparison, whereas <code class="docutils literal"><span class="pre">any_image</span></code> has deep 180ones.</p> 181<p>It is important to note that even though <code class="docutils literal"><span class="pre">any_image_view</span></code> and 182<code class="docutils literal"><span class="pre">any_image</span></code> resemble the static <code class="docutils literal"><span class="pre">image_view</span></code> and <code class="docutils literal"><span class="pre">image</span></code>, they 183do not model the full requirements of <code class="docutils literal"><span class="pre">ImageViewConcept</span></code> and 184<code class="docutils literal"><span class="pre">ImageConcept</span></code>. In particular they don’t provide access to the 185pixels. There is no “any_pixel” or “any_pixel_iterator” in GIL. Such 186constructs could be provided via the <code class="docutils literal"><span class="pre">variant</span></code> mechanism, but doing 187so would result in inefficient algorithms, since the type resolution 188would have to be performed per pixel. Image-level algorithms should be 189implemented via <code class="docutils literal"><span class="pre">apply_operation</span></code>. That said, many common operations 190are shared between the static and dynamic types. In addition, all of 191the image view transformations and many STL-like image view algorithms 192have overloads operating on <code class="docutils literal"><span class="pre">any_image_view</span></code>, as illustrated with 193<code class="docutils literal"><span class="pre">copy_pixels</span></code>:</p> 194<div class="highlight-cpp"><div class="highlight"><pre><span class="n">rgb8_view_t</span> <span class="nf">v1</span><span class="p">(...);</span> <span class="c1">// concrete image view</span> 195<span class="n">bgr8_view_t</span> <span class="nf">v2</span><span class="p">(...);</span> <span class="c1">// concrete image view compatible with v1 and of the same size</span> 196<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> 197 198<span class="c1">// Copies the pixels from v1 into v2.</span> 199<span class="c1">// If the pixels are incompatible triggers compile error</span> 200<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> 201 202<span class="c1">// The source or destination (or both) may be run-time instantiated.</span> 203<span class="c1">// If they happen to be incompatible, throws std::bad_cast</span> 204<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> 205<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> 206<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> 207</pre></div> 208</div> 209<p>By having algorithm overloads supporting dynamic constructs, we create 210a base upon which it is possible to write algorithms that can work 211with either compile-time or runtime images or views. The following 212code, for example, uses the GIL I/O extension to turn an image on disk 213upside down:</p> 214<div class="highlight-cpp"><div class="highlight"><pre><span class="cp">#include</span> <span class="cpf"><boost\gil\extension\io\jpeg_dynamic_io.hpp></span><span class="cp"></span> 215 216<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> 217<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> 218<span class="p">{</span> 219 <span class="n">Image</span> <span class="n">img</span><span class="p">;</span> 220 <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> 221 <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> 222<span class="p">}</span> 223</pre></div> 224</div> 225<p>It can be instantiated with either a compile-time or a runtime image 226because all functions it uses have overloads taking runtime 227constructs. For example, here is how <code class="docutils literal"><span class="pre">rotated180_view</span></code> is 228implemented:</p> 229<div class="highlight-cpp"><div class="highlight"><pre><span class="c1">// implementation using templated view</span> 230<span class="k">template</span> <span class="o"><</span><span class="k">typename</span> <span class="n">View</span><span class="o">></span> 231<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> 232 233<span class="k">namespace</span> <span class="n">detail</span> 234<span class="p">{</span> 235 <span class="c1">// the function, wrapped inside a function object</span> 236 <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> 237 <span class="p">{</span> 238 <span class="k">typedef</span> <span class="n">Result</span> <span class="n">result_type</span><span class="p">;</span> 239 <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> 240<span class="p">{</span> 241 <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> 242 <span class="p">}</span> 243 <span class="p">};</span> 244<span class="p">}</span> 245 246<span class="c1">// overloading of the function using variant. Takes and returns run-time bound view.</span> 247<span class="c1">// The returned view has a dynamic step</span> 248<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> 249<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> 250<span class="p">{</span> 251 <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> 252<span class="p">}</span> 253</pre></div> 254</div> 255<p>Variants should be used with caution (especially algorithms that take 256more than one variant) because they instantiate the algorithm for 257every possible model that the variant can take. This can take a toll 258on compile time and executable size. Despite these limitations, 259<code class="docutils literal"><span class="pre">variant</span></code> is a powerful technique that allows us to combine the 260speed of compile-time resolution with the flexibility of run-time 261resolution. It allows us to treat images of different parameters 262uniformly as a collection and store them in the same container.</p> 263</div> 264 265 266 <div class="navbar" style="text-align:right;"> 267 268 269 <a class="prev" title="Image" href="image.html"><img src="../_static/prev.png" alt="prev"/></a> 270 <a class="up" title="Design Guide" href="index.html"><img src="../_static/up.png" alt="up"/></a> 271 <a class="next" title="Metafunctions" href="metafunctions.html"><img src="../_static/next.png" alt="next"/></a> 272 273 </div> 274 </div> 275 <div class="footer" role="contentinfo"> 276 Last updated on 2020-08-11 15:08:48. 277 Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.5.6. 278 </div> 279 </body> 280</html>