Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add limited range support to FillImageGradient() #1494

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 16 additions & 34 deletions tests/gtest/avifmetadatatest.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright 2022 Google LLC
// SPDX-License-Identifier: BSD-2-Clause

#include <array>
#include <cstring>
#include <tuple>

Expand All @@ -23,24 +22,6 @@ namespace {
// Used to pass the data folder path to the GoogleTest suites.
const char* data_path = nullptr;

// 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> kSampleIcc = {
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> kSampleExif = {
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> kSampleXmp = {
0x3c, 0x3f, 0x78, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x62, 0x65,
0x67, 0x69, 0x6e, 0x3d, 0x22, 0xef, 0xbb, 0xbf, 0x22, 0x20, 0x69, 0x64};

//------------------------------------------------------------------------------
// AVIF encode/decode metadata tests

Expand All @@ -61,26 +42,27 @@ TEST_P(AvifMetadataTest, EncodeDecode) {
ASSERT_NE(image, nullptr);
testutil::FillImageGradient(image.get()); // The pixels do not matter.
if (use_icc) {
ASSERT_EQ(avifImageSetProfileICC(image.get(), kSampleIcc.data(),
kSampleIcc.size()),
ASSERT_EQ(avifImageSetProfileICC(image.get(), testutil::kSampleIcc.data(),
testutil::kSampleIcc.size()),
AVIF_RESULT_OK);
}
if (use_exif) {
const avifTransformFlags old_transform_flags = image->transformFlags;
const uint8_t old_irot_angle = image->irot.angle;
const uint8_t old_imir_mode = image->imir.mode;
ASSERT_EQ(avifImageSetMetadataExif(image.get(), kSampleExif.data(),
kSampleExif.size()),
AVIF_RESULT_OK);
// kSampleExif is not a valid Exif payload, just some part of it. These
// fields should not be modified.
ASSERT_EQ(
avifImageSetMetadataExif(image.get(), testutil::kSampleExif.data(),
testutil::kSampleExif.size()),
AVIF_RESULT_OK);
// testutil::kSampleExif is not a valid Exif payload, just some part of it.
// These fields should not be modified.
EXPECT_EQ(image->transformFlags, old_transform_flags);
EXPECT_EQ(image->irot.angle, old_irot_angle);
EXPECT_EQ(image->imir.mode, old_imir_mode);
}
if (use_xmp) {
ASSERT_EQ(avifImageSetMetadataXMP(image.get(), kSampleXmp.data(),
kSampleXmp.size()),
ASSERT_EQ(avifImageSetMetadataXMP(image.get(), testutil::kSampleXmp.data(),
testutil::kSampleXmp.size()),
AVIF_RESULT_OK);
}

Expand All @@ -103,14 +85,14 @@ TEST_P(AvifMetadataTest, EncodeDecode) {

// Compare input and output metadata.
EXPECT_TRUE(testutil::AreByteSequencesEqual(
decoded->icc.data, decoded->icc.size, kSampleIcc.data(),
use_icc ? kSampleIcc.size() : 0u));
decoded->icc.data, decoded->icc.size, testutil::kSampleIcc.data(),
use_icc ? testutil::kSampleIcc.size() : 0u));
EXPECT_TRUE(testutil::AreByteSequencesEqual(
decoded->exif.data, decoded->exif.size, kSampleExif.data(),
use_exif ? kSampleExif.size() : 0u));
decoded->exif.data, decoded->exif.size, testutil::kSampleExif.data(),
use_exif ? testutil::kSampleExif.size() : 0u));
EXPECT_TRUE(testutil::AreByteSequencesEqual(
decoded->xmp.data, decoded->xmp.size, kSampleXmp.data(),
use_xmp ? kSampleXmp.size() : 0u));
decoded->xmp.data, decoded->xmp.size, testutil::kSampleXmp.data(),
use_xmp ? testutil::kSampleXmp.size() : 0u));
}

