blob: b943eec3a21aebfdc026d58679c998f0b01eb86f [file] [log] [blame]
// 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