diff options
Diffstat (limited to 'src/boost/libs/gil/test/legacy/channel.cpp')
-rw-r--r-- | src/boost/libs/gil/test/legacy/channel.cpp | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/src/boost/libs/gil/test/legacy/channel.cpp b/src/boost/libs/gil/test/legacy/channel.cpp new file mode 100644 index 000000000..b4225d20e --- /dev/null +++ b/src/boost/libs/gil/test/legacy/channel.cpp @@ -0,0 +1,408 @@ +// +// Copyright 2005-2007 Adobe Systems Incorporated +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +#include <boost/gil/channel.hpp> +#include <boost/gil/channel_algorithm.hpp> +#include <boost/gil/typedefs.hpp> + +#include <cstdint> +#include <exception> +#include <iostream> +#include <type_traits> + +#if defined(BOOST_CLANG) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wfloat-equal" +#elif BOOST_GCC >= 40700 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#elif BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(push) +#pragma warning(disable:4512) //assignment operator could not be generated +#endif + +using namespace boost::gil; +using namespace std; + +void error_if(bool); + +auto c8_min = channel_traits<uint8_t>::min_value(); +auto c8_max = channel_traits<uint8_t>::max_value(); +auto c8s_min = channel_traits<int8_t>::min_value(); +auto c8s_max = channel_traits<int8_t>::max_value(); +auto c16_min = channel_traits<uint16_t>::min_value(); +auto c16_max = channel_traits<uint16_t>::max_value(); +auto c16s_min = channel_traits<int16_t>::min_value(); +auto c16s_max = channel_traits<int16_t>::max_value(); +auto c32_min = channel_traits<uint32_t>::min_value(); +auto c32_max = channel_traits<uint32_t>::max_value(); +auto c32s_min = channel_traits<int32_t>::min_value(); +auto c32s_max = channel_traits<int32_t>::max_value(); +auto c32f_min = channel_traits<float32_t>::min_value(); +auto c32f_max = channel_traits<float32_t>::max_value(); + + +template <typename ChannelTestCore> +struct do_test : public ChannelTestCore { + using channel_t = typename ChannelTestCore::channel_t; + using channel_value_t = typename channel_traits<channel_t>::value_type; + + do_test() : ChannelTestCore() { + error_if(this->_min_v != channel_traits<channel_t>::min_value()); + error_if(this->_max_v != channel_traits<channel_t>::max_value()); + } + + void test_all() { + test_channel_invert(); + test_channel_convert(); + test_channel_multiply(); + test_channel_math(); + } + + void test_mutable(std::false_type) {} + void test_mutable(std::true_type) { + channel_value_t mv=this->_min_v; + ++this->_min_v; this->_min_v++; + --this->_min_v; this->_min_v--; + error_if(mv!=this->_min_v); + + this->_min_v+=1; + this->_min_v-=1; + error_if(mv!=this->_min_v); + + this->_min_v*=1; + this->_min_v/=1; + error_if(mv!=this->_min_v); + + this->_min_v = 1; // assignable to scalar + this->_min_v = mv; // and to value type + + // test swap + channel_value_t v1=this->_min_v; + channel_value_t v2=this->_max_v; + swap(this->_min_v, this->_max_v); + + channel_value_t v3=this->_min_v; + channel_value_t v4=this->_max_v; + error_if(v1!=v4 || v2!=v3); + } + + void test_channel_math() { + error_if(this->_min_v >= this->_max_v); + error_if(this->_max_v <= this->_min_v); + error_if(this->_min_v > this->_max_v); + error_if(this->_max_v < this->_min_v); + error_if(this->_max_v == this->_min_v); + error_if(!(this->_max_v != this->_min_v)); + + error_if(this->_min_v * 1 != this->_min_v); + error_if(this->_min_v / 1 != this->_min_v); + + error_if((this->_min_v + 1) + 1 != (this->_min_v + 2)); + error_if((this->_max_v - 1) - 1 != (this->_max_v - 2)); + + error_if(this->_min_v != 1 && this->_min_v==1); // comparable to integral + + + test_mutable(std::integral_constant<bool, channel_traits<channel_t>::is_mutable>()); + } + + + void test_channel_invert() { + error_if(channel_invert(this->_min_v) != this->_max_v); + error_if(channel_invert(this->_max_v) != this->_min_v); + } + + void test_channel_multiply() { + error_if(channel_multiply(this->_min_v, this->_min_v) != this->_min_v); + error_if(channel_multiply(this->_max_v, this->_max_v) != this->_max_v); + error_if(channel_multiply(this->_max_v, this->_min_v) != this->_min_v); + } + + void test_channel_convert() { + channel_value_t v_min, v_max; + + v_min=channel_convert<channel_t>(c8_min); + v_max=channel_convert<channel_t>(c8_max); + error_if(v_min!=this->_min_v || v_max!=this->_max_v); + + v_min=channel_convert<channel_t>(c8s_min); + v_max=channel_convert<channel_t>(c8s_max); + error_if(v_min!=this->_min_v || v_max!=this->_max_v); + + v_min=channel_convert<channel_t>(c16_min); + v_max=channel_convert<channel_t>(c16_max); + error_if(v_min!=this->_min_v || v_max!=this->_max_v); + + v_min=channel_convert<channel_t>(c16s_min); + v_max=channel_convert<channel_t>(c16s_max); + error_if(v_min!=this->_min_v || v_max!=this->_max_v); + + v_min=channel_convert<channel_t>(c32_min); + v_max=channel_convert<channel_t>(c32_max); + error_if(v_min!=this->_min_v || v_max!=this->_max_v); + + v_min=channel_convert<channel_t>(c32s_min); + v_max=channel_convert<channel_t>(c32s_max); + error_if(v_min!=this->_min_v || v_max!=this->_max_v); + + v_min=channel_convert<channel_t>(c32f_min); + v_max=channel_convert<channel_t>(c32f_max); + error_if(v_min!=this->_min_v || v_max!=this->_max_v); + } +}; + +// Different core classes depending on the different types of channels - channel values, references and subbyte references +// The cores ensure there are two members, _min_v and _max_v initialized with the minimum and maximum channel value. +// The different channel types have different ways to initialize them, thus require different cores + +// For channel values simply initialize the value directly +template <typename ChannelValue> +class value_core { +protected: + using channel_t = ChannelValue; + channel_t _min_v; + channel_t _max_v; + + value_core() + : _min_v(channel_traits<ChannelValue>::min_value()) + , _max_v(channel_traits<ChannelValue>::max_value()) + { + boost::function_requires<ChannelValueConcept<ChannelValue> >(); + } +}; + +// For channel references we need to have separate channel values +template <typename ChannelRef> +class reference_core : public value_core<typename channel_traits<ChannelRef>::value_type> +{ + using parent_t = value_core<typename channel_traits<ChannelRef>::value_type>; + +protected: + using channel_t = ChannelRef; + channel_t _min_v; + channel_t _max_v; + + reference_core() + : parent_t() + , _min_v(parent_t::_min_v) + , _max_v(parent_t::_max_v) + { + boost::function_requires<ChannelConcept<ChannelRef> >(); + } +}; + +// For subbyte channel references we need to store the bit buffers somewhere +template <typename ChannelSubbyteRef, typename ChannelMutableRef = ChannelSubbyteRef> +class packed_reference_core { +protected: + using channel_t = ChannelSubbyteRef; + using integer_t = typename channel_t::integer_t; + channel_t _min_v, _max_v; + + integer_t _min_buf, _max_buf; + + packed_reference_core() : _min_v(&_min_buf), _max_v(&_max_buf) { + ChannelMutableRef b1(&_min_buf), b2(&_max_buf); + b1 = channel_traits<channel_t>::min_value(); + b2 = channel_traits<channel_t>::max_value(); + + boost::function_requires<ChannelConcept<ChannelSubbyteRef> >(); + } +}; + +template <typename ChannelSubbyteRef, typename ChannelMutableRef = ChannelSubbyteRef> +class packed_dynamic_reference_core { +protected: + using channel_t = ChannelSubbyteRef; + channel_t _min_v, _max_v; + + typename channel_t::integer_t _min_buf, _max_buf; + + packed_dynamic_reference_core(int first_bit1=1, int first_bit2=2) : _min_v(&_min_buf,first_bit1), _max_v(&_max_buf,first_bit2) { + ChannelMutableRef b1(&_min_buf,1), b2(&_max_buf,2); + b1 = channel_traits<channel_t>::min_value(); + b2 = channel_traits<channel_t>::max_value(); + + boost::function_requires<ChannelConcept<ChannelSubbyteRef> >(); + } +}; + + +template <typename ChannelValue> +void test_channel_value() { + do_test<value_core<ChannelValue> >().test_all(); +} + +template <typename ChannelRef> +void test_channel_reference() { + do_test<reference_core<ChannelRef> >().test_all(); +} + +template <typename ChannelSubbyteRef> +void test_packed_channel_reference() { + do_test<packed_reference_core<ChannelSubbyteRef,ChannelSubbyteRef> >().test_all(); +} + +template <typename ChannelSubbyteRef, typename MutableRef> +void test_const_packed_channel_reference() { + do_test<packed_reference_core<ChannelSubbyteRef,MutableRef> >().test_all(); +} + +template <typename ChannelSubbyteRef> +void test_packed_dynamic_channel_reference() { + do_test<packed_dynamic_reference_core<ChannelSubbyteRef,ChannelSubbyteRef> >().test_all(); +} + +template <typename ChannelSubbyteRef, typename MutableRef> +void test_const_packed_dynamic_channel_reference() { + do_test<packed_dynamic_reference_core<ChannelSubbyteRef,MutableRef> >().test_all(); +} + +template <typename ChannelValue> +void test_channel_value_impl() { + test_channel_value<ChannelValue>(); + test_channel_reference<ChannelValue&>(); + test_channel_reference<const ChannelValue&>(); +} + +///////////////////////////////////////////////////////// +/// +/// A channel archetype - to test the minimum requirements of the concept +/// +///////////////////////////////////////////////////////// + +struct channel_value_archetype; +struct channel_archetype { + // equality comparable + friend bool operator==(const channel_archetype&,const channel_archetype&) { return true; } + friend bool operator!=(const channel_archetype&,const channel_archetype&) { return false; } + // less-than comparable + friend bool operator<(const channel_archetype&,const channel_archetype&) { return false; } + // convertible to a scalar + operator std::uint8_t() const { return 0; } + + + channel_archetype& operator++() { return *this; } + channel_archetype& operator--() { return *this; } + channel_archetype operator++(int) { return *this; } + channel_archetype operator--(int) { return *this; } + + template <typename Scalar> channel_archetype operator+=(Scalar) { return *this; } + template <typename Scalar> channel_archetype operator-=(Scalar) { return *this; } + template <typename Scalar> channel_archetype operator*=(Scalar) { return *this; } + template <typename Scalar> channel_archetype operator/=(Scalar) { return *this; } + + using value_type = channel_value_archetype; + using reference = channel_archetype; + using const_reference = channel_archetype const; + using pointer = channel_value_archetype *; + using const_pointer = channel_value_archetype const*; + static constexpr bool is_mutable=true; + + static value_type min_value(); + static value_type max_value(); +}; + + +struct channel_value_archetype : public channel_archetype { + channel_value_archetype() {} // default constructible + channel_value_archetype(const channel_value_archetype&) {} // copy constructible + channel_value_archetype& operator=(const channel_value_archetype&){return *this;} // assignable + channel_value_archetype(std::uint8_t) {} +}; + +channel_value_archetype channel_archetype::min_value() { return channel_value_archetype(); } +channel_value_archetype channel_archetype::max_value() { return channel_value_archetype(); } + + +void test_packed_channel_reference() +{ + using channel16_0_5_reference_t = packed_channel_reference<std::uint16_t, 0, 5, true>; + using channel16_5_6_reference_t = packed_channel_reference<std::uint16_t, 5, 6, true>; + using channel16_11_5_reference_t = packed_channel_reference<std::uint16_t, 11, 5, true>; + + std::uint16_t data=0; + channel16_0_5_reference_t channel1(&data); + channel16_5_6_reference_t channel2(&data); + channel16_11_5_reference_t channel3(&data); + + channel1=channel_traits<channel16_0_5_reference_t>::max_value(); + channel2=channel_traits<channel16_5_6_reference_t>::max_value(); + channel3=channel_traits<channel16_11_5_reference_t>::max_value(); + error_if(data!=65535); + + test_packed_channel_reference<channel16_0_5_reference_t>(); + test_packed_channel_reference<channel16_5_6_reference_t>(); + test_packed_channel_reference<channel16_11_5_reference_t>(); +} + +void test_packed_dynamic_channel_reference() +{ + using channel16_5_reference_t = packed_dynamic_channel_reference<std::uint16_t, 5, true>; + using channel16_6_reference_t = packed_dynamic_channel_reference<std::uint16_t, 6, true>; + + std::uint16_t data=0; + channel16_5_reference_t channel1(&data,0); + channel16_6_reference_t channel2(&data,5); + channel16_5_reference_t channel3(&data,11); + + channel1=channel_traits<channel16_5_reference_t>::max_value(); + channel2=channel_traits<channel16_6_reference_t>::max_value(); + channel3=channel_traits<channel16_5_reference_t>::max_value(); + error_if(data!=65535); + + test_packed_dynamic_channel_reference<channel16_5_reference_t>(); +} + +void test_channel() { + test_channel_value_impl<uint8_t>(); + test_channel_value_impl<int8_t>(); + test_channel_value_impl<uint16_t>(); + test_channel_value_impl<int16_t>(); + test_channel_value_impl<uint32_t>(); + test_channel_value_impl<int16_t>(); + + test_channel_value_impl<float32_t>(); + + test_packed_channel_reference(); + test_packed_dynamic_channel_reference(); + + // Do only compile-time tests for the archetype (because asserts like val1<val2 fail) + boost::function_requires<MutableChannelConcept<channel_archetype> >(); + + do_test<value_core<channel_value_archetype> >(); + do_test<reference_core<channel_archetype> >(); + do_test<reference_core<const channel_archetype&> >(); +} + +int main() +{ + try + { + test_channel(); + + return EXIT_SUCCESS; + } + catch (std::exception const& e) + { + std::cerr << e.what() << std::endl; + return EXIT_FAILURE; + } + catch (...) + { + return EXIT_FAILURE; + } +} + +// TODO: +// - provide algorithm performance overloads for scoped channel and packed channels +// - Update concepts and documentation +// - What to do about pointer types?! +// - Performance!! +// - is channel_convert the same as native? +// - is operator++ on float32_t the same as native? How about if operator++ is defined in scoped_channel to do _value++? |