mirror of
https://github.com/boostorg/gil.git
synced 2026-01-24 18:02:17 +00:00
Improve utilities sending channels, pixels and other GIL objects to
output stream for logging of test errors.
Fix missing namespace qualification in IO tests.
Comment TARGA test case with FIXME that was accidentally
uncommented in cc64bdd1a4
485 lines
15 KiB
C++
485 lines
15 KiB
C++
//
|
|
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
|
|
//
|
|
// 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.hpp>
|
|
#include <boost/gil/extension/numeric/channel_numeric_operations.hpp>
|
|
|
|
#include <boost/core/lightweight_test.hpp>
|
|
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
|
|
#include "test_utility_output_stream.hpp"
|
|
#include "core/channel/test_fixture.hpp"
|
|
|
|
namespace gil = boost::gil;
|
|
namespace fixture = boost::gil::test::fixture;
|
|
|
|
struct test_plus_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_plus_t<channel_t, channel_t, channel_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel_t(0));
|
|
BOOST_TEST_EQ(f(100, 27), channel_t(127));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
struct test_plus_integer_mixed_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
{
|
|
using channel1_t = channel_t;
|
|
using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
|
|
gil::channel_plus_t<channel1_t, channel2_t, channel1_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel1_t(0));
|
|
BOOST_TEST_EQ(f(100, 27), channel_t(127));
|
|
}
|
|
{
|
|
using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
|
|
using channel2_t = channel_t;
|
|
gil::channel_plus_t<channel1_t, channel2_t, channel2_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel2_t(0));
|
|
BOOST_TEST_EQ(f(100, 27), channel_t(127));
|
|
}
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_integer_mixed_types{});
|
|
}
|
|
};
|
|
|
|
struct test_plus_integer_signed_types_with_overflow
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
// Signed integer overflow is UB, so just check addition does not yield mathematically
|
|
// expected value but is constrained by the range of representable values for given type.
|
|
|
|
auto const max_value = gil::channel_traits<channel_t>::max_value();
|
|
gil::channel_plus_t<channel_t, channel_t, channel_t> f;
|
|
BOOST_TEST_NE(f(max_value, 1), std::int64_t(max_value) + 1);
|
|
BOOST_TEST_NE(f(max_value, max_value), std::int64_t(max_value) + max_value);
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_signed_types>(test_plus_integer_signed_types_with_overflow{});
|
|
}
|
|
};
|
|
|
|
struct test_plus_integer_unsigned_types_with_wraparound
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
// The C Standard, 6.2.5, paragraph 9 [ISO/IEC 9899:2011], states:
|
|
// A computation involving unsigned operands can never overflow, because a result that
|
|
// cannot be represented by the resulting unsigned integer type is reduced modulo the number
|
|
// that is one greater than the largest value that can be represented by the resulting type.
|
|
|
|
auto const max_value = gil::channel_traits<channel_t>::max_value();
|
|
auto const min_value = gil::channel_traits<channel_t>::min_value();
|
|
gil::channel_plus_t<channel_t, channel_t, channel_t> f;
|
|
BOOST_TEST_EQ(f(max_value, 1), min_value);
|
|
BOOST_TEST_EQ(f(max_value, max_value), max_value - 1);
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_unsigned_types>(test_plus_integer_unsigned_types_with_wraparound{});
|
|
}
|
|
};
|
|
|
|
struct test_minus_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_minus_t<channel_t, channel_t, channel_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel_t(0));
|
|
BOOST_TEST_EQ(f(100, 27), channel_t(73));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
struct test_minus_integer_mixed_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
{
|
|
using channel1_t = channel_t;
|
|
using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
|
|
gil::channel_minus_t<channel1_t, channel2_t, channel1_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel1_t(0));
|
|
BOOST_TEST_EQ(f(100, 27), channel_t(73));
|
|
}
|
|
{
|
|
using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
|
|
using channel2_t = channel_t;
|
|
gil::channel_minus_t<channel1_t, channel2_t, channel2_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel2_t(0));
|
|
BOOST_TEST_EQ(f(100, 27), channel_t(73));
|
|
}
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_integer_mixed_types{});
|
|
}
|
|
};
|
|
|
|
struct test_multiplies_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_multiplies_t<channel_t, channel_t, channel_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel_t(0));
|
|
BOOST_TEST_EQ(f(1, 1), channel_t(1));
|
|
BOOST_TEST_EQ(f(4, 2), channel_t(8));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
struct test_multiplies_integer_mixed_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
{
|
|
using channel1_t = channel_t;
|
|
using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
|
|
gil::channel_multiplies_t<channel1_t, channel2_t, channel1_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel1_t(0));
|
|
BOOST_TEST_EQ(f(4, 2), channel_t(8));
|
|
}
|
|
{
|
|
using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
|
|
using channel2_t = channel_t;
|
|
gil::channel_multiplies_t<channel1_t, channel2_t, channel2_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel2_t(0));
|
|
BOOST_TEST_EQ(f(4, 2), channel_t(8));
|
|
}
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_integer_mixed_types{});
|
|
}
|
|
};
|
|
|
|
struct test_divides_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_divides_t<channel_t, channel_t, channel_t> f;
|
|
BOOST_TEST_EQ(f(0, 1), channel_t(0));
|
|
BOOST_TEST_EQ(f(1, 1), channel_t(1));
|
|
BOOST_TEST_EQ(f(4, 2), channel_t(2));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
struct test_divides_integer_mixed_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
{
|
|
using channel1_t = channel_t;
|
|
using channel2_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
|
|
gil::channel_divides_t<channel1_t, channel2_t, channel1_t> f;
|
|
BOOST_TEST_EQ(f(0, 1), channel1_t(0));
|
|
BOOST_TEST_EQ(f(4, 2), channel_t(2));
|
|
}
|
|
{
|
|
using channel1_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
|
|
using channel2_t = channel_t;
|
|
gil::channel_divides_t<channel1_t, channel2_t, channel2_t> f;
|
|
BOOST_TEST_EQ(f(0, 1), channel2_t(0));
|
|
BOOST_TEST_EQ(f(4, 2), channel_t(2));
|
|
}
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_integer_mixed_types{});
|
|
}
|
|
};
|
|
|
|
struct test_plus_scalar_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_plus_scalar_t<channel_t, int, channel_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel_t(0));
|
|
BOOST_TEST_EQ(f(100, 27), channel_t(127));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_scalar_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
struct test_plus_scalar_integer_mixed_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
using channel_result_t = std::uint8_t;
|
|
gil::channel_plus_scalar_t<channel_t, int, channel_result_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel_result_t(0));
|
|
BOOST_TEST_EQ(f(100, 27), channel_result_t(127));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_plus_scalar_integer_mixed_types{});
|
|
}
|
|
};
|
|
|
|
struct test_minus_scalar_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_minus_scalar_t<channel_t, int, channel_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel_t(0));
|
|
BOOST_TEST_EQ(f(100, 27), channel_t(73));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_scalar_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
struct test_minus_scalar_integer_mixed_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
using channel_result_t = std::uint8_t;
|
|
gil::channel_minus_scalar_t<channel_t, int, std::uint8_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel_result_t(0));
|
|
BOOST_TEST_EQ(f(100, 27), channel_result_t(73));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_minus_scalar_integer_mixed_types{});
|
|
}
|
|
};
|
|
|
|
struct test_multiplies_scalar_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_multiplies_scalar_t<channel_t, channel_t, channel_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel_t(0));
|
|
BOOST_TEST_EQ(f(1, 1), channel_t(1));
|
|
BOOST_TEST_EQ(f(4, 2), channel_t(8));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_scalar_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
struct test_multiplies_scalar_integer_mixed_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
using channel_result_t = std::uint8_t;
|
|
gil::channel_multiplies_scalar_t<channel_t, int, channel_result_t> f;
|
|
BOOST_TEST_EQ(f(0, 0), channel_result_t(0));
|
|
BOOST_TEST_EQ(f(4, 2), channel_result_t(8));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_multiplies_scalar_integer_mixed_types{});
|
|
}
|
|
};
|
|
|
|
struct test_divides_scalar_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_divides_scalar_t<channel_t, channel_t, channel_t> f;
|
|
BOOST_TEST_EQ(f(0, 1), channel_t(0));
|
|
BOOST_TEST_EQ(f(1, 1), channel_t(1));
|
|
BOOST_TEST_EQ(f(4, 2), channel_t(2));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_scalar_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
struct test_divides_scalar_integer_mixed_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
using channel_result_t = std::uint8_t; // duplicates only one of fixture::channel_integer_types
|
|
gil::channel_divides_scalar_t<channel_t, int, channel_result_t> f;
|
|
BOOST_TEST_EQ(f(0, 1), channel_t(0));
|
|
BOOST_TEST_EQ(f(4, 2), channel_t(2));
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_divides_scalar_integer_mixed_types{});
|
|
}
|
|
};
|
|
|
|
struct test_halves_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_halves_t<channel_t> f;
|
|
{
|
|
channel_t c(0);
|
|
f(c);
|
|
BOOST_TEST_EQ(c, channel_t(0));
|
|
}
|
|
{
|
|
channel_t c(2);
|
|
f(c);
|
|
BOOST_TEST_EQ(c, channel_t(1));
|
|
}
|
|
{
|
|
channel_t c(4);
|
|
f(c);
|
|
BOOST_TEST_EQ(c, channel_t(2));
|
|
}
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_halves_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
struct test_zeros_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_zeros_t<channel_t> f;
|
|
{
|
|
channel_t c(0);
|
|
f(c);
|
|
BOOST_TEST_EQ(c, channel_t(0));
|
|
}
|
|
{
|
|
channel_t c(2);
|
|
f(c);
|
|
BOOST_TEST_EQ(c, channel_t(0));
|
|
}
|
|
{
|
|
channel_t c(4);
|
|
f(c);
|
|
BOOST_TEST_EQ(c, channel_t(0));
|
|
}
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_zeros_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
struct test_assigns_integer_same_types
|
|
{
|
|
template <typename Channel>
|
|
void operator()(Channel const&)
|
|
{
|
|
using channel_t = Channel;
|
|
gil::channel_assigns_t<channel_t, channel_t> f;
|
|
{
|
|
channel_t c1(10);
|
|
channel_t c2(20);
|
|
f(c1, c2);
|
|
BOOST_TEST_EQ(c2, c1);
|
|
}
|
|
}
|
|
static void run()
|
|
{
|
|
boost::mp11::mp_for_each<fixture::channel_integer_types>(test_assigns_integer_same_types{});
|
|
}
|
|
};
|
|
|
|
int main()
|
|
{
|
|
test_plus_integer_same_types::run();
|
|
test_plus_integer_mixed_types::run();
|
|
test_plus_integer_signed_types_with_overflow::run();
|
|
test_plus_integer_unsigned_types_with_wraparound::run();
|
|
|
|
test_minus_integer_same_types::run();
|
|
test_minus_integer_mixed_types::run();
|
|
|
|
test_multiplies_integer_same_types::run();
|
|
test_multiplies_integer_mixed_types::run();
|
|
|
|
test_divides_integer_same_types::run();
|
|
test_divides_integer_mixed_types::run();
|
|
|
|
test_plus_scalar_integer_same_types::run();
|
|
test_plus_scalar_integer_mixed_types::run();
|
|
|
|
test_minus_scalar_integer_same_types::run();
|
|
test_minus_scalar_integer_mixed_types::run();
|
|
|
|
test_multiplies_scalar_integer_same_types::run();
|
|
test_multiplies_scalar_integer_mixed_types::run();
|
|
|
|
test_divides_scalar_integer_same_types::run();
|
|
test_divides_scalar_integer_mixed_types::run();
|
|
|
|
test_halves_integer_same_types::run();
|
|
test_zeros_integer_same_types::run();
|
|
test_assigns_integer_same_types::run();
|
|
|
|
return ::boost::report_errors();
|
|
}
|