Shorten avifgridapitest and avify4mtest
Move code to aviftest_helpers for clarity and to be reused by other tests.
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 717ab9d..49c0d7c 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -56,12 +56,12 @@
find_package(GTest REQUIRED)
endif()
- add_executable(avifgridapitest avifgridapitest.cc)
+ add_executable(avifgridapitest avifgridapitest.cc aviftest_helpers.cc)
target_link_libraries(avifgridapitest avif ${AVIF_PLATFORM_LIBRARIES} ${GTEST_BOTH_LIBRARIES})
target_include_directories(avifgridapitest PRIVATE ${GTEST_INCLUDE_DIRS})
add_test(NAME avifgridapitest COMMAND avifgridapitest)
- add_executable(avify4mtest avify4mtest.cc)
+ add_executable(avify4mtest avify4mtest.cc aviftest_helpers.cc)
target_link_libraries(avify4mtest avif avif_apps ${AVIF_PLATFORM_LIBRARIES} ${GTEST_BOTH_LIBRARIES})
target_include_directories(avify4mtest PRIVATE ${GTEST_INCLUDE_DIRS})
add_test(NAME avify4mtest COMMAND avify4mtest)
diff --git a/tests/avifgridapitest.cc b/tests/avifgridapitest.cc
index c939e29..88bda67 100644
--- a/tests/avifgridapitest.cc
+++ b/tests/avifgridapitest.cc
@@ -3,169 +3,21 @@
#include "avif/avif.h"
-#include <cassert>
-#include <cinttypes>
-#include <cstdio>
-#include <cstring>
#include <tuple>
+#include <vector>
+#include "aviftest_helpers.h"
#include "gtest/gtest.h"
using testing::Combine;
using testing::Values;
using testing::ValuesIn;
+namespace libavif
+{
namespace
{
-//------------------------------------------------------------------------------
-
-// Fills a plane with a repeating gradient.
-void fillPlane(int width, int height, int depth, uint8_t * row, uint32_t rowBytes)
-{
- assert(depth == 8 || depth == 10 || depth == 12); // Values allowed by AV1.
- const int maxValuePlusOne = 1 << depth;
- for (int y = 0; y < height; ++y) {
- if (depth == 8) {
- memset(row, y % maxValuePlusOne, width);
- } else {
- for (int x = 0; x < width; ++x) {
- ((uint16_t *)row)[x] = (uint16_t)(y % maxValuePlusOne);
- }
- }
- row += rowBytes;
- }
-}
-
-// Creates an image where the pixel values are defined but do not matter.
-// Returns false in case of memory failure.
-bool createImage(int width, int height, int depth, avifPixelFormat yuvFormat, bool createAlpha, avifImage ** image)
-{
- *image = avifImageCreate(width, height, depth, yuvFormat);
- if (!*image) {
- printf("ERROR: avifImageCreate() failed\n");
- return false;
- }
- avifImageAllocatePlanes(*image, createAlpha ? AVIF_PLANES_ALL : AVIF_PLANES_YUV);
- if (width * height == 0) {
- return true;
- }
-
- avifPixelFormatInfo formatInfo;
- avifGetPixelFormatInfo((*image)->yuvFormat, &formatInfo);
- uint32_t uvWidth = ((*image)->width + formatInfo.chromaShiftX) >> formatInfo.chromaShiftX;
- uint32_t uvHeight = ((*image)->height + formatInfo.chromaShiftY) >> formatInfo.chromaShiftY;
-
- const int planeCount = formatInfo.monochrome ? 1 : AVIF_PLANE_COUNT_YUV;
- for (int plane = 0; plane < planeCount; ++plane) {
- fillPlane((plane == AVIF_CHAN_Y) ? (*image)->width : uvWidth,
- (plane == AVIF_CHAN_Y) ? (*image)->height : uvHeight,
- (*image)->depth,
- (*image)->yuvPlanes[plane],
- (*image)->yuvRowBytes[plane]);
- }
-
- if (createAlpha) {
- fillPlane((*image)->width, (*image)->height, (*image)->depth, (*image)->alphaPlane, (*image)->alphaRowBytes);
- }
- return true;
-}
-
-// Generates then encodes a grid image. Returns false in case of failure.
-bool encodeGrid(int columns, int rows, int cellWidth, int cellHeight, int depth, avifPixelFormat yuvFormat, bool createAlpha, avifRWData * output)
-{
- bool success = false;
- avifEncoder * encoder = NULL;
- avifImage ** cellImages = (avifImage **)avifAlloc(sizeof(avifImage *) * columns * rows);
- memset(cellImages, 0, sizeof(avifImage *) * columns * rows);
- for (int iCell = 0; iCell < columns * rows; ++iCell) {
- if (!createImage(cellWidth, cellHeight, depth, yuvFormat, createAlpha, &cellImages[iCell])) {
- goto cleanup;
- }
- }
-
- encoder = avifEncoderCreate();
- if (!encoder) {
- printf("ERROR: avifEncoderCreate() failed\n");
- goto cleanup;
- }
- encoder->speed = AVIF_SPEED_FASTEST;
- if (avifEncoderAddImageGrid(encoder, columns, rows, (const avifImage * const *)cellImages, AVIF_ADD_IMAGE_FLAG_SINGLE) !=
- AVIF_RESULT_OK) {
- printf("ERROR: avifEncoderAddImageGrid() failed\n");
- goto cleanup;
- }
- if (avifEncoderFinish(encoder, output) != AVIF_RESULT_OK) {
- printf("ERROR: avifEncoderFinish() failed\n");
- goto cleanup;
- }
-
- success = true;
-cleanup:
- if (encoder) {
- avifEncoderDestroy(encoder);
- }
- if (cellImages) {
- for (int i = 0; i < columns * rows; ++i) {
- if (cellImages[i]) {
- avifImageDestroy(cellImages[i]);
- }
- }
- avifFree(cellImages);
- }
- return success;
-}
-
-//------------------------------------------------------------------------------
-
-// Decodes the data. Returns false in case of failure.
-bool decode(const avifRWData * encodedAvif)
-{
- bool success = false;
- avifImage * const image = avifImageCreateEmpty();
- avifDecoder * const decoder = avifDecoderCreate();
- if (!image || !decoder) {
- printf("ERROR: memory allocation failed\n");
- goto cleanup;
- }
- if (avifDecoderReadMemory(decoder, image, encodedAvif->data, encodedAvif->size) != AVIF_RESULT_OK) {
- printf("ERROR: avifDecoderReadMemory() failed\n");
- goto cleanup;
- }
- success = true;
-cleanup:
- if (image) {
- avifImageDestroy(image);
- }
- if (decoder) {
- avifDecoderDestroy(decoder);
- }
- return success;
-}
-
-//------------------------------------------------------------------------------
-
-// Generates, encodes then decodes a grid image.
-bool encodeDecode(int columns, int rows, int cellWidth, int cellHeight, int depth, avifPixelFormat yuvFormat, bool createAlpha, bool expectedSuccess)
-{
- bool success = false;
- avifRWData encodedAvif = { nullptr, 0 };
- if (encodeGrid(columns, rows, cellWidth, cellHeight, depth, yuvFormat, createAlpha, &encodedAvif) != expectedSuccess) {
- goto cleanup;
- }
- // Only decode if the encoding was expected to succeed.
- // Any successful encoding shall result in a valid decoding.
- if (expectedSuccess && !decode(&encodedAvif)) {
- goto cleanup;
- }
- success = true;
-cleanup:
- avifRWDataFree(&encodedAvif);
- return success;
-}
-
-//------------------------------------------------------------------------------
-
// Pair of cell count and cell size for a single dimension.
struct Cell
{
@@ -186,14 +38,41 @@
const bool createAlpha = std::get<4>(GetParam());
const bool expectedSuccess = std::get<5>(GetParam());
- EXPECT_TRUE(encodeDecode(/*columns=*/horizontal.count,
- /*rows=*/vertical.count,
- /*cellWidth=*/horizontal.size,
- /*cellHeight=*/vertical.size,
- bitDepth,
- yuvFormat,
- createAlpha,
- expectedSuccess));
+ // Construct a grid.
+ std::vector<testutil::avifImagePtr> cellImages;
+ cellImages.reserve(horizontal.count * vertical.count);
+ for (int i = 0; i < horizontal.count * vertical.count; ++i) {
+ cellImages.emplace_back(
+ testutil::createImage(horizontal.size, vertical.size, bitDepth, yuvFormat, createAlpha ? AVIF_PLANES_ALL : AVIF_PLANES_YUV));
+ ASSERT_NE(cellImages.back(), nullptr);
+ testutil::fillImageGradient(cellImages.back().get());
+ }
+
+ // Encode the grid image.
+ testutil::avifEncoderPtr encoder(avifEncoderCreate(), avifEncoderDestroy);
+ ASSERT_NE(encoder, nullptr);
+ encoder->speed = AVIF_SPEED_FASTEST;
+ std::vector<avifImage *> cellImagePtrs(cellImages.size()); // Just here to match libavif API.
+ for (size_t i = 0; i < cellImages.size(); ++i) {
+ cellImagePtrs[i] = cellImages[i].get();
+ }
+ const avifResult result =
+ avifEncoderAddImageGrid(encoder.get(), horizontal.count, vertical.count, cellImagePtrs.data(), AVIF_ADD_IMAGE_FLAG_SINGLE);
+
+ if (expectedSuccess) {
+ ASSERT_EQ(result, AVIF_RESULT_OK);
+ testutil::avifRWDataCleaner encodedAvif;
+ ASSERT_EQ(avifEncoderFinish(encoder.get(), &encodedAvif), AVIF_RESULT_OK);
+
+ // Decode the grid image.
+ testutil::avifImagePtr image(avifImageCreateEmpty(), avifImageDestroy);
+ ASSERT_NE(image, nullptr);
+ testutil::avifDecoderPtr decoder(avifDecoderCreate(), avifDecoderDestroy);
+ ASSERT_NE(decoder, nullptr);
+ ASSERT_EQ(avifDecoderReadMemory(decoder.get(), image.get(), encodedAvif.data, encodedAvif.size), AVIF_RESULT_OK);
+ } else {
+ ASSERT_TRUE(result == AVIF_RESULT_INVALID_IMAGE_GRID || result == AVIF_RESULT_NO_CONTENT);
+ }
}
// A cell cannot be smaller than 64px in any dimension if there are several cells.
@@ -275,3 +154,4 @@
/*expectedSuccess=*/Values(false)));
} // namespace
+} // namespace libavif
diff --git a/tests/aviftest_helpers.cc b/tests/aviftest_helpers.cc
new file mode 100644
index 0000000..3a3f65f
--- /dev/null
+++ b/tests/aviftest_helpers.cc
@@ -0,0 +1,143 @@
+// Copyright 2022 Google LLC. All rights reserved.
+// SPDX-License-Identifier: BSD-2-Clause
+
+#include "aviftest_helpers.h"
+#include "avif/avif.h"
+
+#include <algorithm>
+#include <cassert>
+
+namespace libavif
+{
+namespace testutil
+{
+namespace
+{
+
+constexpr int AVIF_CHAN_A = AVIF_CHAN_V + 1;
+constexpr int AVIF_CHANS[] = { AVIF_CHAN_Y, AVIF_CHAN_U, AVIF_CHAN_V, AVIF_CHAN_A };
+
+} // namespace
+
+//------------------------------------------------------------------------------
+
+avifImagePtr createImage(int width, int height, int depth, avifPixelFormat yuvFormat, avifPlanesFlags planes, avifRange yuvRange)
+{
+ avifImagePtr image(avifImageCreate(width, height, depth, yuvFormat), avifImageDestroy);
+ if (!image) {
+ return { nullptr, nullptr };
+ }
+ image->yuvRange = yuvRange;
+ avifImageAllocatePlanes(image.get(), planes);
+ return image;
+}
+
+void fillImagePlain(avifImage * image, const uint32_t yuva[4])
+{
+ avifPixelFormatInfo info;
+ avifGetPixelFormatInfo(image->yuvFormat, &info);
+
+ for (int c : AVIF_CHANS) {
+ uint8_t * row = (c == AVIF_CHAN_A) ? image->alphaPlane : image->yuvPlanes[c];
+ if (!row) {
+ continue;
+ }
+ const uint32_t rowBytes = (c == AVIF_CHAN_A) ? image->alphaRowBytes : image->yuvRowBytes[c];
+ const uint32_t planeWidth =
+ (c == AVIF_CHAN_Y || c == AVIF_CHAN_A) ? image->width : ((image->width + info.chromaShiftX) >> info.chromaShiftX);
+ const uint32_t planeHeight =
+ (c == AVIF_CHAN_Y || c == AVIF_CHAN_A) ? image->height : ((image->height + info.chromaShiftY) >> info.chromaShiftY);
+ for (uint32_t y = 0; y < planeHeight; ++y) {
+ if (avifImageUsesU16(image)) {
+ std::fill(reinterpret_cast<uint16_t *>(row),
+ reinterpret_cast<uint16_t *>(row) + planeWidth,
+ static_cast<uint16_t>(yuva[c]));
+ } else {
+ std::fill(row, row + planeWidth, static_cast<uint8_t>(yuva[c]));
+ }
+ row += rowBytes;
+ }
+ }
+}
+
+void fillImageGradient(avifImage * image)
+{
+ avifPixelFormatInfo info;
+ avifGetPixelFormatInfo(image->yuvFormat, &info);
+
+ for (int c : AVIF_CHANS) {
+ uint8_t * row = (c == AVIF_CHAN_A) ? image->alphaPlane : image->yuvPlanes[c];
+ if (!row) {
+ continue;
+ }
+ const uint32_t rowBytes = (c == AVIF_CHAN_A) ? image->alphaRowBytes : image->yuvRowBytes[c];
+ const uint32_t planeWidth =
+ (c == AVIF_CHAN_Y || c == AVIF_CHAN_A) ? image->width : ((image->width + info.chromaShiftX) >> info.chromaShiftX);
+ const uint32_t planeHeight =
+ (c == AVIF_CHAN_Y || c == AVIF_CHAN_A) ? image->height : ((image->height + info.chromaShiftY) >> info.chromaShiftY);
+ for (uint32_t y = 0; y < planeHeight; ++y) {
+ for (uint32_t x = 0; x < planeWidth; ++x) {
+ const uint32_t value = (x + y) * ((1u << image->depth) - 1u) / std::max(1u, planeWidth + planeHeight - 2);
+ if (avifImageUsesU16(image)) {
+ reinterpret_cast<uint16_t *>(row)[x] = static_cast<uint16_t>(value);
+ } else {
+ row[x] = static_cast<uint8_t>(value);
+ }
+ }
+ row += rowBytes;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+// Returns true if image1 and image2 are identical.
+bool areImagesEqual(const avifImage & image1, const avifImage & image2)
+{
+ if (image1.width != image2.width || image1.height != image2.height || image1.depth != image2.depth ||
+ image1.yuvFormat != image2.yuvFormat || image1.yuvRange != image2.yuvRange) {
+ return false;
+ }
+ assert(image1.width * image1.height > 0);
+
+ avifPixelFormatInfo info;
+ avifGetPixelFormatInfo(image1.yuvFormat, &info);
+
+ for (int c : AVIF_CHANS) {
+ uint8_t * row1 = (c == AVIF_CHAN_A) ? image1.alphaPlane : image1.yuvPlanes[c];
+ uint8_t * row2 = (c == AVIF_CHAN_A) ? image2.alphaPlane : image2.yuvPlanes[c];
+ if (!row1 != !row2) {
+ return false;
+ }
+ if (!row1) {
+ continue;
+ }
+ const uint32_t rowBytes1 = (c == AVIF_CHAN_A) ? image1.alphaRowBytes : image1.yuvRowBytes[c];
+ const uint32_t rowBytes2 = (c == AVIF_CHAN_A) ? image2.alphaRowBytes : image2.yuvRowBytes[c];
+ const uint32_t planeWidth =
+ (c == AVIF_CHAN_Y || c == AVIF_CHAN_A) ? image1.width : ((image1.width + info.chromaShiftX) >> info.chromaShiftX);
+ const uint32_t planeHeight =
+ (c == AVIF_CHAN_Y || c == AVIF_CHAN_A) ? image1.height : ((image1.height + info.chromaShiftY) >> info.chromaShiftY);
+ for (uint32_t y = 0; y < planeHeight; ++y) {
+ if (avifImageUsesU16(&image1)) {
+ if (!std::equal(reinterpret_cast<uint16_t *>(row1),
+ reinterpret_cast<uint16_t *>(row1) + planeWidth,
+ reinterpret_cast<uint16_t *>(row2))) {
+ return false;
+ }
+ } else {
+ if (!std::equal(row1, row1 + planeWidth, row2)) {
+ return false;
+ }
+ }
+ row1 += rowBytes1;
+ row2 += rowBytes2;
+ }
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------------
+
+} // namespace testutil
+} // namespace libavif
diff --git a/tests/aviftest_helpers.h b/tests/aviftest_helpers.h
new file mode 100644
index 0000000..77d4e56
--- /dev/null
+++ b/tests/aviftest_helpers.h
@@ -0,0 +1,40 @@
+// Copyright 2022 Google LLC
+// SPDX-License-Identifier: BSD-2-Clause
+
+#ifndef LIBAVIF_TESTS_AVIFTEST_HELPERS_H_
+#define LIBAVIF_TESTS_AVIFTEST_HELPERS_H_
+
+#include "avif/avif.h"
+
+#include <memory>
+
+namespace libavif
+{
+namespace testutil
+{
+
+using avifImagePtr = std::unique_ptr<avifImage, decltype(&avifImageDestroy)>;
+using avifEncoderPtr = std::unique_ptr<avifEncoder, decltype(&avifEncoderDestroy)>;
+using avifDecoderPtr = std::unique_ptr<avifDecoder, decltype(&avifDecoderDestroy)>;
+
+class avifRWDataCleaner : public avifRWData
+{
+public:
+ avifRWDataCleaner() : avifRWData({}) {}
+ ~avifRWDataCleaner() { avifRWDataFree(this); }
+};
+
+// Creates an image. Returns null in case of memory failure.
+avifImagePtr createImage(int width, int height, int depth, avifPixelFormat yuvFormat, avifPlanesFlags planes, avifRange yuvRange = AVIF_RANGE_FULL);
+
+// Set all pixels of each plane of an image.
+void fillImagePlain(avifImage * image, const uint32_t yuva[4]);
+void fillImageGradient(avifImage * image);
+
+// Returns true if both images have the same features and pixel values.
+bool areImagesEqual(const avifImage & image1, const avifImage & image2);
+
+} // namespace testutil
+} // namespace libavif
+
+#endif // LIBAVIF_TESTS_AVIFTEST_HELPERS_H_
diff --git a/tests/avify4mtest.cc b/tests/avify4mtest.cc
index cde23a4..4cf4853 100644
--- a/tests/avify4mtest.cc
+++ b/tests/avify4mtest.cc
@@ -5,167 +5,20 @@
#include "y4m.h"
-#include <cassert>
-#include <cinttypes>
-#include <cstdio>
-#include <cstring>
#include <sstream>
#include <tuple>
+#include "aviftest_helpers.h"
#include "gtest/gtest.h"
using testing::Combine;
using testing::Values;
+namespace libavif
+{
namespace
{
-//------------------------------------------------------------------------------
-
-// Returns true if image1 and image2 are identical.
-bool compareYUVA(const avifImage * image1, const avifImage * image2)
-{
- if (image1->width != image2->width || image1->height != image2->height || image1->depth != image2->depth ||
- image1->yuvFormat != image2->yuvFormat || image1->yuvRange != image2->yuvRange) {
- printf("ERROR: input mismatch\n");
- return false;
- }
- assert(image1->width * image1->height > 0);
-
- avifPixelFormatInfo formatInfo;
- avifGetPixelFormatInfo(image1->yuvFormat, &formatInfo);
- const uint32_t uvWidth = (image1->width + formatInfo.chromaShiftX) >> formatInfo.chromaShiftX;
- const uint32_t uvHeight = (image1->height + formatInfo.chromaShiftY) >> formatInfo.chromaShiftY;
-
- const int planeCount = formatInfo.monochrome ? 1 : AVIF_PLANE_COUNT_YUV;
- for (int plane = 0; plane < planeCount; ++plane) {
- const uint32_t widthByteCount =
- ((plane == AVIF_CHAN_Y) ? image1->width : uvWidth) * ((image1->depth > 8) ? sizeof(uint16_t) : sizeof(uint8_t));
- const uint32_t height = (plane == AVIF_CHAN_Y) ? image1->height : uvHeight;
- const uint8_t * row1 = image1->yuvPlanes[plane];
- const uint8_t * row2 = image2->yuvPlanes[plane];
- for (uint32_t y = 0; y < height; ++y) {
- if (memcmp(row1, row2, widthByteCount) != 0) {
- printf("ERROR: different px at row %" PRIu32 ", channel %" PRIu32 "\n", y, plane);
- return false;
- }
- row1 += image1->yuvRowBytes[plane];
- row2 += image2->yuvRowBytes[plane];
- }
- }
-
- if (image1->alphaPlane || image2->alphaPlane) {
- if (!image1->alphaPlane || !image2->alphaPlane || image1->alphaPremultiplied != image2->alphaPremultiplied) {
- printf("ERROR: input mismatch\n");
- return false;
- }
- const uint32_t widthByteCount = image1->width * ((image1->depth > 8) ? sizeof(uint16_t) : sizeof(uint8_t));
- const uint8_t * row1 = image1->alphaPlane;
- const uint8_t * row2 = image2->alphaPlane;
- for (uint32_t y = 0; y < image1->height; ++y) {
- if (memcmp(row1, row2, widthByteCount) != 0) {
- printf("ERROR: different px at row %" PRIu32 ", alpha\n", y);
- return false;
- }
- row1 += image1->alphaRowBytes;
- row2 += image2->alphaRowBytes;
- }
- }
- return true;
-}
-
-//------------------------------------------------------------------------------
-
-// Fills each plane of the image with the maximum allowed value.
-void fillPlanes(avifImage * image)
-{
- const uint16_t yuvValue = (image->yuvRange == AVIF_RANGE_LIMITED) ? (235 << (image->depth - 8)) : ((1 << image->depth) - 1);
- avifPixelFormatInfo formatInfo;
- avifGetPixelFormatInfo(image->yuvFormat, &formatInfo);
- const int planeCount = formatInfo.monochrome ? 1 : AVIF_PLANE_COUNT_YUV;
- for (int plane = 0; plane < planeCount; ++plane) {
- if (image->yuvPlanes[plane]) {
- const uint32_t planeWidth =
- (plane == AVIF_CHAN_Y) ? image->width : ((image->width + formatInfo.chromaShiftX) >> formatInfo.chromaShiftX);
- const uint32_t planeHeight =
- (plane == AVIF_CHAN_Y) ? image->height : ((image->height + formatInfo.chromaShiftY) >> formatInfo.chromaShiftY);
- for (uint32_t y = 0; y < planeHeight; ++y) {
- uint8_t * const row = image->yuvPlanes[plane] + y * image->yuvRowBytes[plane];
- if (image->depth == 8) {
- memset(row, yuvValue, planeWidth);
- } else {
- for (uint32_t x = 0; x < planeWidth; ++x) {
- ((uint16_t *)row)[x] = yuvValue;
- }
- }
- }
- }
- }
- if (image->alphaPlane) {
- const uint16_t alphaValue = (1 << image->depth) - 1;
- for (uint32_t y = 0; y < image->height; ++y) {
- uint8_t * const row = image->alphaPlane + y * image->alphaRowBytes;
- if (image->depth == 8) {
- memset(row, alphaValue, image->width);
- } else {
- for (uint32_t x = 0; x < image->width; ++x) {
- ((uint16_t *)row)[x] = alphaValue;
- }
- }
- }
- }
-}
-
-// Creates an image and encodes then decodes it as a y4m file.
-bool encodeDecodeY4m(uint32_t width,
- uint32_t height,
- uint32_t depth,
- avifPixelFormat yuvFormat,
- avifRange yuvRange,
- bool createAlpha,
- const char filePath[])
-{
- bool success = false;
- avifImage * image = avifImageCreateEmpty();
- avifImage * decoded = avifImageCreateEmpty();
- if (!image || !decoded) {
- printf("ERROR: avifImageCreate() failed\n");
- goto cleanup;
- }
- image->width = width;
- image->height = height;
- image->depth = depth;
- image->yuvFormat = yuvFormat;
- image->yuvRange = yuvRange;
- avifImageAllocatePlanes(image, createAlpha ? AVIF_PLANES_ALL : AVIF_PLANES_YUV);
- fillPlanes(image);
-
- if (!y4mWrite(filePath, image)) {
- printf("ERROR: y4mWrite() failed\n");
- goto cleanup;
- }
- if (!y4mRead(filePath, decoded, /*sourceTiming=*/NULL, /*iter=*/NULL)) {
- printf("ERROR: y4mRead() failed\n");
- goto cleanup;
- }
-
- if (!compareYUVA(image, decoded)) {
- goto cleanup;
- }
-
- success = true;
-cleanup:
- if (image) {
- avifImageDestroy(image);
- }
- if (decoded) {
- avifImageDestroy(decoded);
- }
- return success;
-}
-
-//------------------------------------------------------------------------------
-
class Y4mTest
: public testing::TestWithParam<std::tuple</*width=*/int, /*height=*/int, /*bitDepth=*/int, /*yuvFormat=*/avifPixelFormat, /*yuvRange=*/avifRange, /*createAlpha=*/bool>>
{
@@ -182,7 +35,22 @@
std::ostringstream filePath;
filePath << testing::TempDir() << "avify4mtest_" << width << "_" << height << "_" << bitDepth << "_" << yuvFormat << "_"
<< yuvRange << "_" << createAlpha;
- EXPECT_TRUE(encodeDecodeY4m(width, height, bitDepth, yuvFormat, yuvRange, createAlpha, filePath.str().c_str()));
+
+ testutil::avifImagePtr image =
+ testutil::createImage(width, height, bitDepth, yuvFormat, createAlpha ? AVIF_PLANES_ALL : AVIF_PLANES_YUV, yuvRange);
+ ASSERT_NE(image, nullptr);
+ const uint32_t yuva[] = { (yuvRange == AVIF_RANGE_LIMITED) ? (235u << (bitDepth - 8)) : ((1u << bitDepth) - 1),
+ (yuvRange == AVIF_RANGE_LIMITED) ? (240u << (bitDepth - 8)) : ((1u << bitDepth) - 1),
+ (yuvRange == AVIF_RANGE_LIMITED) ? (240u << (bitDepth - 8)) : ((1u << bitDepth) - 1),
+ (1u << bitDepth) - 1 };
+ testutil::fillImagePlain(image.get(), yuva);
+ ASSERT_TRUE(y4mWrite(filePath.str().c_str(), image.get()));
+
+ testutil::avifImagePtr decoded(avifImageCreateEmpty(), avifImageDestroy);
+ ASSERT_NE(decoded, nullptr);
+ ASSERT_TRUE(y4mRead(filePath.str().c_str(), decoded.get(), /*sourceTiming=*/nullptr, /*iter=*/nullptr));
+
+ EXPECT_TRUE(testutil::areImagesEqual(*image, *decoded));
}
INSTANTIATE_TEST_SUITE_P(OpaqueCombinations,
@@ -205,3 +73,4 @@
/*createAlpha=*/Values(true)));
} // namespace
+} // namespace libavif