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_