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