Files
2026-06-14 19:09:18 +01:00

136 lines
5.6 KiB
C++

/* -*- tab-width: 4; -*- */
/* vi: set sw=2 ts=4 expandtab: */
/*
* Copyright 2010-2020 Mark Callow.
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @internal
* @file
* @~English
*
* @brief Tests of internal API functions.
*
* @author Mark Callow, github.com/MarkCallow
*/
#if defined(_WIN32)
#define _CRT_SECURE_NO_WARNINGS
#if _MSC_VER < 1900
#define snprintf _snprintf
#endif
#endif
#include "gtest/gtest.h"
#include "image.hpp"
namespace {
////////////////////////
// normalisation tests
////////////////////////
template<typename ColorType>
void test_color(ColorType input, ColorType output) {
ColorType color;
for (uint32_t i = 0; i < color.comps_count(); ++i) {
color.set(i, static_cast<typename ColorType::value_type>(input[i]));
}
// Verify color components were set correctly
for (uint32_t i = 0; i < color.comps_count(); ++i) {
EXPECT_EQ(color[i], static_cast<typename ColorType::value_type>(input[i]));
}
color.normalize();
for (uint32_t i = 0; i < color.comps_count(); ++i) {
EXPECT_EQ(color[i], static_cast<typename ColorType::value_type>(output[i]));
}
}
static constexpr uint32_t min_val{0};
static constexpr uint32_t max_val[3]={255, 65535, 4294967295};
static constexpr uint32_t some_val[3]={31, 191, 178};
template<uint32_t componentCount>
void test_by_channel( const uint32_t min_res[], const uint32_t max_res[],
const uint32_t some_res8[], const uint32_t some_res16[], const uint32_t some_res32[]) {
{
color<uint8_t, componentCount> c8i{(uint8_t)min_val, (uint8_t)min_val, (uint8_t)min_val, (uint8_t)min_val};
color<uint8_t, componentCount> c8o{(uint8_t)min_res[0], (uint8_t)min_res[0], (uint8_t)min_res[0], 0};
test_color(c8i, c8o);
}
{
color<uint8_t, componentCount> c8i{(uint8_t)max_val[0], (uint8_t)max_val[0], (uint8_t)max_val[0], (uint8_t)max_val[0]};
color<uint8_t, componentCount> c8o{(uint8_t)max_res[0], (uint8_t)max_res[0], (uint8_t)max_res[0], (uint8_t)max_val[0]};
test_color(c8i, c8o);
}
{
color<uint8_t, componentCount> c8i{(uint8_t)some_val[0], (uint8_t)some_val[1], (uint8_t)some_val[2], 0};
color<uint8_t, componentCount> c8o{(uint8_t)some_res8[0], (uint8_t)some_res8[1], (uint8_t)some_res8[2], 0};
test_color(c8i, c8o);
}
{
color<uint16_t, componentCount> c16i{(uint16_t)min_val, (uint16_t)min_val, (uint16_t)min_val, (uint16_t)min_val};
color<uint16_t, componentCount> c16o{(uint16_t)min_res[1], (uint16_t)min_res[1], (uint16_t)min_res[1], 0};
test_color(c16i, c16o);
}
{
color<uint16_t, componentCount> c16i{(uint16_t)max_val[1], (uint16_t)max_val[1], (uint16_t)max_val[1], (uint16_t)max_val[1]};
color<uint16_t, componentCount> c16o{(uint16_t)max_res[1], (uint16_t)max_res[1], (uint16_t)max_res[1], (uint16_t)max_val[1]};
test_color(c16i, c16o);
}
{
color<uint16_t, componentCount> c16i{(uint16_t)some_val[0], (uint16_t)some_val[1], (uint16_t)some_val[2], 0};
color<uint16_t, componentCount> c16o{(uint16_t)some_res16[0], (uint16_t)some_res16[1], (uint16_t)some_res16[2], 0};
test_color(c16i, c16o);
}
{
color<uint32_t, componentCount> c32i{(uint32_t)min_val, (uint32_t)min_val, (uint32_t)min_val, (uint32_t)min_val};
color<uint32_t, componentCount> c32o{(uint32_t)min_res[2], (uint32_t)min_res[2], (uint32_t)min_res[2], 0};
test_color(c32i, c32o);
}
{
color<uint32_t, componentCount> c32i{(uint32_t)max_val[2], (uint32_t)max_val[2], (uint32_t)max_val[2], (uint32_t)max_val[2]};
color<uint32_t, componentCount> c32o{(uint32_t)max_res[2], (uint32_t)max_res[2], (uint32_t)max_res[2], (uint32_t)max_val[2]};
test_color(c32i, c32o);
}
{
color<uint32_t, componentCount> c32i{(uint32_t)some_val[0], (uint32_t)some_val[1], (uint32_t)some_val[2], 0};
color<uint32_t, componentCount> c32o{(uint32_t)some_res32[0], (uint32_t)some_res32[1], (uint32_t)some_res32[2], 0};
test_color(c32i, c32o);
}
}
// Hand tested vectors and their normalised results in GeoGebra
static constexpr uint32_t min_res[3]={54, 13849, 907633408}; // These are -0.577350 float in 8bit-UNORM, 16bit-UNORM and 32bit-UNORM values
static constexpr uint32_t max_res[3]={201, 51686, 3387333888};
static constexpr uint32_t some_res8[3]={30, 192, 179};
static constexpr uint32_t some_res16[3]={13790, 13883, 13875};
static constexpr uint32_t some_res32[3]={907633408, 907633408, 907633408};
static constexpr uint32_t min_res2[3]={37, 9597, 628983424};
static constexpr uint32_t max_res2[3]={218, 55938, 3665984000};
static constexpr uint32_t some_res8_2[3]={21, 198, 128};
static constexpr uint32_t some_res16_2[3]={9541, 9654, 32768};
static constexpr uint32_t some_res32_2[3]={628983424, 628983424, 2147483648};
static constexpr uint32_t min_res1[3]={0, 0, 0};
static constexpr uint32_t max_res1[3]={255, 65535, 4294967295};
static constexpr uint32_t some_res8_1[3]={255, 0, 0}; // Second and third values are unused because its single channel image result
static constexpr uint32_t some_res16_1[3]={65535, 0, 0}; // Same as above
static constexpr uint32_t some_res32_1[3]={4294967295, 0, 0}; // Same as above
TEST(NormaliseColorTest, multi_channel_test) {
test_by_channel<4>(min_res, max_res, some_res8, some_res16, some_res32);
test_by_channel<3>(min_res, max_res, some_res8, some_res16, some_res32);
test_by_channel<2>(min_res2, max_res2, some_res8_2, some_res16_2, some_res32_2);
test_by_channel<1>(min_res1, max_res1, some_res8_1, some_res16_1, some_res32_1);
}
} // namespace