libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

benchmark_codec.cc (6143B)


      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_codec.h"
      7 
      8 #include <jxl/types.h>
      9 #include <stdint.h>
     10 #include <stdlib.h>
     11 #include <string.h>
     12 
     13 #include <string>
     14 #include <utility>
     15 #include <vector>
     16 
     17 #include "lib/extras/packed_image_convert.h"
     18 #include "lib/extras/time.h"
     19 #include "lib/jxl/base/status.h"
     20 #include "lib/jxl/color_encoding_internal.h"
     21 #include "lib/jxl/image.h"
     22 #include "lib/jxl/image_bundle.h"
     23 #include "lib/jxl/image_ops.h"
     24 #include "tools/benchmark/benchmark_args.h"
     25 #include "tools/benchmark/benchmark_codec_custom.h"
     26 #include "tools/benchmark/benchmark_codec_jpeg.h"
     27 #include "tools/benchmark/benchmark_codec_jxl.h"
     28 #include "tools/benchmark/benchmark_stats.h"
     29 #include "tools/speed_stats.h"
     30 #include "tools/thread_pool_internal.h"
     31 
     32 #ifdef BENCHMARK_PNG
     33 #include "tools/benchmark/benchmark_codec_png.h"
     34 #endif  // BENCHMARK_PNG
     35 
     36 #ifdef BENCHMARK_WEBP
     37 #include "tools/benchmark/benchmark_codec_webp.h"
     38 #endif  // BENCHMARK_WEBP
     39 
     40 #ifdef BENCHMARK_AVIF
     41 #include "tools/benchmark/benchmark_codec_avif.h"
     42 #endif  // BENCHMARK_AVIF
     43 
     44 namespace jpegxl {
     45 namespace tools {
     46 
     47 using ::jxl::Image3F;
     48 
     49 void ImageCodec::ParseParameters(const std::string& parameters) {
     50   params_ = parameters;
     51   std::vector<std::string> parts = SplitString(parameters, ':');
     52   for (size_t i = 0; i < parts.size(); ++i) {
     53     if (!ParseParam(parts[i])) {
     54       JXL_ABORT("Invalid parameter %s", parts[i].c_str());
     55     }
     56   }
     57 }
     58 
     59 Status ImageCodec::ParseParam(const std::string& param) {
     60   if (param[0] == 'q') {  // libjpeg-style quality, [0,100]
     61     const std::string quality_param = param.substr(1);
     62     char* end;
     63     const float q_target = strtof(quality_param.c_str(), &end);
     64     if (end == quality_param.c_str() ||
     65         end != quality_param.c_str() + quality_param.size()) {
     66       return false;
     67     }
     68     q_target_ = q_target;
     69     return true;
     70   }
     71   if (param[0] == 'd') {  // butteraugli distance
     72     const std::string distance_param = param.substr(1);
     73     char* end;
     74     const float butteraugli_target = strtof(distance_param.c_str(), &end);
     75     if (end == distance_param.c_str() ||
     76         end != distance_param.c_str() + distance_param.size()) {
     77       return false;
     78     }
     79     butteraugli_target_ = butteraugli_target;
     80     return true;
     81   } else if (param[0] == 'r') {
     82     bitrate_target_ = strtof(param.substr(1).c_str(), nullptr);
     83     return true;
     84   }
     85   return false;
     86 }
     87 
     88 // Low-overhead "codec" for measuring benchmark overhead.
     89 class NoneCodec : public ImageCodec {
     90  public:
     91   explicit NoneCodec(const BenchmarkArgs& args) : ImageCodec(args) {}
     92   Status ParseParam(const std::string& param) override { return true; }
     93 
     94   Status Compress(const std::string& filename, const PackedPixelFile& ppf,
     95                   ThreadPool* pool, std::vector<uint8_t>* compressed,
     96                   jpegxl::tools::SpeedStats* speed_stats) override {
     97     const double start = jxl::Now();
     98     // Encode image size so we "decompress" something of the same size, as
     99     // required by butteraugli.
    100     const uint32_t xsize = ppf.xsize();
    101     const uint32_t ysize = ppf.ysize();
    102     compressed->resize(8);
    103     memcpy(compressed->data(), &xsize, 4);
    104     memcpy(compressed->data() + 4, &ysize, 4);
    105     const double end = jxl::Now();
    106     speed_stats->NotifyElapsed(end - start);
    107     return true;
    108   }
    109 
    110   Status Decompress(const std::string& filename,
    111                     const Span<const uint8_t> compressed, ThreadPool* pool,
    112                     PackedPixelFile* ppf,
    113                     jpegxl::tools::SpeedStats* speed_stats) override {
    114     CodecInOut io;
    115     JXL_RETURN_IF_ERROR(
    116         Decompress(filename, compressed, pool, &io, speed_stats));
    117     JxlPixelFormat format{0, JXL_TYPE_UINT16, JXL_NATIVE_ENDIAN, 0};
    118     return jxl::extras::ConvertCodecInOutToPackedPixelFile(
    119         io, format, io.Main().c_current(), pool, ppf);
    120   };
    121 
    122   static Status Decompress(const std::string& filename,
    123                            const Span<const uint8_t> compressed,
    124                            ThreadPool* pool, CodecInOut* io,
    125                            jpegxl::tools::SpeedStats* speed_stats) {
    126     const double start = jxl::Now();
    127     JXL_ASSERT(compressed.size() == 8);
    128     uint32_t xsize;
    129     uint32_t ysize;
    130     memcpy(&xsize, compressed.data(), 4);
    131     memcpy(&ysize, compressed.data() + 4, 4);
    132     JXL_ASSIGN_OR_RETURN(Image3F image, Image3F::Create(xsize, ysize));
    133     ZeroFillImage(&image);
    134     io->metadata.m.SetFloat32Samples();
    135     io->metadata.m.color_encoding = ColorEncoding::SRGB();
    136     io->SetFromImage(std::move(image), io->metadata.m.color_encoding);
    137     const double end = jxl::Now();
    138     speed_stats->NotifyElapsed(end - start);
    139     return true;
    140   }
    141 
    142   void GetMoreStats(BenchmarkStats* stats) override {}
    143 };
    144 
    145 ImageCodecPtr CreateImageCodec(const std::string& description) {
    146   std::string name = description;
    147   std::string parameters;
    148   size_t colon = description.find(':');
    149   if (colon < description.size()) {
    150     name = description.substr(0, colon);
    151     parameters = description.substr(colon + 1);
    152   }
    153   ImageCodecPtr result;
    154   if (name == "jxl") {
    155     result.reset(CreateNewJxlCodec(*Args()));
    156 #if !defined(__wasm__)
    157   } else if (name == "custom") {
    158     result.reset(CreateNewCustomCodec(*Args()));
    159 #endif
    160   } else if (name == "jpeg") {
    161     result.reset(CreateNewJPEGCodec(*Args()));
    162 #ifdef BENCHMARK_PNG
    163   } else if (name == "png") {
    164     result.reset(CreateNewPNGCodec(*Args()));
    165 #endif  // BENCHMARK_PNG
    166   } else if (name == "none") {
    167     result.reset(new NoneCodec(*Args()));
    168 #ifdef BENCHMARK_WEBP
    169   } else if (name == "webp") {
    170     result.reset(CreateNewWebPCodec(*Args()));
    171 #endif  // BENCHMARK_WEBP
    172 #ifdef BENCHMARK_AVIF
    173   } else if (name == "avif") {
    174     result.reset(CreateNewAvifCodec(*Args()));
    175 #endif  // BENCHMARK_AVIF
    176   }
    177   if (!result.get()) {
    178     JXL_ABORT("Unknown image codec: %s", name.c_str());
    179   }
    180   result->set_description(description);
    181   if (!parameters.empty()) result->ParseParameters(parameters);
    182   return result;
    183 }
    184 
    185 }  // namespace tools
    186 }  // namespace jpegxl