channel.rst 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. Channel
  2. =======
  3. .. contents::
  4. :local:
  5. :depth: 2
  6. Overview
  7. --------
  8. A channel indicates the intensity of a color component (for example, the red
  9. channel in an RGB pixel). Typical channel operations are getting, comparing
  10. and setting the channel values. Channels have associated minimum and maximum
  11. value. GIL channels model the following concept:
  12. .. code-block:: cpp
  13. concept ChannelConcept<typename T> : EqualityComparable<T>
  14. {
  15. typename value_type = T; // use channel_traits<T>::value_type to access it
  16. where ChannelValueConcept<value_type>;
  17. typename reference = T&; // use channel_traits<T>::reference to access it
  18. typename pointer = T*; // use channel_traits<T>::pointer to access it
  19. typename const_reference = const T&; // use channel_traits<T>::const_reference to access it
  20. typename const_pointer = const T*; // use channel_traits<T>::const_pointer to access it
  21. static const bool is_mutable; // use channel_traits<T>::is_mutable to access it
  22. static T min_value(); // use channel_traits<T>::min_value to access it
  23. static T max_value(); // use channel_traits<T>::min_value to access it
  24. };
  25. concept MutableChannelConcept<ChannelConcept T> : Swappable<T>, Assignable<T> {};
  26. concept ChannelValueConcept<ChannelConcept T> : Regular<T> {};
  27. GIL allows built-in integral and floating point types to be channels.
  28. Therefore the associated types and range information are defined in
  29. ``channel_traits`` with the following default implementation:
  30. .. code-block:: cpp
  31. template <typename T>
  32. struct channel_traits
  33. {
  34. typedef T value_type;
  35. typedef T& reference;
  36. typedef T* pointer;
  37. typedef T& const const_reference;
  38. typedef T* const const_pointer;
  39. static value_type min_value() { return std::numeric_limits<T>::min(); }
  40. static value_type max_value() { return std::numeric_limits<T>::max(); }
  41. };
  42. Two channel types are *compatible* if they have the same value type:
  43. .. code-block:: cpp
  44. concept ChannelsCompatibleConcept<ChannelConcept T1, ChannelConcept T2>
  45. {
  46. where SameType<T1::value_type, T2::value_type>;
  47. };
  48. A channel may be *convertible* to another channel:
  49. .. code-block:: cpp
  50. template <ChannelConcept Src, ChannelValueConcept Dst>
  51. concept ChannelConvertibleConcept
  52. {
  53. Dst channel_convert(Src);
  54. };
  55. Note that ``ChannelConcept`` and ``MutableChannelConcept`` do not require a
  56. default constructor. Channels that also support default construction (and thus
  57. are regular types) model ``ChannelValueConcept``.
  58. To understand the motivation for this distinction, consider a 16-bit RGB pixel
  59. in a "565" bit pattern. Its channels correspond to bit ranges. To support such
  60. channels, we need to create a custom proxy class corresponding to a reference
  61. to a sub-byte channel.
  62. Such a proxy reference class models only ``ChannelConcept``, because, similar
  63. to native C++ references, it may not have a default constructor.
  64. Note also that algorithms may impose additional requirements on channels,
  65. such as support for arithmetic operations.
  66. .. seealso::
  67. - `ChannelConcept<T> <reference/structboost_1_1gil_1_1_channel_concept.html>`_
  68. - `ChannelValueConcept<T> <reference/structboost_1_1gil_1_1_channel_value_concept.html>`_
  69. - `MutableChannelConcept<T> <reference/structboost_1_1gil_1_1_mutable_channel_concept.html>`_
  70. - `ChannelsCompatibleConcept<T1,T2> <reference/structboost_1_1gil_1_1_channels_compatible_concept.html>`_
  71. - `ChannelConvertibleConcept<SrcChannel,DstChannel> <reference/structboost_1_1gil_1_1_channel_convertible_concept.html>`_
  72. Models
  73. ------
  74. All C++11 fundamental integer and float point types are valid channels.
  75. The minimum and maximum values of a channel modeled by a built-in type
  76. correspond to the minimum and maximum physical range of the built-in type, as
  77. specified by its ``std::numeric_limits``. Sometimes the physical range is not
  78. appropriate. GIL provides ``scoped_channel_value``, a model for a channel
  79. adapter that allows for specifying a custom range.
  80. We use it to define a ``[0..1]`` floating point channel type as follows:
  81. .. code-block:: cpp
  82. struct float_zero { static float apply() { return 0.0f; } };
  83. struct float_one { static float apply() { return 1.0f; } };
  84. typedef scoped_channel_value<float,float_zero,float_one> bits32f;
  85. GIL also provides models for channels corresponding to ranges of bits:
  86. .. code-block:: cpp
  87. // Value of a channel defined over NumBits bits. Models ChannelValueConcept
  88. template <int NumBits> class packed_channel_value;
  89. // Reference to a channel defined over NumBits bits. Models ChannelConcept
  90. template <int FirstBit,
  91. int NumBits, // Defines the sequence of bits in the data value that contain the channel
  92. bool Mutable> // true if the reference is mutable
  93. class packed_channel_reference;
  94. // Reference to a channel defined over NumBits bits. Its FirstBit is a run-time parameter. Models ChannelConcept
  95. template <int NumBits, // Defines the sequence of bits in the data value that contain the channel
  96. bool Mutable> // true if the reference is mutable
  97. class packed_dynamic_channel_reference;
  98. Note that there are two models of a reference proxy which differ based on
  99. whether the offset of the channel range is specified as a template or a
  100. run-time parameter. The first model is faster and more compact while the
  101. second model is more flexible. For example, the second model allows us to
  102. construct an iterator over bit range channels.
  103. Algorithms
  104. ----------
  105. Here is how to construct the three channels of a 16-bit "565" pixel and set
  106. them to their maximum value:
  107. .. code-block:: cpp
  108. using channel16_0_5_reference_t = packed_channel_reference<0, 5, true>;
  109. using channel16_5_6_reference_t = packed_channel_reference<5, 6, true>;
  110. using channel16_11_5_reference_t = packed_channel_reference<11, 5, true>;
  111. std::uint16_t data=0;
  112. channel16_0_5_reference_t channel1(&data);
  113. channel16_5_6_reference_t channel2(&data);
  114. channel16_11_5_reference_t channel3(&data);
  115. channel1 = channel_traits<channel16_0_5_reference_t>::max_value();
  116. channel2 = channel_traits<channel16_5_6_reference_t>::max_value();
  117. channel3 = channel_traits<channel16_11_5_reference_t>::max_value();
  118. assert(data == 65535);
  119. Assignment, equality comparison and copy construction are defined only between
  120. compatible channels:
  121. .. code-block:: cpp
  122. packed_channel_value<5> channel_6bit = channel1;
  123. channel_6bit = channel3;
  124. // compile error: Assignment between incompatible channels
  125. //channel_6bit = channel2;
  126. All channel models provided by GIL are pairwise convertible:
  127. .. code-block:: cpp
  128. channel1 = channel_traits<channel16_0_5_reference_t>::max_value();
  129. assert(channel1 == 31);
  130. bits16 chan16 = channel_convert<bits16>(channel1);
  131. assert(chan16 == 65535);
  132. Channel conversion is a lossy operation. GIL's channel conversion is a linear
  133. transformation between the ranges of the source and destination channel.
  134. It maps precisely the minimum to the minimum and the maximum to the maximum.
  135. (For example, to convert from uint8_t to uint16_t GIL does not do a bit shift
  136. because it will not properly match the maximum values. Instead GIL multiplies
  137. the source by 257).
  138. All channel models that GIL provides are convertible from/to an integral or
  139. floating point type. Thus they support arithmetic operations. Here are the
  140. channel-level algorithms that GIL provides:
  141. .. code-block:: cpp
  142. // Converts a source channel value into a destination channel.
  143. // Linearly maps the value of the source into the range of the destination.
  144. template <typename DstChannel, typename SrcChannel>
  145. typename channel_traits<DstChannel>::value_type channel_convert(SrcChannel src);
  146. // returns max_value - x + min_value
  147. template <typename Channel>
  148. typename channel_traits<Channel>::value_type channel_invert(Channel x);
  149. // returns a * b / max_value
  150. template <typename Channel>
  151. typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b);