/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_ |