test_utils.h (8340B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #ifndef LIB_JXL_TEST_UTILS_H_ 7 #define LIB_JXL_TEST_UTILS_H_ 8 9 // TODO(eustas): reduce includes (move to .cc) 10 11 // Macros and functions useful for tests. 12 13 #include <jxl/codestream_header.h> 14 #include <jxl/thread_parallel_runner_cxx.h> 15 16 #include <cstddef> 17 #include <cstdint> 18 #include <ostream> 19 #include <vector> 20 21 #include "lib/extras/dec/jxl.h" 22 #include "lib/extras/enc/jxl.h" 23 #include "lib/extras/packed_image.h" 24 #include "lib/jxl/base/data_parallel.h" 25 #include "lib/jxl/base/span.h" 26 #include "lib/jxl/base/status.h" 27 #include "lib/jxl/butteraugli/butteraugli.h" 28 #include "lib/jxl/codec_in_out.h" 29 #include "lib/jxl/color_encoding_internal.h" 30 #include "lib/jxl/enc_params.h" 31 32 #define TEST_LIBJPEG_SUPPORT() \ 33 do { \ 34 if (!jxl::extras::CanDecode(jxl::extras::Codec::kJPG)) { \ 35 fprintf(stderr, "Skipping test because of missing libjpeg codec.\n"); \ 36 return; \ 37 } \ 38 } while (0) 39 40 namespace jxl { 41 42 struct AuxOut; 43 class CodecInOut; 44 class PaddedBytes; 45 struct PassesEncoderState; 46 class ThreadPool; 47 48 namespace test { 49 50 std::string GetTestDataPath(const std::string& filename); 51 std::vector<uint8_t> ReadTestData(const std::string& filename); 52 53 void JxlBasicInfoSetFromPixelFormat(JxlBasicInfo* basic_info, 54 const JxlPixelFormat* pixel_format); 55 56 void DefaultAcceptedFormats(extras::JXLDecompressParams& dparams); 57 58 template <typename Params> 59 void SetThreadParallelRunner(Params params, ThreadPool* pool) { 60 if (pool && !params.runner_opaque) { 61 params.runner = pool->runner(); 62 params.runner_opaque = pool->runner_opaque(); 63 } 64 } 65 66 Status DecodeFile(extras::JXLDecompressParams dparams, Span<const uint8_t> file, 67 CodecInOut* JXL_RESTRICT io, ThreadPool* pool = nullptr); 68 69 bool Roundtrip(const CodecInOut* io, const CompressParams& cparams, 70 extras::JXLDecompressParams dparams, 71 CodecInOut* JXL_RESTRICT io2, std::stringstream& failures, 72 size_t* compressed_size = nullptr, ThreadPool* pool = nullptr); 73 74 // Returns compressed size [bytes]. 75 size_t Roundtrip(const extras::PackedPixelFile& ppf_in, 76 const extras::JXLCompressParams& cparams, 77 extras::JXLDecompressParams dparams, ThreadPool* pool, 78 extras::PackedPixelFile* ppf_out); 79 80 // A POD descriptor of a ColorEncoding. Only used in tests as the return value 81 // of AllEncodings(). 82 struct ColorEncodingDescriptor { 83 ColorSpace color_space; 84 WhitePoint white_point; 85 Primaries primaries; 86 TransferFunction tf; 87 RenderingIntent rendering_intent; 88 }; 89 90 ColorEncoding ColorEncodingFromDescriptor(const ColorEncodingDescriptor& desc); 91 92 // Define the operator<< for tests. 93 static inline ::std::ostream& operator<<(::std::ostream& os, 94 const ColorEncodingDescriptor& c) { 95 return os << "ColorEncoding/" << Description(ColorEncodingFromDescriptor(c)); 96 } 97 98 // Returns ColorEncodingDescriptors, which are only used in tests. To obtain a 99 // ColorEncoding object call ColorEncodingFromDescriptor and then call 100 // ColorEncoding::CreateProfile() on that object to generate a profile. 101 std::vector<ColorEncodingDescriptor> AllEncodings(); 102 103 // Returns a CodecInOut based on the buf, xsize, ysize, and the assumption 104 // that the buffer was created using `GetSomeTestImage`. 105 jxl::CodecInOut SomeTestImageToCodecInOut(const std::vector<uint8_t>& buf, 106 size_t num_channels, size_t xsize, 107 size_t ysize); 108 109 bool Near(double expected, double value, double max_dist); 110 111 float LoadLEFloat16(const uint8_t* p); 112 113 float LoadBEFloat16(const uint8_t* p); 114 115 size_t GetPrecision(JxlDataType data_type); 116 117 size_t GetDataBits(JxlDataType data_type); 118 119 // Procedure to convert pixels to double precision, not efficient, but 120 // well-controlled for testing. It uses double, to be able to represent all 121 // precisions needed for the maximum data types the API supports: uint32_t 122 // integers, and, single precision float. The values are in range 0-1 for SDR. 123 std::vector<double> ConvertToRGBA32(const uint8_t* pixels, size_t xsize, 124 size_t ysize, const JxlPixelFormat& format, 125 double factor = 0.0); 126 127 // Returns amount of pixels which differ between the two pictures. Image b is 128 // the image after roundtrip after roundtrip, image a before roundtrip. There 129 // are more strict requirements for the alpha channel and grayscale values of 130 // the output image. 131 size_t ComparePixels(const uint8_t* a, const uint8_t* b, size_t xsize, 132 size_t ysize, const JxlPixelFormat& format_a, 133 const JxlPixelFormat& format_b, 134 double threshold_multiplier = 1.0); 135 136 double DistanceRMS(const uint8_t* a, const uint8_t* b, size_t xsize, 137 size_t ysize, const JxlPixelFormat& format); 138 139 float ButteraugliDistance(const extras::PackedPixelFile& a, 140 const extras::PackedPixelFile& b, 141 ThreadPool* pool = nullptr); 142 143 float ButteraugliDistance(const ImageBundle& rgb0, const ImageBundle& rgb1, 144 const ButteraugliParams& params, 145 const JxlCmsInterface& cms, ImageF* distmap = nullptr, 146 ThreadPool* pool = nullptr, 147 bool ignore_alpha = false); 148 149 float ButteraugliDistance(const std::vector<ImageBundle>& frames0, 150 const std::vector<ImageBundle>& frames1, 151 const ButteraugliParams& params, 152 const JxlCmsInterface& cms, ImageF* distmap = nullptr, 153 ThreadPool* pool = nullptr); 154 155 float Butteraugli3Norm(const extras::PackedPixelFile& a, 156 const extras::PackedPixelFile& b, 157 ThreadPool* pool = nullptr); 158 159 float ComputeDistance2(const extras::PackedPixelFile& a, 160 const extras::PackedPixelFile& b); 161 162 float ComputePSNR(const extras::PackedPixelFile& a, 163 const extras::PackedPixelFile& b); 164 165 bool SameAlpha(const extras::PackedPixelFile& a, 166 const extras::PackedPixelFile& b); 167 168 bool SamePixels(const extras::PackedImage& a, const extras::PackedImage& b); 169 170 bool SamePixels(const extras::PackedPixelFile& a, 171 const extras::PackedPixelFile& b); 172 173 class ThreadPoolForTests { 174 public: 175 explicit ThreadPoolForTests(int num_threads) { 176 runner_ = 177 JxlThreadParallelRunnerMake(/* memory_manager */ nullptr, num_threads); 178 pool_ = 179 jxl::make_unique<ThreadPool>(JxlThreadParallelRunner, runner_.get()); 180 } 181 ThreadPoolForTests(const ThreadPoolForTests&) = delete; 182 ThreadPoolForTests& operator&(const ThreadPoolForTests&) = delete; 183 // TODO(eustas): avoid unary `&` overload? 184 ThreadPool* operator&() { return pool_.get(); } 185 186 private: 187 JxlThreadParallelRunnerPtr runner_; 188 std::unique_ptr<ThreadPool> pool_; 189 }; 190 191 // `icc` may be empty afterwards - if so, call CreateProfile. Does not append, 192 // clears any original data that was in icc. 193 // If `output_limit` is not 0, then returns error if resulting profile would be 194 // longer than `output_limit` 195 Status ReadICC(BitReader* JXL_RESTRICT reader, 196 std::vector<uint8_t>* JXL_RESTRICT icc, size_t output_limit = 0); 197 198 // Compresses pixels from `io` (given in any ColorEncoding). 199 // `io->metadata.m.original` must be set. 200 Status EncodeFile(const CompressParams& params, const CodecInOut* io, 201 std::vector<uint8_t>* compressed, ThreadPool* pool = nullptr); 202 203 constexpr const char* BoolToCStr(bool b) { return b ? "true" : "false"; } 204 205 } // namespace test 206 207 bool operator==(const jxl::Bytes& a, const jxl::Bytes& b); 208 209 // Allow using EXPECT_EQ on jxl::Bytes 210 bool operator!=(const jxl::Bytes& a, const jxl::Bytes& b); 211 212 } // namespace jxl 213 214 #endif // LIB_JXL_TEST_UTILS_H_