extending.rst 6.3 KB

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