blob: cf77c548ae3b87511ddf0b69ab7305433b3c6231 [file] [log] [blame]
// Copyright 2023 Google LLC
// SPDX-License-Identifier: BSD-2-Clause
#include <cstdint>
#include <limits>
#include "avif/avif.h"
#include "aviftest_helpers.h"
#include "gtest/gtest.h"
using testing::Combine;
using testing::Values;
namespace avif {
namespace {
// Used to pass the data folder path to the GoogleTest suites.
const char* data_path = nullptr;
constexpr bool kIgnoreMetadata = true;
//------------------------------------------------------------------------------
class ScaleTest
: public testing::TestWithParam<
std::tuple</*bit_depth=*/int, /*yuv_format=*/avifPixelFormat,
/*create_alpha=*/bool>> {};
TEST_P(ScaleTest, Roundtrip) {
const int bit_depth = std::get<0>(GetParam());
const avifPixelFormat yuv_format = std::get<1>(GetParam());
const bool create_alpha = std::get<2>(GetParam());
const ImagePtr image =
testutil::ReadImage(data_path, "paris_exif_xmp_icc.jpg", yuv_format,
bit_depth, AVIF_CHROMA_DOWNSAMPLING_BEST_QUALITY,
kIgnoreMetadata, kIgnoreMetadata, kIgnoreMetadata);
ASSERT_NE(image, nullptr);
if (create_alpha && !image->alphaPlane) {
// Simulate alpha plane with a view on luma.
image->alphaPlane = image->yuvPlanes[AVIF_CHAN_Y];
image->alphaRowBytes = image->yuvRowBytes[AVIF_CHAN_Y];
image->imageOwnsAlphaPlane = false;
}
ImagePtr scaled_image(avifImageCreateEmpty());
ASSERT_NE(scaled_image, nullptr);
ASSERT_EQ(avifImageCopy(scaled_image.get(), image.get(), AVIF_PLANES_ALL),
AVIF_RESULT_OK);
const uint32_t scaled_width = static_cast<uint32_t>(image->width * 0.9);
const uint32_t scaled_height = static_cast<uint32_t>(image->height * 2.14);
avifDiagnostics diag;
ASSERT_EQ(
avifImageScale(scaled_image.get(), scaled_width, scaled_height, &diag),
AVIF_RESULT_OK)
<< diag.error;
EXPECT_EQ(scaled_image->width, scaled_width);
EXPECT_EQ(scaled_image->height, scaled_height);
ASSERT_EQ(
avifImageScale(scaled_image.get(), image->width, image->height, &diag),
AVIF_RESULT_OK)
<< diag.error;
EXPECT_EQ(scaled_image->width, image->width);
EXPECT_EQ(scaled_image->height, image->height);
const double psnr = testutil::GetPsnr(*image, *scaled_image);
EXPECT_GT(psnr, 30.0);
EXPECT_LT(psnr, 45.0);
}
INSTANTIATE_TEST_SUITE_P(
Some, ScaleTest,
Combine(/*bit_depth=*/Values(8, 10, 12),
Values(AVIF_PIXEL_FORMAT_YUV444, AVIF_PIXEL_FORMAT_YUV422,
AVIF_PIXEL_FORMAT_YUV420, AVIF_PIXEL_FORMAT_YUV400),
/*create_alpha=*/Values(true, false)));
TEST(ScaleTest, LargerThanDefaultLimits) {
const ImagePtr image = testutil::ReadImage(
data_path, "paris_exif_xmp_icc.jpg", AVIF_PIXEL_FORMAT_YUV420, 8,
AVIF_CHROMA_DOWNSAMPLING_BEST_QUALITY, kIgnoreMetadata, kIgnoreMetadata,
kIgnoreMetadata);
ASSERT_NE(image, nullptr);
avifDiagnostics diag;
// dstWidth*dstHeight is larger than AVIF_DEFAULT_IMAGE_SIZE_LIMIT.
EXPECT_NE(avifImageScale(image.get(), 20000, 20000, &diag), AVIF_RESULT_OK);
// dstWidth is larger than AVIF_DEFAULT_IMAGE_DIMENSION_LIMIT.
EXPECT_NE(avifImageScale(image.get(), 40000, 2, &diag), AVIF_RESULT_OK);
// dstHeight is larger than AVIF_DEFAULT_IMAGE_DIMENSION_LIMIT.
EXPECT_NE(avifImageScale(image.get(), 2, 40000, &diag), AVIF_RESULT_OK);
}
//------------------------------------------------------------------------------
} // namespace
} // namespace avif
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
if (argc != 2) {
std::cerr << "There must be exactly one argument containing the path to "
"the test data folder"
<< std::endl;
return 1;
}
avif::data_path = argv[1];
return RUN_ALL_TESTS();
}