INSTANTIATE_TEST_SUITE_P(All, AvifMetadataTest,
Expand Down
33 changes: 30 additions & 3 deletions tests/gtest/aviftest_helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,29 @@ void FillImagePlain(avifImage* image, const uint32_t yuva[4]) {
}

void FillImageGradient(avifImage* image) {
assert(image->yuvRange == AVIF_RANGE_FULL);
for (avifChannelIndex c :
{AVIF_CHAN_Y, AVIF_CHAN_U, AVIF_CHAN_V, AVIF_CHAN_A}) {
const uint32_t limitedRangeMin =
c == AVIF_CHAN_Y ? 16 << (image->depth - 8) : 0;
const uint32_t limitedRangeMax = (c == AVIF_CHAN_Y ? 219 : 224)
<< (image->depth - 8);

const uint32_t plane_width = avifImagePlaneWidth(image, c);
// 0 for A if no alpha and 0 for UV if 4:0:0.
const uint32_t plane_height = avifImagePlaneHeight(image, c);
uint8_t* row = avifImagePlane(image, c);
const uint32_t row_bytes = avifImagePlaneRowBytes(image, c);
for (uint32_t y = 0; y < plane_height; ++y) {
for (uint32_t x = 0; x < plane_width; ++x) {
const uint32_t value = (x + y) * ((1u << image->depth) - 1u) /
std::max(1u, plane_width + plane_height - 2);
uint32_t value;
if (image->yuvRange == AVIF_RANGE_FULL || c == AVIF_CHAN_A) {
value = (x + y) * ((1u << image->depth) - 1u) /
std::max(1u, plane_width + plane_height - 2);
} else {
value = limitedRangeMin +
(x + y) * (limitedRangeMax - limitedRangeMin) /
std::max(1u, plane_width + plane_height - 2);
}
if (avifImageUsesU16(image)) {
reinterpret_cast<uint16_t*>(row)[x] = static_cast<uint16_t>(value);
} else {
Expand Down Expand Up @@ -167,6 +178,22 @@ bool AreImagesEqual(const avifImage& image1, const avifImage& image2,
}
assert(image1.width * image1.height > 0);

if (image1.clli.maxCLL != image2.clli.maxCLL ||
image1.clli.maxPALL != image2.clli.maxPALL) {
return false;
}
if (image1.transformFlags != image2.transformFlags ||
((image1.transformFlags & AVIF_TRANSFORM_PASP) &&
std::memcmp(&image1.pasp, &image2.pasp, sizeof(image1.pasp))) ||
((image1.transformFlags & AVIF_TRANSFORM_CLAP) &&
std::memcmp(&image1.clap, &image2.clap, sizeof(image1.clap))) ||
((image1.transformFlags & AVIF_TRANSFORM_IROT) &&
std::memcmp(&image1.irot, &image2.irot, sizeof(image1.irot))) ||
((image1.transformFlags & AVIF_TRANSFORM_IMIR) &&
std::memcmp(&image1.imir, &image2.imir, sizeof(image1.imir)))) {
return false;
}

for (avifChannelIndex c :
{AVIF_CHAN_Y, AVIF_CHAN_U, AVIF_CHAN_V, AVIF_CHAN_A}) {
if (ignore_alpha && c == AVIF_CHAN_A) continue;
Expand Down
21 changes: 21 additions & 0 deletions tests/gtest/aviftest_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#ifndef LIBAVIF_TESTS_AVIFTEST_HELPERS_H_
#define LIBAVIF_TESTS_AVIFTEST_HELPERS_H_

#include <array>
#include <limits>
#include <memory>

Expand All @@ -12,6 +13,26 @@
namespace libavif {
namespace testutil {

//------------------------------------------------------------------------------

// ICC color profiles are not checked by libavif so the content does not matter.
// This is a truncated widespread ICC color profile.
static const std::array<uint8_t, 24> kSampleIcc = {
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.
static const std::array<uint8_t, 24> kSampleExif = {
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.
static const std::array<uint8_t, 24> kSampleXmp = {
0x3c, 0x3f, 0x78, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x62, 0x65,
0x67, 0x69, 0x6e, 0x3d, 0x22, 0xef, 0xbb, 0xbf, 0x22, 0x20, 0x69, 0x64};

//------------------------------------------------------------------------------
// Memory management

Expand Down