| // Copyright 2023 Google LLC |
| // SPDX-License-Identifier: BSD-2-Clause |
| |
| #include "avif/avif.h" |
| #include "aviftest_helpers.h" |
| #include "gtest/gtest.h" |
| |
| using ::testing::Combine; |
| using ::testing::Values; |
| |
| namespace avif { |
| namespace { |
| |
| //------------------------------------------------------------------------------ |
| |
| class AvifMinimizedImageBoxTest |
| : public testing::TestWithParam<std::tuple< |
| /*width=*/int, /*height=*/int, /*depth=*/int, avifPixelFormat, |
| avifPlanesFlags, avifRange, /*create_icc=*/bool, /*create_exif=*/bool, |
| /*create_xmp=*/bool, avifTransformFlags, /*create_hdr=*/bool>> {}; |
| |
| TEST_P(AvifMinimizedImageBoxTest, All) { |
| const int width = std::get<0>(GetParam()); |
| const int height = std::get<1>(GetParam()); |
| const int depth = std::get<2>(GetParam()); |
| const avifPixelFormat format = std::get<3>(GetParam()); |
| const avifPlanesFlags planes = std::get<4>(GetParam()); |
| const avifRange range = std::get<5>(GetParam()); |
| const bool create_icc = std::get<6>(GetParam()); |
| const bool create_exif = std::get<7>(GetParam()); |
| const bool create_xmp = std::get<8>(GetParam()); |
| const avifTransformFlags create_transform_flags = std::get<9>(GetParam()); |
| const bool create_hdr = std::get<10>(GetParam()); |
| |
| ImagePtr image = |
| testutil::CreateImage(width, height, depth, format, planes, range); |
| ASSERT_NE(image, nullptr); |
| testutil::FillImageGradient(image.get()); // The pixels do not matter. |
| if (create_icc) { |
| ASSERT_EQ(avifImageSetProfileICC(image.get(), testutil::kSampleIcc.data(), |
| testutil::kSampleIcc.size()), |
| AVIF_RESULT_OK); |
| } |
| if (create_exif) { |
| size_t exif_tiff_header_offset; // Must be 0 for 'mif3' brand. |
| ASSERT_EQ(avifGetExifTiffHeaderOffset(testutil::kSampleExif.data(), |
| testutil::kSampleExif.size(), |
| &exif_tiff_header_offset), |
| AVIF_RESULT_OK); |
| ASSERT_EQ( |
| avifImageSetMetadataExif( |
| image.get(), testutil::kSampleExif.data() + exif_tiff_header_offset, |
| testutil::kSampleExif.size() - exif_tiff_header_offset), |
| AVIF_RESULT_OK); |
| } |
| if (create_xmp) { |
| ASSERT_EQ(avifImageSetMetadataXMP(image.get(), testutil::kSampleXmp.data(), |
| testutil::kSampleXmp.size()), |
| AVIF_RESULT_OK); |
| } |
| image->transformFlags = create_transform_flags; |
| if (create_transform_flags & AVIF_TRANSFORM_IROT) { |
| image->irot.angle = 1; |
| } |
| if (create_transform_flags & AVIF_TRANSFORM_IMIR) { |
| image->imir.axis = 0; |
| } |
| if (create_hdr) { |
| image->gainMap = avifGainMapCreate(); |
| ASSERT_NE(image->gainMap, nullptr); |
| image->gainMap->image = |
| testutil::CreateImage(width, height, /*depth=*/8, |
| AVIF_PIXEL_FORMAT_YUV400, AVIF_PLANES_YUV, |
| AVIF_RANGE_FULL) |
| .release(); |
| ASSERT_NE(image->gainMap->image, nullptr); |
| testutil::FillImageGradient(image->gainMap->image); |
| } |
| |
| // Encode. |
| testutil::AvifRwData encoded_mini; |
| EncoderPtr encoder(avifEncoderCreate()); |
| ASSERT_NE(encoder, nullptr); |
| encoder->speed = AVIF_SPEED_FASTEST; |
| encoder->headerFormat = AVIF_HEADER_REDUCED; |
| ASSERT_EQ(avifEncoderWrite(encoder.get(), image.get(), &encoded_mini), |
| AVIF_RESULT_OK); |
| |
| // Decode. |
| ImagePtr decoded_mini(avifImageCreateEmpty()); |
| ASSERT_NE(decoded_mini, nullptr); |
| DecoderPtr decoder_mini(avifDecoderCreate()); |
| ASSERT_NE(decoder_mini, nullptr); |
| decoder_mini->enableParsingGainMapMetadata = AVIF_TRUE; |
| decoder_mini->enableDecodingGainMap = AVIF_TRUE; |
| ASSERT_EQ(avifDecoderReadMemory(decoder_mini.get(), decoded_mini.get(), |
| encoded_mini.data, encoded_mini.size), |
| AVIF_RESULT_OK); |
| |
| // Compare. |
| testutil::AvifRwData encoded_meta = |
| testutil::Encode(image.get(), encoder->speed); |
| ASSERT_NE(encoded_meta.data, nullptr); |
| // At least 200 bytes should be saved. |
| EXPECT_LT(encoded_mini.size, encoded_meta.size - 200); |
| |
| ImagePtr decoded_meta(avifImageCreateEmpty()); |
| ASSERT_NE(decoded_meta, nullptr); |
| DecoderPtr decoder_meta(avifDecoderCreate()); |
| ASSERT_NE(decoder_meta, nullptr); |
| decoder_meta->enableParsingGainMapMetadata = AVIF_TRUE; |
| decoder_meta->enableDecodingGainMap = AVIF_TRUE; |
| ASSERT_EQ(avifDecoderReadMemory(decoder_meta.get(), decoded_meta.get(), |
| encoded_meta.data, encoded_meta.size), |
| AVIF_RESULT_OK); |
| EXPECT_EQ(decoder_meta->gainMapPresent, decoder_mini->gainMapPresent); |
| |
| // Only the container changed. The pixels, features and metadata should be |
| // identical. |
| EXPECT_TRUE( |
| testutil::AreImagesEqual(*decoded_meta.get(), *decoded_mini.get())); |
| EXPECT_EQ(decoded_meta->gainMap != nullptr, decoded_mini->gainMap != nullptr); |
| if (create_hdr) { |
| ASSERT_NE(decoded_meta->gainMap, nullptr); |
| ASSERT_NE(decoded_mini->gainMap, nullptr); |
| ASSERT_NE(decoded_meta->gainMap->image, nullptr); |
| ASSERT_NE(decoded_mini->gainMap->image, nullptr); |
| EXPECT_TRUE(testutil::AreImagesEqual(*decoded_meta->gainMap->image, |
| *decoded_mini->gainMap->image)); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(OnePixel, AvifMinimizedImageBoxTest, |
| Combine(/*width=*/Values(1), /*height=*/Values(1), |
| /*depth=*/Values(8), |
| Values(AVIF_PIXEL_FORMAT_YUV444), |
| Values(AVIF_PLANES_YUV, AVIF_PLANES_ALL), |
| Values(AVIF_RANGE_LIMITED, AVIF_RANGE_FULL), |
| /*create_icc=*/Values(false, true), |
| /*create_exif=*/Values(false, true), |
| /*create_xmp=*/Values(false, true), |
| Values(AVIF_TRANSFORM_NONE), |
| /*create_hdr=*/Values(false))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| DepthsSubsamplings, AvifMinimizedImageBoxTest, |
| Combine(/*width=*/Values(12), /*height=*/Values(34), |
| /*depth=*/Values(8, 10, 12), |
| Values(AVIF_PIXEL_FORMAT_YUV444, AVIF_PIXEL_FORMAT_YUV422, |
| AVIF_PIXEL_FORMAT_YUV420, AVIF_PIXEL_FORMAT_YUV400), |
| Values(AVIF_PLANES_ALL), Values(AVIF_RANGE_FULL), |
| /*create_icc=*/Values(false), /*create_exif=*/Values(false), |
| /*create_xmp=*/Values(false), Values(AVIF_TRANSFORM_NONE), |
| /*create_hdr=*/Values(false))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| Dimensions, AvifMinimizedImageBoxTest, |
| Combine(/*width=*/Values(127), /*height=*/Values(200), /*depth=*/Values(8), |
| Values(AVIF_PIXEL_FORMAT_YUV444), Values(AVIF_PLANES_ALL), |
| Values(AVIF_RANGE_FULL), /*create_icc=*/Values(true), |
| /*create_exif=*/Values(true), /*create_xmp=*/Values(true), |
| Values(AVIF_TRANSFORM_NONE), /*create_hdr=*/Values(false))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| Orientation, AvifMinimizedImageBoxTest, |
| Combine(/*width=*/Values(16), /*height=*/Values(24), /*depth=*/Values(8), |
| Values(AVIF_PIXEL_FORMAT_YUV444), Values(AVIF_PLANES_ALL), |
| Values(AVIF_RANGE_FULL), /*create_icc=*/Values(true), |
| /*create_exif=*/Values(true), /*create_xmp=*/Values(true), |
| Values(AVIF_TRANSFORM_NONE, AVIF_TRANSFORM_IROT, |
| AVIF_TRANSFORM_IMIR, |
| AVIF_TRANSFORM_IROT | AVIF_TRANSFORM_IMIR), |
| /*create_hdr=*/Values(false))); |
| |
| INSTANTIATE_TEST_SUITE_P( |
| Hdr, AvifMinimizedImageBoxTest, |
| Combine(/*width=*/Values(8), /*height=*/Values(10), /*depth=*/Values(10), |
| Values(AVIF_PIXEL_FORMAT_YUV420), |
| Values(AVIF_PLANES_YUV, AVIF_PLANES_ALL), Values(AVIF_RANGE_FULL), |
| /*create_icc=*/Values(false), |
| /*create_exif=*/Values(false), /*create_xmp=*/Values(false), |
| Values(AVIF_TRANSFORM_NONE), /*create_hdr=*/Values(true))); |
| |
| //------------------------------------------------------------------------------ |
| |
| } // namespace |
| } // namespace avif |