Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / gil / test / core / channel / test_fixture.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 // Copyright 2018 Mateusz Loskot <mateusz at loskot dot net>
4 //
5 // Distributed under the Boost Software License, Version 1.0
6 // See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt
8 //
9 #ifndef BOOST_GIL_TEST_TEST_FIXTURE_HPP
10 #define BOOST_GIL_TEST_TEST_FIXTURE_HPP
11
12 #include <boost/gil/channel.hpp>
13 #include <boost/gil/concepts.hpp>
14 #include <boost/gil/typedefs.hpp>
15
16 #include <cstdint>
17 #include <tuple>
18 #include <type_traits>
19
20 namespace boost { namespace gil { namespace test { namespace fixture {
21
22 using channel_byte_types = std::tuple
23     <
24         std::uint8_t,
25         std::int8_t,
26         std::uint16_t,
27         std::int16_t,
28         std::uint32_t,
29         std::int32_t,
30         gil::float32_t,
31         gil::float64_t
32     >;
33
34 using channel_integer_types = std::tuple
35     <
36         std::uint8_t,
37         std::int8_t,
38         std::uint16_t,
39         std::int16_t,
40         std::uint32_t,
41         std::int32_t
42     >;
43
44 using channel_integer_signed_types = std::tuple
45     <
46         std::int8_t,
47         std::int16_t,
48         std::int32_t
49     >;
50
51 using channel_integer_unsigned_types = std::tuple
52     <
53         std::uint8_t,
54         std::uint16_t,
55         std::uint32_t
56     >;
57
58 // FIXME: If float types are convertible between each other,
59 // currently they are not, then move to channel_byte_types and
60 // remove channel_integer_types as redundant.
61 using channel_float_types = std::tuple
62     <
63         gil::float32_t,
64         gil::float64_t
65     >;
66
67 using channel_bitfield_types = std::tuple
68     <
69         std::uint16_t,
70         std::uint32_t,
71         std::uint64_t
72         // TODO: Shall we test signed types for unexpected conversions, etc.?
73     >;
74
75
76 template <typename ChannelValue>
77 struct channel_minmax_value
78 {
79     //static_assert(std::)
80     ChannelValue min_v_;
81     ChannelValue max_v_;
82     channel_minmax_value()
83         : min_v_(gil::channel_traits<ChannelValue>::min_value())
84         , max_v_(gil::channel_traits<ChannelValue>::max_value())
85     {}
86 };
87
88 template <typename ChannelFixtureBase>
89 struct channel : public ChannelFixtureBase
90 {
91     using channel_t = typename ChannelFixtureBase::channel_t;
92     using channel_value_t = typename gil::channel_traits<channel_t>::value_type;
93
94     channel()
95     {
96         BOOST_TEST(this->min_v_ == gil::channel_traits<channel_t>::min_value());
97         BOOST_TEST(this->max_v_ == gil::channel_traits<channel_t>::max_value());
98     }
99 };
100
101 // The channel fixtures are defined for different types of channels
102 // (ie. channel values, references and subbyte references)
103 // ensure there are two members, min_v_ and max_v_ initialized
104 // with the minimum and maximum channel value.
105 // The different channel types have different ways to initialize them,
106 // thus require different fixtures provided.
107
108 // For basic channel types values can be initialized directly.
109 template <typename ChannelValue>
110 struct channel_value
111 {
112     using channel_t = ChannelValue;
113     channel_t min_v_;
114     channel_t max_v_;
115
116     channel_value()
117         : min_v_(gil::channel_traits<ChannelValue>::min_value())
118         , max_v_(gil::channel_traits<ChannelValue>::max_value())
119     {
120         boost::function_requires<gil::ChannelValueConcept<ChannelValue>>();
121     }
122 };
123
124 // For channel references we need to have separate channel values.
125 template <typename ChannelRef>
126 struct channel_reference
127     : public channel_value<typename gil::channel_traits<ChannelRef>::value_type>
128 {
129     using parent_t = channel_value<typename gil::channel_traits<ChannelRef>::value_type>;
130     using channel_t = ChannelRef;
131     channel_t min_v_;
132     channel_t max_v_;
133
134     channel_reference()
135         : parent_t()
136         , min_v_(parent_t::min_v_)
137         , max_v_(parent_t::max_v_)
138     {
139         boost::function_requires<ChannelConcept<ChannelRef>>();
140     }
141 };
142
143 // For sub-byte channel references we need to store the bit buffers somewhere
144 template <typename ChannelSubbyteRef, typename ChannelMutableRef = ChannelSubbyteRef>
145 struct packed_channel_reference
146 {
147     using channel_t = ChannelSubbyteRef;
148     using integer_t = typename channel_t::integer_t;
149     channel_t min_v_;
150     channel_t max_v_;
151     integer_t min_bitbuf_;
152     integer_t max_bitbuf_;
153
154     packed_channel_reference() : min_v_(&min_bitbuf_), max_v_(&max_bitbuf_)
155     {
156         boost::function_requires<ChannelConcept<ChannelSubbyteRef>>();
157
158         ChannelMutableRef b1(&min_bitbuf_);
159         b1 = gil::channel_traits<channel_t>::min_value();
160         ChannelMutableRef b2(&max_bitbuf_);
161         b2 = gil::channel_traits<channel_t>::max_value();
162     }
163 };
164
165 // For sub-byte channel references we need to store the bit buffers somewhere
166 template <typename ChannelSubbyteRef, typename ChannelMutableRef = ChannelSubbyteRef>
167 struct packed_dynamic_channel_reference
168 {
169     using channel_t = ChannelSubbyteRef;
170     using integer_t = typename channel_t::integer_t;
171     channel_t min_v_;
172     channel_t max_v_;
173     integer_t min_bitbuf_;
174     integer_t max_bitbuf_;
175
176     packed_dynamic_channel_reference(int first_bit1 = 1, int first_bit2 = 2)
177         : min_v_(&min_bitbuf_, first_bit1)
178         , max_v_(&max_bitbuf_, first_bit2)
179     {
180         boost::function_requires<ChannelConcept<ChannelSubbyteRef>>();
181
182         ChannelMutableRef b1(&min_bitbuf_, 1);
183         b1 = gil::channel_traits<channel_t>::min_value();
184         ChannelMutableRef b2(&max_bitbuf_, 2);
185         b2 = gil::channel_traits<channel_t>::max_value();
186     }
187 };
188
189 // Concrete fixture for 16-bit pack of 5,6,5-bit channels
190 template <typename BitField>
191 struct packed_channels565
192 {
193     static_assert(sizeof(BitField) >= sizeof(std::uint16_t), "16-bit or more required");
194     using channel_0_5_t = gil::packed_channel_reference<BitField, 0, 5,true>;
195     using channel_5_6_t = gil::packed_channel_reference<BitField, 5, 6,true>;
196     using channel_11_5_t = gil::packed_channel_reference<BitField, 11, 5,true>;
197
198     using fixture_0_5_t = fixture::packed_channel_reference<channel_0_5_t>;
199     using fixture_5_6_t = fixture::packed_channel_reference<channel_5_6_t>;
200     using fixture_11_5_t = fixture::packed_channel_reference<channel_11_5_t>;
201
202     std::uint16_t data_ = 0;
203     channel_0_5_t channel1_;
204     channel_5_6_t channel2_;
205     channel_11_5_t channel3_;
206
207     packed_channels565() : channel1_(&data_), channel2_(&data_), channel3_(&data_)
208     {
209         channel1_ = gil::channel_traits<channel_0_5_t>::max_value();
210         channel2_ = gil::channel_traits<channel_5_6_t>::max_value();
211         channel3_ = gil::channel_traits<channel_11_5_t>::max_value();
212         BOOST_TEST(data_ == 65535);
213     }
214 };
215
216 // Concrete fixture for dynamically-referenced 16-bit pack of 5,6,5-bit channels
217 template <typename BitField>
218 struct packed_dynamic_channels565
219 {
220     static_assert(sizeof(BitField) >= sizeof(std::uint16_t), "16-bit or more required");
221     using channel_5_t = gil::packed_dynamic_channel_reference<BitField,5,true>;
222     using channel_6_t = gil::packed_dynamic_channel_reference<BitField,6,true>;
223
224     using fixture_5_t = fixture::packed_dynamic_channel_reference<channel_5_t>;
225     using fixture_6_t = fixture::packed_dynamic_channel_reference<channel_6_t>;
226
227     std::uint16_t data_ = 0;
228     channel_5_t channel1_;
229     channel_6_t channel2_;
230     channel_5_t channel3_;
231
232     packed_dynamic_channels565()
233         : channel1_(&data_, 0)
234         , channel2_(&data_, 5)
235         , channel3_(&data_, 11)
236     {
237         channel1_ = gil::channel_traits<channel_5_t>::max_value();
238         channel2_ = gil::channel_traits<channel_6_t>::max_value();
239         channel3_ = gil::channel_traits<channel_5_t>::max_value();
240         BOOST_TEST(data_ == 65535);
241     }
242 };
243
244 }}}} // namespace boost::gil::test::fixture
245
246 #endif