benchmark_args.cc (10772B)
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 #include "tools/benchmark/benchmark_args.h" 7 8 #include <stddef.h> 9 #include <stdlib.h> 10 11 #include <algorithm> 12 #include <string> 13 #include <vector> 14 15 #include "lib/extras/codec.h" 16 #include "lib/extras/dec/color_description.h" 17 #include "lib/jxl/base/status.h" 18 #include "lib/jxl/color_encoding_internal.h" 19 #include "tools/benchmark/benchmark_codec_custom.h" // for AddCommand.. 20 #include "tools/benchmark/benchmark_codec_jpeg.h" // for AddCommand.. 21 #include "tools/benchmark/benchmark_codec_jxl.h" 22 23 #ifdef BENCHMARK_PNG 24 #include "tools/benchmark/benchmark_codec_png.h" 25 #endif // BENCHMARK_PNG 26 27 #ifdef BENCHMARK_WEBP 28 #include "tools/benchmark/benchmark_codec_webp.h" 29 #endif // BENCHMARK_WEBP 30 31 #ifdef BENCHMARK_AVIF 32 #include "tools/benchmark/benchmark_codec_avif.h" 33 #endif // BENCHMARK_AVIF 34 35 namespace jpegxl { 36 namespace tools { 37 38 std::vector<std::string> SplitString(const std::string& s, char c) { 39 std::vector<std::string> result; 40 size_t pos = 0; 41 for (size_t i = 0; i <= s.size(); i++) { 42 if (i == s.size() || s[i] == c) { 43 result.push_back(s.substr(pos, i - pos)); 44 pos = i + 1; 45 } 46 } 47 return result; 48 } 49 50 int ParseIntParam(const std::string& param, int lower_bound, int upper_bound) { 51 int val = strtol(param.substr(1).c_str(), nullptr, 10); 52 JXL_CHECK(val >= lower_bound && val <= upper_bound); 53 return val; 54 } 55 56 BenchmarkArgs* Args() { 57 static BenchmarkArgs args; 58 return &args; 59 } 60 61 Status BenchmarkArgs::AddCommandLineOptions() { 62 AddString(&input, "input", "File or file pattern matching input files."); 63 AddString(&codec, "codec", 64 "Comma separated list of image codec descriptions to benchmark.", 65 "jxl"); 66 AddFlag(&print_details, "print_details", 67 "Prints size and distortion for each image. Not safe for " 68 "concurrent benchmark runs.", 69 false); 70 AddFlag(&print_details_csv, "print_details_csv", 71 "When print_details is used, print as CSV.", false); 72 AddString(&extra_metrics, "extra_metrics", 73 "Extra metrics to be computed. Only displayed with --print_details " 74 "or --print_details_csv. Comma-separated list of NAME:COMMAND " 75 "pairs; COMMAND is invoked with the original image as the first " 76 "argument, the decompressed image as a second argument, and the " 77 "name of the file where to write the metric value (as a single " 78 "floating point number) as the third argument.", 79 ""); 80 AddFlag( 81 &print_more_stats, "print_more_stats", 82 "Prints codec-specific stats. Not safe for concurrent benchmark runs.", 83 false); 84 AddFlag(&print_distance_percentiles, "print_distance_percentiles", 85 "Prints distance percentiles for the corpus. Not safe for " 86 "concurrent benchmark runs.", 87 false); 88 AddFlag(&silent_errors, "silent_errors", 89 "If true, doesn't print error messages on compression or" 90 " decompression errors. Errors counts are still visible in the" 91 " 'Errors' column of the result table. Please note that depending" 92 " depending on the JXL build settings, error messages and asserts" 93 " from within the codec may be printed irrespective of this flag" 94 " anyway, use release build to ensure no messages.", 95 false); 96 AddFlag(&save_compressed, "save_compressed", 97 "Saves the compressed files for each input image and each codec.", 98 false); 99 AddFlag(&save_decompressed, "save_decompressed", 100 "Saves the decompressed files as PNG for each input image " 101 "and each codec.", 102 false); 103 AddString(&output_extension, "output_extension", 104 "Extension (starting with dot) to use for saving output images.", 105 ".png"); 106 AddString(&output_description, "output_description", 107 "Color encoding (see ParseDescription; e.g. RGB_D65_SRG_Rel_709) " 108 "for saving output images, " 109 " defaults to sRGB."); 110 111 AddFloat(&intensity_target, "intensity_target", 112 "Intended viewing intensity target in nits. Defaults to 255 for " 113 "SDR images, 4000 for HDR images (when the input image uses PQ or " 114 "HLG transfer function)", 115 0); 116 117 AddString(&color_hints_string, "dec-hints", 118 "Color encoding hints for the input images to encoder. Comma " 119 "separated key=value pairs. The key color_space indicates " 120 "ColorEncoding (see ParseDescription; e.g. RGB_D65_SRG_Rel_709) " 121 "for input images without color encoding (such as PNM)"); 122 123 AddUnsigned( 124 &override_bitdepth, "override_bitdepth", 125 "If nonzero, store the given bit depth in the JPEG XL file metadata" 126 " (1-32), instead of using the bit depth from the original input" 127 " image.", 128 0); 129 130 AddDouble(&mul_output, "mul_output", 131 "If nonzero, multiplies linear sRGB by this and clamps to 255", 132 0.0); 133 AddFlag(&save_heatmap, "save_heatmap", "Saves the heatmap images.", true); 134 AddDouble(&heatmap_good, "heatmap_good", 135 "If greater than zero, use this as the good " 136 "threshold for creating heatmap images.", 137 0.0); 138 AddDouble(&heatmap_bad, "heatmap_bad", 139 "If greater than zero, use this as the bad " 140 "threshold for creating heatmap images.", 141 0.0); 142 143 AddFlag(&write_html_report, "write_html_report", 144 "Creates an html report with original and compressed images.", false); 145 AddFlag(&html_report_self_contained, "html_report_self_contained", 146 "Base64-encode the images in the HTML report rather than use " 147 "external file names. May cause very large HTML data size.", 148 false); 149 AddFlag(&html_report_use_decompressed, "html_report_use_decompressed", 150 "Show the compressed image as decompressed to --output_extension.", 151 true); 152 AddFlag(&html_report_add_heatmap, "html_report_add_heatmap", 153 "Add heatmaps to the image comparisons.", false); 154 155 AddFlag( 156 &markdown, "markdown", 157 "Adds formatting around ASCII table to render correctly in Markdown based" 158 " interfaces", 159 true); 160 161 AddFlag(&more_columns, "more_columns", "Print extra columns in the table", 162 false); 163 164 AddString(&originals_url, "originals_url", 165 "Url prefix to serve original images from in the html report."); 166 AddString(&output_dir, "output_dir", 167 "If not empty, save compressed and decompressed " 168 "images here."); 169 170 AddSigned(&num_threads, "num_threads", 171 "The number of threads for concurrent benchmarking. Defaults to " 172 "1 thread per CPU core (if negative).", 173 -1); 174 AddSigned(&inner_threads, "inner_threads", 175 "The number of extra threads per task. " 176 "Defaults to occupy cores (if negative).", 177 -1); 178 AddUnsigned(&encode_reps, "encode_reps", 179 "How many times to encode (>1 for more precise measurements). " 180 "Defaults to 1.", 181 1); 182 AddUnsigned(&decode_reps, "decode_reps", 183 "How many times to decode (>1 for more precise measurements). " 184 "Defaults to 1.", 185 1); 186 187 AddString(&sample_tmp_dir, "sample_tmp_dir", 188 "Directory to put samples from input images."); 189 190 AddSigned(&num_samples, "num_samples", "How many sample areas to take.", 0); 191 AddSigned(&sample_dimensions, "sample_dimensions", 192 "How big areas to sample from the input.", 64); 193 194 AddDouble(&error_pnorm, "error_pnorm", 195 "smallest p norm for pooling butteraugli values", 3.0); 196 197 AddFlag(&show_progress, "show_progress", 198 "Show activity dots per completed file during benchmark.", false); 199 200 AddFlag(&skip_butteraugli, "skip_butteraugli", 201 "If true, doesn't compute distance metrics, only compression and" 202 " decompression speed and size. Distance numbers shown in the" 203 " table are invalid.", 204 false); 205 206 AddFlag( 207 &decode_only, "decode_only", 208 "If true, only decodes, and the input files must be compressed with a " 209 "compatible format for the given codec(s). Only measures decompression " 210 "speed and sizes, and can only use a single set of compatible decoders. " 211 "Distance numbers and compression speeds shown in the table are invalid.", 212 false); 213 214 if (!AddCommandLineOptionsCustomCodec(this)) return false; 215 if (!AddCommandLineOptionsJxlCodec(this)) return false; 216 if (!AddCommandLineOptionsJPEGCodec(this)) return false; 217 218 #ifdef BENCHMARK_PNG 219 if (!AddCommandLineOptionsPNGCodec(this)) return false; 220 #endif // BENCHMARK_PNG 221 #ifdef BENCHMARK_WEBP 222 if (!AddCommandLineOptionsWebPCodec(this)) return false; 223 #endif // BENCHMARK_WEBP 224 #ifdef BENCHMARK_AVIF 225 if (!AddCommandLineOptionsAvifCodec(this)) return false; 226 #endif // BENCHMARK_AVIF 227 228 return true; 229 } 230 231 Status BenchmarkArgs::ValidateArgs() { 232 if (input.empty()) { 233 fprintf(stderr, "Missing --input filename(s).\n"); 234 return false; 235 } 236 if (jxl::extras::CodecFromPath(output_extension) == 237 jxl::extras::Codec::kUnknown) { 238 JXL_WARNING("Unrecognized output_extension %s, try .png", 239 output_extension.c_str()); 240 return false; // already warned 241 } 242 243 // If empty, don't do anything; callers must only use output_encoding if 244 // output_description is not empty. 245 if (!output_description.empty()) { 246 // Validate, but also create the profile (only needs to happen once). 247 JxlColorEncoding output_encoding_external; 248 if (!jxl::ParseDescription(output_description, &output_encoding_external)) { 249 JXL_WARNING("Unrecognized output_description %s, try RGB_D65_SRG_Rel_Lin", 250 output_description.c_str()); 251 return false; // already warned 252 } 253 JXL_RETURN_IF_ERROR(output_encoding.FromExternal(output_encoding_external)); 254 JXL_RETURN_IF_ERROR(!output_encoding.ICC().empty()); 255 } 256 257 JXL_RETURN_IF_ERROR(ValidateArgsJxlCodec(this)); 258 259 if (print_details_csv) print_details = true; 260 261 if (override_bitdepth > 32) { 262 return JXL_FAILURE("override_bitdepth must be <= 32"); 263 } 264 265 if (!color_hints_string.empty()) { 266 std::vector<std::string> hints = SplitString(color_hints_string, ','); 267 for (const auto& hint : hints) { 268 std::vector<std::string> kv = SplitString(hint, '='); 269 if (kv.size() != 2) { 270 return JXL_FAILURE( 271 "dec-hints key value pairs must have the form 'key=value'"); 272 } 273 color_hints.Add(kv[0], kv[1]); 274 } 275 } 276 277 return true; 278 } 279 280 } // namespace tools 281 } // namespace jpegxl