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