libjxl

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

quantizer.h (5855B)


      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 #ifndef LIB_JXL_QUANTIZER_H_
      7 #define LIB_JXL_QUANTIZER_H_
      8 
      9 #include <stddef.h>
     10 #include <stdint.h>
     11 #include <stdlib.h>
     12 
     13 #include <algorithm>
     14 #include <cmath>
     15 #include <utility>
     16 #include <vector>
     17 
     18 #include "lib/jxl/ac_strategy.h"
     19 #include "lib/jxl/base/bits.h"
     20 #include "lib/jxl/base/compiler_specific.h"
     21 #include "lib/jxl/base/status.h"
     22 #include "lib/jxl/dct_util.h"
     23 #include "lib/jxl/dec_bit_reader.h"
     24 #include "lib/jxl/fields.h"
     25 #include "lib/jxl/image.h"
     26 #include "lib/jxl/quant_weights.h"
     27 
     28 // Quantizes DC and AC coefficients, with separate quantization tables according
     29 // to the quant_kind (which is currently computed from the AC strategy and the
     30 // block index inside that strategy).
     31 
     32 namespace jxl {
     33 
     34 static constexpr int kGlobalScaleDenom = 1 << 16;
     35 static constexpr int kGlobalScaleNumerator = 4096;
     36 
     37 // zero-biases for quantizing channels X, Y, B
     38 static constexpr float kZeroBiasDefault[3] = {0.5f, 0.5f, 0.5f};
     39 
     40 // Returns adjusted version of a quantized integer, such that its value is
     41 // closer to the expected value of the original.
     42 // The residuals of AC coefficients that we quantize are not uniformly
     43 // distributed. Numerical experiments show that they have a distribution with
     44 // the "shape" of 1/(1+x^2) [up to some coefficients]. This means that the
     45 // expected value of a coefficient that gets quantized to x will not be x
     46 // itself, but (at least with reasonable approximation):
     47 // - 0 if x is 0
     48 // - x * biases[c] if x is 1 or -1
     49 // - x - biases[3]/x otherwise
     50 // This follows from computing the distribution of the quantization bias, which
     51 // can be approximated fairly well by <constant>/x when |x| is at least two.
     52 static constexpr float kBiasNumerator = 0.145f;
     53 
     54 static constexpr float kDefaultQuantBias[4] = {
     55     1.0f - 0.05465007330715401f,
     56     1.0f - 0.07005449891748593f,
     57     1.0f - 0.049935103337343655f,
     58     0.145f,
     59 };
     60 
     61 struct QuantizerParams;
     62 
     63 class Quantizer {
     64  public:
     65   explicit Quantizer(const DequantMatrices* dequant);
     66   Quantizer(const DequantMatrices* dequant, int quant_dc, int global_scale);
     67 
     68   static constexpr int32_t kQuantMax = 256;
     69 
     70   static JXL_INLINE int32_t ClampVal(float val) {
     71     return static_cast<int32_t>(
     72         std::max(1.0f, std::min<float>(val, kQuantMax)));
     73   }
     74 
     75   float ScaleGlobalScale(const float scale) {
     76     int new_global_scale = static_cast<int>(std::lround(global_scale_ * scale));
     77     float scale_out = new_global_scale * 1.0f / global_scale_;
     78     global_scale_ = new_global_scale;
     79     RecomputeFromGlobalScale();
     80     return scale_out;
     81   }
     82 
     83   // Recomputes other derived fields after global_scale_ has changed.
     84   void RecomputeFromGlobalScale() {
     85     global_scale_float_ = global_scale_ * (1.0 / kGlobalScaleDenom);
     86     inv_global_scale_ = 1.0 * kGlobalScaleDenom / global_scale_;
     87     inv_quant_dc_ = inv_global_scale_ / quant_dc_;
     88     for (size_t c = 0; c < 3; c++) {
     89       mul_dc_[c] = GetDcStep(c);
     90       inv_mul_dc_[c] = GetInvDcStep(c);
     91     }
     92   }
     93 
     94   // Returns scaling factor such that Scale() * (RawDC() or RawQuantField())
     95   // pixels yields the same float values returned by GetQuantField.
     96   JXL_INLINE float Scale() const { return global_scale_float_; }
     97 
     98   // Reciprocal of Scale().
     99   JXL_INLINE float InvGlobalScale() const { return inv_global_scale_; }
    100 
    101   void SetQuantFieldRect(const ImageF& qf, const Rect& rect,
    102                          ImageI* JXL_RESTRICT raw_quant_field) const;
    103 
    104   void SetQuantField(float quant_dc, const ImageF& qf,
    105                      ImageI* JXL_RESTRICT raw_quant_field);
    106 
    107   void SetQuant(float quant_dc, float quant_ac,
    108                 ImageI* JXL_RESTRICT raw_quant_field);
    109 
    110   // Returns the DC quantization base value, which is currently global (not
    111   // adaptive). The actual scale factor used to dequantize pixels in channel c
    112   // is: inv_quant_dc() * dequant_->DCQuant(c).
    113   float inv_quant_dc() const { return inv_quant_dc_; }
    114 
    115   // Dequantize by multiplying with this times dequant_matrix.
    116   float inv_quant_ac(int32_t quant) const { return inv_global_scale_ / quant; }
    117 
    118   QuantizerParams GetParams() const;
    119 
    120   Status Decode(BitReader* reader);
    121 
    122   void DumpQuantizationMap(const ImageI& raw_quant_field) const;
    123 
    124   JXL_INLINE const float* DequantMatrix(size_t quant_kind, size_t c) const {
    125     return dequant_->Matrix(quant_kind, c);
    126   }
    127 
    128   JXL_INLINE const float* InvDequantMatrix(size_t quant_kind, size_t c) const {
    129     return dequant_->InvMatrix(quant_kind, c);
    130   }
    131 
    132   // Calculates DC quantization step.
    133   JXL_INLINE float GetDcStep(size_t c) const {
    134     return inv_quant_dc_ * dequant_->DCQuant(c);
    135   }
    136   JXL_INLINE float GetInvDcStep(size_t c) const {
    137     return dequant_->InvDCQuant(c) * (global_scale_float_ * quant_dc_);
    138   }
    139 
    140   JXL_INLINE const float* MulDC() const { return mul_dc_; }
    141   JXL_INLINE const float* InvMulDC() const { return inv_mul_dc_; }
    142 
    143   JXL_INLINE void ClearDCMul() {
    144     std::fill(mul_dc_, mul_dc_ + 4, 1.f);
    145     std::fill(inv_mul_dc_, inv_mul_dc_ + 4, 1.f);
    146   }
    147 
    148   void ComputeGlobalScaleAndQuant(float quant_dc, float quant_median,
    149                                   float quant_median_absd);
    150 
    151  private:
    152   float mul_dc_[4];
    153   float inv_mul_dc_[4];
    154 
    155   // These are serialized:
    156   int global_scale_;
    157   int quant_dc_;
    158 
    159   // These are derived from global_scale_:
    160   float inv_global_scale_;
    161   float global_scale_float_;  // reciprocal of inv_global_scale_
    162   float inv_quant_dc_;
    163 
    164   float zero_bias_[3];
    165   const DequantMatrices* dequant_;
    166 };
    167 
    168 struct QuantizerParams : public Fields {
    169   QuantizerParams() { Bundle::Init(this); }
    170   JXL_FIELDS_NAME(QuantizerParams)
    171 
    172   Status VisitFields(Visitor* JXL_RESTRICT visitor) override;
    173 
    174   uint32_t global_scale;
    175   uint32_t quant_dc;
    176 };
    177 
    178 }  // namespace jxl
    179 
    180 #endif  // LIB_JXL_QUANTIZER_H_