Coverage Report

Created: 2022-08-24 06:04

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