// Copyright 2022 Google LLC
// SPDX-License-Identifier: BSD-2-Clause

#include "avif/avif.h"
#include "aviftest_helpers.h"
#include "gtest/gtest.h"

namespace libavif {
namespace {

//------------------------------------------------------------------------------

TEST(AlphaMultiplyTest, OpaqueIsNoOp) {
  for (bool premultiplied_input : {false, true}) {
    if (!premultiplied_input) {
      // TODO(yguyon): Fix the issue and remove this condition.
      //               The issue is that avifPrepareReformatState() will result
      //               in different YUV(A)-to-RGB conversion algorithm choices
      //               (built-in or libyuv) depending on the presence of an
      //               alpha channel, no matter if it is opaque or not, because
      //               it considers that unpremultiplied YUVA samples should be
      //               premultiplied before discarding alpha and converting to
      //               RGB.
      continue;
    }

    // YUVA.
    testutil::AvifImagePtr opaque_alpha = testutil::CreateImage(
        1024, 1024, /*depth=*/8, AVIF_PIXEL_FORMAT_YUV444, AVIF_PLANES_ALL);
    const uint32_t yuva[] = {255, 255, 255, 255};
    testutil::FillImagePlain(opaque_alpha.get(), yuva);
    opaque_alpha->alphaPremultiplied = premultiplied_input;

    // View on YUV (no alpha), to make sure the color values are identical.
    testutil::AvifImagePtr no_alpha(avifImageCreateEmpty(), avifImageDestroy);
    ASSERT_NE(no_alpha, nullptr);
    const avifCropRect rect = {0, 0, opaque_alpha->width, opaque_alpha->height};
    ASSERT_EQ(avifImageSetViewRect(no_alpha.get(), opaque_alpha.get(), &rect),
              AVIF_RESULT_OK);
    avifImageFreePlanes(no_alpha.get(), AVIF_PLANES_A);

    // Decorrelate YUV and Alpha.
    testutil::FillImageGradient(no_alpha.get());

    // Convert to RGB and discard any Alpha.
    testutil::AvifRgbImage opaque_rgb(opaque_alpha.get(), opaque_alpha->depth,
                                      AVIF_RGB_FORMAT_RGB);
    ASSERT_EQ(avifImageYUVToRGB(opaque_alpha.get(), &opaque_rgb),
              AVIF_RESULT_OK);
    testutil::AvifRgbImage no_alpha_rgb(no_alpha.get(), no_alpha->depth,
                                        AVIF_RGB_FORMAT_RGB);
    ASSERT_EQ(avifImageYUVToRGB(no_alpha.get(), &no_alpha_rgb), AVIF_RESULT_OK);

    // YUV samples with opaque alpha and with missing alpha should be converted
    // to the same RGB values.
    EXPECT_TRUE(testutil::AreByteSequencesEqual(
        opaque_rgb.pixels, opaque_rgb.height * opaque_rgb.rowBytes,
        no_alpha_rgb.pixels, no_alpha_rgb.height * no_alpha_rgb.rowBytes));

    // TODO(yguyon): Also compare avifImageYUVToRGB() with ignoreAlpha.
  }
}

//------------------------------------------------------------------------------

}  // namespace
}  // namespace libavif
