blob: 4ed5ef1efca8869e99a054116a708c55186e3988 [file] [log] [blame]
// Copyright 2022 Google LLC. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause
#include <fstream>
#include <iostream>
#include <string>
#include <tuple>
#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;
avifRWDataRealloc(&bytes,
file.good() ? static_cast<size_t>(file.tellg()) : 0);
file.seekg(0, std::ios::beg);
file.read(reinterpret_cast<char*>(bytes.data),
static_cast<std::streamsize>(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);
}
//------------------------------------------------------------------------------
class IncrementalTest
: public testing::TestWithParam<std::tuple<
/*width=*/uint32_t, /*height=*/uint32_t, /*create_alpha=*/bool,
/*flat_cells=*/bool, /*encoded_avif_is_persistent=*/bool,
/*give_size_hint=*/bool, /*use_nth_image_api=*/bool>> {};
// 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);
}
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();
}