11 A channel indicates the intensity of a color component (for example, the red
12 channel in an RGB pixel). Typical channel operations are getting, comparing
13 and setting the channel values. Channels have associated minimum and maximum
14 value. GIL channels model the following concept:
18 concept ChannelConcept<typename T> : EqualityComparable<T>
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
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
32 concept MutableChannelConcept<ChannelConcept T> : Swappable<T>, Assignable<T> {};
34 concept ChannelValueConcept<ChannelConcept T> : Regular<T> {};
36 GIL allows built-in integral and floating point types to be channels.
37 Therefore the associated types and range information are defined in
38 ``channel_traits`` with the following default implementation:
48 typedef T& const const_reference;
49 typedef T* const const_pointer;
51 static value_type min_value() { return std::numeric_limits<T>::min(); }
52 static value_type max_value() { return std::numeric_limits<T>::max(); }
55 Two channel types are *compatible* if they have the same value type:
59 concept ChannelsCompatibleConcept<ChannelConcept T1, ChannelConcept T2>
61 where SameType<T1::value_type, T2::value_type>;
64 A channel may be *convertible* to another channel:
68 template <ChannelConcept Src, ChannelValueConcept Dst>
69 concept ChannelConvertibleConcept
71 Dst channel_convert(Src);
74 Note that ``ChannelConcept`` and ``MutableChannelConcept`` do not require a
75 default constructor. Channels that also support default construction (and thus
76 are regular types) model ``ChannelValueConcept``.
77 To understand the motivation for this distinction, consider a 16-bit RGB pixel
78 in a "565" bit pattern. Its channels correspond to bit ranges. To support such
79 channels, we need to create a custom proxy class corresponding to a reference
80 to a sub-byte channel.
81 Such a proxy reference class models only ``ChannelConcept``, because, similar
82 to native C++ references, it may not have a default constructor.
84 Note also that algorithms may impose additional requirements on channels,
85 such as support for arithmetic operations.
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>`_
98 All C++11 fundamental integer and float point types are valid channels.
100 The minimum and maximum values of a channel modeled by a built-in type
101 correspond to the minimum and maximum physical range of the built-in type, as
102 specified by its ``std::numeric_limits``. Sometimes the physical range is not
103 appropriate. GIL provides ``scoped_channel_value``, a model for a channel
104 adapter that allows for specifying a custom range.
105 We use it to define a ``[0..1]`` floating point channel type as follows:
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;
113 GIL also provides models for channels corresponding to ranges of bits:
117 // Value of a channel defined over NumBits bits. Models ChannelValueConcept
118 template <int NumBits> class packed_channel_value;
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;
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;
131 Note that there are two models of a reference proxy which differ based on
132 whether the offset of the channel range is specified as a template or a
133 run-time parameter. The first model is faster and more compact while the
134 second model is more flexible. For example, the second model allows us to
135 construct an iterator over bit range channels.
140 Here is how to construct the three channels of a 16-bit "565" pixel and set
141 them to their maximum value:
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>;
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);
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);
159 Assignment, equality comparison and copy construction are defined only between
164 packed_channel_value<5> channel_6bit = channel1;
165 channel_6bit = channel3;
167 // compile error: Assignment between incompatible channels
168 //channel_6bit = channel2;
170 All channel models provided by GIL are pairwise convertible:
174 channel1 = channel_traits<channel16_0_5_reference_t>::max_value();
175 assert(channel1 == 31);
177 bits16 chan16 = channel_convert<bits16>(channel1);
178 assert(chan16 == 65535);
180 Channel conversion is a lossy operation. GIL's channel conversion is a linear
181 transformation between the ranges of the source and destination channel.
182 It 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
184 because it will not properly match the maximum values. Instead GIL multiplies
187 All channel models that GIL provides are convertible from/to an integral or
188 floating point type. Thus they support arithmetic operations. Here are the
189 channel-level algorithms that GIL provides:
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);
198 // returns max_value - x + min_value
199 template <typename Channel>
200 typename channel_traits<Channel>::value_type channel_invert(Channel x);
202 // returns a * b / max_value
203 template <typename Channel>
204 typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b);