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.
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:
26 .. image:: images/interleaved.jpg
30 .. image:: images/planar.jpg
32 Note also that rows may optionally be aligned resulting in a potential
33 padding at the end of rows.
35 The Generic Image Library (GIL) provides models for images that vary in:
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.)
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.
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.
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/
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
70 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf
72 Here are some common concepts that will be used in GIL. Most of them
74 http://www.generic-programming.org/languages/conceptcpp/concept_web.php
77 auto concept DefaultConstructible<typename T>
82 auto concept CopyConstructible<typename T>
88 auto concept Assignable<typename T, typename U = T>
91 result_type operator=(T&, U);
94 auto concept EqualityComparable<typename T, typename U = T>
96 bool operator==(T x, T y);
97 bool operator!=(T x, T y) { return !(x==y); }
100 concept SameType<typename T, typename U> { /* unspecified */ };
101 template<typename T> concept_map SameType<T, T> { /* unspecified */ };
103 auto concept Swappable<typename T>
105 void swap(T& t, T& u);
108 Here are some additional basic concepts that GIL needs::
110 auto concept Regular<typename T> : DefaultConstructible<T>, CopyConstructible<T>, EqualityComparable<T>, Assignable<T>, Swappable<T> {};
112 auto concept Metafunction<typename T>
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::
124 concept PointNDConcept<typename T> : Regular<T>
126 // the type of a coordinate along each axis
127 template <size_t K> struct axis; where Metafunction<axis>;
129 const size_t num_dimensions;
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();
136 GIL uses a two-dimensional point, which is a refinement of
137 ``PointNDConcept`` in which both dimensions are of the same type::
139 concept Point2DConcept<typename T> : PointNDConcept<T>
141 where num_dimensions == 2;
142 where SameType<axis<0>::type, axis<1>::type>;
144 typename value_type = axis<0>::type;
146 const value_type& operator[](const T&, size_t i);
147 value_type& operator[]( T&, size_t i);
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>`_
159 GIL provides a model of ``Point2DConcept``, ``point<T>`` where
160 ``T`` is the coordinate type.
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
171 concept ChannelConcept<typename T> : EqualityComparable<T>
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
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
185 concept MutableChannelConcept<ChannelConcept T> : Swappable<T>, Assignable<T> {};
187 concept ChannelValueConcept<ChannelConcept T> : Regular<T> {};
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
194 template <typename T>
195 struct channel_traits
197 typedef T value_type;
198 typedef T& reference;
200 typedef T& const const_reference;
201 typedef T* const const_pointer;
203 static value_type min_value() { return std::numeric_limits<T>::min(); }
204 static value_type max_value() { return std::numeric_limits<T>::max(); }
207 Two channel types are *compatible* if they have the same value type::
209 concept ChannelsCompatibleConcept<ChannelConcept T1, ChannelConcept T2>
211 where SameType<T1::value_type, T2::value_type>;
214 A channel may be *convertible* to another channel::
216 template <ChannelConcept Src, ChannelValueConcept Dst>
217 concept ChannelConvertibleConcept
219 Dst channel_convert(Src);
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.
233 Note also that algorithms may impose additional requirements on
234 channels, such as support for arithmetic operations.
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>`_
246 All C++11 fundamental integer and float point types are valid channels.
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::
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;
260 GIL also provides models for channels corresponding to ranges of bits::
262 // Value of a channel defined over NumBits bits. Models ChannelValueConcept
263 template <int NumBits> class packed_channel_value;
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;
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;
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.
285 Here is how to construct the three channels of a 16-bit "565" pixel
286 and set them to their maximum value::
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;
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);
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();
302 Assignment, equality comparison and copy construction are defined only
303 between compatible channels::
305 packed_channel_value<5> channel_6bit = channel1;
306 channel_6bit = channel3;
308 //channel_6bit = channel2; // compile error: Assignment between incompatible channels.
310 All channel models provided by GIL are pairwise convertible::
312 channel1 = channel_traits<channel16_0_5_reference_t>::max_value();
313 assert(channel1 == 31);
315 bits16 chan16 = channel_convert<bits16>(channel1);
316 assert(chan16 == 65535);
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).
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::
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);
334 // returns max_value - x + min_value
335 template <typename Channel>
336 typename channel_traits<Channel>::value_type channel_invert(Channel x);
338 // returns a * b / max_value
339 template <typename Channel>
340 typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b);
342 Color Space and Layout
343 ----------------------
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.
349 Two color spaces are considered *compatible* if they are equal
350 (i.e. have the same set of colors in the same order).
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>`_
360 GIL currently provides the following color spaces:
367 It also provides unnamed N-channel color spaces of two to five channels:
374 Besides the standard layouts, it also provides:
381 As an example, here is how GIL defines the RGBA color space::
387 typedef mpl::vector4<red_t,green_t,blue_t,alpha_t> rgba_t;
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
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.
399 Thus they are grouped in GIL's layout::
401 template <typename ColorSpace,
402 typename ChannelMapping = mpl::range_c<int,0,mpl::size<ColorSpace>::value> >
405 typedef ColorSpace color_space_t;
406 typedef ChannelMapping channel_mapping_t;
409 Here is how to create layouts for the RGBA color space::
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;
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
428 Color base models must satisfy the following concepts::
430 concept ColorBaseConcept<typename T> : CopyConstructible<T>, EqualityComparable<T>
432 // a GIL layout (the color space and element permutation)
435 // The type of K-th element
436 template <int K> struct kth_element_type;
437 where Metafunction<kth_element_type>;
439 // The result of at_c
440 template <int K> struct kth_element_const_reference_type;
441 where Metafunction<kth_element_const_reference_type>;
443 template <int K> kth_element_const_reference_type<T,K>::type at_c(T);
445 template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<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&);
454 concept MutableColorBaseConcept<ColorBaseConcept T> : Assignable<T>, Swappable<T>
456 template <int K> struct kth_element_reference_type;
457 where Metafunction<kth_element_reference_type>;
459 template <int K> kth_element_reference_type<T,K>::type at_c(T);
461 template <ColorBaseConcept T2> where { ColorBasesCompatibleConcept<T,T2> }
462 T& operator=(T&, const T2&);
465 concept ColorBaseValueConcept<typename T> : MutableColorBaseConcept<T>, Regular<T>
469 concept HomogeneousColorBaseConcept<ColorBaseConcept CB>
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;
476 concept MutableHomogeneousColorBaseConcept<MutableColorBaseConcept CB> : HomogeneousColorBaseConcept<CB>
478 kth_element_reference_type<0>::type dynamic_at_c(const CB&, std::size_t n);
481 concept HomogeneousColorBaseValueConcept<typename T> : MutableHomogeneousColorBaseConcept<T>, Regular<T>
485 concept ColorBasesCompatibleConcept<ColorBaseConcept C1, ColorBaseConcept C2>
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>;
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
508 Two color bases are *compatible* if they have the same color space and
509 their elements (paired semantically) are convertible to each other.
514 GIL provides a model for a homogeneous color base (a color base whose
515 elements all have the same type). ::
519 template <typename Element, typename Layout, int K> struct homogeneous_color_base;
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.
530 GIL provides the following functions and metafunctions operating on
533 // Metafunction returning an mpl::int_ equal to the number of elements in the color base
534 template <class ColorBase> struct size;
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;
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)
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;
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());
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;
561 GIL also provides the following algorithms which operate on color
562 bases. Note that they all pair the elements semantically::
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);
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);
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);
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);
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&);
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``::
612 template <int K> struct element_recursion
614 template <typename P1,typename P2>
615 static bool static_equal(const P1& p1, const P2& p2)
617 return element_recursion<K-1>::static_equal(p1,p2) &&
618 semantic_at_c<K-1>(p1)==semantic_at_c<N-1>(p2);
621 template <> struct element_recursion<0>
623 template <typename P1,typename P2>
624 static bool static_equal(const P1&, const P2&) { return true; }
628 template <typename P1,typename P2>
629 bool static_equal(const P1& p1, const P2& p2)
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);
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
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
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::
664 concept PixelBasedConcept<typename T>
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>;
677 concept HomogeneousPixelBasedConcept<PixelBasedConcept T>
679 typename channel_type<T>;
680 where Metafunction<channel_type<T> >;
681 where ChannelConcept<channel_type<T>::type>;
684 Pixels model the following concepts::
686 concept PixelConcept<typename P> : ColorBaseConcept<P>, PixelBasedConcept<P>
688 where is_pixel<P>::value==true;
689 // where for each K [0..size<P>::value-1]:
690 // ChannelConcept<kth_element_type<K> >;
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;
697 template <PixelConcept P2> where { PixelConcept<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&);
705 concept MutablePixelConcept<typename P> : PixelConcept<P>, MutableColorBaseConcept<P>
707 where is_mutable==true;
710 concept HomogeneousPixelConcept<PixelConcept P> : HomogeneousColorBaseConcept<P>, HomogeneousPixelBasedConcept<P>
712 P::template element_const_reference_type<P>::type operator[](P p, std::size_t i) const { return dynamic_at_c(P,i); }
715 concept MutableHomogeneousPixelConcept<MutablePixelConcept P> : MutableHomogeneousColorBaseConcept<P>
717 P::template element_reference_type<P>::type operator[](P p, std::size_t i) { return dynamic_at_c(p,i); }
720 concept PixelValueConcept<typename P> : PixelConcept<P>, Regular<P>
722 where SameType<value_type,P>;
725 concept PixelsCompatibleConcept<PixelConcept P1, PixelConcept P2> : ColorBasesCompatibleConcept<P1,P2>
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>;
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::
737 template <PixelConcept SrcPixel, MutablePixelConcept DstPixel>
738 concept PixelConvertibleConcept
740 void color_convert(const SrcPixel&, DstPixel&);
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.
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>`_
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::
766 // models HomogeneousPixelValueConcept
767 template <typename ChannelValue, typename Layout> struct pixel;
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;
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
776 rgb8 = bgr8; // assignment and equality is defined between compatible pixels
777 assert(rgb8 == bgr8); // assignment and equality operate on the semantic channels
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)
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``::
790 // models HomogeneousPixel
791 template <typename ChannelReference, typename ColorSpace> struct planar_pixel_reference;
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;
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.
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::
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;
810 function_requires<PixelValueConcept<rgb565_pixel_t> >();
811 static_assert(sizeof(rgb565_pixel_t) == 2, "");
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;
816 function_requires<PixelValueConcept<bgr556_pixel_t> >();
818 // rgb565 is compatible with bgr556.
819 function_requires<PixelsCompatibleConcept<rgb565_pixel_t,bgr556_pixel_t> >();
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::
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;
836 // A mutable iterator over BGR232 pixels
837 typedef bit_aligned_pixel_iterator<bgr232_ref_t> bgr232_ptr_t;
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, "");
843 bgr232_pixel_t red(0,0,3); // = 0RRGGGBB, = 01100000 = 0x60
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);
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)
855 // Result: 0x60 0x30 0x11 0x0C 0x06 0x83 0xC1
860 Since pixels model ``ColorBaseConcept`` and ``PixelBasedConcept`` all
861 algorithms and metafunctions of color bases can work with them as
864 // This is how to access the first semantic channel (red)
865 assert(semantic_at_c<0>(rgb8) == semantic_at_c<0>(bgr8));
867 // This is how to access the red channel by name
868 assert(get_color<red_t>(rgb8) == get_color<red_t>(bgr8));
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()));
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> > ));
879 // Pixels contain just the three channels and nothing extra
880 BOOST_MPL_ASSERT(sizeof(rgb8_pixel_t)==3);
882 rgb8_planar_ref_t ref(bgr8); // copy construction is allowed from a compatible mutable pixel type
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
887 // Create a zero packed pixel and a full regular unpacked pixel.
889 rgb8_pixel_t rgb_full(255,255,255);
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));
897 GIL also provides the ``color_convert`` algorithm to convert between
898 pixels of different color spaces and channel types::
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);
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::
918 concept PixelIteratorConcept<RandomAccessTraversalIteratorConcept Iterator> : PixelBasedConcept<Iterator>
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
927 template <typename Iterator>
928 concept MutablePixelIteratorConcept : PixelIteratorConcept<Iterator>, MutableRandomAccessIteratorConcept<Iterator> {};
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>`_
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.
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::
948 template <typename ChannelPtr, typename ColorSpace> struct planar_pixel_iterator;
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;
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::
960 template <typename T>
961 struct inc : public std::unary_function<T,T>
963 T operator()(T x) const { return ++x; }
966 template <typename ChannelPtr, typename ColorSpace>
967 planar_pixel_iterator<ChannelPtr,ColorSpace>&
968 planar_pixel_iterator<ChannelPtr,ColorSpace>::operator++()
970 static_transform(*this,*this,inc<ChannelPtr>());
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.
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::
989 concept IteratorAdaptorConcept<RandomAccessTraversalIteratorConcept Iterator>
991 where SameType<is_iterator_adaptor<Iterator>::type, mpl::true_>;
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>;
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>;
1002 const iterator_adaptor_get_base<Iterator>::type& Iterator::base() const;
1005 template <boost_concepts::Mutable_ForwardIteratorConcept Iterator>
1006 concept MutableIteratorAdaptorConcept : IteratorAdaptorConcept<Iterator> {};
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>`_
1016 GIL provides several models of ``IteratorAdaptorConcept``:
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``
1028 Pixel Dereference Adaptor
1029 ~~~~~~~~~~~~~~~~~~~~~~~~~
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`` ::
1036 template <boost::UnaryFunctionConcept D>
1037 concept PixelDereferenceAdaptorConcept : DefaultConstructibleConcept<D>, CopyConstructibleConcept<D>, AssignableConcept<D>
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;
1045 where Convertible<value_type, result_type>;
1051 GIL provides several models of ``PixelDereferenceAdaptorConcept``:
1053 * ``color_convert_deref_fn``: a function object that performs color
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``
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.
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
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)
1084 Step iterators are forward traversal iterators that allow changing the
1085 step between adjacent values::
1087 concept StepIteratorConcept<boost_concepts::ForwardTraversalConcept Iterator>
1089 template <Integral D> void Iterator::set_step(D step);
1092 concept MutableStepIteratorConcept<boost_concepts::Mutable_ForwardIteratorConcept Iterator> : StepIteratorConcept<Iterator> {};
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.
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
1112 concept MemoryBasedIteratorConcept<boost_concepts::RandomAccessTraversalConcept Iterator>
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); }
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
1127 concept HasDynamicXStepTypeConcept<typename T>
1129 typename dynamic_x_step_type<T>;
1130 where Metafunction<dynamic_x_step_type<T> >;
1133 All models of pixel iterators, locators and image views that GIL
1134 provides support ``HasDynamicXStepTypeConcept``.
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>`_
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::
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);
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``.
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::
1177 concept RandomAccessNDLocatorConcept<Regular Loc>
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;
1186 static const size_t num_dimensions; // dimensionality of the locator
1187 where num_dimensions = point_t::num_dimensions;
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;
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);
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&);
1208 reference operator*(const Loc&);
1209 reference operator[](const Loc&, const difference_type&);
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&);
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;
1221 template <typename Loc>
1222 concept MutableRandomAccessNDLocatorConcept : RandomAccessNDLocatorConcept<Loc> {
1223 where Mutable<reference>;
1226 Two-dimensional locators have additional requirements::
1228 concept RandomAccess2DLocatorConcept<RandomAccessNDLocatorConcept Loc>
1230 where num_dimensions==2;
1231 where Point2DConcept<point_t>;
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;
1238 // Only available to locators that have dynamic step in Y
1239 //Loc::Loc(const Loc& loc, y_coord_t);
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);
1244 x_iterator& Loc::x();
1245 x_iterator const& Loc::x() const;
1246 y_iterator& Loc::y();
1247 y_iterator const& Loc::y() const;
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;
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;
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;
1264 concept MutableRandomAccess2DLocatorConcept<RandomAccess2DLocatorConcept Loc> : MutableRandomAccessNDLocatorConcept<Loc> {};
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::
1270 concept HasDynamicYStepTypeConcept<typename T>
1272 typename dynamic_y_step_type<T>;
1273 where Metafunction<dynamic_y_step_type<T> >;
1276 All locators and image views that GIL provides model
1277 ``HasDynamicYStepTypeConcept``.
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
1284 concept HasTransposedTypeConcept<typename T>
1286 typename transposed_type<T>;
1287 where Metafunction<transposed_type<T> >;
1290 All GIL provided locators and views model
1291 ``HasTransposedTypeConcept``.
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
1297 concept PixelLocatorConcept<RandomAccess2DLocatorConcept Loc>
1299 where PixelValueConcept<value_type>;
1300 where PixelIteratorConcept<x_iterator>;
1301 where PixelIteratorConcept<y_iterator>;
1302 where x_coord_t == y_coord_t;
1304 typename coord_t = x_coord_t;
1307 concept MutablePixelLocatorConcept<PixelLocatorConcept Loc> : MutableRandomAccess2DLocatorConcept<Loc> {};
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>`_
1323 GIL provides two models of ``PixelLocatorConcept`` - a memory-based
1324 locator, ``memory_based_2d_locator`` and a virtual locator
1325 ``virtual_2d_locator``.
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``). ::
1333 template <typename StepIterator> // Models StepIteratorConcept, MemoryBasedIteratorConcept
1334 class memory_based_2d_locator;
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.
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:
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
1352 - ``memory_based_step_iterator<planar_pixel_iterator<T*,C> >`` - for planar
1353 images with non-standard step
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.
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.
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:
1369 .. image:: images/step_iterator.gif
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.
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``.
1384 Here is some sample code using locators::
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
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
1407 Iterator over 2D image
1408 ~~~~~~~~~~~~~~~~~~~~~~
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::
1419 template <typename Locator> // Models PixelLocatorConcept
1420 class iterator_from_2d
1423 iterator_from_2d(const Locator& loc, int x, int width);
1425 iterator_from_2d& operator++(); // if (++_x<_width) ++_p.x(); else _p+=point_t(-_width,1);
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.
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
1460 concept RandomAccessNDImageViewConcept<Regular View>
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()
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>;
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);
1486 static const size_t num_dimensions = point_t::num_dimensions;
1488 // Create from a locator at the top-left corner and dimensions
1489 View::View(const locator&, const point_type&);
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?
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;
1504 reference operator()(View,const point_t&) const;
1507 concept MutableRandomAccessNDImageViewConcept<RandomAccessNDImageViewConcept View>
1509 where Mutable<reference>;
1512 Two-dimensional image views have the following extra requirements::
1514 concept RandomAccess2DImageViewConcept<RandomAccessNDImageViewConcept View>
1516 where num_dimensions==2;
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;
1524 x_coord_t View::width() const;
1525 y_coord_t View::height() const;
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;
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;
1538 xy_locator View::xy_at(const point_t&) const;
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;
1549 concept MutableRandomAccess2DImageViewConcept<RandomAccess2DImageViewConcept View>
1550 : MutableRandomAccessNDImageViewConcept<View> {};
1552 Image views that GIL typically uses operate on value types that model
1553 ``PixelValueConcept`` and have some additional requirements::
1555 concept ImageViewConcept<RandomAccess2DImageViewConcept View>
1557 where PixelValueConcept<value_type>;
1558 where PixelIteratorConcept<x_iterator>;
1559 where PixelIteratorConcept<y_iterator>;
1560 where x_coord_t == y_coord_t;
1562 typename coord_t = x_coord_t;
1564 std::size_t View::num_channels() const;
1568 concept MutableImageViewConcept<ImageViewConcept View> : MutableRandomAccess2DImageViewConcept<View> {};
1570 Two image views are compatible if they have compatible pixels and the
1571 same number of dimensions::
1573 concept ViewsCompatibleConcept<ImageViewConcept V1, ImageViewConcept V2>
1575 where PixelsCompatibleConcept<V1::value_type, V2::value_type>;
1576 where V1::num_dimensions == V2::num_dimensions;
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.
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>`_
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::
1602 template <typename Locator> // Models PixelLocatorConcept (could be MutablePixelLocatorConcept)
1606 typedef Locator xy_locator;
1607 typedef iterator_from_2d<Locator> iterator;
1610 xy_locator _pixels; // 2D pixel locator at the top left corner of the image view range
1611 point_t _dimensions; // width and height
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
1623 Creating Views from Raw Pixels
1624 ++++++++++++++++++++++++++++++
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::
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)
1635 Planar views are defined for every color space and take each plane
1636 separately. Here is the RGB one::
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);
1642 Note that the supplied pixel/channel iterators could be constant
1643 (read-only), in which case the returned view is a constant-value
1646 Creating Image Views from Other Image Views
1647 +++++++++++++++++++++++++++++++++++++++++++
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::
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> {};
1658 template <typename View>
1659 struct dynamic_xy_step_transposed_type : public dynamic_xy_step_type<typename transposed_type<View>::type> {};
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
1667 typedef ... type; // image view adaptor with value type DstP, over SrcView
1670 // single-channel view of the N-th channel of a given view
1671 template <typename SrcView>
1672 struct nth_channel_view_type
1677 GIL Provides the following view transformations::
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);
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);
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);
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);
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);
1702 template <typename View>
1703 nth_channel_view_type<View>::view_t nth_channel_view(const View& view, int n);
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. ::
1711 template <typename View>
1712 typename dynamic_y_step_type<View>::type flipped_up_down_view(const View& src)
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));
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.
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)``::
1733 rgb16_image_t img(100,100); // an RGB interleaved image
1735 // grayscale view over the green (index 1) channel of img
1736 gray16_step_view_t green=nth_channel_view(view(img),1);
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));
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.
1745 STL-Style Algorithms on Image Views
1746 +++++++++++++++++++++++++++++++++++
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
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);
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);
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);
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);
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);
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);
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);
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);
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.
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.
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
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
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.
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
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).
1865 In the most general form images are N-dimensional and satisfy the
1868 concept RandomAccessNDImageConcept<typename Img> : Regular<Img>
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;
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);
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);
1882 const point_t& Img::dimensions() const;
1883 const const_view_t& const_view(const Img&);
1884 const view_t& view(Img&);
1887 Two-dimensional images have additional requirements::
1889 concept RandomAccess2DImageConcept<RandomAccessNDImageConcept Img>
1891 typename x_coord_t = const_view_t::x_coord_t;
1892 typename y_coord_t = const_view_t::y_coord_t;
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);
1897 x_coord_t Img::width() const;
1898 y_coord_t Img::height() const;
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);
1904 GIL's images have views that model ``ImageViewConcept`` and
1905 operate on pixels.::
1907 concept ImageConcept<RandomAccess2DImageConcept Img>
1909 where MutableImageViewConcept<view_t>;
1910 typename coord_t = view_t::coord_t;
1913 Images, unlike locators and image views, don't have 'mutable' set of
1914 concepts because immutable images are not very useful.
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>`_
1925 GIL provides a class, ``image``, which is templated over the value
1926 type (the pixel) and models ``ImageConcept``::
1928 template <typename Pixel, \\ Models PixelValueConcept
1929 bool IsPlanar, \\ planar or interleaved image
1930 typename A=std::allocator<unsigned char> >
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.
1943 Run-time specified images and image views
1944 -----------------------------------------
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?
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
1959 #include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
1960 using namespace boost;
1962 #define ASSERT_SAME(A,B) static_assert(is_same< A,B >::value, "")
1964 // Define the set of allowed images
1965 typedef mpl::vector<rgb8_image_t, cmyk16_planar_image_t> my_images_t;
1967 // Create any_image class (or any_image_view) class
1968 typedef any_image<my_images_t> my_any_image_t;
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);
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);
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);
1981 // Assign it a concrete image at run time:
1982 my_any_image_t myImg = my_any_image_t(rgb8_image_t(100,100));
1984 // Change it to another at run time. The previous image gets destroyed
1985 myImg = cmyk16_planar_image_t(200,100);
1987 // Assigning to an image not in the allowed set throws an exception
1988 myImg = gray8_image_t(); // will throw std::bad_cast
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.
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
2004 template <typename Types> // models MPL Random Access Container
2010 typedef Types types_t;
2013 variant(const variant& v);
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);
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);
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);
2028 template <typename T> static bool has_type();
2030 template <typename T> const T& _dynamic_cast() const;
2031 template <typename T> T& _dynamic_cast();
2033 template <typename T> bool current_type_is() const;
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);
2041 template <typename BOP, typename Types1, typename Types2>
2042 BOP::result_type apply_operation( variant<Types1>& v1, variant<Types2>& v2, UOP op);
2044 template <typename BOP, typename Types1, typename Types2>
2045 BOP::result_type apply_operation(const variant<Types1>& v1, variant<Types2>& v2, UOP op);
2047 template <typename BOP, typename Types1, typename Types2>
2048 BOP::result_type apply_operation(const variant<Types1>& v1, const variant<Types2>& v2, UOP op);
2050 GIL's ``any_image_view`` and ``any_image`` are subclasses of ``variant``::
2052 template <typename ImageViewTypes>
2053 class any_image_view : public variant<ImageViewTypes>
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;
2062 template <typename T> explicit any_image_view(const T& obj);
2063 any_image_view(const any_image_view& v);
2065 template <typename T> any_image_view& operator=(const T& obj);
2066 any_image_view& operator=(const any_image_view& v);
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;
2075 template <typename ImageTypes>
2076 class any_image : public variant<ImageTypes>
2078 typedef variant<ImageTypes> parent_t;
2080 typedef ... const_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;
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);
2091 template <typename T> any_image& operator=(const T& obj);
2092 any_image& operator=(const any_image& v);
2094 void recreate(const point_t& dims, unsigned alignment=1);
2095 void recreate(x_coord_t width, y_coord_t height, unsigned alignment=1);
2097 std::size_t num_channels() const;
2098 point_t dimensions() const;
2099 x_coord_t width() const;
2100 y_coord_t height() const;
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
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
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
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
2139 // Copies the pixels from v1 into v2.
2140 // If the pixels are incompatible triggers compile error
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);
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
2155 #include <boost\gil\extension\io\jpeg_dynamic_io.hpp>
2157 template <typename Image> // Could be rgb8_image_t or any_image<...>
2158 void save_180rot(const std::string& file_name)
2161 jpeg_read_image(file_name, img);
2162 jpeg_write_view(file_name, rotated180_view(view(img)));
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
2170 // implementation using templated view
2171 template <typename View>
2172 typename dynamic_xy_step_type<View>::type rotated180_view(const View& src) { ... }
2176 // the function, wrapped inside a function object
2177 template <typename Result> struct rotated180_view_fn
2179 typedef Result result_type;
2180 template <typename View> result_type operator()(const View& src) const
2182 return result_type(rotated180_view(src));
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)
2192 return apply_operation(src,detail::rotated180_view_fn<typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type>());
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.
2205 Useful Metafunctions and Typedefs
2206 ---------------------------------
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:
2213 *ColorSpace* + *BitDepth* + ["s|f"] + ["c"] + ["_planar"] +
2214 ["_step"] + *ClassType* + "_t"
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::
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.
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::
2238 template <typename ChannelValue, typename Layout, bool IsPlanar=false, bool IsMutable=true>
2239 struct pixel_reference_type { typedef ... type; };
2241 template <typename Channel, typename Layout>
2242 struct pixel_value_type { typedef ... type; };
2244 template <typename ChannelValue, typename Layout, bool IsPlanar=false, bool IsStep=false, bool IsMutable=true>
2245 struct iterator_type { typedef ... type; };
2247 template <typename ChannelValue, typename Layout, bool IsPlanar=false, bool IsXStep=false, bool IsMutable=true>
2248 struct locator_type { typedef ... type; };
2250 template <typename ChannelValue, typename Layout, bool IsPlanar=false, bool IsXStep=false, bool IsMutable=true>
2251 struct view_type { typedef ... type; };
2253 template <typename ChannelValue, typename Layout, bool IsPlanar=false, typename Alloc=std::allocator<unsigned char> >
2254 struct image_type { typedef ... type; };
2256 template <typename BitField, typename ChannelBitSizeVector, typename Layout, typename Alloc=std::allocator<unsigned char> >
2257 struct packed_image_type { typedef ... type; };
2259 template <typename ChannelBitSizeVector, typename Layout, typename Alloc=std::allocator<unsigned char> >
2260 struct bit_aligned_image_type { typedef ... type; };
2262 There are also helper metafunctions to construct packed and
2263 bit-aligned images with up to five channels::
2265 template <typename BitField, unsigned Size1,
2266 typename Layout, typename Alloc=std::allocator<unsigned char> >
2267 struct packed_image1_type { typedef ... type; };
2269 template <typename BitField, unsigned Size1, unsigned Size2,
2270 typename Layout, typename Alloc=std::allocator<unsigned char> >
2271 struct packed_image2_type { typedef ... type; };
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; };
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; };
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; };
2285 template <unsigned Size1,
2286 typename Layout, typename Alloc=std::allocator<unsigned char> >
2287 struct bit_aligned_image1_type { typedef ... type; };
2289 template <unsigned Size1, unsigned Size2,
2290 typename Layout, typename Alloc=std::allocator<unsigned char> >
2291 struct bit_aligned_image2_type { typedef ... type; };
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; };
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; };
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; };
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::
2310 template <typename Pixel, bool IsPlanar=false, bool IsStep=false, bool IsMutable=true>
2311 struct iterator_type_from_pixel { typedef ... type; };
2313 template <typename Pixel, bool IsPlanar=false, bool IsStepX=false, bool IsMutable=true>
2314 struct view_type_from_pixel { typedef ... type; };
2316 Using a heterogeneous pixel type will result in heterogeneous
2317 iterators and views. Types can also be constructed from horizontal
2320 template <typename XIterator>
2321 struct type_from_x_iterator
2323 typedef ... step_iterator_t;
2324 typedef ... xy_locator_t;
2328 There are metafunctions to construct the type of a construct from an
2329 existing type by changing one or more of its properties::
2331 template <typename PixelReference,
2332 typename ChannelValue, typename Layout, typename IsPlanar, typename IsMutable>
2333 struct derived_pixel_reference_type
2335 typedef ... type; // Models PixelConcept
2338 template <typename Iterator,
2339 typename ChannelValue, typename Layout, typename IsPlanar, typename IsStep, typename IsMutable>
2340 struct derived_iterator_type
2342 typedef ... type; // Models PixelIteratorConcept
2345 template <typename View,
2346 typename ChannelValue, typename Layout, typename IsPlanar, typename IsXStep, typename IsMutable>
2347 struct derived_view_type
2349 typedef ... type; // Models ImageViewConcept
2352 template <typename Image,
2353 typename ChannelValue, typename Layout, typename IsPlanar>
2354 struct derived_image_type
2356 typedef ... type; // Models ImageConcept
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::
2365 typedef typename derived_view_type<View, boost::use_default, gray_t, mpl::true_>::type VT;
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::
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; };
2376 // Defined by homogeneous constructs
2377 template <typename T> struct channel_type { typedef ... type; };
2378 template <typename T> struct num_channels { typedef ... type; };
2380 These are metafunctions, some of which return integral types which can
2381 be evaluated like this::
2383 static_assert(is_planar<rgb8_planar_view_t>::value == true, "");
2385 GIL also supports type analysis metafunctions of the form:
2386 [pixel_reference/iterator/locator/view/image] + "_is_" +
2387 [basic/mutable/step]. For example::
2389 if (view_is_mutable<View>::value)
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.
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:
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
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
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
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)::
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*);
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&);
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);
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&);
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);
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&);
2469 // Determines whether the given view type is supported for reading
2470 template <typename View> struct jpeg_read_support
2472 static const bool value = ...;
2475 // Determines whether the given view type is supported for writing
2476 template <typename View> struct jpeg_write_support
2478 static const bool value = ...;
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
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>&);
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>&);
2496 All of the above methods have overloads taking ``std::string`` instead
2502 Pixel-level Sample Code
2503 ~~~~~~~~~~~~~~~~~~~~~~~
2505 Here are some operations you can do with pixel values,
2506 pointers and references::
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
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
2520 rgb8c_planar_ref_t ref=*ptr; // just like built-in reference, dereferencing a planar pointer returns a planar reference
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
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)
2531 Here is how to use pixels in generic code::
2533 template <typename GrayPixel, typename RGBPixel>
2534 void gray_to_rgb(const GrayPixel& src, RGBPixel& dst)
2536 gil_function_requires<PixelConcept<GrayPixel> >();
2537 gil_function_requires<MutableHomogeneousPixelConcept<RGBPixel> >();
2539 typedef typename color_space_type<GrayPixel>::type gray_cs_t;
2540 static_assert(boost::is_same<gray_cs_t,gray_t>::value, "");
2542 typedef typename color_space_type<RGBPixel>::type rgb_cs_t;
2543 static_assert(boost::is_same<rgb_cs_t,rgb_t>::value, "");
2545 typedef typename channel_type<GrayPixel>::type gray_channel_t;
2546 typedef typename channel_type<RGBPixel>::type rgb_channel_t;
2548 gray_channel_t gray = get_color(src,gray_color_t());
2549 static_fill(dst, channel_convert<rgb_channel_t>(gray));
2552 // example use patterns:
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));
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]);
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.
2568 Creating a Copy of an Image with a Safe Buffer
2569 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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::
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)
2579 gil_function_requires<ImageViewConcept<SrcView> >();
2580 gil_function_requires<ImageConcept<DstImage> >();
2581 gil_function_requires<ViewsCompatibleConcept<SrcView, typename DstImage::view_t> >();
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());
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::
2595 template <typename SrcView, typename DstImage>
2596 void create_with_margin(const SrcView& src, int k, DstImage& result)
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()));
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.
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::
2624 template <typename GrayView, typename R>
2625 void grayimage_histogram(const GrayView& img, R& hist)
2627 for (typename GrayView::iterator it=img.begin(); it!=img.end(); ++it)
2631 Using ``boost::lambda`` and GIL's ``for_each_pixel`` algorithm, we can
2632 write this more compactly::
2634 template <typename GrayView, typename R>
2635 void grayimage_histogram(const GrayView& v, R& hist)
2637 for_each_pixel(v, ++var(hist)[_1]);
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
2645 template <typename View, typename R>
2646 void luminosity_histogram(const View& v, R& hist)
2648 grayimage_histogram(color_converted_view<gray8_pixel_t>(v),hist);
2651 This is how to invoke it::
2653 unsigned char hist[256];
2654 std::fill(hist,hist+256,0);
2655 luminosity_histogram(my_view,hist);
2657 If we want to view the histogram of the second channel of the image in
2658 the top left 100x100 area, we call::
2660 grayimage_histogram(nth_channel_view(subimage_view(img,0,0,100,100),1),hist);
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
2670 The following code illustrates the power of using image views::
2672 jpeg_read_image("monkey.jpg", 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);
2680 The intermediate images are shown here:
2682 .. image:: images/monkey_steps.jpg
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.
2689 Extending the Generic Image Library
2690 -----------------------------------
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.
2700 Defining New Color Spaces
2701 ~~~~~~~~~~~~~~~~~~~~~~~~~
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).
2711 Defining New Channel Types
2712 ~~~~~~~~~~~~~~~~~~~~~~~~~~
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::
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
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``.
2726 Overloading Color Conversion
2727 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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
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> {};
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>
2747 template <typename SrcP, typename DstP> // Model PixelConcept
2748 void operator()(const SrcP& src, DstP& dst) const
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()));
2755 // create a color converter object that dispatches to your own implementation
2756 struct my_color_converter
2758 template <typename SrcP, typename DstP> // Model PixelConcept
2759 void operator()(const SrcP& src,DstP& dst) const
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);
2767 GIL's color conversion functions take the color converter as an
2768 optional parameter. You can pass your own color converter::
2770 color_converted_view<gray8_pixel_t>(img_view,my_color_converter());
2772 Defining New Image Views
2773 ~~~~~~~~~~~~~~~~~~~~~~~~
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::
2786 template <typename SrcConstRefP, // const reference to the source pixel
2787 typename DstP> // Destination pixel value (models PixelValueConcept)
2788 class color_convert_deref_fn
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;
2799 result_type operator()(argument_type srcP) const {
2801 color_convert(srcP,dstP);
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
2811 template <typename SrcView, typename DstP>
2812 struct color_converted_view_type
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;
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()); }
2823 Finally our ``color_converted_view`` code simply creates
2824 color-converted view from the source view::
2826 template <typename DstP, typename View> inline
2827 typename color_converted_view_type<View,DstP>::type color_convert_view(const View& src)
2829 return color_converted_view_type<View,DstP>::make(src);
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.
2841 Creating a reference proxy
2842 ~~~~~~~~~~~~~~~~~~~~~~~~~~
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::
2851 struct rgb_planar_pixel_iterator
2853 typedef my_reference_proxy<T> reference;
2854 reference operator*() const { return reference(red,green,blue); }
2857 The problem arises when an iterator is dereferenced directly into a
2858 function that takes a mutable pixel::
2860 template <typename Pixel> // Models MutablePixelConcept
2861 void invert_pixel(Pixel& p);
2863 rgb_planar_pixel_iterator myIt;
2864 invert_pixel(*myIt); // compile error!
2866 C++ does not allow for matching a temporary object against a
2867 non-constant reference. The solution is to:
2869 * Use const qualifier on all members of the reference proxy object::
2871 template <typename T>
2872 struct my_reference_proxy
2874 const my_reference_proxy& operator=(const my_reference_proxy& p) const;
2875 const my_reference_proxy* operator->() const { return this; }
2879 * Use different classes to denote mutable and constant reference
2880 (maybe based on the constness of the template parameter)
2882 * Define the reference type of your iterator with const qualifier::
2884 struct iterator_traits<rgb_planar_pixel_iterator>
2886 typedef const my_reference_proxy<T> reference;
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::
2899 template <typename T>
2900 void swap(my_reference_proxy<T>& x, my_reference_proxy<T>& y)
2908 Lastly, remember that constructors and copy-constructors of proxy
2909 references are always shallow and assignment operators are deep.
2911 We are grateful to Dave Abrahams, Sean Parent and Alex Stepanov for
2912 suggesting the above solution.
2917 The Generic Image Library is designed with the following five goals in
2920 :Generality: Abstracts image representations from algorithms on
2921 images. It allows for writing code once and have it work for any
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
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
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.