blob: c80372fc5c8d09b3ac76e6cac08fec4ef85d29df [file] [log] [blame]
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cmath>
#include "pw_unit_test/framework.h"
#include "samples/risp4ml/isp_stages/gamma.h"
static constexpr uint16_t kRgbPipelineBpp = 16;
static constexpr uint16_t kPostGammaPipelineBpp = 16;
GammaParams linear_params = {
.enable = true,
.lut = {0, 256, 512, 768, 1024, 1280, 1536, 1792, 2048,
2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4352,
4608, 4864, 5120, 5376, 5632, 5888, 6144, 6400, 6656,
6912, 7168, 7424, 7680, 7936, 8192, 8704, 9216, 9728,
10240, 10752, 11264, 11776, 12288, 12800, 13312, 13824, 14336,
14848, 15360, 15872, 16384, 17408, 18432, 19456, 20480, 21504,
22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, 30720,
31744, 32768, 34816, 36864, 38912, 40960, 43008, 45056, 47104,
49152, 51200, 53248, 55296, 57344, 59392, 61440, 63488, 65535}};
GammaParams rgb_params = {
.enable = true,
.lut = {0, 3255, 5552, 7237, 8618, 9809, 10868, 11828, 12710,
13531, 14300, 15026, 15713, 16368, 16995, 17596, 18173, 18731,
19269, 19790, 20295, 20786, 21264, 21728, 22182, 22624, 23056,
23479, 23892, 24297, 24694, 25083, 25466, 26209, 26928, 27623,
28298, 28953, 29590, 30211, 30816, 31406, 31983, 32547, 33099,
33640, 34170, 34689, 35199, 36192, 37151, 38080, 38980, 39855,
40705, 41534, 42341, 43129, 43899, 44652, 45389, 46111, 46818,
47512, 48192, 49517, 50798, 52037, 53239, 54407, 55542, 56648,
57726, 58778, 59806, 60811, 61794, 62757, 63702, 64627, 65535}};
class GammaTest : public ::testing::Test {
protected:
void setup(uint16_t width) {
in_ = image_new(3, 2, width);
for (uint16_t c = 0; c < in_->num_channels; ++c) {
for (uint16_t y = 0; y < in_->height; ++y) {
for (uint16_t x = 0; x < in_->width; ++x) {
*image_pixel(in_, c, y, x) = x;
}
}
}
out_ = image_new(3, 2, width);
const uint32_t num_bytes =
in_->num_channels * in_->height * in_->width * sizeof(pixel_type_t);
memcpy(out_->data, in_->data, num_bytes);
}
void TearDown() override {
image_delete(in_);
image_delete(out_);
}
float sRgb_gamma(float in_) {
return (in_ < 0.0031308f) ? 12.92f * in_
: 1.055f * std::pow(in_, 1.0f / 2.4f) - 0.055f;
}
Image* in_;
Image* out_;
};
TEST_F(GammaTest, Bypass) {
setup((1 << 15) - 1);
GammaParams params = rgb_params;
params.enable = false;
set_gamma_params(&params);
gamma_process(out_);
for (uint16_t c = 0; c < in_->num_channels; ++c) {
for (uint16_t y = 0; y < in_->height; ++y) {
for (uint16_t x = 0; x < in_->width; ++x) {
pixel_type_t expected_val =
x >> (kRgbPipelineBpp - kPostGammaPipelineBpp);
ASSERT_EQ(expected_val, image_pixel_val(out_, c, y, x));
}
}
}
}
TEST_F(GammaTest, Linear) {
setup((1 << 15) - 2);
set_gamma_params(&linear_params);
gamma_process(out_);
for (uint16_t c = 0; c < in_->num_channels; ++c) {
for (uint16_t y = 0; y < in_->height; ++y) {
for (uint16_t x = 0; x < in_->width; ++x) {
ASSERT_EQ(image_pixel_val(out_, 0, y, x),
image_pixel_val(in_, 0, y, x));
}
}
}
}
TEST_F(GammaTest, sRgbLUT) {
setup((1 << 15) - 1);
constexpr float kToleranceRatio = 0.03;
set_gamma_params(&rgb_params);
gamma_process(out_);
for (uint16_t c = 0; c < in_->num_channels; ++c) {
for (uint16_t y = 0; y < in_->height; ++y) {
for (uint16_t x = 0; x < in_->width; ++x) {
pixel_type_t expected_val =
(pixel_type_t)((1 << kRgbPipelineBpp) *
sRgb_gamma(static_cast<float>(x) /
(1 << kRgbPipelineBpp)));
float tolerance = ceilf(kToleranceRatio * expected_val);
float diff = std::abs((float)expected_val -
(float)image_pixel_val(out_, c, y, x));
ASSERT_LE(diff, tolerance);
}
}
}
}