From db72bb1313a637f9c3aeaf56e3bac43f22254d2d Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Fri, 30 Aug 2024 13:50:10 +0200 Subject: [PATCH] Clean YCgCo-R a bit. (#2418) --- src/reformat.c | 3 +- tests/gtest/avifrgbtoyuvtest.cc | 67 ++++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/reformat.c b/src/reformat.c index d59435dedc..3a34d5fb59 100644 --- a/src/reformat.c +++ b/src/reformat.c @@ -361,7 +361,7 @@ avifResult avifImageRGBToYUV(avifImage * image, const avifRGBImage * rgb) yuvBlock[bI][bJ].v = 0.5f * (rgbPixel[0] - rgbPixel[2]); #if defined(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R) } else if (state.yuv.mode == AVIF_REFORMAT_MODE_YCGCO_RE || state.yuv.mode == AVIF_REFORMAT_MODE_YCGCO_RO) { - // Formulas from JVET-U0093. + // Formulas 58,59,60,61 from https://www.itu.int/rec/T-REC-H.273-202407-P const int R = (int)avifRoundf(AVIF_CLAMP(rgbPixel[0] * rgbMaxChannelF, 0.0f, rgbMaxChannelF)); const int G = (int)avifRoundf(AVIF_CLAMP(rgbPixel[1] * rgbMaxChannelF, 0.0f, rgbMaxChannelF)); const int B = (int)avifRoundf(AVIF_CLAMP(rgbPixel[2] * rgbMaxChannelF, 0.0f, rgbMaxChannelF)); @@ -771,6 +771,7 @@ static avifResult avifImageYUVAnyToRGBAnySlow(const avifImage * image, R = t + Cr; #if defined(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R) } else if (state->yuv.mode == AVIF_REFORMAT_MODE_YCGCO_RE || state->yuv.mode == AVIF_REFORMAT_MODE_YCGCO_RO) { + // YCgCoRe/YCgCoRo: Formulas 62,63,64,65 from https://www.itu.int/rec/T-REC-H.273-202407-P const int YY = unormY; const int Cg = (int)avifRoundf(Cb * yuvMaxChannel); const int Co = (int)avifRoundf(Cr * yuvMaxChannel); diff --git a/tests/gtest/avifrgbtoyuvtest.cc b/tests/gtest/avifrgbtoyuvtest.cc index d03e5ef1c3..5db8e909b1 100644 --- a/tests/gtest/avifrgbtoyuvtest.cc +++ b/tests/gtest/avifrgbtoyuvtest.cc @@ -358,26 +358,45 @@ TEST(RGBToYUVTest, AllMatrixCoefficients) { for (avifRange yuv_range : {AVIF_RANGE_LIMITED, AVIF_RANGE_FULL}) { for (decltype(AVIF_MATRIX_COEFFICIENTS_IDENTITY) matrix_coefficients : { - AVIF_MATRIX_COEFFICIENTS_BT709, - AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED, - AVIF_MATRIX_COEFFICIENTS_FCC, - AVIF_MATRIX_COEFFICIENTS_BT470BG, - AVIF_MATRIX_COEFFICIENTS_BT601, - AVIF_MATRIX_COEFFICIENTS_SMPTE240, - AVIF_MATRIX_COEFFICIENTS_YCGCO, - AVIF_MATRIX_COEFFICIENTS_BT2020_NCL, - AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL - // These are unsupported. See avifPrepareReformatState(). - // AVIF_MATRIX_COEFFICIENTS_BT2020_CL - // AVIF_MATRIX_COEFFICIENTS_SMPTE2085 - // AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL - // AVIF_MATRIX_COEFFICIENTS_ICTCP + AVIF_MATRIX_COEFFICIENTS_BT709, + AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED, + AVIF_MATRIX_COEFFICIENTS_FCC, + AVIF_MATRIX_COEFFICIENTS_BT470BG, + AVIF_MATRIX_COEFFICIENTS_BT601, + AVIF_MATRIX_COEFFICIENTS_SMPTE240, + AVIF_MATRIX_COEFFICIENTS_YCGCO, + AVIF_MATRIX_COEFFICIENTS_BT2020_NCL, + AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL, +#if defined(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R) + AVIF_MATRIX_COEFFICIENTS_YCGCO_RE, + AVIF_MATRIX_COEFFICIENTS_YCGCO_RO, +#endif + // These are unsupported. See avifPrepareReformatState(). + // AVIF_MATRIX_COEFFICIENTS_BT2020_CL + // AVIF_MATRIX_COEFFICIENTS_SMPTE2085 + // AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL + // AVIF_MATRIX_COEFFICIENTS_ICTCP }) { if (matrix_coefficients == AVIF_MATRIX_COEFFICIENTS_YCGCO && yuv_range == AVIF_RANGE_LIMITED) { // See avifPrepareReformatState(). continue; } +#if defined(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R) + if ((matrix_coefficients == AVIF_MATRIX_COEFFICIENTS_YCGCO_RE && + yuv_depth - 2 != rgb_depth) || + (matrix_coefficients == AVIF_MATRIX_COEFFICIENTS_YCGCO_RO && + yuv_depth - 1 != rgb_depth)) { + // See avifPrepareReformatState(). + continue; + } + if ((matrix_coefficients == AVIF_MATRIX_COEFFICIENTS_YCGCO_RE || + matrix_coefficients == AVIF_MATRIX_COEFFICIENTS_YCGCO_RO) && + yuv_range != AVIF_RANGE_FULL) { + // YCgCo-R is for lossless. + continue; + } +#endif for (avifChromaDownsampling chroma_downsampling : {AVIF_CHROMA_DOWNSAMPLING_FASTEST, AVIF_CHROMA_DOWNSAMPLING_BEST_QUALITY}) { @@ -458,6 +477,10 @@ constexpr avifMatrixCoefficients kMatrixCoefficientsBT709 = AVIF_MATRIX_COEFFICIENTS_BT709; constexpr avifMatrixCoefficients kMatrixCoefficientsIdentity = AVIF_MATRIX_COEFFICIENTS_IDENTITY; +#if defined(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R) +constexpr avifMatrixCoefficients kMatrixCoefficientsYCgCoRe = + AVIF_MATRIX_COEFFICIENTS_YCGCO_RE; +#endif // This is the default avifenc setup when encoding from 8b PNG files to AVIF. INSTANTIATE_TEST_SUITE_P( @@ -592,6 +615,22 @@ INSTANTIATE_TEST_SUITE_P(MonochromeLossless16b, RGBToYUVTest, /*max_abs_average_diff=*/Values(0.), /*min_psnr=*/Values(99.))); +#if defined(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R) +// Tests YCGCO_RE is lossless. +INSTANTIATE_TEST_SUITE_P(YCgCo_Re8b, RGBToYUVTest, + Combine(/*rgb_depth=*/Values(8), + /*yuv_depth=*/Values(10), + Values(AVIF_RGB_FORMAT_RGBA), + Values(AVIF_PIXEL_FORMAT_YUV444), + Values(AVIF_RANGE_FULL), + Values(kMatrixCoefficientsYCgCoRe), + Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), + /*add_noise=*/Values(true), + /*rgb_step=*/Values(101), + /*max_abs_average_diff=*/Values(0.), + /*min_psnr=*/Values(99.))); +#endif + // Coverage for reformat_libsharpyuv.c. INSTANTIATE_TEST_SUITE_P( SharpYuv8Bit, RGBToYUVTest,