| // Copyright 2022 Google LLC. All rights reserved. |
| // SPDX-License-Identifier: BSD-2-Clause |
| |
| #include "avif/avif.h" |
| |
| #include <array> |
| #include <tuple> |
| |
| #include "aviftest_helpers.h" |
| #include "gtest/gtest.h" |
| |
| using ::testing::Bool; |
| using ::testing::Combine; |
| |
| namespace libavif |
| { |
| namespace |
| { |
| |
| //------------------------------------------------------------------------------ |
| |
| // ICC color profiles are not checked by libavif so the content does not matter. |
| // This is a truncated widespread ICC color profile. |
| const std::array<uint8_t, 24> sampleICC = { 0x00, 0x00, 0x02, 0x0c, 0x6c, 0x63, 0x6d, 0x73, 0x02, 0x10, 0x00, 0x00, |
| 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20 }; |
| |
| // Exif bytes are partially checked by libavif. This is a truncated widespread Exif metadata chunk. |
| const std::array<uint8_t, 24> sampleExif = { 0xff, 0x1, 0x45, 0x78, 0x69, 0x76, 0x32, 0xff, 0xe1, 0x12, 0x5a, 0x45, |
| 0x78, 0x69, 0x66, 0x0, 0x0, 0x49, 0x49, 0x2a, 0x0, 0x8, 0x0, 0x0 }; |
| |
| // XMP bytes are not checked by libavif so the content does not matter. |
| // This is a truncated widespread XMP metadata chunk. |
| const std::array<uint8_t, 24> sampleXMP = { 0x3c, 0x3f, 0x78, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x62, 0x65, |
| 0x67, 0x69, 0x6e, 0x3d, 0x22, 0xef, 0xbb, 0xbf, 0x22, 0x20, 0x69, 0x64 }; |
| |
| //------------------------------------------------------------------------------ |
| |
| class MetadataTest : public testing::TestWithParam<std::tuple</*useICC=*/bool, /*useExif=*/bool, /*useXMP=*/bool>> |
| { |
| }; |
| |
| // Encodes, decodes then verifies that the output metadata matches the input metadata defined by the parameters. |
| TEST_P(MetadataTest, EncodeDecode) |
| { |
| const bool useICC = std::get<0>(GetParam()); |
| const bool useExif = std::get<1>(GetParam()); |
| const bool useXMP = std::get<2>(GetParam()); |
| |
| testutil::avifImagePtr image = |
| testutil::createImage(/*width=*/12, /*height=*/34, /*depth=*/10, AVIF_PIXEL_FORMAT_YUV444, AVIF_PLANES_ALL); |
| ASSERT_NE(image, nullptr); |
| testutil::fillImageGradient(image.get()); // The pixels do not matter. |
| if (useICC) { |
| avifImageSetProfileICC(image.get(), sampleICC.data(), sampleICC.size()); |
| } |
| if (useExif) { |
| avifImageSetMetadataExif(image.get(), sampleExif.data(), sampleExif.size()); |
| } |
| if (useXMP) { |
| avifImageSetMetadataXMP(image.get(), sampleXMP.data(), sampleXMP.size()); |
| } |
| |
| // Encode. |
| testutil::avifEncoderPtr encoder(avifEncoderCreate(), avifEncoderDestroy); |
| ASSERT_NE(encoder, nullptr); |
| encoder->speed = AVIF_SPEED_FASTEST; |
| testutil::avifRWDataCleaner encodedAvif; |
| ASSERT_EQ(avifEncoderWrite(encoder.get(), image.get(), &encodedAvif), AVIF_RESULT_OK); |
| |
| // Decode. |
| testutil::avifImagePtr decoded(avifImageCreateEmpty(), avifImageDestroy); |
| ASSERT_NE(decoded, nullptr); |
| testutil::avifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy); |
| ASSERT_NE(decoder, nullptr); |
| ASSERT_EQ(avifDecoderReadMemory(decoder.get(), decoded.get(), encodedAvif.data, encodedAvif.size), AVIF_RESULT_OK); |
| |
| // Compare input and output metadata. |
| if (useICC) { |
| ASSERT_EQ(decoded->icc.size, sampleICC.size()); |
| EXPECT_TRUE(std::equal(sampleICC.begin(), sampleICC.end(), decoded->icc.data)); |
| } else { |
| EXPECT_EQ(decoded->icc.size, 0u); |
| } |
| if (useExif) { |
| ASSERT_EQ(decoded->exif.size, sampleExif.size()); |
| EXPECT_TRUE(std::equal(sampleExif.begin(), sampleExif.end(), decoded->exif.data)); |
| } else { |
| EXPECT_EQ(decoded->exif.size, 0u); |
| } |
| if (useXMP) { |
| ASSERT_EQ(decoded->xmp.size, sampleXMP.size()); |
| EXPECT_TRUE(std::equal(sampleXMP.begin(), sampleXMP.end(), decoded->xmp.data)); |
| } else { |
| EXPECT_EQ(decoded->xmp.size, 0u); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(All, MetadataTest, Combine(/*useICC=*/Bool(), /*useExif=*/Bool(), /*useXMP=*/Bool())); |
| |
| } // namespace |
| } // namespace libavif |