libjxl

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

benchmark_codec_custom.cc (7482B)


      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_custom.h"
      7 
      8 #include <jxl/types.h>
      9 #include <stdio.h>
     10 
     11 #include <cstdint>
     12 #include <string>
     13 #include <utility>
     14 #include <vector>
     15 
     16 #include "lib/extras/dec/color_hints.h"
     17 #include "lib/extras/packed_image_convert.h"
     18 #include "lib/jxl/base/span.h"
     19 #include "lib/jxl/base/status.h"
     20 #include "tools/benchmark/benchmark_args.h"
     21 #include "tools/benchmark/benchmark_codec.h"
     22 #include "tools/speed_stats.h"
     23 
     24 // Not supported on Windows due to Linux-specific functions.
     25 #ifndef _WIN32
     26 
     27 #include <libgen.h>
     28 
     29 #include <fstream>
     30 
     31 #include "lib/extras/codec.h"
     32 #include "lib/extras/time.h"
     33 #include "lib/jxl/image_bundle.h"
     34 #include "tools/benchmark/benchmark_utils.h"
     35 #include "tools/file_io.h"
     36 #include "tools/thread_pool_internal.h"
     37 
     38 namespace jpegxl {
     39 namespace tools {
     40 
     41 struct CustomCodecArgs {
     42   std::string extension;
     43   std::string colorspace;
     44   bool quiet;
     45 };
     46 
     47 static CustomCodecArgs* const custom_args = new CustomCodecArgs;
     48 
     49 Status AddCommandLineOptionsCustomCodec(BenchmarkArgs* args) {
     50   args->AddString(
     51       &custom_args->extension, "custom_codec_extension",
     52       "Converts input and output of codec to this file type (default: png).",
     53       "png");
     54   args->AddString(
     55       &custom_args->colorspace, "custom_codec_colorspace",
     56       "If not empty, converts input and output of codec to this colorspace.",
     57       "");
     58   args->AddFlag(&custom_args->quiet, "custom_codec_quiet",
     59                 "Whether stdin and stdout of custom codec should be shown.",
     60                 false);
     61   return true;
     62 }
     63 
     64 namespace {
     65 
     66 // This uses `output_filename` to determine the name of the corresponding
     67 // `.time` file.
     68 template <typename F>
     69 Status ReportCodecRunningTime(F&& function, std::string output_filename,
     70                               jpegxl::tools::SpeedStats* const speed_stats) {
     71   const double start = jxl::Now();
     72   JXL_RETURN_IF_ERROR(function());
     73   const double end = jxl::Now();
     74   const std::string time_filename =
     75       GetBaseName(std::move(output_filename)) + ".time";
     76   std::ifstream time_stream(time_filename);
     77   double time;
     78   if (time_stream >> time) {
     79     // Report the time measured by the external codec itself.
     80     speed_stats->NotifyElapsed(time);
     81   } else {
     82     // Fall back to the less accurate time that we measured.
     83     speed_stats->NotifyElapsed(end - start);
     84   }
     85   if (time_stream.is_open()) {
     86     remove(time_filename.c_str());
     87   }
     88   return true;
     89 }
     90 
     91 class CustomCodec : public ImageCodec {
     92  public:
     93   explicit CustomCodec(const BenchmarkArgs& args) : ImageCodec(args) {}
     94 
     95   Status ParseParam(const std::string& param) override {
     96     if (param_index_ == 0) {
     97       description_ = "";
     98     }
     99     switch (param_index_) {
    100       case 0:
    101         extension_ = param;
    102         description_ += param;
    103         break;
    104       case 1:
    105         compress_command_ = param;
    106         description_ += std::string(":");
    107         if (param.find_last_of('/') < param.size()) {
    108           description_ += param.substr(param.find_last_of('/') + 1);
    109         } else {
    110           description_ += param;
    111         }
    112         break;
    113       case 2:
    114         decompress_command_ = param;
    115         break;
    116       default:
    117         compress_args_.push_back(param);
    118         description_ += std::string(":");
    119         if (param.size() > 2 && param[0] == '-' && param[1] == '-') {
    120           description_ += param.substr(2);
    121         } else if (param.size() > 2 && param[0] == '-') {
    122           description_ += param.substr(1);
    123         } else {
    124           description_ += param;
    125         }
    126         break;
    127     }
    128     ++param_index_;
    129     return true;
    130   }
    131 
    132   Status Compress(const std::string& filename, const PackedPixelFile& ppf,
    133                   ThreadPool* pool, std::vector<uint8_t>* compressed,
    134                   jpegxl::tools::SpeedStats* speed_stats) override {
    135     JXL_RETURN_IF_ERROR(param_index_ > 2);
    136 
    137     const std::string basename = GetBaseName(filename);
    138     TemporaryFile in_file(basename, custom_args->extension);
    139     TemporaryFile encoded_file(basename, extension_);
    140     std::string in_filename;
    141     std::string encoded_filename;
    142     JXL_RETURN_IF_ERROR(in_file.GetFileName(&in_filename));
    143     JXL_RETURN_IF_ERROR(encoded_file.GetFileName(&encoded_filename));
    144     // TODO(szabadka) Support custom_args->colorspace again.
    145     std::vector<uint8_t> encoded;
    146     JXL_RETURN_IF_ERROR(Encode(ppf, in_filename, &encoded, pool));
    147     JXL_RETURN_IF_ERROR(WriteFile(in_filename, encoded));
    148     std::vector<std::string> arguments = compress_args_;
    149     arguments.push_back(in_filename);
    150     arguments.push_back(encoded_filename);
    151     JXL_RETURN_IF_ERROR(ReportCodecRunningTime(
    152         [&, this] {
    153           return RunCommand(compress_command_, arguments, custom_args->quiet);
    154         },
    155         encoded_filename, speed_stats));
    156     return ReadFile(encoded_filename, compressed);
    157   }
    158 
    159   Status Decompress(const std::string& filename,
    160                     const Span<const uint8_t> compressed, ThreadPool* pool,
    161                     PackedPixelFile* ppf,
    162                     jpegxl::tools::SpeedStats* speed_stats) override {
    163     CodecInOut io;
    164     JXL_RETURN_IF_ERROR(
    165         Decompress(filename, compressed, pool, &io, speed_stats));
    166     JxlPixelFormat format{0, JXL_TYPE_UINT16, JXL_NATIVE_ENDIAN, 0};
    167     return jxl::extras::ConvertCodecInOutToPackedPixelFile(
    168         io, format, io.Main().c_current(), pool, ppf);
    169   };
    170 
    171   Status Decompress(const std::string& filename,
    172                     const Span<const uint8_t> compressed, ThreadPool* pool,
    173                     CodecInOut* io, jpegxl::tools::SpeedStats* speed_stats) {
    174     const std::string basename = GetBaseName(filename);
    175     TemporaryFile encoded_file(basename, extension_);
    176     TemporaryFile out_file(basename, custom_args->extension);
    177     std::string encoded_filename;
    178     std::string out_filename;
    179     JXL_RETURN_IF_ERROR(encoded_file.GetFileName(&encoded_filename));
    180     JXL_RETURN_IF_ERROR(out_file.GetFileName(&out_filename));
    181 
    182     JXL_RETURN_IF_ERROR(WriteFile(encoded_filename, compressed));
    183     JXL_RETURN_IF_ERROR(ReportCodecRunningTime(
    184         [&, this] {
    185           return RunCommand(
    186               decompress_command_,
    187               std::vector<std::string>{encoded_filename, out_filename},
    188               custom_args->quiet);
    189         },
    190         out_filename, speed_stats));
    191     jxl::extras::ColorHints hints;
    192     if (!custom_args->colorspace.empty()) {
    193       hints.Add("color_space", custom_args->colorspace);
    194     }
    195     std::vector<uint8_t> encoded;
    196     JXL_RETURN_IF_ERROR(ReadFile(out_filename, &encoded));
    197     JXL_RETURN_IF_ERROR(
    198         jxl::SetFromBytes(jxl::Bytes(encoded), hints, io, pool));
    199     io->metadata.m.SetIntensityTarget(saved_intensity_target_);
    200     return true;
    201   }
    202 
    203  private:
    204   std::string extension_;
    205   std::string compress_command_;
    206   std::string decompress_command_;
    207   std::vector<std::string> compress_args_;
    208   int param_index_ = 0;
    209   int saved_intensity_target_ = 255;
    210 };
    211 
    212 }  // namespace
    213 
    214 ImageCodec* CreateNewCustomCodec(const BenchmarkArgs& args) {
    215   return new CustomCodec(args);
    216 }
    217 
    218 }  // namespace tools
    219 }  // namespace jpegxl
    220 
    221 #else
    222 
    223 namespace jpegxl {
    224 namespace tools {
    225 
    226 ImageCodec* CreateNewCustomCodec(const BenchmarkArgs& args) { return nullptr; }
    227 Status AddCommandLineOptionsCustomCodec(BenchmarkArgs* args) { return true; }
    228 
    229 }  // namespace tools
    230 }  // namespace jpegxl
    231 
    232 #endif  // _MSC_VER