| // Copyright 2025 Google LLC | |
| // SPDX-License-Identifier: BSD-2-Clause | |
| #include <iostream> | |
| #include <string> | |
| #include "avif/avif.h" | |
| #include "avif/avif_cxx.h" | |
| #include "aviftest_helpers.h" | |
| #include "gtest/gtest.h" | |
| namespace avif { | |
| namespace { | |
| // Used to pass the data folder path to the GoogleTest suites. | |
| const char* data_path = nullptr; | |
| //------------------------------------------------------------------------------ | |
| #if defined(AVIF_ENABLE_EXPERIMENTAL_EXTENDED_PIXI) | |
| TEST(AvifPixiTest, SameOutput) { | |
| ImagePtr image = | |
| testutil::CreateImage(4, 4, 8, AVIF_PIXEL_FORMAT_YUV420, AVIF_PLANES_YUV); | |
| ASSERT_NE(image, nullptr); | |
| image->yuvChromaSamplePosition = AVIF_CHROMA_SAMPLE_POSITION_VERTICAL; | |
| testutil::FillImageGradient(image.get()); // The pixels do not matter. | |
| // Encode. | |
| testutil::AvifRwData encoded_regular_pixi; | |
| EncoderPtr encoder_regular_pixi(avifEncoderCreate()); | |
| ASSERT_NE(encoder_regular_pixi, nullptr); | |
| encoder_regular_pixi->speed = AVIF_SPEED_FASTEST; | |
| encoder_regular_pixi->headerFormat = AVIF_HEADER_DEFAULT; | |
| ASSERT_EQ(avifEncoderWrite(encoder_regular_pixi.get(), image.get(), | |
| &encoded_regular_pixi), | |
| AVIF_RESULT_OK); | |
| testutil::AvifRwData encoded_extended_pixi; | |
| EncoderPtr encoder_extended_pixi(avifEncoderCreate()); | |
| ASSERT_NE(encoder_extended_pixi, nullptr); | |
| encoder_extended_pixi->speed = AVIF_SPEED_FASTEST; | |
| encoder_extended_pixi->headerFormat = AVIF_HEADER_EXTENDED_PIXI; | |
| ASSERT_EQ(avifEncoderWrite(encoder_extended_pixi.get(), image.get(), | |
| &encoded_extended_pixi), | |
| AVIF_RESULT_OK); | |
| EXPECT_LT(encoded_regular_pixi.size, encoded_extended_pixi.size); | |
| // Decode. | |
| ImagePtr decoded_regular_pixi(avifImageCreateEmpty()); | |
| ASSERT_NE(decoded_regular_pixi, nullptr); | |
| DecoderPtr decoder_regular_pixi(avifDecoderCreate()); | |
| ASSERT_NE(decoder_regular_pixi, nullptr); | |
| decoder_regular_pixi->imageContentToDecode |= AVIF_IMAGE_CONTENT_GAIN_MAP; | |
| ASSERT_EQ(avifDecoderReadMemory( | |
| decoder_regular_pixi.get(), decoded_regular_pixi.get(), | |
| encoded_regular_pixi.data, encoded_regular_pixi.size), | |
| AVIF_RESULT_OK); | |
| ImagePtr decoded_extended_pixi(avifImageCreateEmpty()); | |
| ASSERT_NE(decoded_extended_pixi, nullptr); | |
| DecoderPtr decoder_extended_pixi(avifDecoderCreate()); | |
| ASSERT_NE(decoder_extended_pixi, nullptr); | |
| decoder_extended_pixi->imageContentToDecode |= AVIF_IMAGE_CONTENT_GAIN_MAP; | |
| ASSERT_EQ(avifDecoderReadMemory( | |
| decoder_extended_pixi.get(), decoded_extended_pixi.get(), | |
| encoded_extended_pixi.data, encoded_extended_pixi.size), | |
| AVIF_RESULT_OK); | |
| EXPECT_TRUE( | |
| testutil::AreImagesEqual(*decoded_regular_pixi, *decoded_extended_pixi)); | |
| } | |
| #endif // AVIF_ENABLE_EXPERIMENTAL_EXTENDED_PIXI | |
| TEST(AvifPixiTest, ExtendedPixiWorksEvenWithoutCMakeFlagOn) { | |
| const testutil::AvifRwData avif = | |
| testutil::ReadFile(std::string(data_path) + "extended_pixi.avif"); | |
| ASSERT_NE(avif.size, 0u); | |
| ImagePtr image(avifImageCreateEmpty()); | |
| ASSERT_NE(image, nullptr); | |
| DecoderPtr decoder(avifDecoderCreate()); | |
| ASSERT_NE(decoder, nullptr); | |
| ASSERT_EQ( | |
| avifDecoderReadMemory(decoder.get(), image.get(), avif.data, avif.size), | |
| AVIF_RESULT_OK); | |
| EXPECT_EQ(image->yuvFormat, AVIF_PIXEL_FORMAT_YUV420); | |
| EXPECT_EQ(image->yuvChromaSamplePosition, | |
| AVIF_CHROMA_SAMPLE_POSITION_VERTICAL); | |
| } | |
| TEST(AvifHeaderFormatTest, ABI) { | |
| // avifEncoder::headerFormat was of type avifHeaderFormat in libavif | |
| // version 1.1.1: | |
| // https://github.com/AOMediaCodec/libavif/blob/v1.1.1/include/avif/avif.h#L1498 | |
| // It was later changed to avifHeaderFormatFlags to be able to combine | |
| // multiple avifHeaderFormat features. Check that it was not an ABI | |
| // incompatible change. | |
| EXPECT_EQ(sizeof(avifEncoder::headerFormat), sizeof(avifHeaderFormat)); | |
| #if defined(AVIF_ENABLE_EXPERIMENTAL_EXTENDED_PIXI) | |
| // Check that the field can be assigned with a combination of flags without | |
| // compile errors: | |
| EncoderPtr encoder(avifEncoderCreate()); | |
| ASSERT_NE(encoder, nullptr); | |
| encoder->headerFormat = AVIF_HEADER_DEFAULT | AVIF_HEADER_EXTENDED_PIXI; | |
| #endif // AVIF_ENABLE_EXPERIMENTAL_EXTENDED_PIXI | |
| } | |
| //------------------------------------------------------------------------------ | |
| } // namespace | |
| } // namespace avif | |
| int main(int argc, char** argv) { | |
| ::testing::InitGoogleTest(&argc, argv); | |
| if (argc != 2) { | |
| std::cerr << "There must be exactly one argument containing the path to " | |
| "the test data folder" | |
| << std::endl; | |
| return 1; | |
| } | |
| avif::data_path = argv[1]; | |
| return RUN_ALL_TESTS(); | |
| } |