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_CORE_CHANNEL_TEST_FIXTURE_HPP 10 #define BOOST_GIL_TEST_CORE_CHANNEL_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 #include "test_utility_output_stream.hpp" 21 22 namespace boost { namespace gil { namespace test { namespace fixture { 23 24 using channel_byte_types = std::tuple 25 < 26 std::uint8_t, 27 std::int8_t, 28 std::uint16_t, 29 std::int16_t, 30 std::uint32_t, 31 std::int32_t, 32 gil::float32_t, 33 gil::float64_t 34 >; 35 36 using channel_integer_types = std::tuple 37 < 38 std::uint8_t, 39 std::int8_t, 40 std::uint16_t, 41 std::int16_t, 42 std::uint32_t, 43 std::int32_t 44 >; 45 46 using channel_integer_signed_types = std::tuple 47 < 48 std::int8_t, 49 std::int16_t, 50 std::int32_t 51 >; 52 53 using channel_integer_unsigned_types = std::tuple 54 < 55 std::uint8_t, 56 std::uint16_t, 57 std::uint32_t 58 >; 59 60 // FIXME: If float types are convertible between each other, 61 // currently they are not, then move to channel_byte_types and 62 // remove channel_integer_types as redundant. 63 using channel_float_types = std::tuple 64 < 65 gil::float32_t, 66 gil::float64_t 67 >; 68 69 using channel_bitfield_types = std::tuple 70 < 71 std::uint16_t, 72 std::uint32_t, 73 std::uint64_t 74 // TODO: Shall we test signed types for unexpected conversions, etc.? 75 >; 76 77 78 template <typename ChannelValue> 79 struct channel_minmax_value 80 { 81 //static_assert(std::) 82 ChannelValue min_v_; 83 ChannelValue max_v_; channel_minmax_valueboost::gil::test::fixture::channel_minmax_value84 channel_minmax_value() 85 : min_v_(gil::channel_traits<ChannelValue>::min_value()) 86 , max_v_(gil::channel_traits<ChannelValue>::max_value()) 87 {} 88 }; 89 90 template <typename ChannelFixtureBase> 91 struct channel : public ChannelFixtureBase 92 { 93 using channel_t = typename ChannelFixtureBase::channel_t; 94 using channel_value_t = typename gil::channel_traits<channel_t>::value_type; 95 channelboost::gil::test::fixture::channel96 channel() 97 { 98 BOOST_TEST_EQ(this->min_v_, gil::channel_traits<channel_t>::min_value()); 99 BOOST_TEST_EQ(this->max_v_, gil::channel_traits<channel_t>::max_value()); 100 } 101 }; 102 103 // The channel fixtures are defined for different types of channels 104 // (ie. channel values, references and subbyte references) 105 // ensure there are two members, min_v_ and max_v_ initialized 106 // with the minimum and maximum channel value. 107 // The different channel types have different ways to initialize them, 108 // thus require different fixtures provided. 109 110 // For basic channel types values can be initialized directly. 111 template <typename ChannelValue> 112 struct channel_value 113 { 114 using channel_t = ChannelValue; 115 channel_t min_v_; 116 channel_t max_v_; 117 channel_valueboost::gil::test::fixture::channel_value118 channel_value() 119 : min_v_(gil::channel_traits<ChannelValue>::min_value()) 120 , max_v_(gil::channel_traits<ChannelValue>::max_value()) 121 { 122 boost::function_requires<gil::ChannelValueConcept<ChannelValue>>(); 123 } 124 }; 125 126 // For channel references we need to have separate channel values. 127 template <typename ChannelRef> 128 struct channel_reference 129 : public channel_value<typename gil::channel_traits<ChannelRef>::value_type> 130 { 131 using parent_t = channel_value<typename gil::channel_traits<ChannelRef>::value_type>; 132 using channel_t = ChannelRef; 133 channel_t min_v_; 134 channel_t max_v_; 135 channel_referenceboost::gil::test::fixture::channel_reference136 channel_reference() 137 : parent_t() 138 , min_v_(parent_t::min_v_) 139 , max_v_(parent_t::max_v_) 140 { 141 boost::function_requires<ChannelConcept<ChannelRef>>(); 142 } 143 }; 144 145 // For sub-byte channel references we need to store the bit buffers somewhere 146 template <typename ChannelSubbyteRef, typename ChannelMutableRef = ChannelSubbyteRef> 147 struct packed_channel_reference 148 { 149 using channel_t = ChannelSubbyteRef; 150 using integer_t = typename channel_t::integer_t; 151 channel_t min_v_; 152 channel_t max_v_; 153 integer_t min_bitbuf_; 154 integer_t max_bitbuf_; 155 packed_channel_referenceboost::gil::test::fixture::packed_channel_reference156 packed_channel_reference() : min_v_(&min_bitbuf_), max_v_(&max_bitbuf_) 157 { 158 boost::function_requires<ChannelConcept<ChannelSubbyteRef>>(); 159 160 ChannelMutableRef b1(&min_bitbuf_); 161 b1 = gil::channel_traits<channel_t>::min_value(); 162 ChannelMutableRef b2(&max_bitbuf_); 163 b2 = gil::channel_traits<channel_t>::max_value(); 164 } 165 }; 166 167 // For sub-byte channel references we need to store the bit buffers somewhere 168 template <typename ChannelSubbyteRef, typename ChannelMutableRef = ChannelSubbyteRef> 169 struct packed_dynamic_channel_reference 170 { 171 using channel_t = ChannelSubbyteRef; 172 using integer_t = typename channel_t::integer_t; 173 channel_t min_v_; 174 channel_t max_v_; 175 integer_t min_bitbuf_; 176 integer_t max_bitbuf_; 177 packed_dynamic_channel_referenceboost::gil::test::fixture::packed_dynamic_channel_reference178 packed_dynamic_channel_reference(int first_bit1 = 1, int first_bit2 = 2) 179 : min_v_(&min_bitbuf_, first_bit1) 180 , max_v_(&max_bitbuf_, first_bit2) 181 { 182 boost::function_requires<ChannelConcept<ChannelSubbyteRef>>(); 183 184 ChannelMutableRef b1(&min_bitbuf_, 1); 185 b1 = gil::channel_traits<channel_t>::min_value(); 186 ChannelMutableRef b2(&max_bitbuf_, 2); 187 b2 = gil::channel_traits<channel_t>::max_value(); 188 } 189 }; 190 191 // Concrete fixture for 16-bit pack of 5,6,5-bit channels 192 template <typename BitField> 193 struct packed_channels565 194 { 195 static_assert(sizeof(BitField) >= sizeof(std::uint16_t), "16-bit or more required"); 196 using channel_0_5_t = gil::packed_channel_reference<BitField, 0, 5,true>; 197 using channel_5_6_t = gil::packed_channel_reference<BitField, 5, 6,true>; 198 using channel_11_5_t = gil::packed_channel_reference<BitField, 11, 5,true>; 199 200 using fixture_0_5_t = fixture::packed_channel_reference<channel_0_5_t>; 201 using fixture_5_6_t = fixture::packed_channel_reference<channel_5_6_t>; 202 using fixture_11_5_t = fixture::packed_channel_reference<channel_11_5_t>; 203 204 std::uint16_t data_ = 0; 205 channel_0_5_t channel1_; 206 channel_5_6_t channel2_; 207 channel_11_5_t channel3_; 208 packed_channels565boost::gil::test::fixture::packed_channels565209 packed_channels565() : channel1_(&data_), channel2_(&data_), channel3_(&data_) 210 { 211 channel1_ = gil::channel_traits<channel_0_5_t>::max_value(); 212 channel2_ = gil::channel_traits<channel_5_6_t>::max_value(); 213 channel3_ = gil::channel_traits<channel_11_5_t>::max_value(); 214 #ifdef BOOST_TEST_EQ 215 BOOST_TEST_EQ(data_, 65535); 216 #endif 217 } 218 }; 219 220 // Concrete fixture for dynamically-referenced 16-bit pack of 5,6,5-bit channels 221 template <typename BitField> 222 struct packed_dynamic_channels565 223 { 224 static_assert(sizeof(BitField) >= sizeof(std::uint16_t), "16-bit or more required"); 225 using channel_5_t = gil::packed_dynamic_channel_reference<BitField,5,true>; 226 using channel_6_t = gil::packed_dynamic_channel_reference<BitField,6,true>; 227 228 using fixture_5_t = fixture::packed_dynamic_channel_reference<channel_5_t>; 229 using fixture_6_t = fixture::packed_dynamic_channel_reference<channel_6_t>; 230 231 std::uint16_t data_ = 0; 232 channel_5_t channel1_; 233 channel_6_t channel2_; 234 channel_5_t channel3_; 235 packed_dynamic_channels565boost::gil::test::fixture::packed_dynamic_channels565236 packed_dynamic_channels565() 237 : channel1_(&data_, 0) 238 , channel2_(&data_, 5) 239 , channel3_(&data_, 11) 240 { 241 channel1_ = gil::channel_traits<channel_5_t>::max_value(); 242 channel2_ = gil::channel_traits<channel_6_t>::max_value(); 243 channel3_ = gil::channel_traits<channel_5_t>::max_value(); 244 #ifdef BOOST_TEST_EQ 245 BOOST_TEST_EQ(data_, 65535); 246 #endif 247 } 248 }; 249 250 }}}} // namespace boost::gil::test::fixture 251 252 #endif 253