Coverage Report

Created: 2025-08-28 07:16

/src/libavif/tests/gtest/aviftest_helpers.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2022 Google LLC
2
// SPDX-License-Identifier: BSD-2-Clause
3
4
#ifndef LIBAVIF_TESTS_AVIFTEST_HELPERS_H_
5
#define LIBAVIF_TESTS_AVIFTEST_HELPERS_H_
6
7
#include <array>
8
#include <cstdint>
9
#include <limits>
10
#include <memory>
11
#include <string>
12
#include <vector>
13
14
#include "avif/avif.h"
15
#include "avif/avif_cxx.h"
16
17
//------------------------------------------------------------------------------
18
// Duplicated from internal.h
19
// Used for debugging. Define AVIF_BREAK_ON_ERROR to catch the earliest failure
20
// during encoding or decoding.
21
#if defined(AVIF_BREAK_ON_ERROR)
22
static inline void avifBreakOnError() {
23
  // Same mechanism as OpenCV's error() function, or replace by a breakpoint.
24
  int* p = NULL;
25
  *p = 0;
26
}
27
#else
28
#define avifBreakOnError()
29
#endif
30
31
// Used by stream related things.
32
#define AVIF_CHECK(A)     \
33
  do {                    \
34
    if (!(A)) {           \
35
      avifBreakOnError(); \
36
      return AVIF_FALSE;  \
37
    }                     \
38
  } while (0)
39
40
// Used instead of CHECK if needing to return a specific error on failure,
41
// instead of AVIF_FALSE
42
#define AVIF_CHECKERR(A, ERR) \
43
18.4k
  do {                        \
44
18.4k
    if (!(A)) {               \
45
0
      avifBreakOnError();     \
46
0
      return ERR;             \
47
0
    }                         \
48
18.4k
  } while (0)
49
50
// Forward any error to the caller now or continue execution.
51
#define AVIF_CHECKRES(A)              \
52
30.7k
  do {                                \
53
30.7k
    const avifResult result__ = (A);  \
54
30.7k
    if (result__ != AVIF_RESULT_OK) { \
55
559
      avifBreakOnError();             \
56
559
      return result__;                \
57
559
    }                                 \
58
30.7k
  } while (0)
