libjxl

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

djpegli.cc (5939B)


      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 <stdint.h>
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 
     10 #include <string>
     11 #include <vector>
     12 
     13 #include "lib/extras/dec/jpegli.h"
     14 #include "lib/extras/enc/apng.h"
     15 #include "lib/extras/enc/encode.h"
     16 #include "lib/extras/time.h"
     17 #include "lib/jxl/base/printf_macros.h"
     18 #include "tools/cmdline.h"
     19 #include "tools/file_io.h"
     20 #include "tools/speed_stats.h"
     21 
     22 namespace jpegxl {
     23 namespace tools {
     24 namespace {
     25 
     26 struct Args {
     27   void AddCommandLineOptions(CommandLineParser* cmdline) {
     28     std::string output_help("The output can be ");
     29     if (jxl::extras::GetAPNGEncoder()) {
     30       output_help.append("PNG, ");
     31     }
     32     output_help.append("PFM or PPM/PGM/PNM");
     33     cmdline->AddPositionalOption("INPUT", /* required = */ true,
     34                                  "The JPG input file.", &file_in);
     35 
     36     cmdline->AddPositionalOption("OUTPUT", /* required = */ true, output_help,
     37                                  &file_out);
     38     cmdline->AddOptionFlag('\0', "disable_output",
     39                            "No output file will be written (for benchmarking)",
     40                            &disable_output, &SetBooleanTrue);
     41 
     42     cmdline->AddOptionValue('\0', "bitdepth", "8|16",
     43                             "Sets the output bitdepth for integer based "
     44                             "formats, can be 8 (default) "
     45                             "or 16. Has no impact on PFM output.",
     46                             &bitdepth, &ParseUnsigned);
     47 
     48     cmdline->AddOptionValue('\0', "num_reps", "N",
     49                             "Sets the number of times to decompress the image. "
     50                             "Used for benchmarking, the default is 1.",
     51                             &num_reps, &ParseUnsigned);
     52 
     53     cmdline->AddOptionFlag('\0', "quiet", "Silence output (except for errors).",
     54                            &quiet, &SetBooleanTrue);
     55   }
     56 
     57   const char* file_in = nullptr;
     58   const char* file_out = nullptr;
     59   bool disable_output = false;
     60   size_t bitdepth = 8;
     61   size_t num_reps = 1;
     62   bool quiet = false;
     63 };
     64 
     65 bool ValidateArgs(const Args& args) {
     66   if (args.bitdepth != 8 && args.bitdepth != 16) {
     67     fprintf(stderr, "Invalid --bitdepth argument\n");
     68     return false;
     69   }
     70   return true;
     71 }
     72 
     73 void SetDecompressParams(const Args& args, const std::string& extension,
     74                          jxl::extras::JpegDecompressParams* params) {
     75   if (extension == ".pfm") {
     76     params->output_data_type = JXL_TYPE_FLOAT;
     77     params->output_endianness = JXL_BIG_ENDIAN;
     78   } else if (args.bitdepth == 16) {
     79     params->output_data_type = JXL_TYPE_UINT16;
     80     params->output_endianness = JXL_BIG_ENDIAN;
     81   }
     82   if (extension == ".pgm") {
     83     params->force_grayscale = true;
     84   } else if (extension == ".ppm") {
     85     params->force_rgb = true;
     86   }
     87 }
     88 
     89 int DJpegliMain(int argc, const char* argv[]) {
     90   Args args;
     91   CommandLineParser cmdline;
     92   args.AddCommandLineOptions(&cmdline);
     93 
     94   if (!cmdline.Parse(argc, const_cast<const char**>(argv))) {
     95     // Parse already printed the actual error cause.
     96     fprintf(stderr, "Use '%s -h' for more information.\n", argv[0]);
     97     return EXIT_FAILURE;
     98   }
     99 
    100   if (cmdline.HelpFlagPassed() || !args.file_in) {
    101     cmdline.PrintHelp();
    102     return EXIT_SUCCESS;
    103   }
    104 
    105   if (!args.file_out && !args.disable_output) {
    106     fprintf(stderr,
    107             "No output file specified and --disable_output flag not passed.\n");
    108     return EXIT_FAILURE;
    109   }
    110 
    111   if (args.disable_output && !args.quiet) {
    112     fprintf(stderr,
    113             "Decoding will be performed, but the result will be discarded.\n");
    114   }
    115 
    116   if (!ValidateArgs(args)) {
    117     return EXIT_FAILURE;
    118   }
    119 
    120   std::vector<uint8_t> jpeg_bytes;
    121   if (!ReadFile(args.file_in, &jpeg_bytes)) {
    122     fprintf(stderr, "Failed to read input image %s\n", args.file_in);
    123     return EXIT_FAILURE;
    124   }
    125 
    126   if (!args.quiet) {
    127     fprintf(stderr, "Read %" PRIuS " compressed bytes.\n", jpeg_bytes.size());
    128   }
    129 
    130   std::string filename_out;
    131   std::string extension;
    132   if (args.file_out) {
    133     filename_out = std::string(args.file_out);
    134     size_t pos = filename_out.find_last_of('.');
    135     if (pos >= filename_out.size()) {
    136       fprintf(stderr, "Unrecognized output extension.\n");
    137       return EXIT_FAILURE;
    138     }
    139     extension = filename_out.substr(pos);
    140   }
    141 
    142   jxl::extras::JpegDecompressParams dparams;
    143   SetDecompressParams(args, extension, &dparams);
    144 
    145   jxl::extras::PackedPixelFile ppf;
    146   jpegxl::tools::SpeedStats stats;
    147   for (size_t num_rep = 0; num_rep < args.num_reps; ++num_rep) {
    148     const double t0 = jxl::Now();
    149     if (!jxl::extras::DecodeJpeg(jpeg_bytes, dparams, nullptr, &ppf)) {
    150       fprintf(stderr, "jpegli decoding failed\n");
    151       return EXIT_FAILURE;
    152     }
    153     const double t1 = jxl::Now();
    154     stats.NotifyElapsed(t1 - t0);
    155     stats.SetImageSize(ppf.info.xsize, ppf.info.ysize);
    156   }
    157 
    158   if (!args.quiet) {
    159     stats.Print(1);
    160   }
    161 
    162   if (args.disable_output) {
    163     return EXIT_SUCCESS;
    164   }
    165 
    166   if (extension == ".pnm") {
    167     extension = ppf.info.num_color_channels == 3 ? ".ppm" : ".pgm";
    168   }
    169 
    170   std::unique_ptr<jxl::extras::Encoder> encoder =
    171       jxl::extras::Encoder::FromExtension(extension);
    172   if (encoder == nullptr) {
    173     fprintf(stderr, "Can't decode to the file extension '%s'\n",
    174             extension.c_str());
    175     return EXIT_FAILURE;
    176   }
    177   jxl::extras::EncodedImage encoded_image;
    178   if (!encoder->Encode(ppf, &encoded_image, nullptr) ||
    179       encoded_image.bitstreams.empty()) {
    180     fprintf(stderr, "Encode failed\n");
    181     return EXIT_FAILURE;
    182   }
    183   if (!WriteFile(filename_out, encoded_image.bitstreams[0])) {
    184     fprintf(stderr, "Failed to write output file %s\n", filename_out.c_str());
    185     return EXIT_FAILURE;
    186   }
    187 
    188   return EXIT_SUCCESS;
    189 }
    190 
    191 }  // namespace
    192 }  // namespace tools
    193 }  // namespace jpegxl
    194 
    195 int main(int argc, const char* argv[]) {
    196   return jpegxl::tools::DJpegliMain(argc, argv);
    197 }