test: libipa: Add tests for Quantized types

Provide use case tests for the Quantized types to ensure construction
and usages are consistent and work as expected.

Reviewed-by: Isaac Scott <isaac.scott@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Kieran Bingham
2026-02-19 15:05:03 +00:00
parent be64005a8e
commit cb40945db6
2 changed files with 146 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ libipa_test = [
{'name': 'histogram', 'sources': ['histogram.cpp']},
{'name': 'interpolator', 'sources': ['interpolator.cpp']},
{'name': 'pwl', 'sources': ['pwl.cpp'] },
{'name': 'quantized', 'sources': ['quantized.cpp']},
]
foreach test : libipa_test

View File

@@ -0,0 +1,145 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2026, Ideas on Board
*
* Dual Type and Quantizer tests
*/
#include "../src/ipa/libipa/quantized.h"
#include <algorithm>
#include <cmath>
#include <iostream>
#include <stdint.h>
#include "test.h"
using namespace std;
using namespace libcamera;
using namespace ipa;
struct BrightnessHueTraits {
using QuantizedType = uint8_t;
static QuantizedType fromFloat(float v)
{
int quantized = std::lround(v * 128.0f);
return std::clamp<int>(quantized, -128, 127);
}
static float toFloat(QuantizedType v)
{
return static_cast<float>(v) / 128.0f;
}
};
using BrightnessHueQuantizer = Quantized<BrightnessHueTraits>;
struct ContrastSaturationTraits {
using QuantizedType = uint8_t;
static QuantizedType fromFloat(float v)
{
int quantized = std::lround(v * 128.0f);
return std::clamp<int>(quantized, 0, 255);
}
static float toFloat(QuantizedType v)
{
return static_cast<float>(v) / 128.0f;
}
};
using ContrastSaturationQuantizer = Quantized<ContrastSaturationTraits>;
using BrightnessQ = BrightnessHueQuantizer;
using HueQ = BrightnessHueQuantizer;
using ContrastQ = ContrastSaturationQuantizer;
using SaturationQ = ContrastSaturationQuantizer;
class QuantizedTest : public Test
{
protected:
int run()
{
/* Test construction from float */
{
BrightnessQ b(0.5f);
if (b.quantized() != 64 || std::abs(b.value() - 0.5f) > 0.01f)
return TestFail;
}
/* Test construction from T */
{
ContrastQ c(uint8_t(128));
if (c.quantized() != 128 || std::abs(c.value() - 1.0f) > 0.01f)
return TestFail;
}
/*
* Only construction from the exact storage type or a float
* is permitted.
*/
static_assert(!std::is_constructible_v<BrightnessQ, unsigned int>);
static_assert(!std::is_constructible_v<BrightnessQ, int8_t>);
static_assert(!std::is_constructible_v<BrightnessQ, double>);
static_assert(!std::is_constructible_v<ContrastQ, int>);
static_assert(!std::is_constructible_v<ContrastQ, int8_t>);
static_assert(!std::is_constructible_v<ContrastQ, unsigned int>);
/* Test equality */
{
BrightnessQ b1(0.5f), b2(uint8_t(64));
if (!(b1 == b2))
return TestFail;
}
/* Test inequality */
{
BrightnessQ b1(0.5f), b2(-0.5f);
if (!(b1 != b2))
return TestFail;
}
/* Test copying */
{
BrightnessQ b1(0.25f);
BrightnessQ b2 = b1;
if (!(b1 == b2))
return TestFail;
}
/* Test assignment */
{
ContrastQ c1(1.5f);
ContrastQ c2(0.0f);
c2 = c1;
if (!(c1 == c2))
return TestFail;
}
/*
* Test construction from different floats mapping to same
* quantized value
*/
{
/* Two floats that have the same quantized value. */
const float f1 = 1.007f;
const float f2 = 1.008f;
ContrastQ c1(f1);
ContrastQ c2(f2);
/* Quantized values must match */
if (!(c1.quantized() == c2.quantized()))
return TestFail;
/* Float values must now match */
if (!(c1.value() == c2.value()))
return TestFail;
if (!(c1 == c2))
return TestFail;
}
return TestPass;
}
};
TEST_REGISTER(QuantizedTest)