Imported Upstream version 1.71.0
[platform/upstream/boost.git] / libs / gil / doc / design_guide.rst
1 Design Guide
2 ============
3
4 .. contents::
5    :local:
6    :depth: 1
7
8 Overview
9 --------
10 Images are essential in any image processing, vision and video
11 project, and yet the variability in image representations makes it
12 difficult to write imaging algorithms that are both generic and
13 efficient. In this section we will describe some of the challenges
14 that we would like to address.
15
16 In the following discussion an *image* is a 2D array of pixels. A
17 *pixel* is a set of color channels that represents the color at a
18 given point in an image. Each *channel* represents the value of a
19 color component.  There are two common memory structures for an
20 image. *Interleaved* images are represented by grouping the pixels
21 together in memory and interleaving all channels together, whereas
22 *planar* images keep the channels in separate color planes. Here is a
23 4x3 RGB image in which the second pixel of the first row is marked in
24 red, in interleaved form:
25
26 .. image:: images/interleaved.jpg
27
28 and in planar form:
29
30 .. image:: images/planar.jpg
31
32 Note also that rows may optionally be aligned resulting in a potential
33 padding at the end of rows.
34
35 The Generic Image Library (GIL) provides models for images that vary in:
36
37 * Structure (planar vs. interleaved)
38 * Color space and presence of alpha (RGB, RGBA, CMYK, etc.)
39 * Channel depth (8-bit, 16-bit, etc.)
40 * Order of channels (RGB vs. BGR, etc.)
41 * Row alignment policy (no alignment, word-alignment, etc.)
42
43 It also supports user-defined models of images, and images whose
44 parameters are specified at run-time.  GIL abstracts image
45 representation from algorithms applied on images and allows us to
46 write the algorithm once and have it work on any of the above image
47 variations while generating code that is comparable in speed to that
48 of hand-writing the algorithm for a specific image type.
49
50 This document follows bottom-up design. Each section defines concepts
51 that build on top of concepts defined in previous sections.  It is
52 recommended to read the sections in order.
53
54 About Concepts
55 --------------
56
57 All constructs in GIL are models of GIL concepts. A *concept* is a
58 set of requirements that a type (or a set of related types) must
59 fulfill to be used correctly in generic algorithms. The requirements
60 include syntactic and algorithmic guarantees.  For example, GIL's
61 class ``pixel`` is a model of GIL's ``PixelConcept``. The user may
62 substitute the pixel class with one of their own, and, as long as it
63 satisfies the requirements of ``PixelConcept``, all other GIL classes
64 and algorithms can be used with it. See more about concepts here:
65 http://www.generic-programming.org/languages/conceptcpp/
66
67 In this document we will use a syntax for defining concepts that is
68 described in a proposal for a Concepts extension to C++0x specified
69 here:
70 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf
71
72 Here are some common concepts that will be used in GIL. Most of them
73 are defined here:
74 http://www.generic-programming.org/languages/conceptcpp/concept_web.php
75 ::
76
77   auto concept DefaultConstructible<typename T>
78   {
79     T::T();
80   };
81
82   auto concept CopyConstructible<typename T>
83   {
84     T::T(T);
85     T::~T();
86   };
87
88   auto concept Assignable<typename T, typename U = T>
89   {
90     typename result_type;
91     result_type operator=(T&, U);
92   };
93
94   auto concept EqualityComparable<typename T, typename U = T>
95   {
96     bool operator==(T x, T y);
97     bool operator!=(T x, T y) { return !(x==y); }
98   };
99
100   concept SameType<typename T, typename U> { /* unspecified */ };
101   template<typename T> concept_map SameType<T, T> { /* unspecified */ };
102
103   auto concept Swappable<typename T>
104   {
105     void swap(T& t, T& u);
106   };
107
108 Here are some additional basic concepts that GIL needs::
109
110   auto concept Regular<typename T> : DefaultConstructible<T>, CopyConstructible<T>, EqualityComparable<T>, Assignable<T>, Swappable<T> {};
111
112   auto concept Metafunction<typename T>
113   {
114     typename type;
115   };
116
117 Point
118 -----
119
120 A point defines the location of a pixel inside an image. It can also
121 be used to describe the dimensions of an image.  In most general
122 terms, points are N-dimensional and model the following concept::
123
124   concept PointNDConcept<typename T> : Regular<T>
125   {
126     // the type of a coordinate along each axis
127     template <size_t K> struct axis; where Metafunction<axis>;
128
129     const size_t num_dimensions;
130
131     // accessor/modifier of the value of each axis.
132     template <size_t K> const typename axis<K>::type& T::axis_value() const;
133     template <size_t K>       typename axis<K>::type& T::axis_value();
134   };
135
136 GIL uses a two-dimensional point, which is a refinement of
137 ``PointNDConcept`` in which both dimensions are of the same type::
138
139   concept Point2DConcept<typename T> : PointNDConcept<T>
140   {
141     where num_dimensions == 2;
142     where SameType<axis<0>::type, axis<1>::type>;
143
144     typename value_type = axis<0>::type;
145
146     const value_type& operator[](const T&, size_t i);
147           value_type& operator[](      T&, size_t i);
148
149     value_type x,y;
150   };
151
152 .. seealso::
153    - `PointNDConcept <reference/structboost_1_1gil_1_1_point_n_d_concept.html>`_
154    - `Point2DConcept <reference/structboost_1_1gil_1_1_point2_d_concept.html>`_
155
156 Models
157 ~~~~~~
158
159 GIL provides a model of ``Point2DConcept``, ``point<T>`` where
160 ``T`` is the coordinate type.
161
162 Channel
163 -------
164
165 A channel indicates the intensity of a color component (for example,
166 the red channel in an RGB pixel).  Typical channel operations are
167 getting, comparing and setting the channel values. Channels have
168 associated minimum and maximum value. GIL channels model the following
169 concept::
170
171   concept ChannelConcept<typename T> : EqualityComparable<T>
172   {
173     typename value_type      = T;        // use channel_traits<T>::value_type to access it
174        where ChannelValueConcept<value_type>;
175     typename reference       = T&;       // use channel_traits<T>::reference to access it
176     typename pointer         = T*;       // use channel_traits<T>::pointer to access it
177     typename const_reference = const T&; // use channel_traits<T>::const_reference to access it
178     typename const_pointer   = const T*; // use channel_traits<T>::const_pointer to access it
179     static const bool is_mutable;        // use channel_traits<T>::is_mutable to access it
180
181     static T min_value();                // use channel_traits<T>::min_value to access it
182     static T max_value();                // use channel_traits<T>::min_value to access it
183   };
184
185   concept MutableChannelConcept<ChannelConcept T> : Swappable<T>, Assignable<T> {};
186
187   concept ChannelValueConcept<ChannelConcept T> : Regular<T> {};
188
189 GIL allows built-in integral and floating point types to be
190 channels. Therefore the associated types and range information are
191 defined in ``channel_traits`` with the following default
192 implementation::
193
194   template <typename T>
195   struct channel_traits
196   {
197     typedef T         value_type;
198     typedef T&        reference;
199     typedef T*        pointer;
200     typedef T& const  const_reference;
201     typedef T* const  const_pointer;
202
203     static value_type min_value() { return std::numeric_limits<T>::min(); }
204     static value_type max_value() { return std::numeric_limits<T>::max(); }
205   };
206
207 Two channel types are *compatible* if they have the same value type::
208
209   concept ChannelsCompatibleConcept<ChannelConcept T1, ChannelConcept T2>
210   {
211     where SameType<T1::value_type, T2::value_type>;
212   };
213
214 A channel may be *convertible* to another channel::
215
216   template <ChannelConcept Src, ChannelValueConcept Dst>
217   concept ChannelConvertibleConcept
218   {
219     Dst channel_convert(Src);
220   };
221
222 Note that ``ChannelConcept`` and ``MutableChannelConcept`` do not
223 require a default constructor. Channels that also support default
224 construction (and thus are regular types) model
225 ``ChannelValueConcept``. To understand the motivation for this
226 distinction, consider a 16-bit RGB pixel in a "565" bit pattern. Its
227 channels correspond to bit ranges. To support such channels, we need
228 to create a custom proxy class corresponding to a reference to a
229 sub-byte channel.  Such a proxy reference class models only
230 ``ChannelConcept``, because, similar to native C++ references, it may
231 not have a default constructor.
232
233 Note also that algorithms may impose additional requirements on
234 channels, such as support for arithmetic operations.
235
236 .. seealso::
237    - `ChannelConcept<T> <reference/structboost_1_1gil_1_1_channel_concept.html>`_
238    - `ChannelValueConcept<T> <reference/structboost_1_1gil_1_1_channel_value_concept.html>`_
239    - `MutableChannelConcept<T> <reference/structboost_1_1gil_1_1_mutable_channel_concept.html>`_
240    - `ChannelsCompatibleConcept<T1,T2> <reference/structboost_1_1gil_1_1_channels_compatible_concept.html>`_
241    - `ChannelConvertibleConcept<SrcChannel,DstChannel> <reference/structboost_1_1gil_1_1_channel_convertible_concept.html>`_
242
243 Models
244 ~~~~~~
245
246 All C++11 fundamental integer and float point types are valid channels.
247
248 The minimum and maximum values of a channel modeled by a built-in type
249 correspond to the minimum and maximum physical range of the built-in
250 type, as specified by its ``std::numeric_limits``. Sometimes the
251 physical range is not appropriate. GIL provides
252 ``scoped_channel_value``, a model for a channel adapter that allows
253 for specifying a custom range. We use it to define a [0..1] floating
254 point channel type as follows::
255
256   struct float_zero { static float apply() { return 0.0f; } };
257   struct float_one  { static float apply() { return 1.0f; } };
258   typedef scoped_channel_value<float,float_zero,float_one> bits32f;
259
260 GIL also provides models for channels corresponding to ranges of bits::
261
262   // Value of a channel defined over NumBits bits. Models ChannelValueConcept
263   template <int NumBits> class packed_channel_value;
264
265   // Reference to a channel defined over NumBits bits. Models ChannelConcept
266   template <int FirstBit,
267           int NumBits,       // Defines the sequence of bits in the data value that contain the channel
268           bool Mutable>      // true if the reference is mutable
269   class packed_channel_reference;
270
271   // Reference to a channel defined over NumBits bits. Its FirstBit is a run-time parameter. Models ChannelConcept
272   template <int NumBits,       // Defines the sequence of bits in the data value that contain the channel
273           bool Mutable>      // true if the reference is mutable
274   class packed_dynamic_channel_reference;
275
276 Note that there are two models of a reference proxy which differ based
277 on whether the offset of the channel range is specified as a template
278 or a run-time parameter. The first model is faster and more compact
279 while the second model is more flexible. For example, the second model
280 allows us to construct an iterator over bit range channels.
281
282 Algorithms
283 ~~~~~~~~~~
284
285 Here is how to construct the three channels of a 16-bit "565" pixel
286 and set them to their maximum value::
287
288   typedef packed_channel_reference<0,5,true> channel16_0_5_reference_t;
289   typedef packed_channel_reference<5,6,true> channel16_5_6_reference_t;
290   typedef packed_channel_reference<11,5,true> channel16_11_5_reference_t;
291
292   boost::uint16_t data=0;
293   channel16_0_5_reference_t   channel1(&data);
294   channel16_5_6_reference_t   channel2(&data);
295   channel16_11_5_reference_t  channel3(&data);
296
297   channel1=channel_traits<channel16_0_5_reference_t>::max_value();
298   channel2=channel_traits<channel16_5_6_reference_t>::max_value();
299   channel3=channel_traits<channel16_11_5_reference_t>::max_value();
300   assert(data==65535);
301
302 Assignment, equality comparison and copy construction are defined only
303 between compatible channels::
304
305   packed_channel_value<5> channel_6bit = channel1;
306   channel_6bit = channel3;
307
308   //channel_6bit = channel2; // compile error: Assignment between incompatible channels.
309
310 All channel models provided by GIL are pairwise convertible::
311
312   channel1 = channel_traits<channel16_0_5_reference_t>::max_value();
313   assert(channel1 == 31);
314
315   bits16 chan16 = channel_convert<bits16>(channel1);
316   assert(chan16 == 65535);
317
318 Channel conversion is a lossy operation. GIL's channel conversion is a
319 linear transformation between the ranges of the source and destination
320 channel.  It maps precisely the minimum to the minimum and the maximum
321 to the maximum. (For example, to convert from uint8_t to uint16_t GIL
322 does not do a bit shift because it will not properly match the maximum
323 values. Instead GIL multiplies the source by 257).
324
325 All channel models that GIL provides are convertible from/to an
326 integral or floating point type. Thus they support arithmetic
327 operations.  Here are the channel-level algorithms that GIL provides::
328
329   // Converts a source channel value into a destination channel.
330   // Linearly maps the value of the source into the range of the destination.
331   template <typename DstChannel, typename SrcChannel>
332   typename channel_traits<DstChannel>::value_type channel_convert(SrcChannel src);
333
334   // returns max_value - x + min_value
335   template <typename Channel>
336   typename channel_traits<Channel>::value_type channel_invert(Channel x);
337
338   // returns a * b / max_value
339   template <typename Channel>
340   typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b);
341
342 Color Space and Layout
343 ----------------------
344
345 A color space captures the set and interpretation of channels comprising
346 a pixel. In Boost.GIL, color space is defined as an MPL random access
347 sequence containing the types of all elements in the color space.
348
349 Two color spaces are considered *compatible* if they are equal
350 (i.e. have the same set of colors in the same order).
351
352 .. seealso::
353    - `ColorSpaceConcept<ColorSpace> <reference/structboost_1_1gil_1_1_color_space_concept.html>`_
354    - `ColorSpacesCompatibleConcept<ColorSpace1,ColorSpace2> <reference/structboost_1_1gil_1_1_color_spaces_compatible_concept.html>`_
355    - `ChannelMappingConcept<Mapping> <reference/structboost_1_1gil_1_1_channel_mapping_concept.html>`_
356
357 Models
358 ~~~~~~
359
360 GIL currently provides the following color spaces:
361
362 - ``gray_t``
363 - ``rgb_t``
364 - ``rgba_t``
365 - ``cmyk_t``
366
367 It also provides unnamed N-channel color spaces of two to five channels:
368
369 - ``devicen_t<2>``
370 - ``devicen_t<3>``
371 - ``devicen_t<4>``
372 - ``devicen_t<5>``
373
374 Besides the standard layouts, it also provides:
375
376 - ``bgr_layout_t``
377 - ``bgra_layout_t``
378 - ``abgr_layout_t``
379 - ``argb_layout_t``
380
381 As an example, here is how GIL defines the RGBA color space::
382
383   struct red_t{};
384   struct green_t{};
385   struct blue_t{};
386   struct alpha_t{};
387   typedef mpl::vector4<red_t,green_t,blue_t,alpha_t> rgba_t;
388
389 The ordering of the channels in the color space definition specifies
390 their semantic order. For example, ``red_t`` is the first semantic
391 channel of ``rgba_t``.  While there is a unique semantic ordering of
392 the channels in a color space, channels may vary in their physical
393 ordering in memory
394
395 The mapping of channels is specified by ``ChannelMappingConcept``,
396 which is an MPL random access sequence of integral types.
397 A color space and its associated mapping are often used together.
398
399 Thus they are grouped in GIL's layout::
400
401   template <typename ColorSpace,
402           typename ChannelMapping = mpl::range_c<int,0,mpl::size<ColorSpace>::value> >
403   struct layout
404   {
405     typedef ColorSpace      color_space_t;
406     typedef ChannelMapping  channel_mapping_t;
407   };
408
409 Here is how to create layouts for the RGBA color space::
410
411   typedef layout<rgba_t> rgba_layout_t; // default ordering is 0,1,2,3...
412   typedef layout<rgba_t, mpl::vector4_c<int,2,1,0,3> > bgra_layout_t;
413   typedef layout<rgba_t, mpl::vector4_c<int,1,2,3,0> > argb_layout_t;
414   typedef layout<rgba_t, mpl::vector4_c<int,3,2,1,0> > abgr_layout_t;
415
416 Color Base
417 ----------
418
419 A color base is a container of color elements. The most common use of
420 color base is in the implementation of a pixel, in which case the
421 color elements are channel values. The color base concept, however,
422 can be used in other scenarios. For example, a planar pixel has
423 channels that are not contiguous in memory. Its reference is a proxy
424 class that uses a color base whose elements are channel
425 references. Its iterator uses a color base whose elements are channel
426 iterators.
427
428 Color base models must satisfy the following concepts::
429
430   concept ColorBaseConcept<typename T> : CopyConstructible<T>, EqualityComparable<T>
431   {
432     // a GIL layout (the color space and element permutation)
433     typename layout_t;
434
435     // The type of K-th element
436     template <int K> struct kth_element_type;
437         where Metafunction<kth_element_type>;
438
439     // The result of at_c
440     template <int K> struct kth_element_const_reference_type;
441         where Metafunction<kth_element_const_reference_type>;
442
443     template <int K> kth_element_const_reference_type<T,K>::type at_c(T);
444
445     template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> }
446         T::T(T2);
447     template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> }
448         bool operator==(const T&, const T2&);
449     template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> }
450         bool operator!=(const T&, const T2&);
451
452   };
453
454   concept MutableColorBaseConcept<ColorBaseConcept T> : Assignable<T>, Swappable<T>
455   {
456     template <int K> struct kth_element_reference_type;
457         where Metafunction<kth_element_reference_type>;
458
459     template <int K> kth_element_reference_type<T,K>::type at_c(T);
460
461     template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> }
462         T& operator=(T&, const T2&);
463   };
464
465   concept ColorBaseValueConcept<typename T> : MutableColorBaseConcept<T>, Regular<T>
466   {
467   };
468
469   concept HomogeneousColorBaseConcept<ColorBaseConcept CB>
470   {
471     // For all K in [0 ... size<C1>::value-1):
472     //     where SameType<kth_element_type<K>::type, kth_element_type<K+1>::type>;
473     kth_element_const_reference_type<0>::type dynamic_at_c(const CB&, std::size_t n) const;
474   };
475
476   concept MutableHomogeneousColorBaseConcept<MutableColorBaseConcept CB> : HomogeneousColorBaseConcept<CB>
477   {
478     kth_element_reference_type<0>::type dynamic_at_c(const CB&, std::size_t n);
479   };
480
481   concept HomogeneousColorBaseValueConcept<typename T> : MutableHomogeneousColorBaseConcept<T>, Regular<T>
482   {
483   };
484
485   concept ColorBasesCompatibleConcept<ColorBaseConcept C1, ColorBaseConcept C2>
486   {
487     where SameType<C1::layout_t::color_space_t, C2::layout_t::color_space_t>;
488     // also, for all K in [0 ... size<C1>::value):
489     //     where Convertible<kth_semantic_element_type<C1,K>::type, kth_semantic_element_type<C2,K>::type>;
490     //     where Convertible<kth_semantic_element_type<C2,K>::type, kth_semantic_element_type<C1,K>::type>;
491   };
492
493 A color base must have an associated layout (which consists of a color
494 space, as well as an ordering of the channels).  There are two ways to
495 index the elements of a color base: A physical index corresponds to
496 the way they are ordered in memory, and a semantic index corresponds
497 to the way the elements are ordered in their color space.  For
498 example, in the RGB color space the elements are ordered as {red_t,
499 green_t, blue_t}. For a color base with a BGR layout, the first
500 element in physical ordering is the blue element, whereas the first
501 semantic element is the red one.  Models of ``ColorBaseConcept`` are
502 required to provide the ``at_c<K>(ColorBase)`` function, which allows
503 for accessing the elements based on their physical order. GIL provides
504 a ``semantic_at_c<K>(ColorBase)`` function (described later) which can
505 operate on any model of ColorBaseConcept and returns the corresponding
506 semantic element.
507
508 Two color bases are *compatible* if they have the same color space and
509 their elements (paired semantically) are convertible to each other.
510
511 Models
512 ~~~~~~
513
514 GIL provides a model for a homogeneous color base (a color base whose
515 elements all have the same type). ::
516
517   namespace detail
518   {
519     template <typename Element, typename Layout, int K> struct homogeneous_color_base;
520   }
521
522 It is used in the implementation of GIL's pixel, planar pixel
523 reference and planar pixel iterator.  Another model of
524 ``ColorBaseConcept`` is ``packed_pixel`` - it is a pixel whose
525 channels are bit ranges. See the :ref:`design_guide:Pixel` section for more.
526
527 Algorithms
528 ~~~~~~~~~~
529
530 GIL provides the following functions and metafunctions operating on
531 color bases::
532
533   // Metafunction returning an mpl::int_ equal to the number of elements in the color base
534   template <class ColorBase> struct size;
535
536   // Returns the type of the return value of semantic_at_c<K>(color_base)
537   template <class ColorBase, int K> struct kth_semantic_element_reference_type;
538   template <class ColorBase, int K> struct kth_semantic_element_const_reference_type;
539
540   // Returns a reference to the element with K-th semantic index.
541   template <class ColorBase, int K>
542   typename kth_semantic_element_reference_type<ColorBase,K>::type       semantic_at_c(ColorBase& p)
543   template <class ColorBase, int K>
544   typename kth_semantic_element_const_reference_type<ColorBase,K>::type semantic_at_c(const ColorBase& p)
545
546   // Returns the type of the return value of get_color<Color>(color_base)
547   template <typename Color, typename ColorBase> struct color_reference_t;
548   template <typename Color, typename ColorBase> struct color_const_reference_t;
549
550   // Returns a reference to the element corresponding to the given color
551   template <typename ColorBase, typename Color>
552   typename color_reference_t<Color,ColorBase>::type get_color(ColorBase& cb, Color=Color());
553   template <typename ColorBase, typename Color>
554   typename color_const_reference_t<Color,ColorBase>::type get_color(const ColorBase& cb, Color=Color());
555
556   // Returns the element type of the color base. Defined for homogeneous color bases only
557   template <typename ColorBase> struct element_type;
558   template <typename ColorBase> struct element_reference_type;
559   template <typename ColorBase> struct element_const_reference_type;
560
561 GIL also provides the following algorithms which operate on color
562 bases. Note that they all pair the elements semantically::
563
564   // Equivalents to std::equal, std::copy, std::fill, std::generate
565   template <typename CB1,typename CB2>   bool static_equal(const CB1& p1, const CB2& p2);
566   template <typename Src,typename Dst>   void static_copy(const Src& src, Dst& dst);
567   template <typename CB, typename Op>    void static_generate(CB& dst,Op op);
568
569   // Equivalents to std::transform
570   template <typename CB ,             typename Dst,typename Op> Op static_transform(      CB&,Dst&,Op);
571   template <typename CB ,             typename Dst,typename Op> Op static_transform(const CB&,Dst&,Op);
572   template <typename CB1,typename CB2,typename Dst,typename Op> Op static_transform(      CB1&,      CB2&,Dst&,Op);
573   template <typename CB1,typename CB2,typename Dst,typename Op> Op static_transform(const CB1&,      CB2&,Dst&,Op);
574   template <typename CB1,typename CB2,typename Dst,typename Op> Op static_transform(      CB1&,const CB2&,Dst&,Op);
575   template <typename CB1,typename CB2,typename Dst,typename Op> Op static_transform(const CB1&,const CB2&,Dst&,Op);
576
577   // Equivalents to std::for_each
578   template <typename CB1,                          typename Op> Op static_for_each(      CB1&,Op);
579   template <typename CB1,                          typename Op> Op static_for_each(const CB1&,Op);
580   template <typename CB1,typename CB2,             typename Op> Op static_for_each(      CB1&,      CB2&,Op);
581   template <typename CB1,typename CB2,             typename Op> Op static_for_each(      CB1&,const CB2&,Op);
582   template <typename CB1,typename CB2,             typename Op> Op static_for_each(const CB1&,      CB2&,Op);
583   template <typename CB1,typename CB2,             typename Op> Op static_for_each(const CB1&,const CB2&,Op);
584   template <typename CB1,typename CB2,typename CB3,typename Op> Op static_for_each(      CB1&,      CB2&,      CB3&,Op);
585   template <typename CB1,typename CB2,typename CB3,typename Op> Op static_for_each(      CB1&,      CB2&,const CB3&,Op);
586   template <typename CB1,typename CB2,typename CB3,typename Op> Op static_for_each(      CB1&,const CB2&,      CB3&,Op);
587   template <typename CB1,typename CB2,typename CB3,typename Op> Op static_for_each(      CB1&,const CB2&,const CB3&,Op);
588   template <typename CB1,typename CB2,typename CB3,typename Op> Op static_for_each(const CB1&,      CB2&,      CB3&,Op);
589   template <typename CB1,typename CB2,typename CB3,typename Op> Op static_for_each(const CB1&,      CB2&,const CB3&,Op);
590   template <typename CB1,typename CB2,typename CB3,typename Op> Op static_for_each(const CB1&,const CB2&,      CB3&,Op);
591   template <typename CB1,typename CB2,typename CB3,typename Op> Op static_for_each(const CB1&,const CB2&,const CB3&,Op);
592
593   // The following algorithms are only defined for homogeneous color bases:
594   // Equivalent to std::fill
595   template <typename HCB, typename Element> void static_fill(HCB& p, const Element& v);
596
597   // Equivalents to std::min_element and std::max_element
598   template <typename HCB> typename element_const_reference_type<HCB>::type static_min(const HCB&);
599   template <typename HCB> typename element_reference_type<HCB>::type       static_min(      HCB&);
600   template <typename HCB> typename element_const_reference_type<HCB>::type static_max(const HCB&);
601   template <typename HCB> typename element_reference_type<HCB>::type       static_max(      HCB&);
602
603 These algorithms are designed after the corresponding STL algorithms,
604 except that instead of ranges they take color bases and operate on
605 their elements.  In addition, they are implemented with a compile-time
606 recursion (thus the prefix "static\_"). Finally, they pair the
607 elements semantically instead of based on their physical order in
608 memory. For example, here is the implementation of ``static_equal``::
609
610   namespace detail
611   {
612     template <int K> struct element_recursion
613     {
614       template <typename P1,typename P2>
615       static bool static_equal(const P1& p1, const P2& p2)
616       {
617         return element_recursion<K-1>::static_equal(p1,p2) &&
618                semantic_at_c<K-1>(p1)==semantic_at_c<N-1>(p2);
619       }
620     };
621     template <> struct element_recursion<0>
622     {
623       template <typename P1,typename P2>
624       static bool static_equal(const P1&, const P2&) { return true; }
625     };
626   }
627
628   template <typename P1,typename P2>
629   bool static_equal(const P1& p1, const P2& p2)
630   {
631     gil_function_requires<ColorSpacesCompatibleConcept<P1::layout_t::color_space_t,P2::layout_t::color_space_t> >();
632     return detail::element_recursion<size<P1>::value>::static_equal(p1,p2);
633   }
634
635 This algorithm is used when invoking ``operator==`` on two pixels, for
636 example. By using semantic accessors we are properly comparing an RGB
637 pixel to a BGR pixel. Notice also that all of the above algorithms
638 taking more than one color base require that they all have the same
639 color space.
640
641 Pixel
642 -----
643
644 A pixel is a set of channels defining the color at a given point in an
645 image. Conceptually, a pixel is little more than a color base whose
646 elements model ``ChannelConcept``.  All properties of pixels inherit
647 from color bases: pixels may be *homogeneous* if all of their channels
648 have the same type; otherwise they are called *heterogeneous*. The
649 channels of a pixel may be addressed using semantic or physical
650 indexing, or by color; all color-base algorithms work on pixels as
651 well. Two pixels are *compatible* if their color spaces are the same
652 and their channels, paired semantically, are compatible.  Note that
653 constness, memory organization and reference/value are ignored. For
654 example, an 8-bit RGB planar reference is compatible to a constant
655 8-bit BGR interleaved pixel value. Most pairwise pixel operations
656 (copy construction, assignment, equality, etc.) are only defined for
657 compatible pixels.
658
659 Pixels (as well as other GIL constructs built on pixels, such as
660 iterators, locators, views and images) must provide metafunctions to
661 access their color space, channel mapping, number of channels, and
662 (for homogeneous pixels) the channel type::
663
664   concept PixelBasedConcept<typename T>
665   {
666     typename color_space_type<T>;
667         where Metafunction<color_space_type<T> >;
668         where ColorSpaceConcept<color_space_type<T>::type>;
669     typename channel_mapping_type<T>;
670         where Metafunction<channel_mapping_type<T> >;
671         where ChannelMappingConcept<channel_mapping_type<T>::type>;
672     typename is_planar<T>;
673         where Metafunction<is_planar<T> >;
674         where SameType<is_planar<T>::type, bool>;
675   };
676
677   concept HomogeneousPixelBasedConcept<PixelBasedConcept T>
678   {
679     typename channel_type<T>;
680         where Metafunction<channel_type<T> >;
681         where ChannelConcept<channel_type<T>::type>;
682   };
683
684 Pixels model the following concepts::
685
686   concept PixelConcept<typename P> : ColorBaseConcept<P>, PixelBasedConcept<P>
687   {
688     where is_pixel<P>::value==true;
689     // where for each K [0..size<P>::value-1]:
690     //      ChannelConcept<kth_element_type<K> >;
691
692     typename value_type;       where PixelValueConcept<value_type>;
693     typename reference;        where PixelConcept<reference>;
694     typename const_reference;  where PixelConcept<const_reference>;
695     static const bool P::is_mutable;
696
697     template <PixelConcept P2> where { PixelConcept<P,P2> }
698         P::P(P2);
699     template <PixelConcept P2> where { PixelConcept<P,P2> }
700         bool operator==(const P&, const P2&);
701     template <PixelConcept P2> where { PixelConcept<P,P2> }
702         bool operator!=(const P&, const P2&);
703   };
704
705   concept MutablePixelConcept<typename P> : PixelConcept<P>, MutableColorBaseConcept<P>
706   {
707     where is_mutable==true;
708   };
709
710   concept HomogeneousPixelConcept<PixelConcept P> : HomogeneousColorBaseConcept<P>, HomogeneousPixelBasedConcept<P>
711   {
712     P::template element_const_reference_type<P>::type operator[](P p, std::size_t i) const { return dynamic_at_c(P,i); }
713   };
714
715   concept MutableHomogeneousPixelConcept<MutablePixelConcept P> : MutableHomogeneousColorBaseConcept<P>
716   {
717     P::template element_reference_type<P>::type operator[](P p, std::size_t i) { return dynamic_at_c(p,i); }
718   };
719
720   concept PixelValueConcept<typename P> : PixelConcept<P>, Regular<P>
721   {
722     where SameType<value_type,P>;
723   };
724
725   concept PixelsCompatibleConcept<PixelConcept P1, PixelConcept P2> : ColorBasesCompatibleConcept<P1,P2>
726   {
727     // where for each K [0..size<P1>::value):
728     //    ChannelsCompatibleConcept<kth_semantic_element_type<P1,K>::type, kth_semantic_element_type<P2,K>::type>;
729   };
730
731 A pixel is *convertible* to a second pixel if it is possible to
732 approximate its color in the form of the second pixel. Conversion is
733 an explicit, non-symmetric and often lossy operation (due to both
734 channel and color space approximation). Convertibility requires
735 modeling the following concept::
736
737   template <PixelConcept SrcPixel, MutablePixelConcept DstPixel>
738   concept PixelConvertibleConcept
739   {
740     void color_convert(const SrcPixel&, DstPixel&);
741   };
742
743 The distinction between ``PixelConcept`` and ``PixelValueConcept`` is
744 analogous to that for channels and color bases - pixel reference
745 proxies model both, but only pixel values model the latter.
746
747 .. seealso::
748
749    - `PixelBasedConcept<P> <reference/structboost_1_1gil_1_1_pixel_based_concept.html>`_
750    - `PixelConcept<Pixel> <reference/structboost_1_1gil_1_1_pixel_concept.html>`_
751    - `MutablePixelConcept<Pixel> <reference/structboost_1_1gil_1_1_mutable_pixel_concept.html>`_
752    - `PixelValueConcept<Pixel> <reference/structboost_1_1gil_1_1_pixel_value_concept.html>`_
753    - `HomogeneousPixelConcept<Pixel> <reference/structboost_1_1gil_1_1_homogeneous_pixel_based_concept.html>`_
754    - `MutableHomogeneousPixelConcept<Pixel> <reference/structboost_1_1gil_1_1_mutable_homogeneous_pixel_concept.html>`_
755    - `HomogeneousPixelValueConcept<Pixel> <reference/structboost_1_1gil_1_1_homogeneous_pixel_value_concept.html>`_
756    - `PixelsCompatibleConcept<Pixel1, Pixel2> <reference/structboost_1_1gil_1_1_pixels_compatible_concept.html>`_
757    - `PixelConvertibleConcept<SrcPixel, DstPixel> <reference/structboost_1_1gil_1_1_pixel_convertible_concept.html>`_
758
759 Models
760 ~~~~~~
761
762 The most commonly used pixel is a homogeneous pixel whose values are
763 together in memory.  For this purpose GIL provides the struct
764 ``pixel``, templated over the channel value and layout::
765
766   // models HomogeneousPixelValueConcept
767   template <typename ChannelValue, typename Layout> struct pixel;
768
769   // Those typedefs are already provided by GIL
770   typedef pixel<bits8, rgb_layout_t> rgb8_pixel_t;
771   typedef pixel<bits8, bgr_layout_t> bgr8_pixel_t;
772
773   bgr8_pixel_t bgr8(255,0,0);     // pixels can be initialized with the channels directly
774   rgb8_pixel_t rgb8(bgr8);        // compatible pixels can also be copy-constructed
775
776   rgb8 = bgr8;            // assignment and equality is defined between compatible pixels
777   assert(rgb8 == bgr8);   // assignment and equality operate on the semantic channels
778
779   // The first physical channels of the two pixels are different
780   assert(at_c<0>(rgb8) != at_c<0>(bgr8));
781   assert(dynamic_at_c(bgr8,0) != dynamic_at_c(rgb8,0));
782   assert(rgb8[0] != bgr8[0]); // same as above (but operator[] is defined for pixels only)
783
784 Planar pixels have their channels distributed in memory. While they
785 share the same value type (``pixel``) with interleaved pixels, their
786 reference type is a proxy class containing references to each of the
787 channels. This is implemented with the struct
788 ``planar_pixel_reference``::
789
790   // models HomogeneousPixel
791   template <typename ChannelReference, typename ColorSpace> struct planar_pixel_reference;
792
793   // Define the type of a mutable and read-only reference. (These typedefs are already provided by GIL)
794   typedef planar_pixel_reference<      bits8&,rgb_t> rgb8_planar_ref_t;
795   typedef planar_pixel_reference<const bits8&,rgb_t> rgb8c_planar_ref_t;
796
797 Note that, unlike the ``pixel`` struct, planar pixel references are
798 templated over the color space, not over the pixel layout. They always
799 use a canonical channel ordering. Ordering of their elements is
800 unnecessary because their elements are references to the channels.
801
802 Sometimes the channels of a pixel may not be byte-aligned. For example
803 an RGB pixel in '5-5-6' format is a 16-bit pixel whose red, green and
804 blue channels occupy bits [0..4],[5..9] and [10..15] respectively. GIL
805 provides a model for such packed pixel formats::
806
807   // define an rgb565 pixel
808   typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,5,6,5>, rgb_layout_t>::type rgb565_pixel_t;
809
810   function_requires<PixelValueConcept<rgb565_pixel_t> >();
811   static_assert(sizeof(rgb565_pixel_t) == 2, "");
812
813   // define a bgr556 pixel
814   typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,5,6,5>, bgr_layout_t>::type bgr556_pixel_t;
815
816   function_requires<PixelValueConcept<bgr556_pixel_t> >();
817
818   // rgb565 is compatible with bgr556.
819   function_requires<PixelsCompatibleConcept<rgb565_pixel_t,bgr556_pixel_t> >();
820
821 In some cases, the pixel itself may not be byte aligned. For example,
822 consider an RGB pixel in '2-3-2' format. Its size is 7 bits.  GIL
823 refers to such pixels, pixel iterators and images as
824 "bit-aligned". Bit-aligned pixels (and images) are more complex than
825 packed ones.  Since packed pixels are byte-aligned, we can use a C++
826 reference as the reference type to a packed pixel, and a C pointer as
827 an x_iterator over a row of packed pixels. For bit-aligned constructs
828 we need a special reference proxy class (bit_aligned_pixel_reference)
829 and iterator class (bit_aligned_pixel_iterator). The value type of
830 bit-aligned pixels is a packed_pixel. Here is how to use bit_aligned
831 pixels and pixel iterators::
832
833   // Mutable reference to a BGR232 pixel
834   typedef const bit_aligned_pixel_reference<unsigned char, mpl::vector3_c<unsigned,2,3,2>, bgr_layout_t, true>  bgr232_ref_t;
835
836   // A mutable iterator over BGR232 pixels
837   typedef bit_aligned_pixel_iterator<bgr232_ref_t> bgr232_ptr_t;
838
839   // BGR232 pixel value. It is a packed_pixel of size 1 byte. (The last bit is unused)
840   typedef std::iterator_traits<bgr232_ptr_t>::value_type bgr232_pixel_t;
841   static_assert(sizeof(bgr232_pixel_t) == 1, "");
842
843   bgr232_pixel_t red(0,0,3); // = 0RRGGGBB, = 01100000 = 0x60
844
845   // a buffer of 7 bytes fits exactly 8 BGR232 pixels.
846   unsigned char pix_buffer[7];
847   std::fill(pix_buffer,pix_buffer+7,0);
848
849   // Fill the 8 pixels with red
850   bgr232_ptr_t pix_it(&pix_buffer[0],0);  // start at bit 0 of the first pixel
851   for (int i=0; i<8; ++i)
852   {
853     *pix_it++ = red;
854   }
855   // Result: 0x60 0x30 0x11 0x0C 0x06 0x83 0xC1
856
857 Algorithms
858 ~~~~~~~~~~
859
860 Since pixels model ``ColorBaseConcept`` and ``PixelBasedConcept`` all
861 algorithms and metafunctions of color bases can work with them as
862 well::
863
864   // This is how to access the first semantic channel (red)
865   assert(semantic_at_c<0>(rgb8) == semantic_at_c<0>(bgr8));
866
867   // This is how to access the red channel by name
868   assert(get_color<red_t>(rgb8) == get_color<red_t>(bgr8));
869
870   // This is another way of doing it (some compilers don't like the first one)
871   assert(get_color(rgb8,red_t()) == get_color(bgr8,red_t()));
872
873   // This is how to use the PixelBasedConcept metafunctions
874   BOOST_MPL_ASSERT(num_channels<rgb8_pixel_t>::value == 3);
875   BOOST_MPL_ASSERT((is_same<channel_type<rgb8_pixel_t>::type, bits8>));
876   BOOST_MPL_ASSERT((is_same<color_space_type<bgr8_pixel_t>::type, rgb_t> ));
877   BOOST_MPL_ASSERT((is_same<channel_mapping_type<bgr8_pixel_t>::type, mpl::vector3_c<int,2,1,0> > ));
878
879   // Pixels contain just the three channels and nothing extra
880   BOOST_MPL_ASSERT(sizeof(rgb8_pixel_t)==3);
881
882   rgb8_planar_ref_t ref(bgr8);    // copy construction is allowed from a compatible mutable pixel type
883
884   get_color<red_t>(ref) = 10;     // assignment is ok because the reference is mutable
885   assert(get_color<red_t>(bgr8)==10);  // references modify the value they are bound to
886
887   // Create a zero packed pixel and a full regular unpacked pixel.
888   rgb565_pixel_t r565;
889   rgb8_pixel_t rgb_full(255,255,255);
890
891   // Convert all channels of the unpacked pixel to the packed one & assert the packed one is full
892   get_color(r565,red_t())   = channel_convert<rgb565_channel0_t>(get_color(rgb_full,red_t()));
893   get_color(r565,green_t()) = channel_convert<rgb565_channel1_t>(get_color(rgb_full,green_t()));
894   get_color(r565,blue_t())  = channel_convert<rgb565_channel2_t>(get_color(rgb_full,blue_t()));
895   assert(r565 == rgb565_pixel_t((uint16_t)65535));
896
897 GIL also provides the ``color_convert`` algorithm to convert between
898 pixels of different color spaces and channel types::
899
900   rgb8_pixel_t red_in_rgb8(255,0,0);
901   cmyk16_pixel_t red_in_cmyk16;
902   color_convert(red_in_rgb8,red_in_cmyk16);
903
904
905 Pixel Iterator
906 --------------
907
908 Fundamental Iterator
909 ~~~~~~~~~~~~~~~~~~~~
910
911 Pixel iterators are random traversal iterators whose ``value_type
912 models`` ``PixelValueConcept``.  Pixel iterators provide metafunctions
913 to determine whether they are mutable (i.e. whether they allow for
914 modifying the pixel they refer to), to get the immutable (read-only)
915 type of the iterator, and to determine whether they are plain
916 iterators or adaptors over another pixel iterator::
917
918   concept PixelIteratorConcept<RandomAccessTraversalIteratorConcept Iterator> : PixelBasedConcept<Iterator>
919   {
920     where PixelValueConcept<value_type>;
921     typename const_iterator_type<It>::type;
922         where PixelIteratorConcept<const_iterator_type<It>::type>;
923     static const bool  iterator_is_mutable<It>::value;
924     static const bool  is_iterator_adaptor<It>::value;   // is it an iterator adaptor
925   };
926
927   template <typename Iterator>
928   concept MutablePixelIteratorConcept : PixelIteratorConcept<Iterator>, MutableRandomAccessIteratorConcept<Iterator> {};
929
930 .. seealso::
931
932    - `PixelIteratorConcept<Iterator> <reference/group___pixel_iterator_concept_pixel_iterator.html>`_
933    - `MutablePixelIteratorConcept<Iterator> <reference/structboost_1_1gil_1_1_mutable_pixel_iterator_concept.html>`_
934
935 Models
936 ++++++
937
938 A built-in pointer to pixel, ``pixel<ChannelValue,Layout>*``, is GIL's
939 model for pixel iterator over interleaved homogeneous pixels.
940 Similarly, ``packed_pixel<PixelData,ChannelRefVec,Layout>*`` is GIL's
941 model for an iterator over interleaved packed pixels.
942
943 For planar homogeneous pixels, GIL provides the class
944 ``planar_pixel_iterator``, templated over a channel iterator and color
945 space. Here is how the standard mutable and read-only planar RGB
946 iterators over unsigned char are defined::
947
948   template <typename ChannelPtr, typename ColorSpace> struct planar_pixel_iterator;
949
950   // GIL provided typedefs
951   typedef planar_pixel_iterator<const bits8*, rgb_t> rgb8c_planar_ptr_t;
952   typedef planar_pixel_iterator<      bits8*, rgb_t> rgb8_planar_ptr_t;
953
954 ``planar_pixel_iterator`` also models ``HomogeneousColorBaseConcept``
955 (it subclasses from ``homogeneous_color_base``) and, as a result, all
956 color base algorithms apply to it. The element type of its color base
957 is a channel iterator. For example, GIL implements ``operator++`` of
958 planar iterators approximately like this::
959
960   template <typename T>
961   struct inc : public std::unary_function<T,T>
962   {
963     T operator()(T x) const { return ++x; }
964   };
965
966   template <typename ChannelPtr, typename ColorSpace>
967   planar_pixel_iterator<ChannelPtr,ColorSpace>&
968   planar_pixel_iterator<ChannelPtr,ColorSpace>::operator++()
969   {
970     static_transform(*this,*this,inc<ChannelPtr>());
971     return *this;
972   }
973
974 Since ``static_transform`` uses compile-time recursion, incrementing
975 an instance of ``rgb8_planar_ptr_t`` amounts to three pointer
976 increments.  GIL also uses the class ``bit_aligned_pixel_iterator`` as
977 a model for a pixel iterator over bit-aligned pixels. Internally it
978 keeps track of the current byte and the bit offset.
979
980 Iterator Adaptor
981 ~~~~~~~~~~~~~~~~
982
983 Iterator adaptor is an iterator that wraps around another
984 iterator. Its ``is_iterator_adaptor`` metafunction must evaluate to
985 true, and it needs to provide a member method to return the base
986 iterator, a metafunction to get its type, and a metafunction to rebind
987 to another base iterator::
988
989   concept IteratorAdaptorConcept<RandomAccessTraversalIteratorConcept Iterator>
990   {
991     where SameType<is_iterator_adaptor<Iterator>::type, mpl::true_>;
992
993     typename iterator_adaptor_get_base<Iterator>;
994         where Metafunction<iterator_adaptor_get_base<Iterator> >;
995         where boost_concepts::ForwardTraversalConcept<iterator_adaptor_get_base<Iterator>::type>;
996
997     typename another_iterator;
998     typename iterator_adaptor_rebind<Iterator,another_iterator>::type;
999         where boost_concepts::ForwardTraversalConcept<another_iterator>;
1000         where IteratorAdaptorConcept<iterator_adaptor_rebind<Iterator,another_iterator>::type>;
1001
1002     const iterator_adaptor_get_base<Iterator>::type& Iterator::base() const;
1003   };
1004
1005   template <boost_concepts::Mutable_ForwardIteratorConcept Iterator>
1006   concept MutableIteratorAdaptorConcept : IteratorAdaptorConcept<Iterator> {};
1007
1008 .. seealso::
1009
1010    - `IteratorAdaptorConcept<Iterator> <reference/structboost_1_1gil_1_1_iterator_adaptor_concept.html>`_
1011    - `MutableIteratorAdaptorConcept<Iterator> <reference/structboost_1_1gil_1_1_mutable_iterator_adaptor_concept.html>`_
1012
1013 Models
1014 ++++++
1015
1016 GIL provides several models of ``IteratorAdaptorConcept``:
1017
1018 * ``memory_based_step_iterator<Iterator>``: An iterator adaptor that
1019   changes the fundamental step of the base iterator (see :ref:`design_guide:Step Iterator`)
1020 * ``dereference_iterator_adaptor<Iterator,Fn>``: An iterator that
1021   applies a unary function ``Fn`` upon dereferencing. It is used, for
1022   example, for on-the-fly color conversion. It can be used to construct
1023   a shallow image "view" that pretends to have a different color space
1024   or channel depth. See :ref:`design_guide:Image View` for more. The
1025   unary function ``Fn`` must model ``PixelDereferenceAdaptorConcept``
1026   (see below).
1027
1028 Pixel Dereference Adaptor
1029 ~~~~~~~~~~~~~~~~~~~~~~~~~
1030
1031 Pixel dereference adaptor is a unary function that can be applied upon
1032 dereferencing a pixel iterator. Its argument type could be anything
1033 (usually a ``PixelConcept``) and the result type must be convertible
1034 to ``PixelConcept`` ::
1035
1036   template <boost::UnaryFunctionConcept D>
1037   concept PixelDereferenceAdaptorConcept : DefaultConstructibleConcept<D>, CopyConstructibleConcept<D>, AssignableConcept<D>
1038   {
1039     typename const_t;         where PixelDereferenceAdaptorConcept<const_t>;
1040     typename value_type;      where PixelValueConcept<value_type>;
1041     typename reference;       where PixelConcept<remove_reference<reference>::type>;  // may be mutable
1042     typename const_reference;   // must not be mutable
1043     static const bool D::is_mutable;
1044
1045     where Convertible<value_type, result_type>;
1046   };
1047
1048 Models
1049 ++++++
1050
1051 GIL provides several models of ``PixelDereferenceAdaptorConcept``:
1052
1053 * ``color_convert_deref_fn``: a function object that performs color
1054   conversion
1055 * ``detail::nth_channel_deref_fn``: a function object that returns a
1056   grayscale pixel corresponding to the n-th channel of a given pixel
1057 * ``deref_compose``: a function object that composes two models of
1058   ``PixelDereferenceAdaptorConcept``. Similar to
1059   ``std::unary_compose``, except it needs to pull the additional
1060   typedefs required by ``PixelDereferenceAdaptorConcept``
1061
1062 GIL uses pixel dereference adaptors to implement image views that
1063 perform color conversion upon dereferencing, or that return the N-th
1064 channel of the underlying pixel. They can be used to model virtual
1065 image views that perform an arbitrary function upon dereferencing, for
1066 example a view of the Mandelbrot
1067 set. ``dereference_iterator_adaptor<Iterator,Fn>`` is an iterator
1068 wrapper over a pixel iterator ``Iterator`` that invokes the given
1069 dereference iterator adaptor ``Fn`` upon dereferencing.
1070
1071 Step Iterator
1072 ~~~~~~~~~~~~~
1073
1074 Sometimes we want to traverse pixels with a unit step other than the
1075 one provided by the fundamental pixel iterators.  Examples where this
1076 would be useful:
1077
1078 * a single-channel view of the red channel of an RGB interleaved image
1079 * left-to-right flipped image (step = -fundamental_step)
1080 * subsampled view, taking every N-th pixel (step = N*fundamental_step)
1081 * traversal in vertical direction (step = number of bytes per row)
1082 * any combination of the above (steps are multiplied)
1083
1084 Step iterators are forward traversal iterators that allow changing the
1085 step between adjacent values::
1086
1087   concept StepIteratorConcept<boost_concepts::ForwardTraversalConcept Iterator>
1088   {
1089     template <Integral D> void Iterator::set_step(D step);
1090   };
1091
1092   concept MutableStepIteratorConcept<boost_concepts::Mutable_ForwardIteratorConcept Iterator> : StepIteratorConcept<Iterator> {};
1093
1094 GIL currently provides a step iterator whose ``value_type models``
1095 ``PixelValueConcept``. In addition, the step is specified in memory
1096 units (which are bytes or bits).  This is necessary, for example, when
1097 implementing an iterator navigating along a column of pixels - the
1098 size of a row of pixels may sometimes not be divisible by the size of
1099 a pixel; for example rows may be word-aligned.
1100
1101 To advance in bytes/bits, the base iterator must model
1102 MemoryBasedIteratorConcept. A memory-based iterator has an inherent
1103 memory unit, which is either a bit or a byte.  It must supply
1104 functions returning the number of bits per memory unit (1 or 8), the
1105 current step in memory units, the memory-unit distance between two
1106 iterators, and a reference a given distance in memunits away. It must
1107 also supply a function that advances an iterator a given distance in
1108 memory units.  ``memunit_advanced`` and ``memunit_advanced_ref`` have
1109 a default implementation but some iterators may supply a more
1110 efficient version::
1111
1112   concept MemoryBasedIteratorConcept<boost_concepts::RandomAccessTraversalConcept Iterator>
1113   {
1114     typename byte_to_memunit<Iterator>; where metafunction<byte_to_memunit<Iterator> >;
1115     std::ptrdiff_t      memunit_step(const Iterator&);
1116     std::ptrdiff_t      memunit_distance(const Iterator& , const Iterator&);
1117     void                memunit_advance(Iterator&, std::ptrdiff_t diff);
1118     Iterator            memunit_advanced(const Iterator& p, std::ptrdiff_t diff) { Iterator tmp; memunit_advance(tmp,diff); return tmp; }
1119     Iterator::reference memunit_advanced_ref(const Iterator& p, std::ptrdiff_t diff) { return *memunit_advanced(p,diff); }
1120   };
1121
1122 It is useful to be able to construct a step iterator over another
1123 iterator. More generally, given a type, we want to be able to
1124 construct an equivalent type that allows for dynamically specified
1125 horizontal step::
1126
1127   concept HasDynamicXStepTypeConcept<typename T>
1128   {
1129     typename dynamic_x_step_type<T>;
1130         where Metafunction<dynamic_x_step_type<T> >;
1131   };
1132
1133 All models of pixel iterators, locators and image views that GIL
1134 provides support ``HasDynamicXStepTypeConcept``.
1135
1136 .. seealso::
1137
1138    - `StepIteratorConcept<Iterator> <reference/structboost_1_1gil_1_1_step_iterator_concept.html>`_
1139    - `MutableStepIteratorConcept<Iterator> <reference/structboost_1_1gil_1_1_mutable_step_iterator_concept.html>`_
1140    - `MemoryBasedIteratorConcept<Iterator> <reference/structboost_1_1gil_1_1_memory_based_iterator_concept.html>`_
1141    - `HasDynamicXStepTypeConcept<T> <reference/structboost_1_1gil_1_1_has_dynamic_x_step_type_concept.html>`_
1142
1143 Models
1144 ++++++
1145
1146 All standard memory-based iterators GIL currently provides model
1147 ``MemoryBasedIteratorConcept``.  GIL provides the class
1148 ``memory_based_step_iterator`` which models ``PixelIteratorConcept``,
1149 ``StepIteratorConcept``, and ``MemoryBasedIteratorConcept``.  It takes
1150 the base iterator as a template parameter (which must model
1151 ``PixelIteratorConcept`` and ``MemoryBasedIteratorConcept``) and
1152 allows changing the step dynamically. GIL's implementation contains
1153 the base iterator and a ``ptrdiff_t`` denoting the number of memory
1154 units (bytes or bits) to skip for a unit step. It may also be used
1155 with a negative number. GIL provides a function to create a step
1156 iterator from a base iterator and a step::
1157
1158   template <typename I>  // Models MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept
1159   typename dynamic_x_step_type<I>::type make_step_iterator(const I& it, std::ptrdiff_t step);
1160
1161 GIL also provides a model of an iterator over a virtual array of
1162 pixels, ``position_iterator``. It is a step iterator that keeps track
1163 of the pixel position and invokes a function object to get the value
1164 of the pixel upon dereferencing. It models ``PixelIteratorConcept``
1165 and ``StepIteratorConcept`` but not ``MemoryBasedIteratorConcept``.
1166
1167 Pixel Locator
1168 ~~~~~~~~~~~~~
1169
1170 A Locator allows for navigation in two or more dimensions. Locators
1171 are N-dimensional iterators in spirit, but we use a different name
1172 because they don't satisfy all the requirements of iterators. For
1173 example, they don't supply increment and decrement operators because
1174 it is unclear which dimension the operators should advance along.
1175 N-dimensional locators model the following concept::
1176
1177   concept RandomAccessNDLocatorConcept<Regular Loc>
1178   {
1179     typename value_type;        // value over which the locator navigates
1180     typename reference;         // result of dereferencing
1181     typename difference_type; where PointNDConcept<difference_type>; // return value of operator-.
1182     typename const_t;           // same as Loc, but operating over immutable values
1183     typename cached_location_t; // type to store relative location (for efficient repeated access)
1184     typename point_t  = difference_type;
1185
1186     static const size_t num_dimensions; // dimensionality of the locator
1187     where num_dimensions = point_t::num_dimensions;
1188
1189     // The difference_type and iterator type along each dimension. The iterators may only differ in
1190     // difference_type. Their value_type must be the same as Loc::value_type
1191     template <size_t D> struct axis {
1192         typename coord_t = point_t::axis<D>::coord_t;
1193         typename iterator; where RandomAccessTraversalConcept<iterator>; // iterator along D-th axis.
1194         where iterator::value_type == value_type;
1195     };
1196
1197     // Defines the type of a locator similar to this type, except it invokes Deref upon dereferencing
1198     template <PixelDereferenceAdaptorConcept Deref> struct add_deref {
1199         typename type;        where RandomAccessNDLocatorConcept<type>;
1200         static type make(const Loc& loc, const Deref& deref);
1201     };
1202
1203     Loc& operator+=(Loc&, const difference_type&);
1204     Loc& operator-=(Loc&, const difference_type&);
1205     Loc operator+(const Loc&, const difference_type&);
1206     Loc operator-(const Loc&, const difference_type&);
1207
1208     reference operator*(const Loc&);
1209     reference operator[](const Loc&, const difference_type&);
1210
1211     // Storing relative location for faster repeated access and accessing it
1212     cached_location_t Loc::cache_location(const difference_type&) const;
1213     reference operator[](const Loc&,const cached_location_t&);
1214
1215     // Accessing iterators along a given dimension at the current location or at a given offset
1216     template <size_t D> axis<D>::iterator&       Loc::axis_iterator();
1217     template <size_t D> axis<D>::iterator const& Loc::axis_iterator() const;
1218     template <size_t D> axis<D>::iterator        Loc::axis_iterator(const difference_type&) const;
1219   };
1220
1221   template <typename Loc>
1222   concept MutableRandomAccessNDLocatorConcept : RandomAccessNDLocatorConcept<Loc> {
1223     where Mutable<reference>;
1224   };
1225
1226 Two-dimensional locators have additional requirements::
1227
1228   concept RandomAccess2DLocatorConcept<RandomAccessNDLocatorConcept Loc>
1229   {
1230     where num_dimensions==2;
1231     where Point2DConcept<point_t>;
1232
1233     typename x_iterator = axis<0>::iterator;
1234     typename y_iterator = axis<1>::iterator;
1235     typename x_coord_t  = axis<0>::coord_t;
1236     typename y_coord_t  = axis<1>::coord_t;
1237
1238     // Only available to locators that have dynamic step in Y
1239     //Loc::Loc(const Loc& loc, y_coord_t);
1240
1241     // Only available to locators that have dynamic step in X and Y
1242     //Loc::Loc(const Loc& loc, x_coord_t, y_coord_t, bool transposed=false);
1243
1244     x_iterator&       Loc::x();
1245     x_iterator const& Loc::x() const;
1246     y_iterator&       Loc::y();
1247     y_iterator const& Loc::y() const;
1248
1249     x_iterator Loc::x_at(const difference_type&) const;
1250     y_iterator Loc::y_at(const difference_type&) const;
1251     Loc Loc::xy_at(const difference_type&) const;
1252
1253     // x/y versions of all methods that can take difference type
1254     x_iterator        Loc::x_at(x_coord_t, y_coord_t) const;
1255     y_iterator        Loc::y_at(x_coord_t, y_coord_t) const;
1256     Loc               Loc::xy_at(x_coord_t, y_coord_t) const;
1257     reference         operator()(const Loc&, x_coord_t, y_coord_t);
1258     cached_location_t Loc::cache_location(x_coord_t, y_coord_t) const;
1259
1260     bool      Loc::is_1d_traversable(x_coord_t width) const;
1261     y_coord_t Loc::y_distance_to(const Loc& loc2, x_coord_t x_diff) const;
1262   };
1263
1264   concept MutableRandomAccess2DLocatorConcept<RandomAccess2DLocatorConcept Loc> : MutableRandomAccessNDLocatorConcept<Loc> {};
1265
1266 2D locators can have a dynamic step not just horizontally, but also
1267 vertically. This gives rise to the Y equivalent of
1268 HasDynamicXStepTypeConcept::
1269
1270   concept HasDynamicYStepTypeConcept<typename T>
1271   {
1272     typename dynamic_y_step_type<T>;
1273         where Metafunction<dynamic_y_step_type<T> >;
1274   };
1275
1276 All locators and image views that GIL provides model
1277 ``HasDynamicYStepTypeConcept``.
1278
1279 Sometimes it is necessary to swap the meaning of X and Y for a given
1280 locator or image view type (for example, GIL provides a function to
1281 transpose an image view).  Such locators and views must be
1282 transposable::
1283
1284   concept HasTransposedTypeConcept<typename T>
1285   {
1286     typename transposed_type<T>;
1287         where Metafunction<transposed_type<T> >;
1288   };
1289
1290 All GIL provided locators and views model
1291 ``HasTransposedTypeConcept``.
1292
1293 The locators GIL uses operate over models of ``PixelConcept`` and
1294 their x and y dimension types are the same. They model the following
1295 concept::
1296
1297   concept PixelLocatorConcept<RandomAccess2DLocatorConcept Loc>
1298   {
1299     where PixelValueConcept<value_type>;
1300     where PixelIteratorConcept<x_iterator>;
1301     where PixelIteratorConcept<y_iterator>;
1302     where x_coord_t == y_coord_t;
1303
1304     typename coord_t = x_coord_t;
1305   };
1306
1307   concept MutablePixelLocatorConcept<PixelLocatorConcept Loc> : MutableRandomAccess2DLocatorConcept<Loc> {};
1308
1309 .. seealso::
1310
1311    - `HasDynamicYStepTypeConcept<T> <reference/structboost_1_1gil_1_1_has_dynamic_y_step_type_concept.html>`_
1312    - `HasTransposedTypeConcept<T> <reference/structboost_1_1gil_1_1_has_transposed_type_concept.html>`_
1313    - `RandomAccessNDLocatorConcept<Locator> <reference/structboost_1_1gil_1_1_random_access_n_d_locator_concept.html>`_
1314    - `MutableRandomAccessNDLocatorConcept<Locator> <reference/structboost_1_1gil_1_1_mutable_random_access_n_d_locator_concept.html>`_
1315    - `RandomAccess2DLocatorConcept<Locator> <reference/structboost_1_1gil_1_1_random_access2_d_locator_concept.html>`_
1316    - `MutableRandomAccess2DLocatorConcept<Locator> <reference/structboost_1_1gil_1_1_mutable_random_access2_d_locator_concept.html>`_
1317    - `PixelLocatorConcept<Locator> <reference/structboost_1_1gil_1_1_pixel_locator_concept.html>`_
1318    - `MutablePixelLocatorConcept<Locator> <reference/structboost_1_1gil_1_1_mutable_pixel_locator_concept.html>`_
1319
1320 Models
1321 ++++++
1322
1323 GIL provides two models of ``PixelLocatorConcept`` - a memory-based
1324 locator, ``memory_based_2d_locator`` and a virtual locator
1325 ``virtual_2d_locator``.
1326
1327 ``memory_based_2d_locator`` is a locator over planar or interleaved
1328 images that have their pixels in memory.  It takes a model of
1329 ``StepIteratorConcept`` over pixels as a template parameter. (When
1330 instantiated with a model of ``MutableStepIteratorConcept``, it models
1331 ``MutablePixelLocatorConcept``). ::
1332
1333   template <typename StepIterator>  // Models StepIteratorConcept, MemoryBasedIteratorConcept
1334   class memory_based_2d_locator;
1335
1336 The step of ``StepIterator`` must be the number of memory units (bytes
1337 or bits) per row (thus it must be memunit advanceable). The class
1338 ``memory_based_2d_locator`` is a wrapper around ``StepIterator`` and
1339 uses it to navigate vertically, while its base iterator is used to
1340 navigate horizontally.
1341
1342 Combining fundamental and step iterators allows us to create locators
1343 that describe complex pixel memory organizations. First, we have a
1344 choice of iterator to use for horizontal direction, i.e. for iterating
1345 over the pixels on the same row.  Using the fundamental and step
1346 iterators gives us four choices:
1347
1348 - ``pixel<T,C>*`` - for interleaved images
1349 - ``planar_pixel_iterator<T*,C>`` - for planar images
1350 - ``memory_based_step_iterator<pixel<T,C>*>`` - for interleaved images with
1351   non-standard step)
1352 - ``memory_based_step_iterator<planar_pixel_iterator<T*,C> >`` - for planar
1353   images with non-standard step
1354
1355 Of course, one could provide their own custom x-iterator. One such
1356 example described later is an iterator adaptor that performs color
1357 conversion when dereferenced.
1358
1359 Given a horizontal iterator ``XIterator``, we could choose the
1360 ``y-iterator``, the iterator that moves along a column, as
1361 ``memory_based_step_iterator<XIterator>`` with a step equal to the
1362 number of memory units (bytes or bits) per row. Again, one is free to
1363 provide their own y-iterator.
1364
1365 Then we can instantiate
1366 ``memory_based_2d_locator<memory_based_step_iterator<XIterator> >`` to
1367 obtain a 2D pixel locator, as the diagram indicates:
1368
1369 .. image:: images/step_iterator.gif
1370
1371 ``virtual_2d_locator`` is a locator that is instantiated with a
1372 function object invoked upon dereferencing a pixel. It returns the
1373 value of a pixel given its X,Y coordinates. Virtual locators can be
1374 used to implement virtual image views that can model any user-defined
1375 function. See the GIL tutorial for an example of using virtual
1376 locators to create a view of the Mandelbrot set.
1377
1378 Both the virtual and the memory-based locators subclass from
1379 ``pixel_2d_locator_base``, a base class that provides most of the
1380 interface required by ``PixelLocatorConcept``. Users may find this
1381 base class useful if they need to provide other models of
1382 ``PixelLocatorConcept``.
1383
1384 Here is some sample code using locators::
1385
1386   loc=img.xy_at(10,10);            // start at pixel (x=10,y=10)
1387   above=loc.cache_location(0,-1);  // remember relative locations of neighbors above and below
1388   below=loc.cache_location(0, 1);
1389   ++loc.x();                       // move to (11,10)
1390   loc.y()+=15;                     // move to (11,25)
1391   loc-=point<std::ptrdiff_t>(1,1);// move to (10,24)
1392   *loc=(loc(0,-1)+loc(0,1))/2;     // set pixel (10,24) to the average of (10,23) and (10,25) (grayscale pixels only)
1393   *loc=(loc[above]+loc[below])/2;  // the same, but faster using cached relative neighbor locations
1394
1395 The standard GIL locators are fast and lightweight objects. For
1396 example, the locator for a simple interleaved image consists of one
1397 raw pointer to the pixel location plus one integer for the row size in
1398 bytes, for a total of 8 bytes. ``++loc.x()`` amounts to incrementing a
1399 raw pointer (or N pointers for planar images). Computing 2D offsets is
1400 slower as it requires multiplication and addition.  Filters, for
1401 example, need to access the same neighbors for every pixel in the
1402 image, in which case the relative positions can be cached into a raw
1403 byte difference using ``cache_location``. In the above example
1404 ``loc[above]`` for simple interleaved images amounts to a raw array
1405 index operator.
1406
1407 Iterator over 2D image
1408 ~~~~~~~~~~~~~~~~~~~~~~
1409
1410 Sometimes we want to perform the same, location-independent operation
1411 over all pixels of an image. In such a case it is useful to represent
1412 the pixels as a one-dimensional array. GIL's ``iterator_from_2d`` is a
1413 random access traversal iterator that visits all pixels in an image in
1414 the natural memory-friendly order left-to-right inside
1415 top-to-bottom. It takes a locator, the width of the image and the
1416 current X position. This is sufficient information for it to determine
1417 when to do a "carriage return". Synopsis::
1418
1419   template <typename Locator>  // Models PixelLocatorConcept
1420   class iterator_from_2d
1421   {
1422   public:
1423     iterator_from_2d(const Locator& loc, int x, int width);
1424
1425     iterator_from_2d& operator++(); // if (++_x<_width) ++_p.x(); else _p+=point_t(-_width,1);
1426
1427     ...
1428   private:
1429     int _x, _width;
1430     Locator _p;
1431   };
1432
1433 Iterating through the pixels in an image using ``iterator_from_2d`` is
1434 slower than going through all rows and using the x-iterator at each
1435 row.  This is because two comparisons are done per iteration step -
1436 one for the end condition of the loop using the iterators, and one
1437 inside ``iterator_from_2d::operator++`` to determine whether we are at
1438 the end of a row. For fast operations, such as pixel copy, this second
1439 check adds about 15% performance delay (measured for interleaved
1440 images on Intel platform). GIL overrides some STL algorithms, such as
1441  ``std::copy`` and ``std::fill``, when invoked with
1442 ``iterator_from_2d``-s, to go through each row using their base
1443 x-iterators, and, if the image has no padding
1444 (i.e. ``iterator_from_2d::is_1d_traversable()`` returns true) to
1445 simply iterate using the x-iterators directly.
1446
1447
1448 Image View
1449 ----------
1450
1451 An image view is a generalization of STL range concept to multiple
1452 dimensions. Similar to ranges (and iterators), image views are
1453 shallow, don't own the underlying data and don't propagate their
1454 constness over the data. For example, a constant image view cannot be
1455 resized, but may allow modifying the pixels. For pixel-immutable
1456 operations, use constant-value image view (also called non-mutable
1457 image view).  Most general N-dimensional views satisfy the following
1458 concept::
1459
1460   concept RandomAccessNDImageViewConcept<Regular View>
1461   {
1462     typename value_type;      // for pixel-based views, the pixel type
1463     typename reference;       // result of dereferencing
1464     typename difference_type; // result of operator-(iterator,iterator) (1-dimensional!)
1465     typename const_t;  where RandomAccessNDImageViewConcept<View>; // same as View, but over immutable values
1466     typename point_t;  where PointNDConcept<point_t>; // N-dimensional point
1467     typename locator;  where RandomAccessNDLocatorConcept<locator>; // N-dimensional locator.
1468     typename iterator; where RandomAccessTraversalConcept<iterator>; // 1-dimensional iterator over all values
1469     typename reverse_iterator; where RandomAccessTraversalConcept<reverse_iterator>;
1470     typename size_type;       // the return value of size()
1471
1472     // Equivalent to RandomAccessNDLocatorConcept::axis
1473     template <size_t D> struct axis {
1474         typename coord_t = point_t::axis<D>::coord_t;
1475         typename iterator; where RandomAccessTraversalConcept<iterator>;   // iterator along D-th axis.
1476         where SameType<coord_t, iterator::difference_type>;
1477         where SameType<iterator::value_type,value_type>;
1478     };
1479
1480     // Defines the type of a view similar to this type, except it invokes Deref upon dereferencing
1481     template <PixelDereferenceAdaptorConcept Deref> struct add_deref {
1482         typename type;        where RandomAccessNDImageViewConcept<type>;
1483         static type make(const View& v, const Deref& deref);
1484     };
1485
1486     static const size_t num_dimensions = point_t::num_dimensions;
1487
1488     // Create from a locator at the top-left corner and dimensions
1489     View::View(const locator&, const point_type&);
1490
1491     size_type        View::size()       const; // total number of elements
1492     reference        operator[](View, const difference_type&) const; // 1-dimensional reference
1493     iterator         View::begin()      const;
1494     iterator         View::end()        const;
1495     reverse_iterator View::rbegin()     const;
1496     reverse_iterator View::rend()       const;
1497     iterator         View::at(const point_t&);
1498     point_t          View::dimensions() const; // number of elements along each dimension
1499     bool             View::is_1d_traversable() const;   // Does an iterator over the first dimension visit each value?
1500
1501     // iterator along a given dimension starting at a given point
1502     template <size_t D> View::axis<D>::iterator View::axis_iterator(const point_t&) const;
1503
1504     reference operator()(View,const point_t&) const;
1505   };
1506
1507   concept MutableRandomAccessNDImageViewConcept<RandomAccessNDImageViewConcept View>
1508   {
1509     where Mutable<reference>;
1510   };
1511
1512 Two-dimensional image views have the following extra requirements::
1513
1514   concept RandomAccess2DImageViewConcept<RandomAccessNDImageViewConcept View>
1515   {
1516     where num_dimensions==2;
1517
1518     typename x_iterator = axis<0>::iterator;
1519     typename y_iterator = axis<1>::iterator;
1520     typename x_coord_t  = axis<0>::coord_t;
1521     typename y_coord_t  = axis<1>::coord_t;
1522     typename xy_locator = locator;
1523
1524     x_coord_t View::width()  const;
1525     y_coord_t View::height() const;
1526
1527     // X-navigation
1528     x_iterator View::x_at(const point_t&) const;
1529     x_iterator View::row_begin(y_coord_t) const;
1530     x_iterator View::row_end  (y_coord_t) const;
1531
1532     // Y-navigation
1533     y_iterator View::y_at(const point_t&) const;
1534     y_iterator View::col_begin(x_coord_t) const;
1535     y_iterator View::col_end  (x_coord_t) const;
1536
1537     // navigating in 2D
1538     xy_locator View::xy_at(const point_t&) const;
1539
1540     // (x,y) versions of all methods taking point_t
1541     View::View(x_coord_t,y_coord_t,const locator&);
1542     iterator View::at(x_coord_t,y_coord_t) const;
1543     reference operator()(View,x_coord_t,y_coord_t) const;
1544     xy_locator View::xy_at(x_coord_t,y_coord_t) const;
1545     x_iterator View::x_at(x_coord_t,y_coord_t) const;
1546     y_iterator View::y_at(x_coord_t,y_coord_t) const;
1547   };
1548
1549   concept MutableRandomAccess2DImageViewConcept<RandomAccess2DImageViewConcept View>
1550   : MutableRandomAccessNDImageViewConcept<View> {};
1551
1552 Image views that GIL typically uses operate on value types that model
1553 ``PixelValueConcept`` and have some additional requirements::
1554
1555   concept ImageViewConcept<RandomAccess2DImageViewConcept View>
1556   {
1557     where PixelValueConcept<value_type>;
1558     where PixelIteratorConcept<x_iterator>;
1559     where PixelIteratorConcept<y_iterator>;
1560     where x_coord_t == y_coord_t;
1561
1562     typename coord_t = x_coord_t;
1563
1564     std::size_t View::num_channels() const;
1565   };
1566
1567
1568   concept MutableImageViewConcept<ImageViewConcept View> : MutableRandomAccess2DImageViewConcept<View> {};
1569
1570 Two image views are compatible if they have compatible pixels and the
1571 same number of dimensions::
1572
1573   concept ViewsCompatibleConcept<ImageViewConcept V1, ImageViewConcept V2>
1574   {
1575     where PixelsCompatibleConcept<V1::value_type, V2::value_type>;
1576     where V1::num_dimensions == V2::num_dimensions;
1577   };
1578
1579 Compatible views must also have the same dimensions (i.e. the same
1580 width and height). Many algorithms taking multiple views require that
1581 they be pairwise compatible.
1582
1583 .. seealso::
1584
1585    - `RandomAccessNDImageViewConcept<View> <reference/structboost_1_1gil_1_1_random_access_n_d_image_view_concept.html>`_
1586    - `MutableRandomAccessNDImageViewConcept<View> <reference/structboost_1_1gil_1_1_mutable_random_access_n_d_image_view_concept.html>`_
1587    - `RandomAccess2DImageViewConcept<View> <reference/structboost_1_1gil_1_1_random_access2_d_image_view_concept.html>`_
1588    - `MutableRandomAccess2DImageViewConcept<View> <reference/structboost_1_1gil_1_1_mutable_random_access2_d_image_view_concept.html>`_
1589    - `ImageViewConcept<View> <reference/structboost_1_1gil_1_1_image_view_concept.html>`_
1590    - `MutableImageViewConcept<View> <reference/structboost_1_1gil_1_1_mutable_image_view_concept.html>`_
1591    - `ViewsCompatibleConcept<View1,View2> <reference/structboost_1_1gil_1_1_views_compatible_concept.html>`_
1592
1593 Models
1594 ~~~~~~
1595
1596 GIL provides a model for ``ImageViewConcept`` called
1597 ``image_view``. It is templated over a model of
1598 ``PixelLocatorConcept``.  (If instantiated with a model of
1599 ``MutablePixelLocatorConcept``, it models
1600 ``MutableImageViewConcept``). Synopsis::
1601
1602   template <typename Locator>  // Models PixelLocatorConcept (could be MutablePixelLocatorConcept)
1603   class image_view
1604   {
1605   public:
1606     typedef Locator xy_locator;
1607     typedef iterator_from_2d<Locator> iterator;
1608     ...
1609   private:
1610     xy_locator _pixels;     // 2D pixel locator at the top left corner of the image view range
1611     point_t    _dimensions; // width and height
1612   };
1613
1614 Image views are lightweight objects. A regular interleaved view is
1615 typically 16 bytes long - two integers for the width and height
1616 (inside dimensions) one for the number of bytes between adjacent rows
1617 (inside the locator) and one pointer to the beginning of the pixel
1618 block.
1619
1620 Algorithms
1621 ~~~~~~~~~~
1622
1623 Creating Views from Raw Pixels
1624 ++++++++++++++++++++++++++++++
1625
1626 Standard image views can be constructed from raw data of any supported
1627 color space, bit depth, channel ordering or planar vs. interleaved
1628 structure.  Interleaved views are constructed using
1629 ``interleaved_view``, supplying the image dimensions, number of bytes
1630 per row, and a pointer to the first pixel::
1631
1632   template <typename Iterator> // Models pixel iterator (like rgb8_ptr_t or rgb8c_ptr_t)
1633   image_view<...> interleaved_view(ptrdiff_t width, ptrdiff_t height, Iterator pixels, ptrdiff_t rowsize)
1634
1635 Planar views are defined for every color space and take each plane
1636 separately. Here is the RGB one::
1637
1638   template <typename IC>  // Models channel iterator (like bits8* or const bits8*)
1639   image_view<...> planar_rgb_view(ptrdiff_t width, ptrdiff_t height,
1640                                  IC r, IC g, IC b, ptrdiff_t rowsize);
1641
1642 Note that the supplied pixel/channel iterators could be constant
1643 (read-only), in which case the returned view is a constant-value
1644 (immutable) view.
1645
1646 Creating Image Views from Other Image Views
1647 +++++++++++++++++++++++++++++++++++++++++++
1648
1649 It is possible to construct one image view from another by changing
1650 some policy of how image data is interpreted. The result could be a
1651 view whose type is derived from the type of the source. GIL uses the
1652 following metafunctions to get the derived types::
1653
1654   // Some result view types
1655   template <typename View>
1656   struct dynamic_xy_step_type : public dynamic_y_step_type<typename dynamic_x_step_type<View>::type> {};
1657
1658   template <typename View>
1659   struct dynamic_xy_step_transposed_type : public dynamic_xy_step_type<typename transposed_type<View>::type> {};
1660
1661   // color and bit depth converted view to match pixel type P
1662   template <typename SrcView, // Models ImageViewConcept
1663           typename DstP,    // Models PixelConcept
1664           typename ColorConverter=gil::default_color_converter>
1665   struct color_converted_view_type
1666   {
1667     typedef ... type;     // image view adaptor with value type DstP, over SrcView
1668   };
1669
1670   // single-channel view of the N-th channel of a given view
1671   template <typename SrcView>
1672   struct nth_channel_view_type
1673   {
1674     typedef ... type;
1675   };
1676
1677 GIL Provides the following view transformations::
1678
1679   // flipped upside-down, left-to-right, transposed view
1680   template <typename View> typename dynamic_y_step_type<View>::type             flipped_up_down_view(const View& src);
1681   template <typename View> typename dynamic_x_step_type<View>::type             flipped_left_right_view(const View& src);
1682   template <typename View> typename dynamic_xy_step_transposed_type<View>::type transposed_view(const View& src);
1683
1684   // rotations
1685   template <typename View> typename dynamic_xy_step_type<View>::type            rotated180_view(const View& src);
1686   template <typename View> typename dynamic_xy_step_transposed_type<View>::type rotated90cw_view(const View& src);
1687   template <typename View> typename dynamic_xy_step_transposed_type<View>::type rotated90ccw_view(const View& src);
1688
1689   // view of an axis-aligned rectangular area within an image
1690   template <typename View> View                                                 subimage_view(const View& src,
1691              const View::point_t& top_left, const View::point_t& dimensions);
1692
1693   // subsampled view (skipping pixels in X and Y)
1694   template <typename View> typename dynamic_xy_step_type<View>::type            subsampled_view(const View& src,
1695              const View::point_t& step);
1696
1697   template <typename View, typename P>
1698   color_converted_view_type<View,P>::type                                       color_converted_view(const View& src);
1699   template <typename View, typename P, typename CCV> // with a custom color converter
1700   color_converted_view_type<View,P,CCV>::type                                   color_converted_view(const View& src);
1701
1702   template <typename View>
1703   nth_channel_view_type<View>::view_t                                           nth_channel_view(const View& view, int n);
1704
1705 The implementations of most of these view factory methods are
1706 straightforward. Here is, for example, how the flip views are
1707 implemented.  The flip upside-down view creates a view whose first
1708 pixel is the bottom left pixel of the original view and whose y-step
1709 is the negated step of the source. ::
1710
1711   template <typename View>
1712   typename dynamic_y_step_type<View>::type flipped_up_down_view(const View& src)
1713   {
1714     gil_function_requires<ImageViewConcept<View> >();
1715     typedef typename dynamic_y_step_type<View>::type RView;
1716     return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1));
1717   }
1718
1719 The call to ``gil_function_requires`` ensures (at compile time) that
1720 the template parameter is a valid model of ``ImageViewConcept``. Using
1721 it generates easier to track compile errors, creates no extra code and
1722 has no run-time performance impact.  We are using the
1723 ``boost::concept_check library``, but wrapping it in
1724 ``gil_function_requires``, which performs the check if the
1725 ``BOOST_GIL_USE_CONCEPT_CHECK`` is set. It is unset by default,
1726 because there is a significant increase in compile time when using
1727 concept checks. We will skip ``gil_function_requires`` in the code
1728 examples in this guide for the sake of succinctness.
1729
1730 Image views can be freely composed (see section :ref:`design_guide:Useful Metafunctions and Typedefs`
1731 for the typedefs ``rgb16_image_t`` and ``gray16_step_view_t)``::
1732
1733   rgb16_image_t img(100,100);    // an RGB interleaved image
1734
1735   // grayscale view over the green (index 1) channel of img
1736   gray16_step_view_t green=nth_channel_view(view(img),1);
1737
1738   // 50x50 view of the green channel of img, upside down and taking every other pixel in X and in Y
1739   gray16_step_view_t ud_fud=flipped_up_down_view(subsampled_view(green,2,2));
1740
1741 As previously stated, image views are fast, constant-time, shallow
1742 views over the pixel data. The above code does not copy any pixels; it
1743 operates on the pixel data allocated when ``img`` was created.
1744
1745 STL-Style Algorithms on Image Views
1746 +++++++++++++++++++++++++++++++++++
1747
1748 Image views provide 1D iteration of their pixels via begin() and end()
1749 methods, which makes it possible to use STL algorithms with
1750 them. However, using nested loops over X and Y is in many cases more
1751 efficient. The algorithms in this section resemble STL algorithms, but
1752 they abstract away the nested loops and take views (as opposed to
1753 ranges) as input.::
1754
1755   // Equivalents of std::copy and std::uninitialized_copy
1756   // where ImageViewConcept<V1>, MutableImageViewConcept<V2>, ViewsCompatibleConcept<V1,V2>
1757   template <typename V1, typename V2>
1758   void copy_pixels(const V1& src, const V2& dst);
1759   template <typename V1, typename V2>
1760   void uninitialized_copy_pixels(const V1& src, const V2& dst);
1761
1762   // Equivalents of std::fill and std::uninitialized_fill
1763   // where MutableImageViewConcept<V>, PixelConcept<Value>, PixelsCompatibleConcept<Value,V::value_type>
1764   template <typename V, typename Value>
1765   void fill_pixels(const V& dst, const Value& val);
1766   template <typename V, typename Value>
1767   void uninitialized_fill_pixels(const V& dst, const Value& val);
1768
1769   // Equivalent of std::for_each
1770   // where ImageViewConcept<V>, boost::UnaryFunctionConcept<F>
1771   // where PixelsCompatibleConcept<V::reference, F::argument_type>
1772   template <typename V, typename F>
1773   F for_each_pixel(const V& view, F fun);
1774   template <typename V, typename F>
1775   F for_each_pixel_position(const V& view, F fun);
1776
1777   // Equivalent of std::generate
1778   // where MutableImageViewConcept<V>, boost::UnaryFunctionConcept<F>
1779   // where PixelsCompatibleConcept<V::reference, F::argument_type>
1780   template <typename V, typename F>
1781   void generate_pixels(const V& dst, F fun);
1782
1783   // Equivalent of std::transform with one source
1784   // where ImageViewConcept<V1>, MutableImageViewConcept<V2>
1785   // where boost::UnaryFunctionConcept<F>
1786   // where PixelsCompatibleConcept<V1::const_reference, F::argument_type>
1787   // where PixelsCompatibleConcept<F::result_type, V2::reference>
1788   template <typename V1, typename V2, typename F>
1789   F transform_pixels(const V1& src, const V2& dst, F fun);
1790   template <typename V1, typename V2, typename F>
1791   F transform_pixel_positions(const V1& src, const V2& dst, F fun);
1792
1793   // Equivalent of std::transform with two sources
1794   // where ImageViewConcept<V1>, ImageViewConcept<V2>, MutableImageViewConcept<V3>
1795   // where boost::BinaryFunctionConcept<F>
1796   // where PixelsCompatibleConcept<V1::const_reference, F::first_argument_type>
1797   // where PixelsCompatibleConcept<V2::const_reference, F::second_argument_type>
1798   // where PixelsCompatibleConcept<F::result_type, V3::reference>
1799   template <typename V1, typename V2, typename V3, typename F>
1800   F transform_pixels(const V1& src1, const V2& src2, const V3& dst, F fun);
1801   template <typename V1, typename V2, typename V3, typename F>
1802   F transform_pixel_positions(const V1& src1, const V2& src2, const V3& dst, F fun);
1803
1804   // Copies a view into another, color converting the pixels if needed, with the default or user-defined color converter
1805   // where ImageViewConcept<V1>, MutableImageViewConcept<V2>
1806   // V1::value_type must be convertible to V2::value_type.
1807   template <typename V1, typename V2>
1808   void copy_and_convert_pixels(const V1& src, const V2& dst);
1809   template <typename V1, typename V2, typename ColorConverter>
1810   void copy_and_convert_pixels(const V1& src, const V2& dst, ColorConverter ccv);
1811
1812   // Equivalent of std::equal
1813   // where ImageViewConcept<V1>, ImageViewConcept<V2>, ViewsCompatibleConcept<V1,V2>
1814   template <typename V1, typename V2>
1815   bool equal_pixels(const V1& view1, const V2& view2);
1816
1817 Algorithms that take multiple views require that they have the same
1818 dimensions.  ``for_each_pixel_position`` and
1819 ``transform_pixel_positions`` pass pixel locators, as opposed to pixel
1820 references, to their function objects.  This allows for writing
1821 algorithms that use pixel neighbors, as the tutorial demonstrates.
1822
1823 Most of these algorithms check whether the image views are
1824 1D-traversable. A 1D-traversable image view has no gaps at the end of
1825 the rows.  In other words, if an x_iterator of that view is advanced
1826 past the last pixel in a row it will move to the first pixel of the
1827 next row.  When image views are 1D-traversable, the algorithms use a
1828 single loop and run more efficiently. If one or more of the input
1829 views are not 1D-traversable, the algorithms fall-back to an X-loop
1830 nested inside a Y-loop.
1831
1832 The algorithms typically delegate the work to their corresponding STL
1833 algorithms. For example, ``copy_pixels`` calls ``std::copy`` either
1834 for each row, or, when the images are 1D-traversable, once for all
1835 pixels.
1836
1837 In addition, overloads are sometimes provided for the STL
1838 algorithms. For example, ``std::copy`` for planar iterators is
1839 overloaded to perform ``std::copy`` for each of the
1840 planes. ``std::copy`` over bitwise-copyable pixels results in
1841 ``std::copy`` over unsigned char, which STL typically implements via
1842 ``memmove``.
1843
1844 As a result ``copy_pixels`` may result in a single call to ``memmove``
1845 for interleaved 1D-traversable views, or one per each plane of planar
1846 1D-traversable views, or one per each row of interleaved
1847 non-1D-traversable images, etc.
1848
1849 GIL also provides some beta-versions of image processing algorithms,
1850 such as resampling and convolution in a numerics extension available
1851 on http://stlab.adobe.com/gil/download.html. This code is in early
1852 stage of development and is not optimized for speed
1853
1854 Image
1855 -----
1856
1857 An image is a container that owns the pixels of a given image view. It
1858 allocates them in its constructor and deletes them in the
1859 destructor. It has a deep assignment operator and copy
1860 constructor. Images are used rarely, just when data ownership is
1861 important. Most STL algorithms operate on ranges, not
1862 containers. Similarly most GIL algorithms operate on image views
1863 (which images provide).
1864
1865 In the most general form images are N-dimensional and satisfy the
1866 following concept::
1867
1868   concept RandomAccessNDImageConcept<typename Img> : Regular<Img>
1869   {
1870     typename view_t; where MutableRandomAccessNDImageViewConcept<view_t>;
1871     typename const_view_t = view_t::const_t;
1872     typename point_t      = view_t::point_t;
1873     typename value_type   = view_t::value_type;
1874     typename allocator_type;
1875
1876     Img::Img(point_t dims, std::size_t alignment=0);
1877     Img::Img(point_t dims, value_type fill_value, std::size_t alignment);
1878
1879     void Img::recreate(point_t new_dims, std::size_t alignment=0);
1880     void Img::recreate(point_t new_dims, value_type fill_value, std::size_t alignment);
1881
1882     const point_t&        Img::dimensions() const;
1883     const const_view_t&   const_view(const Img&);
1884     const view_t&         view(Img&);
1885   };
1886
1887 Two-dimensional images have additional requirements::
1888
1889   concept RandomAccess2DImageConcept<RandomAccessNDImageConcept Img>
1890   {
1891     typename x_coord_t = const_view_t::x_coord_t;
1892     typename y_coord_t = const_view_t::y_coord_t;
1893
1894     Img::Img(x_coord_t width, y_coord_t height, std::size_t alignment=0);
1895     Img::Img(x_coord_t width, y_coord_t height, value_type fill_value, std::size_t alignment);
1896
1897     x_coord_t Img::width() const;
1898     y_coord_t Img::height() const;
1899
1900     void Img::recreate(x_coord_t width, y_coord_t height, std::size_t alignment=1);
1901     void Img::recreate(x_coord_t width, y_coord_t height, value_type fill_value, std::size_t alignment);
1902   };
1903
1904 GIL's images have views that model ``ImageViewConcept`` and
1905 operate on pixels.::
1906
1907   concept ImageConcept<RandomAccess2DImageConcept Img>
1908   {
1909     where MutableImageViewConcept<view_t>;
1910     typename coord_t  = view_t::coord_t;
1911   };
1912
1913 Images, unlike locators and image views, don't have 'mutable' set of
1914 concepts because immutable images are not very useful.
1915
1916 .. seealso::
1917
1918    - `RandomAccessNDImageConcept<Image> <reference/structboost_1_1gil_1_1_random_access_n_d_image_concept.html>`_
1919    - `RandomAccess2DImageConcept<Image> <reference/structboost_1_1gil_1_1_random_access2_d_image_concept.html>`_
1920    - `ImageConcept<Image> <reference/structboost_1_1gil_1_1_image_concept.html>`_
1921
1922 Models
1923 ~~~~~~
1924
1925 GIL provides a class, ``image``, which is templated over the value
1926 type (the pixel) and models ``ImageConcept``::
1927
1928   template <typename Pixel, \\ Models PixelValueConcept
1929           bool IsPlanar,  \\ planar or interleaved image
1930           typename A=std::allocator<unsigned char> >
1931   class image;
1932
1933 The image constructor takes an alignment parameter which allows for
1934 constructing images that are word-aligned or 8-byte aligned. The
1935 alignment is specified in bytes. The default value for alignment is 0,
1936 which means there is no padding at the end of rows. Many operations
1937 are faster using such 1D-traversable images, because
1938 ``image_view::x_iterator`` can be used to traverse the pixels, instead
1939 of the more complicated ``image_view::iterator``. Note that when
1940 alignment is 0, packed images are aligned to the bit - i.e. there are
1941 no padding bits at the end of rows of packed images.
1942
1943 Run-time specified images and image views
1944 -----------------------------------------
1945
1946 The color space, channel depth, channel ordering, and
1947 interleaved/planar structure of an image are defined by the type of
1948 its template argument, which makes them compile-time bound. Often some
1949 of these parameters are available only at run time.  Consider, for
1950 example, writing a module that opens the image at a given file path,
1951 rotates it and saves it back in its original color space and channel
1952 depth. How can we possibly write this using our generic image? What
1953 type is the image loading code supposed to return?
1954
1955 GIL's dynamic_image extension allows for images, image views or any
1956 GIL constructs to have their parameters defined at run time. Here is
1957 an example::
1958
1959   #include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
1960   using namespace boost;
1961
1962   #define ASSERT_SAME(A,B) static_assert(is_same< A,B >::value, "")
1963
1964   // Define the set of allowed images
1965   typedef mpl::vector<rgb8_image_t, cmyk16_planar_image_t> my_images_t;
1966
1967   // Create any_image class (or any_image_view) class
1968   typedef any_image<my_images_t> my_any_image_t;
1969
1970   // Associated view types are available (equivalent to the ones in image_t)
1971   typedef any_image_view<mpl::vector2<rgb8_view_t,  cmyk16_planar_view_t > > AV;
1972   ASSERT_SAME(my_any_image_t::view_t, AV);
1973
1974   typedef any_image_view<mpl::vector2<rgb8c_view_t, cmyk16c_planar_view_t> > CAV;
1975   ASSERT_SAME(my_any_image_t::const_view_t, CAV);
1976   ASSERT_SAME(my_any_image_t::const_view_t, my_any_image_t::view_t::const_t);
1977
1978   typedef any_image_view<mpl::vector2<rgb8_step_view_t, cmyk16_planar_step_view_t> > SAV;
1979   ASSERT_SAME(typename dynamic_x_step_type<my_any_image_t::view_t>::type, SAV);
1980
1981   // Assign it a concrete image at run time:
1982   my_any_image_t myImg = my_any_image_t(rgb8_image_t(100,100));
1983
1984   // Change it to another at run time. The previous image gets destroyed
1985   myImg = cmyk16_planar_image_t(200,100);
1986
1987   // Assigning to an image not in the allowed set throws an exception
1988   myImg = gray8_image_t();        // will throw std::bad_cast
1989
1990 ``any_image`` and ``any_image_view`` subclass from GIL's ``variant``
1991 class, which breaks down the instantiated type into a non-templated
1992 underlying base type and a unique instantiation type identifier. The
1993 underlying base instance is represented as a block of bytes. The block
1994 is large enough to hold the largest of the specified types.
1995
1996 GIL's variant is similar to ``boost::variant`` in spirit (hence we
1997 borrow the name from there) but it differs in several ways from the
1998 current boost implementation. Perhaps the biggest difference is that
1999 GIL's variant always takes a single argument, which is a model of MPL
2000 Random Access Sequence enumerating the allowed types. Having a single
2001 interface allows GIL's variant to be used easier in generic
2002 code. Synopsis::
2003
2004   template <typename Types>    // models MPL Random Access Container
2005   class variant
2006   {
2007     ...           _bits;
2008     std::size_t   _index;
2009   public:
2010     typedef Types types_t;
2011
2012     variant();
2013     variant(const variant& v);
2014     virtual ~variant();
2015
2016     variant& operator=(const variant& v);
2017     template <typename TS> friend bool operator==(const variant<TS>& x, const variant<TS>& y);
2018     template <typename TS> friend bool operator!=(const variant<TS>& x, const variant<TS>& y);
2019
2020     // Construct/assign to type T. Throws std::bad_cast if T is not in Types
2021     template <typename T> explicit variant(const T& obj);
2022     template <typename T> variant& operator=(const T& obj);
2023
2024     // Construct/assign by swapping T with its current instance. Only possible if they are swappable
2025     template <typename T> explicit variant(T& obj, bool do_swap);
2026     template <typename T> void move_in(T& obj);
2027
2028     template <typename T> static bool has_type();
2029
2030     template <typename T> const T& _dynamic_cast() const;
2031     template <typename T>       T& _dynamic_cast();
2032
2033     template <typename T> bool current_type_is() const;
2034   };
2035
2036   template <typename UOP, typename Types>
2037    UOP::result_type apply_operation(variant<Types>& v, UOP op);
2038   template <typename UOP, typename Types>
2039    UOP::result_type apply_operation(const variant<Types>& v, UOP op);
2040
2041   template <typename BOP, typename Types1, typename Types2>
2042    BOP::result_type apply_operation(      variant<Types1>& v1,       variant<Types2>& v2, UOP op);
2043
2044   template <typename BOP, typename Types1, typename Types2>
2045    BOP::result_type apply_operation(const variant<Types1>& v1,       variant<Types2>& v2, UOP op);
2046
2047   template <typename BOP, typename Types1, typename Types2>
2048    BOP::result_type apply_operation(const variant<Types1>& v1, const variant<Types2>& v2, UOP op);
2049
2050 GIL's ``any_image_view`` and ``any_image`` are subclasses of ``variant``::
2051
2052   template <typename ImageViewTypes>
2053   class any_image_view : public variant<ImageViewTypes>
2054   {
2055   public:
2056     typedef ... const_t; // immutable equivalent of this
2057     typedef std::ptrdiff_t x_coord_t;
2058     typedef std::ptrdiff_t y_coord_t;
2059     typedef point<std::ptrdiff_t> point_t;
2060
2061     any_image_view();
2062     template <typename T> explicit any_image_view(const T& obj);
2063     any_image_view(const any_image_view& v);
2064
2065     template <typename T> any_image_view& operator=(const T& obj);
2066     any_image_view&                       operator=(const any_image_view& v);
2067
2068     // parameters of the currently instantiated view
2069     std::size_t num_channels()  const;
2070     point_t     dimensions()    const;
2071     x_coord_t   width()         const;
2072     y_coord_t   height()        const;
2073   };
2074
2075   template <typename ImageTypes>
2076   class any_image : public variant<ImageTypes>
2077   {
2078     typedef variant<ImageTypes> parent_t;
2079   public:
2080     typedef ... const_view_t;
2081     typedef ... view_t;
2082     typedef std::ptrdiff_t x_coord_t;
2083     typedef std::ptrdiff_t y_coord_t;
2084     typedef point<std::ptrdiff_t> point_t;
2085
2086     any_image();
2087     template <typename T> explicit any_image(const T& obj);
2088     template <typename T> explicit any_image(T& obj, bool do_swap);
2089     any_image(const any_image& v);
2090
2091     template <typename T> any_image& operator=(const T& obj);
2092     any_image&                       operator=(const any_image& v);
2093
2094     void recreate(const point_t& dims, unsigned alignment=1);
2095     void recreate(x_coord_t width, y_coord_t height, unsigned alignment=1);
2096
2097     std::size_t num_channels()  const;
2098     point_t     dimensions()    const;
2099     x_coord_t   width()         const;
2100     y_coord_t   height()        const;
2101   };
2102
2103 Operations are invoked on variants via ``apply_operation`` passing a
2104 function object to perform the operation. The code for every allowed
2105 type in the variant is instantiated and the appropriate instantiation
2106 is selected via a switch statement. Since image view algorithms
2107 typically have time complexity at least linear on the number of
2108 pixels, the single switch statement of image view variant adds
2109 practically no measurable performance overhead compared to templated
2110 image views.
2111
2112 Variants behave like the underlying type. Their copy constructor will
2113 invoke the copy constructor of the underlying instance. Equality
2114 operator will check if the two instances are of the same type and then
2115 invoke their operator==, etc. The default constructor of a variant
2116 will default-construct the first type. That means that
2117 ``any_image_view`` has shallow default-constructor, copy-constructor,
2118 assignment and equality comparison, whereas ``any_image`` has deep
2119 ones.
2120
2121 It is important to note that even though ``any_image_view`` and
2122 ``any_image`` resemble the static ``image_view`` and ``image``, they
2123 do not model the full requirements of ``ImageViewConcept`` and
2124 ``ImageConcept``. In particular they don't provide access to the
2125 pixels. There is no "any_pixel" or "any_pixel_iterator" in GIL. Such
2126 constructs could be provided via the ``variant`` mechanism, but doing
2127 so would result in inefficient algorithms, since the type resolution
2128 would have to be performed per pixel. Image-level algorithms should be
2129 implemented via ``apply_operation``. That said, many common operations
2130 are shared between the static and dynamic types. In addition, all of
2131 the image view transformations and many STL-like image view algorithms
2132 have overloads operating on ``any_image_view``, as illustrated with
2133 ``copy_pixels``::
2134
2135   rgb8_view_t v1(...);  // concrete image view
2136   bgr8_view_t v2(...);  // concrete image view compatible with v1 and of the same size
2137   any_image_view<Types>  av(...);  // run-time specified image view
2138
2139   // Copies the pixels from v1 into v2.
2140   // If the pixels are incompatible triggers compile error
2141   copy_pixels(v1,v2);
2142
2143   // The source or destination (or both) may be run-time instantiated.
2144   // If they happen to be incompatible, throws std::bad_cast
2145   copy_pixels(v1, av);
2146   copy_pixels(av, v2);
2147   copy_pixels(av, av);
2148
2149 By having algorithm overloads supporting dynamic constructs, we create
2150 a base upon which it is possible to write algorithms that can work
2151 with either compile-time or runtime images or views. The following
2152 code, for example, uses the GIL I/O extension to turn an image on disk
2153 upside down::
2154
2155   #include <boost\gil\extension\io\jpeg_dynamic_io.hpp>
2156
2157   template <typename Image>    // Could be rgb8_image_t or any_image<...>
2158   void save_180rot(const std::string& file_name)
2159   {
2160     Image img;
2161     jpeg_read_image(file_name, img);
2162     jpeg_write_view(file_name, rotated180_view(view(img)));
2163   }
2164
2165 It can be instantiated with either a compile-time or a runtime image
2166 because all functions it uses have overloads taking runtime
2167 constructs.  For example, here is how ``rotated180_view`` is
2168 implemented::
2169
2170   // implementation using templated view
2171   template <typename View>
2172   typename dynamic_xy_step_type<View>::type rotated180_view(const View& src) { ... }
2173
2174   namespace detail
2175   {
2176     // the function, wrapped inside a function object
2177     template <typename Result> struct rotated180_view_fn
2178     {
2179         typedef Result result_type;
2180         template <typename View> result_type operator()(const View& src) const
2181   {
2182             return result_type(rotated180_view(src));
2183         }
2184     };
2185   }
2186
2187   // overloading of the function using variant. Takes and returns run-time bound view.
2188   // The returned view has a dynamic step
2189   template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
2190   typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type rotated180_view(const any_image_view<ViewTypes>& src)
2191   {
2192     return apply_operation(src,detail::rotated180_view_fn<typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type>());
2193   }
2194
2195 Variants should be used with caution (especially algorithms that take
2196 more than one variant) because they instantiate the algorithm for
2197 every possible model that the variant can take. This can take a toll
2198 on compile time and executable size.  Despite these limitations,
2199 ``variant`` is a powerful technique that allows us to combine the
2200 speed of compile-time resolution with the flexibility of run-time
2201 resolution. It allows us to treat images of different parameters
2202 uniformly as a collection and store them in the same container.
2203
2204
2205 Useful Metafunctions and Typedefs
2206 ---------------------------------
2207
2208 Flexibility comes at a price. GIL types can be very long and hard to
2209 read.  To address this problem, GIL provides typedefs to refer to any
2210 standard image, pixel iterator, pixel locator, pixel reference or
2211 pixel value.  They follow this pattern:
2212
2213 *ColorSpace* + *BitDepth* + ["s|f"] + ["c"] + ["_planar"] +
2214  ["_step"] + *ClassType* + "_t"
2215
2216 where *ColorSpace* also indicates the ordering of components. Examples
2217 are ``rgb``, ``bgr``, ``cmyk``, ``rgba``. *BitDepth* can be, for
2218 example, ``8``,``16``,``32``. By default the bits are unsigned
2219 integral type. Append ``s`` to the bit depth to indicate signed
2220 integral, or ``f`` to indicate floating point. ``c`` indicates object
2221 whose associated pixel reference is immutable. ``_planar`` indicates
2222 planar organization (as opposed to interleaved). ``_step`` indicates
2223 the type has a dynamic step and *ClassType* is ``_image`` (image,
2224 using a standard allocator), ``_view`` (image view), ``_loc`` (pixel
2225 locator), ``_ptr`` (pixel iterator), ``_ref`` (pixel reference),
2226 ``_pixel`` (pixel value). Here are examples::
2227
2228   bgr8_image_t               i;     // 8-bit unsigned (unsigned char) interleaved BGR image
2229   cmyk16_pixel_t;            x;     // 16-bit unsigned (unsigned short) CMYK pixel value;
2230   cmyk16sc_planar_ref_t      p(x);  // const reference to a 16-bit signed integral (signed short) planar CMYK pixel x.
2231   rgb32f_planar_step_ptr_t   ii;    // step iterator to a floating point 32-bit (float) planar RGB pixel.
2232
2233 GIL provides the metafunctions that return the types of standard
2234 homogeneous memory-based GIL constructs given a channel type, a
2235 layout, and whether the construct is planar, has a step along the X
2236 direction, and is mutable::
2237
2238   template <typename ChannelValue, typename Layout, bool IsPlanar=false, bool IsMutable=true>
2239   struct pixel_reference_type { typedef ... type; };
2240
2241   template <typename Channel, typename Layout>
2242   struct pixel_value_type { typedef ... type; };
2243
2244   template <typename ChannelValue, typename Layout, bool IsPlanar=false, bool IsStep=false,  bool IsMutable=true>
2245   struct iterator_type { typedef ... type; };
2246
2247   template <typename ChannelValue, typename Layout, bool IsPlanar=false, bool IsXStep=false, bool IsMutable=true>
2248   struct locator_type { typedef ... type; };
2249
2250   template <typename ChannelValue, typename Layout, bool IsPlanar=false, bool IsXStep=false, bool IsMutable=true>
2251   struct view_type { typedef ... type; };
2252
2253   template <typename ChannelValue, typename Layout, bool IsPlanar=false, typename Alloc=std::allocator<unsigned char> >
2254   struct image_type { typedef ... type; };
2255
2256   template <typename BitField, typename ChannelBitSizeVector, typename Layout, typename Alloc=std::allocator<unsigned char> >
2257   struct packed_image_type { typedef ... type; };
2258
2259   template <typename ChannelBitSizeVector, typename Layout, typename Alloc=std::allocator<unsigned char> >
2260   struct bit_aligned_image_type { typedef ... type; };
2261
2262 There are also helper metafunctions to construct packed and
2263 bit-aligned images with up to five channels::
2264
2265   template <typename BitField, unsigned Size1,
2266           typename Layout, typename Alloc=std::allocator<unsigned char> >
2267   struct packed_image1_type { typedef ... type; };
2268
2269   template <typename BitField, unsigned Size1, unsigned Size2,
2270           typename Layout, typename Alloc=std::allocator<unsigned char> >
2271   struct packed_image2_type { typedef ... type; };
2272
2273   template <typename BitField, unsigned Size1, unsigned Size2, unsigned Size3,
2274           typename Layout, typename Alloc=std::allocator<unsigned char> >
2275   struct packed_image3_type { typedef ... type; };
2276
2277   template <typename BitField, unsigned Size1, unsigned Size2, unsigned Size3, unsigned Size4,
2278           typename Layout, typename Alloc=std::allocator<unsigned char> >
2279   struct packed_image4_type { typedef ... type; };
2280
2281   template <typename BitField, unsigned Size1, unsigned Size2, unsigned Size3, unsigned Size4, unsigned Size5,
2282           typename Layout, typename Alloc=std::allocator<unsigned char> >
2283   struct packed_image5_type { typedef ... type; };
2284
2285   template <unsigned Size1,
2286           typename Layout, typename Alloc=std::allocator<unsigned char> >
2287   struct bit_aligned_image1_type { typedef ... type; };
2288
2289   template <unsigned Size1, unsigned Size2,
2290           typename Layout, typename Alloc=std::allocator<unsigned char> >
2291   struct bit_aligned_image2_type { typedef ... type; };
2292
2293   template <unsigned Size1, unsigned Size2, unsigned Size3,
2294           typename Layout, typename Alloc=std::allocator<unsigned char> >
2295   struct bit_aligned_image3_type { typedef ... type; };
2296
2297   template <unsigned Size1, unsigned Size2, unsigned Size3, unsigned Size4,
2298           typename Layout, typename Alloc=std::allocator<unsigned char> >
2299   struct bit_aligned_image4_type { typedef ... type; };
2300
2301   template <unsigned Size1, unsigned Size2, unsigned Size3, unsigned Size4, unsigned Size5,
2302           typename Layout, typename Alloc=std::allocator<unsigned char> >
2303   struct bit_aligned_image5_type { typedef ... type; };
2304
2305 Here ``ChannelValue`` models ``ChannelValueConcept``. We don't need
2306 ``IsYStep`` because GIL's memory-based locator and view already allow
2307 the vertical step to be specified dynamically. Iterators and views can
2308 be constructed from a pixel type::
2309
2310   template <typename Pixel, bool IsPlanar=false, bool IsStep=false, bool IsMutable=true>
2311   struct iterator_type_from_pixel { typedef ... type; };
2312
2313   template <typename Pixel, bool IsPlanar=false, bool IsStepX=false, bool IsMutable=true>
2314   struct view_type_from_pixel { typedef ... type; };
2315
2316 Using a heterogeneous pixel type will result in heterogeneous
2317 iterators and views. Types can also be constructed from horizontal
2318 iterator::
2319
2320   template <typename XIterator>
2321   struct type_from_x_iterator
2322   {
2323     typedef ... step_iterator_t;
2324     typedef ... xy_locator_t;
2325     typedef ... view_t;
2326   };
2327
2328 There are metafunctions to construct the type of a construct from an
2329 existing type by changing one or more of its properties::
2330
2331   template <typename PixelReference,
2332           typename ChannelValue, typename Layout, typename IsPlanar, typename IsMutable>
2333   struct derived_pixel_reference_type
2334   {
2335     typedef ... type;  // Models PixelConcept
2336   };
2337
2338   template <typename Iterator,
2339           typename ChannelValue, typename Layout, typename IsPlanar, typename IsStep, typename IsMutable>
2340   struct derived_iterator_type
2341   {
2342     typedef ... type;  // Models PixelIteratorConcept
2343   };
2344
2345   template <typename View,
2346           typename ChannelValue, typename Layout, typename IsPlanar, typename IsXStep, typename IsMutable>
2347   struct derived_view_type
2348   {
2349     typedef ... type;  // Models ImageViewConcept
2350   };
2351
2352   template <typename Image,
2353           typename ChannelValue, typename Layout, typename IsPlanar>
2354   struct derived_image_type
2355   {
2356     typedef ... type;  // Models ImageConcept
2357   };
2358
2359 You can replace one or more of its properties and use
2360 ``boost::use_default`` for the rest. In this case ``IsPlanar``,
2361 ``IsStep`` and ``IsMutable`` are MPL boolean constants. For example,
2362 here is how to create the type of a view just like ``View``, but being
2363 grayscale and planar::
2364
2365   typedef typename derived_view_type<View, boost::use_default, gray_t, mpl::true_>::type VT;
2366
2367 You can get pixel-related types of any pixel-based GIL constructs
2368 (pixels, iterators, locators and views) using the following
2369 metafunctions provided by PixelBasedConcept,
2370 HomogeneousPixelBasedConcept and metafunctions built on top of them::
2371
2372   template <typename T> struct color_space_type { typedef ... type; };
2373   template <typename T> struct channel_mapping_type { typedef ... type; };
2374   template <typename T> struct is_planar { typedef ... type; };
2375
2376   // Defined by homogeneous constructs
2377   template <typename T> struct channel_type { typedef ... type; };
2378   template <typename T> struct num_channels { typedef ... type; };
2379
2380 These are metafunctions, some of which return integral types which can
2381 be evaluated like this::
2382
2383   static_assert(is_planar<rgb8_planar_view_t>::value == true, "");
2384
2385 GIL also supports type analysis metafunctions of the form:
2386 [pixel_reference/iterator/locator/view/image] + "_is_" +
2387 [basic/mutable/step]. For example::
2388
2389   if (view_is_mutable<View>::value)
2390   {
2391    ...
2392   }
2393
2394 A *basic* GIL construct is a memory-based construct that uses the
2395 built-in GIL classes and does not have any function object to invoke
2396 upon dereferencing.  For example, a simple planar or interleaved, step
2397 or non-step RGB image view is basic, but a color converted view or a
2398 virtual view is not.
2399
2400 I/O Extension
2401 -------------
2402
2403 GIL's I/O extension provides low level image i/o utilities. It
2404 supports loading and saving several image formats, each of which
2405 requires linking against the corresponding library:
2406
2407 :JPEG: To use JPEG files, include the file
2408        ``gil/extension/io/jpeg_io.hpp``. If you are using run-time
2409        images, you need to include
2410        ``gil/extension/io/jpeg_dynamic_io.hpp`` instead. You need to
2411        compile and link against libjpeg.lib (available at
2412        http://www.ijg.org). You need to have ``jpeglib.h`` in your
2413        include path.
2414
2415 :TIFF: To use TIFF files, include the file
2416        ``gil/extension/io/tiff_io.hpp``. If you are using run-time
2417        images, you need to include
2418        ``gil/extension/io/tiff_dynamic_io.hpp`` instead. You need to
2419        compile and link against libtiff.lib (available at
2420        http://www.libtiff.org). You need to have ``tiffio.h`` in your
2421        include path.
2422
2423 :PNG: To use PNG files, include the file
2424       ``gil/extension/io/png_io.hpp``. If you are using run-time
2425       images, you need to include
2426       ``gil/extension/io/png_dynamic_io.hpp`` instead. You need to
2427       compile and link against libpng.lib (available at
2428       http://wwwlibpng.org). You need to have ``png.h`` in your
2429       include path.
2430
2431 You don't need to install all these libraries; just the ones you will
2432 use.  Here are the I/O APIs for JPEG files (replace "jpeg" with "tiff"
2433 or "png" for the APIs of the other libraries)::
2434
2435   // Returns the width and height of the JPEG file at the specified location.
2436   // Throws std::ios_base::failure if the location does not correspond to a valid JPEG file
2437   point<std::ptrdiff_t> jpeg_read_dimensions(const char*);
2438
2439   // Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it.
2440   // 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.
2441   // Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not
2442   // compatible with the ones specified by Image
2443   template <typename Img> void jpeg_read_image(const char*, Img&);
2444
2445   // Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it,
2446   // color-converting and channel-converting if necessary.
2447   // 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.
2448   // Throws std::ios_base::failure if the file is not a valid JPEG file or if it fails to read it.
2449   template <typename Img>               void jpeg_read_and_convert_image(const char*, Img&);
2450   template <typename Img, typename CCV> void jpeg_read_and_convert_image(const char*, Img&, CCV color_converter);
2451
2452   // Loads the image specified by the given jpeg image file name into the given view.
2453   // 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.
2454   // Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not
2455   // compatible with the ones specified by View, or if its dimensions don't match the ones of the view.
2456   template <typename View> void jpeg_read_view(const char*, const View&);
2457
2458   // Loads the image specified by the given jpeg image file name into the given view and color-converts (and channel-converts) it if necessary.
2459   // 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.
2460   // 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.
2461   template <typename View>               void jpeg_read_and_convert_view(const char*, const View&);
2462   template <typename View, typename CCV> void jpeg_read_and_convert_view(const char*, const View&, CCV color_converter);
2463
2464   // Saves the view to a jpeg file specified by the given jpeg image file name.
2465   // 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.
2466   // Throws std::ios_base::failure if it fails to create the file.
2467   template <typename View> void jpeg_write_view(const char*, const View&);
2468
2469   // Determines whether the given view type is supported for reading
2470   template <typename View> struct jpeg_read_support
2471   {
2472     static const bool value = ...;
2473   };
2474
2475   // Determines whether the given view type is supported for writing
2476   template <typename View> struct jpeg_write_support
2477   {
2478     static const bool value = ...;
2479   };
2480
2481 If you use the dynamic image extension, make sure to include
2482 ``"jpeg_dynamic_io.hpp"`` instead of ``"jpeg_io.hpp"``.  In addition
2483 to the above methods, you have the following overloads dealing with
2484 dynamic images::
2485
2486   // 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
2487   // and creates a new image of that type with the dimensions specified by the image file.
2488   // Throws std::ios_base::failure if none of the types in Images are compatible with the type on disk.
2489   template <typename Images> void jpeg_read_image(const char*, any_image<Images>&);
2490
2491   // Saves the currently instantiated view to a jpeg file specified by the given jpeg image file name.
2492   // Throws std::ios_base::failure if the currently instantiated view type is not supported for writing by the I/O extension
2493   // or if it fails to create the file.
2494   template <typename Views>  void jpeg_write_view(const char*, any_image_view<Views>&);
2495
2496 All of the above methods have overloads taking ``std::string`` instead
2497 of ``const char*``
2498
2499 Sample Code
2500 -----------
2501
2502 Pixel-level Sample Code
2503 ~~~~~~~~~~~~~~~~~~~~~~~
2504
2505 Here are some operations you can do with pixel values,
2506 pointers and references::
2507
2508   rgb8_pixel_t p1(255,0,0);     // make a red RGB pixel
2509   bgr8_pixel_t p2 = p1;         // RGB and BGR are compatible and the channels will be properly mapped.
2510   assert(p1==p2);               // p2 will also be red.
2511   assert(p2[0]!=p1[0]);         // operator[] gives physical channel order (as laid down in memory)
2512   assert(semantic_at_c<0>(p1)==semantic_at_c<0>(p2)); // this is how to compare the two red channels
2513   get_color(p1,green_t()) = get_color(p2,blue_t());  // channels can also be accessed by name
2514
2515   const unsigned char* r;
2516   const unsigned char* g;
2517   const unsigned char* b;
2518   rgb8c_planar_ptr_t ptr(r,g,b); // constructing const planar pointer from const pointers to each plane
2519
2520   rgb8c_planar_ref_t ref=*ptr;   // just like built-in reference, dereferencing a planar pointer returns a planar reference
2521
2522   p2=ref; p2=p1; p2=ptr[7]; p2=rgb8_pixel_t(1,2,3);    // planar/interleaved references and values to RGB/BGR can be freely mixed
2523
2524   //rgb8_planar_ref_t ref2;      // compile error: References have no default constructors
2525   //ref2=*ptr;                   // compile error: Cannot construct non-const reference by dereferencing const pointer
2526   //ptr[3]=p1;                   // compile error: Cannot set the fourth pixel through a const pointer
2527   //p1 = pixel<float, rgb_layout_t>();// compile error: Incompatible channel depth
2528   //p1 = pixel<bits8, rgb_layout_t>();// compile error: Incompatible color space (even though it has the same number of channels)
2529   //p1 = pixel<bits8,rgba_layout_t>();// compile error: Incompatible color space (even though it contains red, green and blue channels)
2530
2531 Here is how to use pixels in generic code::
2532
2533   template <typename GrayPixel, typename RGBPixel>
2534   void gray_to_rgb(const GrayPixel& src, RGBPixel& dst)
2535   {
2536     gil_function_requires<PixelConcept<GrayPixel> >();
2537     gil_function_requires<MutableHomogeneousPixelConcept<RGBPixel> >();
2538
2539     typedef typename color_space_type<GrayPixel>::type gray_cs_t;
2540     static_assert(boost::is_same<gray_cs_t,gray_t>::value, "");
2541
2542     typedef typename color_space_type<RGBPixel>::type  rgb_cs_t;
2543     static_assert(boost::is_same<rgb_cs_t,rgb_t>::value, "");
2544
2545     typedef typename channel_type<GrayPixel>::type gray_channel_t;
2546     typedef typename channel_type<RGBPixel>::type  rgb_channel_t;
2547
2548     gray_channel_t gray = get_color(src,gray_color_t());
2549     static_fill(dst, channel_convert<rgb_channel_t>(gray));
2550   }
2551
2552   // example use patterns:
2553
2554   // converting gray l-value to RGB and storing at (5,5) in a 16-bit BGR interleaved image:
2555   bgr16_view_t b16(...);
2556   gray_to_rgb(gray8_pixel_t(33), b16(5,5));
2557
2558   // storing the first pixel of an 8-bit grayscale image as the 5-th pixel of 32-bit planar RGB image:
2559   rgb32f_planar_view_t rpv32;
2560   gray8_view_t gv8(...);
2561   gray_to_rgb(*gv8.begin(), rpv32[5]);
2562
2563 As the example shows, both the source and the destination can be
2564 references or values, planar or interleaved, as long as they model
2565 ``PixelConcept`` and ``MutablePixelConcept`` respectively.
2566
2567
2568 Creating a Copy of an Image with a Safe Buffer
2569 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2570
2571 Suppose we want to convolve an image with multiple kernels, the
2572 largest of which is 2K+1 x 2K+1 pixels. It may be worth creating a
2573 margin of K pixels around the image borders. Here is how to do it::
2574
2575   template <typename SrcView,   // Models ImageViewConcept (the source view)
2576           typename DstImage>  // Models ImageConcept     (the returned image)
2577   void create_with_margin(const SrcView& src, int k, DstImage& result)
2578   {
2579     gil_function_requires<ImageViewConcept<SrcView> >();
2580     gil_function_requires<ImageConcept<DstImage> >();
2581     gil_function_requires<ViewsCompatibleConcept<SrcView, typename DstImage::view_t> >();
2582
2583     result=DstImage(src.width()+2*k, src.height()+2*k);
2584     typename DstImage::view_t centerImg=subimage_view(view(result), k,k,src.width(),src.height());
2585     std::copy(src.begin(), src.end(), centerImg.begin());
2586   }
2587
2588 We allocated a larger image, then we used ``subimage_view`` to create
2589 a shallow image of its center area of top left corner at (k,k) and of
2590 identical size as ``src``, and finally we copied ``src`` into that
2591 center image. If the margin needs initialization, we could have done
2592 it with ``fill_pixels``. Here is how to simplify this code using the
2593 ``copy_pixels`` algorithm::
2594
2595   template <typename SrcView, typename DstImage>
2596   void create_with_margin(const SrcView& src, int k, DstImage& result)
2597   {
2598     result.recreate(src.width()+2*k, src.height()+2*k);
2599     copy_pixels(src, subimage_view(view(result), k,k,src.width(),src.height()));
2600   }
2601
2602 (Note also that ``image::recreate`` is more efficient than
2603 ``operator=``, as the latter will do an unnecessary copy
2604 construction).  Not only does the above example work for planar and
2605 interleaved images of any color space and pixel depth; it is also
2606 optimized.  GIL overrides ``std::copy`` - when called on two identical
2607 interleaved images with no padding at the end of rows, it simply does
2608 a ``memmove``. For planar images it does ``memmove`` for each
2609 channel. If one of the images has padding, (as in our case) it will
2610 try to do ``memmove`` for each row. When an image has no padding, it
2611 will use its lightweight horizontal iterator (as opposed to the more
2612 complex 1D image iterator that has to check for the end of rows).  It
2613 choses the fastest method, taking into account both static and
2614 run-time parameters.
2615
2616 Histogram
2617 ~~~~~~~~~
2618
2619 The histogram can be computed by counting the number of pixel values
2620 that fall in each bin.  The following method takes a grayscale
2621 (one-dimensional) image view, since only grayscale pixels are
2622 convertible to integers::
2623
2624   template <typename GrayView, typename R>
2625   void grayimage_histogram(const GrayView& img, R& hist)
2626   {
2627     for (typename GrayView::iterator it=img.begin(); it!=img.end(); ++it)
2628         ++hist[*it];
2629   }
2630
2631 Using ``boost::lambda`` and GIL's ``for_each_pixel`` algorithm, we can
2632 write this more compactly::
2633
2634   template <typename GrayView, typename R>
2635   void grayimage_histogram(const GrayView& v, R& hist)
2636   {
2637     for_each_pixel(v, ++var(hist)[_1]);
2638   }
2639
2640 Where ``for_each_pixel`` invokes ``std::for_each`` and ``var`` and
2641 ``_1`` are ``boost::lambda`` constructs.  To compute the luminosity
2642 histogram, we call the above method using the grayscale view of an
2643 image::
2644
2645   template <typename View, typename R>
2646   void luminosity_histogram(const View& v, R& hist)
2647   {
2648     grayimage_histogram(color_converted_view<gray8_pixel_t>(v),hist);
2649   }
2650
2651 This is how to invoke it::
2652
2653   unsigned char hist[256];
2654   std::fill(hist,hist+256,0);
2655   luminosity_histogram(my_view,hist);
2656
2657 If we want to view the histogram of the second channel of the image in
2658 the top left 100x100 area, we call::
2659
2660   grayimage_histogram(nth_channel_view(subimage_view(img,0,0,100,100),1),hist);
2661
2662 No pixels are copied and no extra memory is allocated - the code
2663 operates directly on the source pixels, which could be in any
2664 supported color space and channel depth. They could be either planar
2665 or interleaved.
2666
2667 Using Image Views
2668 ~~~~~~~~~~~~~~~~~
2669
2670 The following code illustrates the power of using image views::
2671
2672   jpeg_read_image("monkey.jpg", img);
2673   step1=view(img);
2674   step2=subimage_view(step1, 200,300, 150,150);
2675   step3=color_converted_view<rgb8_view_t,gray8_pixel_t>(step2);
2676   step4=rotated180_view(step3);
2677   step5=subsampled_view(step4, 2,1);
2678   jpeg_write_view("monkey_transform.jpg", step5);
2679
2680 The intermediate images are shown here:
2681
2682 .. image:: images/monkey_steps.jpg
2683
2684 Notice that no pixels are ever copied. All the work is done inside
2685 ``jpeg_write_view``.  If we call our ``luminosity_histogram`` with
2686 ``step5`` it will do the right thing.
2687
2688
2689 Extending the Generic Image Library
2690 -----------------------------------
2691
2692 You can define your own pixel iterators, locators, image views,
2693 images, channel types, color spaces and algorithms.  You can make
2694 virtual images that live on the disk, inside a jpeg file, somewhere on
2695 the internet, or even fully-synthetic images such as the Mandelbrot
2696 set.  As long as they properly model the corresponding concepts, they
2697 will work with any existing GIL code.  Most such extensions require no
2698 changes to the library and can thus be supplied in another module.
2699
2700 Defining New Color Spaces
2701 ~~~~~~~~~~~~~~~~~~~~~~~~~
2702
2703 Each color space is in a separate file. To add a new color space, just
2704 copy one of the existing ones (like rgb.hpp) and change it
2705 accordingly. If you want color conversion support, you will have to
2706 provide methods to convert between it and the existing color spaces
2707 (see color_convert.h). For convenience you may want to provide useful
2708 typedefs for pixels, pointers, references and images with the new
2709 color space (see typedefs.h).
2710
2711 Defining New Channel Types
2712 ~~~~~~~~~~~~~~~~~~~~~~~~~~
2713
2714 Most of the time you don't need to do anything special to use a new
2715 channel type. You can just use it::
2716
2717   typedef pixel<double,rgb_layout_t>   rgb64_pixel_t;    // 64 bit RGB pixel
2718   typedef rgb64_pixel*                 rgb64_pixel_ptr_t;// pointer to 64-bit interleaved data
2719   typedef image_type<double,rgb_layout_t>::type rgb64_image_t;    // 64-bit interleaved image
2720
2721 If you want to use your own channel class, you will need to provide a
2722 specialization of ``channel_traits`` for it (see channel.hpp).  If you
2723 want to do conversion between your and existing channel types, you
2724 will need to provide an overload of ``channel_convert``.
2725
2726 Overloading Color Conversion
2727 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2728
2729 Suppose you want to provide your own color conversion. For example,
2730 you may want to implement higher quality color conversion using color
2731 profiles.  Typically you may want to redefine color conversion only in
2732 some instances and default to GIL's color conversion in all other
2733 cases. Here is, for example, how to overload color conversion so that
2734 color conversion to gray inverts the result but everything else
2735 remains the same::
2736
2737   // make the default use GIL's default
2738   template <typename SrcColorSpace, typename DstColorSpace>
2739   struct my_color_converter_impl
2740   : public default_color_converter_impl<SrcColorSpace,DstColorSpace> {};
2741
2742   // provide specializations only for cases you care about
2743   // (in this case, if the destination is grayscale, invert it)
2744   template <typename SrcColorSpace>
2745   struct my_color_converter_impl<SrcColorSpace,gray_t>
2746   {
2747     template <typename SrcP, typename DstP>  // Model PixelConcept
2748     void operator()(const SrcP& src, DstP& dst) const
2749     {
2750         default_color_converter_impl<SrcColorSpace,gray_t>()(src,dst);
2751         get_color(dst,gray_color_t())=channel_invert(get_color(dst,gray_color_t()));
2752     }
2753   };
2754
2755   // create a color converter object that dispatches to your own implementation
2756   struct my_color_converter
2757   {
2758     template <typename SrcP, typename DstP>  // Model PixelConcept
2759     void operator()(const SrcP& src,DstP& dst) const
2760     {
2761         typedef typename color_space_type<SrcP>::type SrcColorSpace;
2762         typedef typename color_space_type<DstP>::type DstColorSpace;
2763         my_color_converter_impl<SrcColorSpace,DstColorSpace>()(src,dst);
2764     }
2765   };
2766
2767 GIL's color conversion functions take the color converter as an
2768 optional parameter. You can pass your own color converter::
2769
2770   color_converted_view<gray8_pixel_t>(img_view,my_color_converter());
2771
2772 Defining New Image Views
2773 ~~~~~~~~~~~~~~~~~~~~~~~~
2774
2775 You can provide your own pixel iterators, locators and views,
2776 overriding either the mechanism for getting from one pixel to the next
2777 or doing an arbitrary pixel transformation on dereference. For
2778 example, let's look at the implementation of ``color_converted_view``
2779 (an image factory method that, given any image view, returns a new,
2780 otherwise identical view, except that color conversion is performed on
2781 pixel access).  First we need to define a model of
2782 ``PixelDereferenceAdaptorConcept``; a function object that will be
2783 called when we dereference a pixel iterator.  It will call
2784 ``color_convert`` to convert to the destination pixel type::
2785
2786   template <typename SrcConstRefP,  // const reference to the source pixel
2787           typename DstP>          // Destination pixel value (models PixelValueConcept)
2788   class color_convert_deref_fn
2789   {
2790   public:
2791     typedef color_convert_deref_fn const_t;
2792     typedef DstP                value_type;
2793     typedef value_type          reference;      // read-only dereferencing
2794     typedef const value_type&   const_reference;
2795     typedef SrcConstRefP        argument_type;
2796     typedef reference           result_type;
2797     static bool constexpr is_mutable = false;
2798
2799     result_type operator()(argument_type srcP) const {
2800         result_type dstP;
2801         color_convert(srcP,dstP);
2802         return dstP;
2803     }
2804   };
2805
2806 We then use the ``add_deref`` member struct of image views to
2807 construct the type of a view that invokes a given function object
2808 (``deref_t``) upon dereferencing. In our case, it performs color
2809 conversion::
2810
2811   template <typename SrcView, typename DstP>
2812   struct color_converted_view_type
2813   {
2814   private:
2815     typedef typename SrcView::const_t::reference src_pix_ref;  // const reference to pixel in SrcView
2816     typedef color_convert_deref_fn<src_pix_ref, DstP> deref_t; // the dereference adaptor that performs color conversion
2817     typedef typename SrcView::template add_deref<deref_t> add_ref_t;
2818   public:
2819     typedef typename add_ref_t::type type; // the color converted view type
2820     static type make(const SrcView& sv) { return add_ref_t::make(sv, deref_t()); }
2821   };
2822
2823 Finally our ``color_converted_view`` code simply creates
2824 color-converted view from the source view::
2825
2826   template <typename DstP, typename View> inline
2827   typename color_converted_view_type<View,DstP>::type color_convert_view(const View& src)
2828   {
2829     return color_converted_view_type<View,DstP>::make(src);
2830   }
2831
2832 (The actual color convert view transformation is slightly more
2833 complicated, as it takes an optional color conversion object, which
2834 allows users to specify their own color conversion methods).  See the
2835 GIL tutorial for an example of creating a virtual image view that
2836 defines the Mandelbrot set.
2837
2838 Technicalities
2839 --------------
2840
2841 Creating a reference proxy
2842 ~~~~~~~~~~~~~~~~~~~~~~~~~~
2843
2844 Sometimes it is necessary to create a proxy class that represents a
2845 reference to a given object. Examples of these are GIL's reference to
2846 a planar pixel (``planar_pixel_reference``) and GIL's sub-byte channel
2847 references. Writing a reference proxy class can be tricky. One problem
2848 is that the proxy reference is constructed as a temporary object and
2849 returned by value upon dereferencing the iterator::
2850
2851   struct rgb_planar_pixel_iterator
2852   {
2853    typedef my_reference_proxy<T> reference;
2854    reference operator*() const { return reference(red,green,blue); }
2855   };
2856
2857 The problem arises when an iterator is dereferenced directly into a
2858 function that takes a mutable pixel::
2859
2860   template <typename Pixel>    // Models MutablePixelConcept
2861   void invert_pixel(Pixel& p);
2862
2863   rgb_planar_pixel_iterator myIt;
2864   invert_pixel(*myIt);        // compile error!
2865
2866 C++ does not allow for matching a temporary object against a
2867 non-constant reference. The solution is to:
2868
2869 * Use const qualifier on all members of the reference proxy object::
2870
2871     template <typename T>
2872     struct my_reference_proxy
2873     {
2874       const my_reference_proxy& operator=(const my_reference_proxy& p) const;
2875       const my_reference_proxy* operator->() const { return this; }
2876       ...
2877     };
2878
2879 * Use different classes to denote mutable and constant reference
2880   (maybe based on the constness of the template parameter)
2881
2882 * Define the reference type of your iterator with const qualifier::
2883
2884     struct iterator_traits<rgb_planar_pixel_iterator>
2885     {
2886       typedef const my_reference_proxy<T> reference;
2887     };
2888
2889 A second important issue is providing an overload for ``swap`` for
2890 your reference class. The default ``std::swap`` will not work
2891 correctly. You must use a real value type as the temporary.  A further
2892 complication is that in some implementations of the STL the ``swap``
2893 function is incorrectly called qualified, as ``std::swap``.  The only
2894 way for these STL algorithms to use your overload is if you define it
2895 in the ``std`` namespace::
2896
2897   namespace std
2898   {
2899    template <typename T>
2900    void swap(my_reference_proxy<T>& x, my_reference_proxy<T>& y)
2901    {
2902       my_value<T> tmp=x;
2903       x=y;
2904       y=tmp;
2905    }
2906   }
2907
2908 Lastly, remember that constructors and copy-constructors of proxy
2909 references are always shallow and assignment operators are deep.
2910
2911 We are grateful to Dave Abrahams, Sean Parent and Alex Stepanov for
2912 suggesting the above solution.
2913
2914 Conclusion
2915 ----------
2916
2917 The Generic Image Library is designed with the following five goals in
2918 mind:
2919
2920 :Generality: Abstracts image representations from algorithms on
2921        images. It allows for writing code once and have it work for any
2922        image type.
2923 :Performance: Speed has been instrumental to the design of the
2924         library. The generic algorithms provided in the library are in many
2925         cases comparable in speed to hand-coding the algorithm for a
2926         specific image type.
2927 :Flexibility: Compile-type parameter resolution results in faster
2928         code, but severely limits code flexibility. The library allows for
2929         any image parameter to be specified at run time, at a minor
2930         performance cost.
2931 :Extensibility: Virtually every construct in GIL can be extended - new
2932     channel types, color spaces, layouts, iterators, locators, image
2933     views and images can be provided by modeling the corresponding GIL
2934     concepts.
2935 :Compatibility: The library is designed as an STL complement. Generic
2936     STL algorithms can be used for pixel manipulation, and they are
2937     specifically targeted for optimization. The library works with
2938     existing raw pixel data from another image library.