2 Copyright 2005-2007 Adobe Systems Incorporated
4 Use, modification and distribution are subject to the Boost Software License,
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt).
8 See http://opensource.adobe.com/gil for most recent version including documentation.
10 // channel.cpp : Tests channel
14 #include <boost/gil/gil_config.hpp>
15 #include <boost/gil/channel_algorithm.hpp>
16 #include <boost/gil/gil_concept.hpp>
18 using namespace boost::gil
;
23 bits8 c8_min
= channel_traits
<bits8
>::min_value();
24 bits8 c8_max
= channel_traits
<bits8
>::max_value();
25 bits8s c8s_min
= channel_traits
<bits8s
>::min_value();
26 bits8s c8s_max
= channel_traits
<bits8s
>::max_value();
27 bits16 c16_min
= channel_traits
<bits16
>::min_value();
28 bits16 c16_max
= channel_traits
<bits16
>::max_value();
29 bits16s c16s_min
= channel_traits
<bits16s
>::min_value();
30 bits16s c16s_max
= channel_traits
<bits16s
>::max_value();
31 bits32 c32_min
= channel_traits
<bits32
>::min_value();
32 bits32 c32_max
= channel_traits
<bits32
>::max_value();
33 bits32s c32s_min
= channel_traits
<bits32s
>::min_value();
34 bits32s c32s_max
= channel_traits
<bits32s
>::max_value();
35 bits32f c32f_min
= channel_traits
<bits32f
>::min_value();
36 bits32f c32f_max
= channel_traits
<bits32f
>::max_value();
39 template <typename ChannelTestCore
>
40 struct do_test
: public ChannelTestCore
{
41 typedef typename
ChannelTestCore::channel_t channel_t
;
42 typedef typename channel_traits
<channel_t
>::value_type channel_value_t
;
44 do_test() : ChannelTestCore() {
45 error_if(this->_min_v
!= channel_traits
<channel_t
>::min_value());
46 error_if(this->_max_v
!= channel_traits
<channel_t
>::max_value());
50 test_channel_invert();
51 test_channel_convert();
52 test_channel_multiply();
56 void test_mutable(boost::mpl::false_
) {}
57 void test_mutable(boost::mpl::true_
) {
58 channel_value_t mv
=this->_min_v
;
59 ++this->_min_v
; this->_min_v
++;
60 --this->_min_v
; this->_min_v
--;
61 error_if(mv
!=this->_min_v
);
65 error_if(mv
!=this->_min_v
);
69 error_if(mv
!=this->_min_v
);
71 this->_min_v
= 1; // assignable to scalar
72 this->_min_v
= mv
; // and to value type
75 channel_value_t v1
=this->_min_v
;
76 channel_value_t v2
=this->_max_v
;
77 swap(this->_min_v
, this->_max_v
);
79 channel_value_t v3
=this->_min_v
;
80 channel_value_t v4
=this->_max_v
;
81 error_if(v1
!=v4
|| v2
!=v3
);
84 void test_channel_math() {
85 error_if(this->_min_v
>= this->_max_v
);
86 error_if(this->_max_v
<= this->_min_v
);
87 error_if(this->_min_v
> this->_max_v
);
88 error_if(this->_max_v
< this->_min_v
);
89 error_if(this->_max_v
== this->_min_v
);
90 error_if(!(this->_max_v
!= this->_min_v
));
92 error_if(this->_min_v
* 1 != this->_min_v
);
93 error_if(this->_min_v
/ 1 != this->_min_v
);
95 error_if((this->_min_v
+ 1) + 1 != (this->_min_v
+ 2));
96 error_if((this->_max_v
- 1) - 1 != (this->_max_v
- 2));
98 error_if(this->_min_v
!= 1 && this->_min_v
==1); // comparable to integral
101 test_mutable(boost::mpl::bool_
<channel_traits
<channel_t
>::is_mutable
>());
105 void test_channel_invert() {
106 error_if(channel_invert(this->_min_v
) != this->_max_v
);
107 error_if(channel_invert(this->_max_v
) != this->_min_v
);
110 void test_channel_multiply() {
111 error_if(channel_multiply(this->_min_v
, this->_min_v
) != this->_min_v
);
112 error_if(channel_multiply(this->_max_v
, this->_max_v
) != this->_max_v
);
113 error_if(channel_multiply(this->_max_v
, this->_min_v
) != this->_min_v
);
116 void test_channel_convert() {
117 channel_value_t v_min
, v_max
;
119 v_min
=channel_convert
<channel_t
>(c8_min
);
120 v_max
=channel_convert
<channel_t
>(c8_max
);
121 error_if(v_min
!=this->_min_v
|| v_max
!=this->_max_v
);
123 v_min
=channel_convert
<channel_t
>(c8s_min
);
124 v_max
=channel_convert
<channel_t
>(c8s_max
);
125 error_if(v_min
!=this->_min_v
|| v_max
!=this->_max_v
);
127 v_min
=channel_convert
<channel_t
>(c16_min
);
128 v_max
=channel_convert
<channel_t
>(c16_max
);
129 error_if(v_min
!=this->_min_v
|| v_max
!=this->_max_v
);
131 v_min
=channel_convert
<channel_t
>(c16s_min
);
132 v_max
=channel_convert
<channel_t
>(c16s_max
);
133 error_if(v_min
!=this->_min_v
|| v_max
!=this->_max_v
);
135 v_min
=channel_convert
<channel_t
>(c32_min
);
136 v_max
=channel_convert
<channel_t
>(c32_max
);
137 error_if(v_min
!=this->_min_v
|| v_max
!=this->_max_v
);
139 v_min
=channel_convert
<channel_t
>(c32s_min
);
140 v_max
=channel_convert
<channel_t
>(c32s_max
);
141 error_if(v_min
!=this->_min_v
|| v_max
!=this->_max_v
);
143 v_min
=channel_convert
<channel_t
>(c32f_min
);
144 v_max
=channel_convert
<channel_t
>(c32f_max
);
145 error_if(v_min
!=this->_min_v
|| v_max
!=this->_max_v
);
149 // Different core classes depending on the different types of channels - channel values, references and subbyte references
150 // The cores ensure there are two members, _min_v and _max_v initialized with the minimum and maximum channel value.
151 // The different channel types have different ways to initialize them, thus require different cores
153 // For channel values simply initialize the value directly
154 template <typename ChannelValue
>
157 typedef ChannelValue channel_t
;
158 channel_t _min_v
, _max_v
;
160 value_core() : _min_v(channel_traits
<ChannelValue
>::min_value()), _max_v(channel_traits
<ChannelValue
>::max_value()) {
161 boost::function_requires
<ChannelValueConcept
<ChannelValue
> >();
165 // For channel references we need to have separate channel values
166 template <typename ChannelRef
>
167 class reference_core
: public value_core
<typename channel_traits
<ChannelRef
>::value_type
> {
168 typedef value_core
<typename channel_traits
<ChannelRef
>::value_type
> parent_t
;
170 typedef ChannelRef channel_t
;
171 channel_t _min_v
, _max_v
;
173 reference_core() : parent_t(), _min_v(parent_t::_min_v
), _max_v(parent_t::_max_v
) {
174 boost::function_requires
<ChannelConcept
<ChannelRef
> >();
178 // For subbyte channel references we need to store the bit buffers somewhere
179 template <typename ChannelSubbyteRef
, typename ChannelMutableRef
= ChannelSubbyteRef
>
180 class packed_reference_core
{
182 typedef ChannelSubbyteRef channel_t
;
183 typedef typename
channel_t::integer_t integer_t
;
184 channel_t _min_v
, _max_v
;
186 integer_t _min_buf
, _max_buf
;
188 packed_reference_core() : _min_v(&_min_buf
), _max_v(&_max_buf
) {
189 ChannelMutableRef
b1(&_min_buf
), b2(&_max_buf
);
190 b1
= channel_traits
<channel_t
>::min_value();
191 b2
= channel_traits
<channel_t
>::max_value();
193 boost::function_requires
<ChannelConcept
<ChannelSubbyteRef
> >();
197 template <typename ChannelSubbyteRef
, typename ChannelMutableRef
= ChannelSubbyteRef
>
198 class packed_dynamic_reference_core
{
200 typedef ChannelSubbyteRef channel_t
;
201 channel_t _min_v
, _max_v
;
203 typename
channel_t::integer_t _min_buf
, _max_buf
;
205 packed_dynamic_reference_core(int first_bit1
=1, int first_bit2
=2) : _min_v(&_min_buf
,first_bit1
), _max_v(&_max_buf
,first_bit2
) {
206 ChannelMutableRef
b1(&_min_buf
,1), b2(&_max_buf
,2);
207 b1
= channel_traits
<channel_t
>::min_value();
208 b2
= channel_traits
<channel_t
>::max_value();
210 boost::function_requires
<ChannelConcept
<ChannelSubbyteRef
> >();
215 template <typename ChannelValue
>
216 void test_channel_value() {
217 do_test
<value_core
<ChannelValue
> >().test_all();
220 template <typename ChannelRef
>
221 void test_channel_reference() {
222 do_test
<reference_core
<ChannelRef
> >().test_all();
225 template <typename ChannelSubbyteRef
>
226 void test_packed_channel_reference() {
227 do_test
<packed_reference_core
<ChannelSubbyteRef
,ChannelSubbyteRef
> >().test_all();
230 template <typename ChannelSubbyteRef
, typename MutableRef
>
231 void test_const_packed_channel_reference() {
232 do_test
<packed_reference_core
<ChannelSubbyteRef
,MutableRef
> >().test_all();
235 template <typename ChannelSubbyteRef
>
236 void test_packed_dynamic_channel_reference() {
237 do_test
<packed_dynamic_reference_core
<ChannelSubbyteRef
,ChannelSubbyteRef
> >().test_all();
240 template <typename ChannelSubbyteRef
, typename MutableRef
>
241 void test_const_packed_dynamic_channel_reference() {
242 do_test
<packed_dynamic_reference_core
<ChannelSubbyteRef
,MutableRef
> >().test_all();
245 template <typename ChannelValue
>
246 void test_channel_value_impl() {
247 test_channel_value
<ChannelValue
>();
248 test_channel_reference
<ChannelValue
&>();
249 test_channel_reference
<const ChannelValue
&>();
252 /////////////////////////////////////////////////////////
254 /// A channel archetype - to test the minimum requirements of the concept
256 /////////////////////////////////////////////////////////
258 struct channel_value_archetype
;
259 struct channel_archetype
{
260 // equality comparable
261 friend bool operator==(const channel_archetype
&,const channel_archetype
&) { return true; }
262 friend bool operator!=(const channel_archetype
&,const channel_archetype
&) { return false; }
263 // less-than comparable
264 friend bool operator<(const channel_archetype
&,const channel_archetype
&) { return false; }
265 // convertible to a scalar
266 operator bits8() const { return 0; }
269 channel_archetype
& operator++() { return *this; }
270 channel_archetype
& operator--() { return *this; }
271 channel_archetype
operator++(int) { return *this; }
272 channel_archetype
operator--(int) { return *this; }
274 template <typename Scalar
> channel_archetype
operator+=(Scalar
) { return *this; }
275 template <typename Scalar
> channel_archetype
operator-=(Scalar
) { return *this; }
276 template <typename Scalar
> channel_archetype
operator*=(Scalar
) { return *this; }
277 template <typename Scalar
> channel_archetype
operator/=(Scalar
) { return *this; }
279 typedef channel_value_archetype value_type
;
280 typedef channel_archetype reference
;
281 typedef const channel_archetype const_reference
;
282 typedef channel_value_archetype
* pointer
;
283 typedef const channel_value_archetype
* const_pointer
;
284 BOOST_STATIC_CONSTANT(bool, is_mutable
=true);
286 static value_type
min_value();
287 static value_type
max_value();
291 struct channel_value_archetype
: public channel_archetype
{
292 channel_value_archetype() {} // default constructible
293 channel_value_archetype(const channel_value_archetype
&) {} // copy constructible
294 channel_value_archetype
& operator=(const channel_value_archetype
&){return *this;} // assignable
295 channel_value_archetype(bits8
) {}
298 channel_value_archetype
channel_archetype::min_value() { return channel_value_archetype(); }
299 channel_value_archetype
channel_archetype::max_value() { return channel_value_archetype(); }
302 void test_packed_channel_reference() {
303 typedef packed_channel_reference
<boost::uint16_t, 0,5,true> channel16_0_5_reference_t
;
304 typedef packed_channel_reference
<boost::uint16_t, 5,6,true> channel16_5_6_reference_t
;
305 typedef packed_channel_reference
<boost::uint16_t, 11,5,true> channel16_11_5_reference_t
;
307 boost::uint16_t data
=0;
308 channel16_0_5_reference_t
channel1(&data
);
309 channel16_5_6_reference_t
channel2(&data
);
310 channel16_11_5_reference_t
channel3(&data
);
312 channel1
=channel_traits
<channel16_0_5_reference_t
>::max_value();
313 channel2
=channel_traits
<channel16_5_6_reference_t
>::max_value();
314 channel3
=channel_traits
<channel16_11_5_reference_t
>::max_value();
315 error_if(data
!=65535);
317 test_packed_channel_reference
<channel16_0_5_reference_t
>();
318 test_packed_channel_reference
<channel16_5_6_reference_t
>();
319 test_packed_channel_reference
<channel16_11_5_reference_t
>();
322 void test_packed_dynamic_channel_reference() {
323 typedef packed_dynamic_channel_reference
<boost::uint16_t,5,true> channel16_5_reference_t
;
324 typedef packed_dynamic_channel_reference
<boost::uint16_t,6,true> channel16_6_reference_t
;
326 boost::uint16_t data
=0;
327 channel16_5_reference_t
channel1(&data
,0);
328 channel16_6_reference_t
channel2(&data
,5);
329 channel16_5_reference_t
channel3(&data
,11);
331 channel1
=channel_traits
<channel16_5_reference_t
>::max_value();
332 channel2
=channel_traits
<channel16_6_reference_t
>::max_value();
333 channel3
=channel_traits
<channel16_5_reference_t
>::max_value();
334 error_if(data
!=65535);
336 test_packed_dynamic_channel_reference
<channel16_5_reference_t
>();
339 void test_channel() {
340 test_channel_value_impl
<bits8
>();
341 test_channel_value_impl
<bits8s
>();
342 test_channel_value_impl
<bits16
>();
343 test_channel_value_impl
<bits16s
>();
344 test_channel_value_impl
<bits32
>();
345 test_channel_value_impl
<bits32s
>();
347 test_channel_value_impl
<bits32f
>();
349 test_packed_channel_reference();
350 test_packed_dynamic_channel_reference();
352 // Do only compile-time tests for the archetype (because asserts like val1<val2 fail)
353 boost::function_requires
<MutableChannelConcept
<channel_archetype
> >();
355 do_test
<value_core
<channel_value_archetype
> >();
356 do_test
<reference_core
<channel_archetype
> >();
357 do_test
<reference_core
<const channel_archetype
&> >();
360 int main(int argc
, char* argv
[]) {
366 // - provide algorithm performance overloads for scoped channel and packed channels
367 // - Update concepts and documentation
368 // - What to do about pointer types?!
370 // - is channel_convert the same as native?
371 // - is operator++ on bits32f the same as native? How about if operator++ is defined in scoped_channel to do _value++?