// Copyright 2022 Google LLC // SPDX-License-Identifier: BSD-2-Clause #include #include #include #include #include "avif/avif.h" #include "avifincrtest_helpers.h" #include "aviftest_helpers.h" #include "gtest/gtest.h" using testing::Bool; using testing::Combine; using testing::Values; namespace libavif { namespace { //------------------------------------------------------------------------------ // Used to pass the data folder path to the GoogleTest suites. const char* data_path = nullptr; // Reads the file with file_name into bytes and returns them. testutil::AvifRwData ReadFile(const char* file_name) { std::ifstream file(std::string(data_path) + "/" + file_name, std::ios::binary | std::ios::ate); testutil::AvifRwData bytes; if (avifRWDataRealloc(&bytes, file.good() ? static_cast(file.tellg()) : 0) != AVIF_RESULT_OK) { return {}; } file.seekg(0, std::ios::beg); file.read(reinterpret_cast(bytes.data), static_cast(bytes.size)); return bytes; } //------------------------------------------------------------------------------ // Check that non-incremental and incremental decodings of a grid AVIF produce // the same pixels. TEST(IncrementalTest, Decode) { const testutil::AvifRwData encoded_avif = ReadFile("sofa_grid1x5_420.avif"); ASSERT_NE(encoded_avif.size, 0u); testutil::AvifImagePtr reference(avifImageCreateEmpty(), avifImageDestroy); ASSERT_NE(reference, nullptr); testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy); ASSERT_NE(decoder, nullptr); ASSERT_EQ(avifDecoderReadMemory(decoder.get(), reference.get(), encoded_avif.data, encoded_avif.size), AVIF_RESULT_OK); // Cell height is hardcoded because there is no API to extract it from an // encoded payload. testutil::DecodeIncrementally( encoded_avif, /*is_persistent=*/true, /*give_size_hint=*/true, /*use_nth_image_api=*/false, *reference, /*cell_height=*/154, /*enable_fine_incremental_check=*/true); } //------------------------------------------------------------------------------ class IncrementalTest : public testing::TestWithParam> {}; // Encodes then decodes a window of width*height pixels at the middle of the // image. Check that non-incremental and incremental decodings produce the same // pixels. TEST_P(IncrementalTest, EncodeDecode) { const uint32_t width = std::get<0>(GetParam()); const uint32_t height = std::get<1>(GetParam()); const bool create_alpha = std::get<2>(GetParam()); const bool flat_cells = std::get<3>(GetParam()); const bool encoded_avif_is_persistent = std::get<4>(GetParam()); const bool give_size_hint = std::get<5>(GetParam()); const bool use_nth_image_api = std::get<6>(GetParam()); // Load an image. It does not matter that it comes from an AVIF file. testutil::AvifImagePtr image(avifImageCreateEmpty(), avifImageDestroy); ASSERT_NE(image, nullptr); const testutil::AvifRwData image_bytes = ReadFile("sofa_grid1x5_420.avif"); ASSERT_NE(image_bytes.size, 0u); testutil::AvifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy); ASSERT_NE(decoder, nullptr); ASSERT_EQ(avifDecoderReadMemory(decoder.get(), image.get(), image_bytes.data, image_bytes.size), AVIF_RESULT_OK); // Encode then decode it. testutil::AvifRwData encoded_avif; uint32_t cell_width, cell_height; testutil::EncodeRectAsIncremental(*image, width, height, create_alpha, flat_cells, &encoded_avif, &cell_width, &cell_height); testutil::DecodeNonIncrementallyAndIncrementally( encoded_avif, encoded_avif_is_persistent, give_size_hint, use_nth_image_api, cell_height, /*enable_fine_incremental_check=*/true); } INSTANTIATE_TEST_SUITE_P(WholeImage, IncrementalTest, Combine(/*width=*/Values(1024), /*height=*/Values(770), /*create_alpha=*/Values(true), /*flat_cells=*/Bool(), /*encoded_avif_is_persistent=*/Values(true), /*give_size_hint=*/Values(true), /*use_nth_image_api=*/Values(false))); // avifEncoderAddImageInternal() only accepts grids of one unique cell, or grids // where width and height are both at least 64. INSTANTIATE_TEST_SUITE_P(SingleCell, IncrementalTest, Combine(/*width=*/Values(1), /*height=*/Values(1), /*create_alpha=*/Bool(), /*flat_cells=*/Bool(), /*encoded_avif_is_persistent=*/Bool(), /*give_size_hint=*/Bool(), /*use_nth_image_api=*/Bool())); // Chroma subsampling requires even dimensions. See ISO 23000-22 // section 7.3.11.4.2. INSTANTIATE_TEST_SUITE_P(SinglePixel, IncrementalTest, Combine(/*width=*/Values(64, 66), /*height=*/Values(64, 66), /*create_alpha=*/Bool(), /*flat_cells=*/Bool(), /*encoded_avif_is_persistent=*/Bool(), /*give_size_hint=*/Bool(), /*use_nth_image_api=*/Bool())); //------------------------------------------------------------------------------ } // namespace } // namespace libavif int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); if (argc < 2) { std::cerr << "The path to the test data folder must be provided as an argument" << std::endl; return 1; } libavif::data_path = argv[1]; return RUN_ALL_TESTS(); }