libjxl

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

jxl_decompressor.cc (3472B)


      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/wasm_demo/jxl_decompressor.h"
      7 
      8 #include <jxl/thread_parallel_runner_cxx.h>
      9 
     10 #include <cstring>
     11 #include <memory>
     12 
     13 #include "lib/extras/dec/jxl.h"
     14 #include "tools/wasm_demo/no_png.h"
     15 
     16 extern "C" {
     17 
     18 namespace {
     19 
     20 struct DecompressorOutputPrivate {
     21   // Due to "Standard Layout" rules it is guaranteed that address of the entity
     22   // and its first non-static member are the same.
     23   DecompressorOutput output;
     24 };
     25 
     26 void MaybeMakeCicp(const jxl::extras::PackedPixelFile& ppf,
     27                    std::vector<uint8_t>* cicp) {
     28   cicp->clear();
     29   const JxlColorEncoding& clr = ppf.color_encoding;
     30   uint8_t color_primaries = 0;
     31   uint8_t transfer_function = static_cast<uint8_t>(clr.transfer_function);
     32 
     33   if (clr.color_space != JXL_COLOR_SPACE_RGB) {
     34     return;
     35   }
     36   if (clr.primaries == JXL_PRIMARIES_P3) {
     37     if (clr.white_point == JXL_WHITE_POINT_D65) {
     38       color_primaries = 12;
     39     } else if (clr.white_point == JXL_WHITE_POINT_DCI) {
     40       color_primaries = 11;
     41     } else {
     42       return;
     43     }
     44   } else if (clr.primaries != JXL_PRIMARIES_CUSTOM &&
     45              clr.white_point == JXL_WHITE_POINT_D65) {
     46     color_primaries = static_cast<uint8_t>(clr.primaries);
     47   } else {
     48     return;
     49   }
     50   if (clr.transfer_function == JXL_TRANSFER_FUNCTION_UNKNOWN ||
     51       clr.transfer_function == JXL_TRANSFER_FUNCTION_GAMMA) {
     52     return;
     53   }
     54 
     55   cicp->resize(4);
     56   cicp->at(0) = color_primaries;    // Colour Primaries
     57   cicp->at(1) = transfer_function;  // Transfer Function
     58   cicp->at(2) = 0;                  // Matrix Coefficients
     59   cicp->at(3) = 1;                  // Video Full Range Flag
     60 }
     61 
     62 }  // namespace
     63 
     64 DecompressorOutput* jxlDecompress(const uint8_t* input, size_t input_size) {
     65   DecompressorOutputPrivate* self = new DecompressorOutputPrivate();
     66 
     67   if (!self) {
     68     return nullptr;
     69   }
     70 
     71   auto report_error = [&](uint32_t code, const char* text) {
     72     fprintf(stderr, "%s\n", text);
     73     delete self;
     74     return reinterpret_cast<DecompressorOutput*>(code);
     75   };
     76 
     77   auto thread_pool = JxlThreadParallelRunnerMake(nullptr, 4);
     78   void* runner = thread_pool.get();
     79 
     80   jxl::extras::JXLDecompressParams dparams;
     81   JxlPixelFormat format = {/* num_channels */ 3, JXL_TYPE_UINT16,
     82                            JXL_BIG_ENDIAN, /* align */ 0};
     83   dparams.accepted_formats.push_back(format);
     84   dparams.runner = JxlThreadParallelRunner;
     85   dparams.runner_opaque = runner;
     86   jxl::extras::PackedPixelFile ppf;
     87 
     88   if (!jxl::extras::DecodeImageJXL(input, input_size, dparams, nullptr, &ppf)) {
     89     return report_error(1, "failed to decode jxl");
     90   }
     91 
     92   // Just 1-st frame.
     93   const auto& image = ppf.frames[0].color;
     94   std::vector<uint8_t> cicp;
     95   MaybeMakeCicp(ppf, &cicp);
     96   self->output.data = WrapPixelsToPng(
     97       image.xsize, image.ysize, (format.data_type == JXL_TYPE_UINT16) ? 16 : 8,
     98       /* has_alpha */ false, reinterpret_cast<const uint8_t*>(image.pixels()),
     99       ppf.icc, cicp, &self->output.size);
    100   if (!self->output.data) {
    101     return report_error(2, "failed to encode png");
    102   }
    103 
    104   return &self->output;
    105 }
    106 
    107 void jxlCleanup(DecompressorOutput* output) {
    108   if (output == nullptr) return;
    109   DecompressorOutputPrivate* self =
    110       reinterpret_cast<DecompressorOutputPrivate*>(output);
    111   if (self->output.data) {
    112     free(self->output.data);
    113   }
    114   delete self;
    115 }
    116 
    117 }  // extern "C"