diff --git a/src/util/tests/u_ycbcr_test.cpp b/src/util/tests/u_ycbcr_test.cpp index e4dc42c8a50..202f934ce9b 100644 --- a/src/util/tests/u_ycbcr_test.cpp +++ b/src/util/tests/u_ycbcr_test.cpp @@ -304,6 +304,47 @@ TEST(u_ycbcr_test, narrow_range) } } +TEST(u_ycbcr_test, narrow_range_rgb) +{ + float range[3][2]; + unsigned bpc[3] = {8, 8, 8}; + util_get_narrow_range_rgb_coeffs(range, bpc); + + const struct { + uint8_t input[3]; + float expected[3]; + } test_data[] = { { + { 16, 16, 16 }, + { 0.0f, 0.0f, 0.0f }, + }, { + { 235, 235, 235 }, + { 1.0f, 1.0f, 1.0f }, + }, { + { 16, 89, 89 }, + { 0.0f, 1/3.0f, 1/3.0f }, + }, { + { 89, 16, 16 }, + { 1/3.0f, 0.0f, 0.0f }, + } + }; + + for (size_t i = 0; i < ARRAY_SIZE(test_data); ++i) { + float input[3] = { + test_data[i].input[0] / 255.0f, + test_data[i].input[1] / 255.0f, + test_data[i].input[2] / 255.0f, + }; + + float result[3]; + for (int c = 0; c < 3; ++c) + result[c] = input[c] * range[c][0] + range[c][1]; + + EXPECT_NEAR(test_data[i].expected[0], result[0], 1e-7); + EXPECT_NEAR(test_data[i].expected[1], result[1], 1e-7); + EXPECT_NEAR(test_data[i].expected[2], result[2], 1e-7); + } +} + static void test_to_rgb_narrow_range_coeffs(const float coeffs[3]) { diff --git a/src/util/u_ycbcr.h b/src/util/u_ycbcr.h index 0f3c52a110a..9aac2d5ee34 100644 --- a/src/util/u_ycbcr.h +++ b/src/util/u_ycbcr.h @@ -119,6 +119,17 @@ util_get_narrow_range_coeffs(float out[3][2], const unsigned bpc[3]) out[2][0] = cr_factor; out[2][1] = c_bias; } +static inline void +util_get_narrow_range_rgb_coeffs(float out[3][2], const unsigned bpc[3]) +{ + float factor = util_get_narrow_range_luma_factor(bpc[0]); + float bias = -16.0f / 219; + + out[0][0] = factor; out[0][1] = bias; + out[1][0] = factor; out[1][1] = bias; + out[2][0] = factor; out[2][1] = bias; +} + static inline void util_get_identity_range_coeffs(float out[3][2]) {