Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / gil / doc / design / extending.rst
1 Extending
2 =========
3
4 .. contents::
5    :local:
6    :depth: 2
7
8 Overview
9 --------
10
11 You can define your own pixel iterators, locators, image views,
12 images, channel types, color spaces and algorithms. You can make
13 virtual images that live on the disk, inside a jpeg file, somewhere on
14 the internet, or even fully-synthetic images such as the Mandelbrot
15 set. As long as they properly model the corresponding concepts, they
16 will work with any existing GIL code. Most such extensions require no
17 changes to the library and can thus be supplied in another module.
18
19 Defining new color spaces
20 -------------------------
21
22 Each color space is in a separate file. To add a new color space, just
23 copy one of the existing ones (like rgb.hpp) and change it
24 accordingly. If you want color conversion support, you will have to
25 provide methods to convert between it and the existing color spaces
26 (see color_convert.h). For convenience you may want to provide useful
27 typedefs for pixels, pointers, references and images with the new
28 color space (see typedefs.h).
29
30 Defining new channel types
31 --------------------------
32
33 Most of the time you don't need to do anything special to use a new
34 channel type. You can just use it:
35
36 .. code-block:: cpp
37
38   typedef pixel<double,rgb_layout_t>   rgb64_pixel_t;    // 64 bit RGB pixel
39   typedef rgb64_pixel*                 rgb64_pixel_ptr_t;// pointer to 64-bit interleaved data
40   typedef image_type<double,rgb_layout_t>::type rgb64_image_t;    // 64-bit interleaved image
41
42 If you want to use your own channel class, you will need to provide a
43 specialization of ``channel_traits`` for it (see channel.hpp). If you
44 want to do conversion between your and existing channel types, you
45 will need to provide an overload of ``channel_convert``.
46
47 Overloading color conversion
48 ----------------------------
49
50 Suppose you want to provide your own color conversion. For example,
51 you may want to implement higher quality color conversion using color
52 profiles. Typically you may want to redefine color conversion only in
53 some instances and default to GIL's color conversion in all other
54 cases. Here is, for example, how to overload color conversion so that
55 color conversion to gray inverts the result but everything else
56 remains the same:
57
58 .. code-block:: cpp
59
60   // make the default use GIL's default
61   template <typename SrcColorSpace, typename DstColorSpace>
62   struct my_color_converter_impl
63   : public default_color_converter_impl<SrcColorSpace,DstColorSpace> {};
64
65   // provide specializations only for cases you care about
66   // (in this case, if the destination is grayscale, invert it)
67   template <typename SrcColorSpace>
68   struct my_color_converter_impl<SrcColorSpace,gray_t>
69   {
70     template <typename SrcP, typename DstP>  // Model PixelConcept
71     void operator()(const SrcP& src, DstP& dst) const
72     {
73         default_color_converter_impl<SrcColorSpace,gray_t>()(src,dst);
74         get_color(dst,gray_color_t())=channel_invert(get_color(dst,gray_color_t()));
75     }
76   };
77
78   // create a color converter object that dispatches to your own implementation
79   struct my_color_converter
80   {
81     template <typename SrcP, typename DstP>  // Model PixelConcept
82     void operator()(const SrcP& src,DstP& dst) const
83     {
84         typedef typename color_space_type<SrcP>::type SrcColorSpace;
85         typedef typename color_space_type<DstP>::type DstColorSpace;
86         my_color_converter_impl<SrcColorSpace,DstColorSpace>()(src,dst);
87     }
88   };
89
90 GIL color conversion functions take the color converter as an
91 optional parameter. You can pass your own color converter:
92
93 .. code-block:: cpp
94
95   color_converted_view<gray8_pixel_t>(img_view,my_color_converter());
96
97 Defining new image views
98 ------------------------
99
100 You can provide your own pixel iterators, locators and views,
101 overriding either the mechanism for getting from one pixel to the next
102 or doing an arbitrary pixel transformation on dereference. For
103 example, let's look at the implementation of ``color_converted_view``
104 (an image factory method that, given any image view, returns a new,
105 otherwise identical view, except that color conversion is performed on
106 pixel access). First we need to define a model of
107 ``PixelDereferenceAdaptorConcept``; a function object that will be
108 called when we dereference a pixel iterator. It will call
109 ``color_convert`` to convert to the destination pixel type:
110
111 .. code-block:: cpp
112
113   template <typename SrcConstRefP,  // const reference to the source pixel
114           typename DstP>          // Destination pixel value (models PixelValueConcept)
115   class color_convert_deref_fn
116   {
117   public:
118     typedef color_convert_deref_fn const_t;
119     typedef DstP                value_type;
120     typedef value_type          reference;      // read-only dereferencing
121     typedef const value_type&   const_reference;
122     typedef SrcConstRefP        argument_type;
123     typedef reference           result_type;
124     static bool constexpr is_mutable = false;
125
126     result_type operator()(argument_type srcP) const {
127         result_type dstP;
128         color_convert(srcP,dstP);
129         return dstP;
130     }
131   };
132
133 We then use the ``add_deref`` member struct of image views to construct the
134 type of a view that invokes a given function object (``deref_t``) upon
135 dereferencing. In our case, it performs color conversion:
136
137 .. code-block:: cpp
138
139   template <typename SrcView, typename DstP>
140   struct color_converted_view_type
141   {
142   private:
143     typedef typename SrcView::const_t::reference src_pix_ref;  // const reference to pixel in SrcView
144     typedef color_convert_deref_fn<src_pix_ref, DstP> deref_t; // the dereference adaptor that performs color conversion
145     typedef typename SrcView::template add_deref<deref_t> add_ref_t;
146   public:
147     typedef typename add_ref_t::type type; // the color converted view type
148     static type make(const SrcView& sv) { return add_ref_t::make(sv, deref_t()); }
149   };
150
151 Finally our ``color_converted_view`` code simply creates color-converted view
152 from the source view:
153
154 .. code-block:: cpp
155
156   template <typename DstP, typename View> inline
157   typename color_converted_view_type<View,DstP>::type color_convert_view(const View& src)
158   {
159     return color_converted_view_type<View,DstP>::make(src);
160   }
161
162 (The actual color convert view transformation is slightly more
163 complicated, as it takes an optional color conversion object, which
164 allows users to specify their own color conversion methods). See the
165 GIL tutorial for an example of creating a virtual image view that
166 defines the Mandelbrot set.