59
//------------------------------------------------------------------------------
60
61
namespace avif {
62
namespace testutil {
63
64
//------------------------------------------------------------------------------
65
66
// ICC color profiles are not checked by libavif so the content does not matter.
67
// This is a truncated widespread ICC color profile.
68
static const std::array<uint8_t, 24> kSampleIcc = {
69
    0x00, 0x00, 0x02, 0x0c, 0x6c, 0x63, 0x6d, 0x73, 0x02, 0x10, 0x00, 0x00,
70
    0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20};
71
72
// Exif bytes are partially checked by libavif.
73
// This is a truncated widespread Exif metadata chunk.
74
static const std::array<uint8_t, 24> kSampleExif = {
75
    0xff, 0x1,  0x45, 0x78, 0x69, 0x76, 0x32, 0xff, 0xe1, 0x12, 0x5a, 0x45,
76
    0x78, 0x69, 0x66, 0x0,  0x0,  0x49, 0x49, 0x2a, 0x0,  0x8,  0x0,  0x0};
77
78
// XMP bytes are not checked by libavif so the content does not matter.
79
// This is a truncated widespread XMP metadata chunk.
80
static const std::array<uint8_t, 24> kSampleXmp = {
81
    0x3c, 0x3f, 0x78, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x62, 0x65,
82
    0x67, 0x69, 0x6e, 0x3d, 0x22, 0xef, 0xbb, 0xbf, 0x22, 0x20, 0x69, 0x64};
83
84
//------------------------------------------------------------------------------
85
// Memory management
86
87
class AvifRwData : public avifRWData {
88
 public:
89
44.8k
  AvifRwData() : avifRWData{nullptr, 0} {}
90
  AvifRwData(const AvifRwData&) = delete;
91
  AvifRwData(AvifRwData&& other);
92
44.8k
  ~AvifRwData() { avifRWDataFree(this); }
93
};
94
95
class AvifRgbImage : public avifRGBImage {
96
 public:
97
  AvifRgbImage(const avifImage* yuv, int rgbDepth, avifRGBFormat rgbFormat);
98
5.48k
  ~AvifRgbImage() { avifRGBImageFreePixels(this); }
99
};
100
101
//------------------------------------------------------------------------------
102
// Samples and images
103
104
// Contains the sample position of each channel for a given avifRGBFormat.
105
// The alpha sample position is set to 0 for layouts having no alpha channel.
106
struct RgbChannelOffsets {
107
  uint8_t r, g, b, a;
108
};
109
RgbChannelOffsets GetRgbChannelOffsets(avifRGBFormat format);
110
111
// Creates an image. Returns null in case of memory failure.
112
ImagePtr CreateImage(int width, int height, int depth,
113
                     avifPixelFormat yuv_format, avifPlanesFlags planes,
114
                     avifRange yuv_range = AVIF_RANGE_FULL);
115
116
// Set all pixels of each plane of an image.
117
void FillImagePlain(avifImage* image, const uint32_t yuva[4]);
118
// 'offset' is a value to spatially offset the gradient, useful to create
119
// distinct images.
120
void FillImageGradient(avifImage* image, int offset = 0);
121
void FillImageChannel(avifRGBImage* image, uint32_t channel_offset,
122
                      uint32_t value);
123
124
// Returns true if both arrays are empty or have the same length and bytes.
125
// data1 may be null only when data1_length is 0.
126
// data2 may be null only when data2_length is 0.
127
bool AreByteSequencesEqual(const uint8_t data1[], size_t data1_length,
128
                           const uint8_t data2[], size_t data2_length);
129
bool AreByteSequencesEqual(const avifRWData& data1, const avifRWData& data2);
130
131
// Returns true if both images have the same features, pixel values and
132
// metadata. If ignore_alpha is true, the alpha channel is not taken into
133
// account in the comparison.
134
bool AreImagesEqual(const avifImage& image1, const avifImage& image2,
135
                    bool ignore_alpha = false);
136
137
// Returns true if both images have the same features and pixel values.
138
bool AreImagesEqual(const avifRGBImage& image1, const avifRGBImage& image2);
139
140
// Returns true if both images have the same features and close pixel values.
141
bool AreImagesSimilar(const avifImage& image1, const avifImage& image2,
142
                      double min_psnr = 30, bool ignore_alpha = false);
143
144
// Returns the Peak Signal-to-Noise Ratio of image1 compared to image2.
145
// A value of 99dB means all samples are exactly the same.
146
// A negative value means that the input images cannot be compared.
147
double GetPsnr(const avifImage& image1, const avifImage& image2,
148
               bool ignore_alpha = false);
149
150
// Merges the given image grid cells into a single image.
151
avifResult MergeGrid(int grid_cols, int grid_rows,
152
                     const std::vector<ImagePtr>& cells, avifImage* merged);
153
avifResult MergeGrid(int grid_cols, int grid_rows,
154
                     const std::vector<const avifImage*>& cells,
155
                     avifImage* merged);
156
157
//------------------------------------------------------------------------------
158
159
// Reads the file at file_path into bytes and returns them.
160
testutil::AvifRwData ReadFile(const std::string& file_path);
161
162
//------------------------------------------------------------------------------
163
// Shorter versions of libavif functions
164
165
// Reads the image named file_name located in directory at folder_path.
166
// Returns nullptr in case of error.
167
ImagePtr ReadImage(const char* folder_path, const char* file_name,
168
                   avifPixelFormat requested_format = AVIF_PIXEL_FORMAT_NONE,
169
                   int requested_depth = 0,
170
                   avifChromaDownsampling chroma_downsampling =
171
                       AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC,
172
                   avifBool ignore_icc = false, avifBool ignore_exif = false,
173
                   avifBool ignore_xmp = false,
174
                   avifBool allow_changing_cicp = true,
175
                   avifBool ignore_gain_map = false);
176
// Convenient wrapper around avifPNGWrite() for debugging purposes.
177
// Do not remove.
178
bool WriteImage(const avifImage* image, const char* file_path);
179
180
// Encodes the image with default parameters.
181
// Returns an empty payload in case of error.
182
AvifRwData Encode(const avifImage* image, int speed = AVIF_SPEED_DEFAULT,
183
                  int quality = AVIF_QUALITY_DEFAULT);
184
185
// Decodes the bytes to an image with default parameters.
186
// Returns nullptr in case of error.
187
ImagePtr Decode(const uint8_t* bytes, size_t num_bytes);
188
189
// Decodes the file to an image with default parameters.
190
// Returns nullptr in case of error.
191
ImagePtr DecodeFile(const std::string& path);
192
193
// Returns true if an AV1 encoder is available.
194
bool Av1EncoderAvailable();
195
196
// Returns true if an AV1 decoder is available.
197
bool Av1DecoderAvailable();
198
199
//------------------------------------------------------------------------------
200
// avifIO overlay
201
202
struct AvifIOLimitedReader {
203
  static constexpr uint64_t kNoClamp = std::numeric_limits<uint64_t>::max();
204
205
  avifIO io;
206
  avifIO* underlyingIO;
207
  uint64_t clamp;
208
};
209
210
avifIO* AvifIOCreateLimitedReader(avifIO* underlyingIO, uint64_t clamp);
211
212
//------------------------------------------------------------------------------
213
214
// Splits the input image into grid_cols*grid_rows views to be encoded as a
215
// grid. Returns an empty vector if the input image cannot be split that way.
216
std::vector<ImagePtr> ImageToGrid(const avifImage* image, uint32_t grid_cols,
217
                                  uint32_t grid_rows);
218
219
// Converts a unique_ptr array to a raw pointer array as needed by libavif API.
220
std::vector<const avifImage*> UniquePtrToRawPtr(
221
    const std::vector<ImagePtr>& unique_ptrs);
222
223
//------------------------------------------------------------------------------
224
225
}  // namespace testutil
226
}  // namespace avif
227
228
#endif  // LIBAVIF_TESTS_AVIFTEST_HELPERS_H_