Coverage Report

Created: 2026-10-28 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libjxl/lib/jxl/quant_weights.cc
Line
Count
Source
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
#include "lib/jxl/quant_weights.h"
6
7
#include <jxl/memory_manager.h>
8
9
#include <cmath>
10
#include <cstdint>
11
#include <cstdio>
12
#include <cstdlib>
13
#include <vector>
14
15
#include "lib/jxl/ac_strategy.h"
16
#include "lib/jxl/base/compiler_specific.h"
17
#include "lib/jxl/base/status.h"
18
#include "lib/jxl/coeff_order_fwd.h"
19
#include "lib/jxl/dct_scales.h"
20
#include "lib/jxl/dec_bit_reader.h"
21
#include "lib/jxl/dec_modular.h"
22
#include "lib/jxl/fields.h"
23
#include "lib/jxl/frame_dimensions.h"
24
#include "lib/jxl/memory_manager_internal.h"
25
26
#undef HWY_TARGET_INCLUDE
27
#define HWY_TARGET_INCLUDE "lib/jxl/quant_weights.cc"
28
#include <hwy/foreach_target.h>
29
#include <hwy/highway.h>
30
31
#include "lib/jxl/base/fast_math-inl.h"
32
33
HWY_BEFORE_NAMESPACE();
34
namespace jxl {
35
namespace HWY_NAMESPACE {
36
37
// These templates are not found via ADL.
38
using hwy::HWY_NAMESPACE::Lt;
39
using hwy::HWY_NAMESPACE::MulAdd;
40
using hwy::HWY_NAMESPACE::Sqrt;
41
42
// kQuantWeights[N * N * c + N * y + x] is the relative weight of the (x, y)
43
// coefficient in component c. Higher weights correspond to finer quantization
44
// intervals and more bits spent in encoding.
45
46
static constexpr const float kAlmostZero = 1e-8f;
47
48
void GetQuantWeightsDCT2(const QuantEncoding::DCT2Weights& dct2weights,
49
7.18k
                         float* weights) {
50
28.7k
  for (size_t c = 0; c < 3; c++) {
51
21.5k
    size_t start = c * 64;
52
21.5k
    weights[start] = 0xBAD;
53
21.5k
    weights[start + 1] = weights[start + 8] = dct2weights[c][0];
54
21.5k
    weights[start + 9] = dct2weights[c][1];
55
64.6k
    for (size_t y = 0; y < 2; y++) {
56
129k
      for (size_t x = 0; x < 2; x++) {
57
86.1k
        weights[start + y * 8 + x + 2] = dct2weights[c][2];
58
86.1k
        weights[start + (y + 2) * 8 + x] = dct2weights[c][2];
59
86.1k
      }
60
43.0k
    }
61
64.6k
    for (size_t y = 0; y < 2; y++) {
62
129k
      for (size_t x = 0; x < 2; x++) {
63
86.1k
        weights[start + (y + 2) * 8 + x + 2] = dct2weights[c][3];
64
86.1k
      }
65
43.0k
    }
66
107k
    for (size_t y = 0; y < 4; y++) {
67
430k
      for (size_t x = 0; x < 4; x++) {
68
344k
        weights[start + y * 8 + x + 4] = dct2weights[c][4];
69
344k
        weights[start + (y + 4) * 8 + x] = dct2weights[c][4];
70
344k
      }
71
86.1k
    }
72
107k
    for (size_t y = 0; y < 4; y++) {
73
430k
      for (size_t x = 0; x < 4; x++) {
74
344k
        weights[start + (y + 4) * 8 + x + 4] = dct2weights[c][5];
75
344k
      }
76
86.1k
    }
77
21.5k
  }
78
7.18k
}
Unexecuted instantiation: jxl::N_SSE4::GetQuantWeightsDCT2(std::__1::array<std::__1::array<float, 6ul>, 3ul> const&, float*)
jxl::N_AVX2::GetQuantWeightsDCT2(std::__1::array<std::__1::array<float, 6ul>, 3ul> const&, float*)
Line
Count
Source
49
7.18k
                         float* weights) {
50
28.7k
  for (size_t c = 0; c < 3; c++) {
51
21.5k
    size_t start = c * 64;
52
21.5k
    weights[start] = 0xBAD;
53
21.5k
    weights[start + 1] = weights[start + 8] = dct2weights[c][0];
54
21.5k
    weights[start + 9] = dct2weights[c][1];
55
64.6k
    for (size_t y = 0; y < 2; y++) {
56
129k
      for (size_t x = 0; x < 2; x++) {
57
86.1k
        weights[start + y * 8 + x + 2] = dct2weights[c][2];
58
86.1k
        weights[start + (y + 2) * 8 + x] = dct2weights[c][2];
59
86.1k
      }
60
43.0k
    }
61
64.6k
    for (size_t y = 0; y < 2; y++) {
62
129k
      for (size_t x = 0; x < 2; x++) {
63
86.1k
        weights[start + (y + 2) * 8 + x + 2] = dct2weights[c][3];
64
86.1k
      }
65
43.0k
    }
66
107k
    for (size_t y = 0; y < 4; y++) {
67
430k
      for (size_t x = 0; x < 4; x++) {
68
344k
        weights[start + y * 8 + x + 4] = dct2weights[c][4];
69
344k
        weights[start + (y + 4) * 8 + x] = dct2weights[c][4];
70
344k
      }
71
86.1k
    }
72
107k
    for (size_t y = 0; y < 4; y++) {
73
430k
      for (size_t x = 0; x < 4; x++) {
74
344k
        weights[start + (y + 4) * 8 + x + 4] = dct2weights[c][5];
75
344k
      }
76
86.1k
    }
77
21.5k
  }
78
7.18k
}
Unexecuted instantiation: jxl::N_AVX3::GetQuantWeightsDCT2(std::__1::array<std::__1::array<float, 6ul>, 3ul> const&, float*)
Unexecuted instantiation: jxl::N_AVX3_ZEN4::GetQuantWeightsDCT2(std::__1::array<std::__1::array<float, 6ul>, 3ul> const&, float*)
Unexecuted instantiation: jxl::N_AVX3_SPR::GetQuantWeightsDCT2(std::__1::array<std::__1::array<float, 6ul>, 3ul> const&, float*)
Unexecuted instantiation: jxl::N_SSE2::GetQuantWeightsDCT2(std::__1::array<std::__1::array<float, 6ul>, 3ul> const&, float*)
79
80
void GetQuantWeightsIdentity(const QuantEncoding::IdWeights& idweights,
81
12.1k
                             float* weights) {
82
48.5k
  for (size_t c = 0; c < 3; c++) {
83
2.36M
    for (int i = 0; i < 64; i++) {
84
2.33M
      weights[64 * c + i] = idweights[c][0];
85
2.33M
    }
86
36.4k
    weights[64 * c + 1] = idweights[c][1];
87
36.4k
    weights[64 * c + 8] = idweights[c][1];
88
36.4k
    weights[64 * c + 9] = idweights[c][2];
89
36.4k
  }
90
12.1k
}
Unexecuted instantiation: jxl::N_SSE4::GetQuantWeightsIdentity(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, float*)
jxl::N_AVX2::GetQuantWeightsIdentity(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, float*)
Line
Count
Source
81
12.1k
                             float* weights) {
82
48.5k
  for (size_t c = 0; c < 3; c++) {
83
2.36M
    for (int i = 0; i < 64; i++) {
84
2.33M
      weights[64 * c + i] = idweights[c][0];
85
2.33M
    }
86
36.4k
    weights[64 * c + 1] = idweights[c][1];
87
36.4k
    weights[64 * c + 8] = idweights[c][1];
88
36.4k
    weights[64 * c + 9] = idweights[c][2];
89
36.4k
  }
90
12.1k
}
Unexecuted instantiation: jxl::N_AVX3::GetQuantWeightsIdentity(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, float*)
Unexecuted instantiation: jxl::N_AVX3_ZEN4::GetQuantWeightsIdentity(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, float*)
Unexecuted instantiation: jxl::N_AVX3_SPR::GetQuantWeightsIdentity(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, float*)
Unexecuted instantiation: jxl::N_SSE2::GetQuantWeightsIdentity(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, float*)
91
92
StatusOr<float> Interpolate(float pos, float max, const float* array,
93
341k
                            size_t len) {
94
341k
  float scaled_pos = pos * (len - 1) / max;
95
341k
  size_t idx = scaled_pos;
96
341k
  JXL_ENSURE(idx + 1 < len);
97
341k
  float a = array[idx];
98
341k
  float b = array[idx + 1];
99
341k
  return a * FastPowf(b / a, scaled_pos - idx);
100
341k
}
Unexecuted instantiation: jxl::N_SSE4::Interpolate(float, float, float const*, unsigned long)
jxl::N_AVX2::Interpolate(float, float, float const*, unsigned long)
Line
Count
Source
93
341k
                            size_t len) {
94
341k
  float scaled_pos = pos * (len - 1) / max;
95
341k
  size_t idx = scaled_pos;
96
341k
  JXL_ENSURE(idx + 1 < len);
97
341k
  float a = array[idx];
98
341k
  float b = array[idx + 1];
99
341k
  return a * FastPowf(b / a, scaled_pos - idx);
100
341k
}
Unexecuted instantiation: jxl::N_AVX3::Interpolate(float, float, float const*, unsigned long)
Unexecuted instantiation: jxl::N_AVX3_ZEN4::Interpolate(float, float, float const*, unsigned long)
Unexecuted instantiation: jxl::N_AVX3_SPR::Interpolate(float, float, float const*, unsigned long)
Unexecuted instantiation: jxl::N_SSE2::Interpolate(float, float, float const*, unsigned long)
101
102
1.74M
float Mult(float v) {
103
1.74M
  if (v > 0.0f) return 1.0f + v;
104
1.74M
  return 1.0f / (1.0f - v);
105
1.74M
}
Unexecuted instantiation: jxl::N_SSE4::Mult(float)
jxl::N_AVX2::Mult(float)
Line
Count
Source
102
1.74M
float Mult(float v) {
103
1.74M
  if (v > 0.0f) return 1.0f + v;
104
1.74M
  return 1.0f / (1.0f - v);
105
1.74M
}
Unexecuted instantiation: jxl::N_AVX3::Mult(float)
Unexecuted instantiation: jxl::N_AVX3_ZEN4::Mult(float)
Unexecuted instantiation: jxl::N_AVX3_SPR::Mult(float)
Unexecuted instantiation: jxl::N_SSE2::Mult(float)
106
107
using DF4 = HWY_CAPPED(float, 4);
108
109
hwy::HWY_NAMESPACE::Vec<DF4> InterpolateVec(
110
39.3M
    hwy::HWY_NAMESPACE::Vec<DF4> scaled_pos, const float* array) {
111
39.3M
  HWY_CAPPED(int32_t, 4) di;
112
113
39.3M
  auto idx = ConvertTo(di, scaled_pos);
114
115
39.3M
  auto frac = Sub(scaled_pos, ConvertTo(DF4(), idx));
116
117
  // TODO(veluca): in theory, this could be done with 8 TableLookupBytes, but
118
  // it's probably slower.
119
39.3M
  auto a = GatherIndex(DF4(), array, idx);
120
39.3M
  auto b = GatherIndex(DF4(), array + 1, idx);
121
122
39.3M
  return Mul(a, FastPowf(DF4(), Div(b, a), frac));
123
39.3M
}
Unexecuted instantiation: jxl::N_SSE4::InterpolateVec(hwy::N_SSE4::Vec128<float, 4ul>, float const*)
jxl::N_AVX2::InterpolateVec(hwy::N_AVX2::Vec128<float, 4ul>, float const*)
Line
Count
Source
110
39.3M
    hwy::HWY_NAMESPACE::Vec<DF4> scaled_pos, const float* array) {
111
39.3M
  HWY_CAPPED(int32_t, 4) di;
112
113
39.3M
  auto idx = ConvertTo(di, scaled_pos);
114
115
39.3M
  auto frac = Sub(scaled_pos, ConvertTo(DF4(), idx));
116
117
  // TODO(veluca): in theory, this could be done with 8 TableLookupBytes, but
118
  // it's probably slower.
119
39.3M
  auto a = GatherIndex(DF4(), array, idx);
120
39.3M
  auto b = GatherIndex(DF4(), array + 1, idx);
121
122
39.3M
  return Mul(a, FastPowf(DF4(), Div(b, a), frac));
123
39.3M
}
Unexecuted instantiation: jxl::N_AVX3::InterpolateVec(hwy::N_AVX3::Vec128<float, 4ul>, float const*)
Unexecuted instantiation: jxl::N_AVX3_ZEN4::InterpolateVec(hwy::N_AVX3_ZEN4::Vec128<float, 4ul>, float const*)
Unexecuted instantiation: jxl::N_AVX3_SPR::InterpolateVec(hwy::N_AVX3_SPR::Vec128<float, 4ul>, float const*)
Unexecuted instantiation: jxl::N_SSE2::InterpolateVec(hwy::N_SSE2::Vec128<float, 4ul>, float const*)
124
125
// Computes quant weights for a COLS*ROWS-sized transform, using num_bands
126
// eccentricity bands and num_ebands eccentricity bands. If print_mode is 1,
127
// prints the resulting matrix; if print_mode is 2, prints the matrix in a
128
// format suitable for a 3d plot with gnuplot.
129
Status GetQuantWeights(
130
    size_t ROWS, size_t COLS,
131
    const DctQuantWeightParams::DistanceBandsArray& distance_bands,
132
107k
    size_t num_bands, float* out) {
133
429k
  for (size_t c = 0; c < 3; c++) {
134
322k
    float bands[DctQuantWeightParams::kMaxDistanceBands] = {
135
322k
        distance_bands[c][0]};
136
322k
    if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
137
1.97M
    for (size_t i = 1; i < num_bands; i++) {
138
1.65M
      bands[i] = bands[i - 1] * Mult(distance_bands[c][i]);
139
1.65M
      if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
140
1.65M
    }
141
322k
    float scale = (num_bands - 1) / (kSqrt2 + 1e-6f);
142
322k
    float rcpcol = scale / (COLS - 1);
143
322k
    float rcprow = scale / (ROWS - 1);
144
322k
    JXL_ENSURE(COLS >= Lanes(DF4()));
145
322k
    HWY_ALIGN float l0123[4] = {0, 1, 2, 3};
146
4.65M
    for (uint32_t y = 0; y < ROWS; y++) {
147
4.32M
      float dy = y * rcprow;
148
4.32M
      float dy2 = dy * dy;
149
43.7M
      for (uint32_t x = 0; x < COLS; x += Lanes(DF4())) {
150
39.3M
        auto dx =
151
39.3M
            Mul(Add(Set(DF4(), x), Load(DF4(), l0123)), Set(DF4(), rcpcol));
152
39.3M
        auto scaled_distance = Sqrt(MulAdd(dx, dx, Set(DF4(), dy2)));
153
39.3M
        auto weight = num_bands == 1 ? Set(DF4(), bands[0])
154
39.3M
                                     : InterpolateVec(scaled_distance, bands);
155
39.3M
        StoreU(weight, DF4(), out + c * COLS * ROWS + y * COLS + x);
156
39.3M
      }
157
4.32M
    }
158
322k
  }
159
107k
  return true;
160
107k
}
Unexecuted instantiation: jxl::N_SSE4::GetQuantWeights(unsigned long, unsigned long, std::__1::array<std::__1::array<float, 17ul>, 3ul> const&, unsigned long, float*)
jxl::N_AVX2::GetQuantWeights(unsigned long, unsigned long, std::__1::array<std::__1::array<float, 17ul>, 3ul> const&, unsigned long, float*)
Line
Count
Source
132
107k
    size_t num_bands, float* out) {
133
429k
  for (size_t c = 0; c < 3; c++) {
134
322k
    float bands[DctQuantWeightParams::kMaxDistanceBands] = {
135
322k
        distance_bands[c][0]};
136
322k
    if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
137
1.97M
    for (size_t i = 1; i < num_bands; i++) {
138
1.65M
      bands[i] = bands[i - 1] * Mult(distance_bands[c][i]);
139
1.65M
      if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
140
1.65M
    }
141
322k
    float scale = (num_bands - 1) / (kSqrt2 + 1e-6f);
142
322k
    float rcpcol = scale / (COLS - 1);
143
322k
    float rcprow = scale / (ROWS - 1);
144
322k
    JXL_ENSURE(COLS >= Lanes(DF4()));
145
322k
    HWY_ALIGN float l0123[4] = {0, 1, 2, 3};
146
4.65M
    for (uint32_t y = 0; y < ROWS; y++) {
147
4.32M
      float dy = y * rcprow;
148
4.32M
      float dy2 = dy * dy;
149
43.7M
      for (uint32_t x = 0; x < COLS; x += Lanes(DF4())) {
150
39.3M
        auto dx =
151
39.3M
            Mul(Add(Set(DF4(), x), Load(DF4(), l0123)), Set(DF4(), rcpcol));
152
39.3M
        auto scaled_distance = Sqrt(MulAdd(dx, dx, Set(DF4(), dy2)));
153
39.3M
        auto weight = num_bands == 1 ? Set(DF4(), bands[0])
154
39.3M
                                     : InterpolateVec(scaled_distance, bands);
155
39.3M
        StoreU(weight, DF4(), out + c * COLS * ROWS + y * COLS + x);
156
39.3M
      }
157
4.32M
    }
158
322k
  }
159
107k
  return true;
160
107k
}
Unexecuted instantiation: jxl::N_AVX3::GetQuantWeights(unsigned long, unsigned long, std::__1::array<std::__1::array<float, 17ul>, 3ul> const&, unsigned long, float*)
Unexecuted instantiation: jxl::N_AVX3_ZEN4::GetQuantWeights(unsigned long, unsigned long, std::__1::array<std::__1::array<float, 17ul>, 3ul> const&, unsigned long, float*)
Unexecuted instantiation: jxl::N_AVX3_SPR::GetQuantWeights(unsigned long, unsigned long, std::__1::array<std::__1::array<float, 17ul>, 3ul> const&, unsigned long, float*)
Unexecuted instantiation: jxl::N_SSE2::GetQuantWeights(unsigned long, unsigned long, std::__1::array<std::__1::array<float, 17ul>, 3ul> const&, unsigned long, float*)
161
162
// TODO(veluca): SIMD-fy. With 256x256, this is actually slow.
163
Status ComputeQuantTable(const QuantEncoding& encoding,
164
                         float* JXL_RESTRICT table,
165
                         float* JXL_RESTRICT inv_table, size_t table_num,
166
117k
                         QuantTable kind, size_t* pos) {
167
117k
  constexpr size_t N = kBlockDim;
168
117k
  size_t quant_table_idx = static_cast<size_t>(kind);
169
117k
  size_t wrows = 8 * DequantMatrices::required_size_x[quant_table_idx];
170
117k
  size_t wcols = 8 * DequantMatrices::required_size_y[quant_table_idx];
171
117k
  size_t num = wrows * wcols;
172
173
117k
  std::vector<float> weights(3 * num);
174
175
117k
  switch (encoding.mode) {
176
0
    case QuantEncoding::kQuantModeLibrary: {
177
      // Library and copy quant encoding should get replaced by the actual
178
      // parameters by the caller.
179
0
      JXL_ENSURE(false);
180
0
      break;
181
0
    }
182
12.1k
    case QuantEncoding::kQuantModeID: {
183
12.1k
      JXL_ENSURE(num == kDCTBlockSize);
184
12.1k
      GetQuantWeightsIdentity(encoding.idweights, weights.data());
185
12.1k
      break;
186
12.1k
    }
187
7.18k
    case QuantEncoding::kQuantModeDCT2: {
188
7.18k
      JXL_ENSURE(num == kDCTBlockSize);
189
7.18k
      GetQuantWeightsDCT2(encoding.dct2weights, weights.data());
190
7.18k
      break;
191
7.18k
    }
192
5.28k
    case QuantEncoding::kQuantModeDCT4: {
193
5.28k
      JXL_ENSURE(num == kDCTBlockSize);
194
5.28k
      float weights4x4[3 * 4 * 4];
195
      // Always use 4x4 GetQuantWeights for DCT4 quantization tables.
196
5.28k
      JXL_RETURN_IF_ERROR(
197
5.28k
          GetQuantWeights(4, 4, encoding.dct_params.distance_bands,
198
5.28k
                          encoding.dct_params.num_distance_bands, weights4x4));
199
21.1k
      for (size_t c = 0; c < 3; c++) {
200
142k
        for (size_t y = 0; y < kBlockDim; y++) {
201
1.14M
          for (size_t x = 0; x < kBlockDim; x++) {
202
1.01M
            weights[c * num + y * kBlockDim + x] =
203
1.01M
                weights4x4[c * 16 + (y / 2) * 4 + (x / 2)];
204
1.01M
          }
205
126k
        }
206
15.8k
        weights[c * num + 1] /= encoding.dct4multipliers[c][0];
207
15.8k
        weights[c * num + N] /= encoding.dct4multipliers[c][0];
208
15.8k
        weights[c * num + N + 1] /= encoding.dct4multipliers[c][1];
209
15.8k
      }
210
5.28k
      break;
211
5.28k
    }
212
6.71k
    case QuantEncoding::kQuantModeDCT4X8: {
213
6.71k
      JXL_ENSURE(num == kDCTBlockSize);
214
6.71k
      float weights4x8[3 * 4 * 8];
215
      // Always use 4x8 GetQuantWeights for DCT4X8 quantization tables.
216
6.71k
      JXL_RETURN_IF_ERROR(
217
6.71k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
218
6.71k
                          encoding.dct_params.num_distance_bands, weights4x8));
219
26.8k
      for (size_t c = 0; c < 3; c++) {
220
181k
        for (size_t y = 0; y < kBlockDim; y++) {
221
1.44M
          for (size_t x = 0; x < kBlockDim; x++) {
222
1.28M
            weights[c * num + y * kBlockDim + x] =
223
1.28M
                weights4x8[c * 32 + (y / 2) * 8 + x];
224
1.28M
          }
225
161k
        }
226
20.1k
        weights[c * num + N] /= encoding.dct4x8multipliers[c];
227
20.1k
      }
228
6.71k
      break;
229
6.71k
    }
230
76.3k
    case QuantEncoding::kQuantModeDCT: {
231
76.3k
      JXL_RETURN_IF_ERROR(GetQuantWeights(
232
76.3k
          wrows, wcols, encoding.dct_params.distance_bands,
233
76.3k
          encoding.dct_params.num_distance_bands, weights.data()));
234
76.3k
      break;
235
76.3k
    }
236
76.3k
    case QuantEncoding::kQuantModeRAW: {
237
4
      if (!encoding.qraw.qtable || encoding.qraw.qtable->size() != 3 * num) {
238
0
        return JXL_FAILURE("Invalid table encoding");
239
0
      }
240
4
      int* qtable = encoding.qraw.qtable->data();
241
772
      for (size_t i = 0; i < 3 * num; i++) {
242
768
        weights[i] = 1.f / (encoding.qraw.qtable_den * qtable[i]);
243
768
      }
244
4
      break;
245
4
    }
246
9.50k
    case QuantEncoding::kQuantModeAFV: {
247
9.50k
      constexpr float kFreqs[] = {
248
9.50k
          0xBAD,
249
9.50k
          0xBAD,
250
9.50k
          0.8517778890324296,
251
9.50k
          5.37778436506804,
252
9.50k
          0xBAD,
253
9.50k
          0xBAD,
254
9.50k
          4.734747904497923,
255
9.50k
          5.449245381693219,
256
9.50k
          1.6598270267479331,
257
9.50k
          4,
258
9.50k
          7.275749096817861,
259
9.50k
          10.423227632456525,
260
9.50k
          2.662932286148962,
261
9.50k
          7.630657783650829,
262
9.50k
          8.962388608184032,
263
9.50k
          12.97166202570235,
264
9.50k
      };
265
266
9.50k
      float weights4x8[3 * 4 * 8];
267
9.50k
      JXL_RETURN_IF_ERROR((
268
9.50k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
269
9.50k
                          encoding.dct_params.num_distance_bands, weights4x8)));
270
9.50k
      float weights4x4[3 * 4 * 4];
271
9.50k
      JXL_RETURN_IF_ERROR((GetQuantWeights(
272
9.50k
          4, 4, encoding.dct_params_afv_4x4.distance_bands,
273
9.50k
          encoding.dct_params_afv_4x4.num_distance_bands, weights4x4)));
274
275
9.49k
      constexpr float lo = 0.8517778890324296;
276
9.49k
      constexpr float hi = 12.97166202570235f - lo + 1e-6f;
277
37.9k
      for (size_t c = 0; c < 3; c++) {
278
28.4k
        float bands[4];
279
28.4k
        bands[0] = encoding.afv_weights[c][5];
280
28.4k
        if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
281
113k
        for (size_t i = 1; i < 4; i++) {
282
85.4k
          bands[i] = bands[i - 1] * Mult(encoding.afv_weights[c][i + 5]);
283
85.4k
          if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
284
85.4k
        }
285
28.4k
        size_t start = c * 64;
286
484k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
484k
          weights[start + y * 8 + x] = val;
288
484k
        };
Unexecuted instantiation: quant_weights.cc:jxl::N_SSE4::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)::$_0::operator()(unsigned long, unsigned long, float) const
quant_weights.cc:jxl::N_AVX2::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)::$_0::operator()(unsigned long, unsigned long, float) const
Line
Count
Source
286
484k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
484k
          weights[start + y * 8 + x] = val;
288
484k
        };
Unexecuted instantiation: quant_weights.cc:jxl::N_AVX3::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)::$_0::operator()(unsigned long, unsigned long, float) const
Unexecuted instantiation: quant_weights.cc:jxl::N_AVX3_ZEN4::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)::$_0::operator()(unsigned long, unsigned long, float) const
Unexecuted instantiation: quant_weights.cc:jxl::N_AVX3_SPR::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)::$_0::operator()(unsigned long, unsigned long, float) const
Unexecuted instantiation: quant_weights.cc:jxl::N_SSE2::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)::$_0::operator()(unsigned long, unsigned long, float) const
289
28.4k
        weights[start] = 1;  // Not used, but causes MSAN error otherwise.
290
        // Weights for (0, 1) and (1, 0).
291
28.4k
        set_weight(0, 1, encoding.afv_weights[c][0]);
292
28.4k
        set_weight(1, 0, encoding.afv_weights[c][1]);
293
        // AFV special weights for 3-pixel corner.
294
28.4k
        set_weight(0, 2, encoding.afv_weights[c][2]);
295
28.4k
        set_weight(2, 0, encoding.afv_weights[c][3]);
296
28.4k
        set_weight(2, 2, encoding.afv_weights[c][4]);
297
298
        // All other AFV weights.
299
142k
        for (size_t y = 0; y < 4; y++) {
300
569k
          for (size_t x = 0; x < 4; x++) {
301
455k
            if (x < 2 && y < 2) continue;
302
683k
            JXL_ASSIGN_OR_RETURN(
303
683k
                float val, Interpolate(kFreqs[y * 4 + x] - lo, hi, bands, 4));
304
683k
            set_weight(2 * x, 2 * y, val);
305
683k
          }
306
113k
        }
307
308
        // Put 4x8 weights in odd rows, except (1, 0).
309
142k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
310
1.02M
          for (size_t x = 0; x < kBlockDim; x++) {
311
911k
            if (x == 0 && y == 0) continue;
312
882k
            weights[c * num + (2 * y + 1) * kBlockDim + x] =
313
882k
                weights4x8[c * 32 + y * 8 + x];
314
882k
          }
315
113k
        }
316
        // Put 4x4 weights in even rows / odd columns, except (0, 1).
317
142k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
318
569k
          for (size_t x = 0; x < kBlockDim / 2; x++) {
319
455k
            if (x == 0 && y == 0) continue;
320
427k
            weights[c * num + (2 * y) * kBlockDim + 2 * x + 1] =
321
427k
                weights4x4[c * 16 + y * 4 + x];
322
427k
          }
323
113k
        }
324
28.4k
      }
325
9.48k
      break;
326
9.49k
    }
327
117k
  }
328
117k
  size_t prev_pos = *pos;
329
117k
  HWY_CAPPED(float, 64) d;
330
20.5M
  for (size_t i = 0; i < num * 3; i += Lanes(d)) {
331
20.3M
    auto inv_val = LoadU(d, weights.data() + i);
332
20.3M
    if (JXL_UNLIKELY(!AllFalse(d, Ge(inv_val, Set(d, 1.0f / kAlmostZero))) ||
333
20.3M
                     !AllFalse(d, Lt(inv_val, Set(d, kAlmostZero))))) {
334
57
      return JXL_FAILURE("Invalid quantization table");
335
57
    }
336
20.3M
    auto val = Div(Set(d, 1.0f), inv_val);
337
20.3M
    StoreU(val, d, table + *pos + i);
338
20.3M
    StoreU(inv_val, d, inv_table + *pos + i);
339
20.3M
  }
340
117k
  (*pos) += 3 * num;
341
342
  // Ensure that the lowest frequencies have a 0 inverse table.
343
  // This does not affect en/decoding, but allows AC strategy selection to be
344
  // slightly simpler.
345
117k
  size_t xs = DequantMatrices::required_size_x[quant_table_idx];
346
117k
  size_t ys = DequantMatrices::required_size_y[quant_table_idx];
347
117k
  CoefficientLayout(&ys, &xs);
348
468k
  for (size_t c = 0; c < 3; c++) {
349
968k
    for (size_t y = 0; y < ys; y++) {
350
3.16M
      for (size_t x = 0; x < xs; x++) {
351
2.54M
        inv_table[prev_pos + c * ys * xs * kDCTBlockSize + y * kBlockDim * xs +
352
2.54M
                  x] = 0;
353
2.54M
      }
354
616k
    }
355
351k
  }
356
117k
  return true;
357
117k
}
Unexecuted instantiation: jxl::N_SSE4::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)
jxl::N_AVX2::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)
Line
Count
Source
166
117k
                         QuantTable kind, size_t* pos) {
167
117k
  constexpr size_t N = kBlockDim;
168
117k
  size_t quant_table_idx = static_cast<size_t>(kind);
169
117k
  size_t wrows = 8 * DequantMatrices::required_size_x[quant_table_idx];
170
117k
  size_t wcols = 8 * DequantMatrices::required_size_y[quant_table_idx];
171
117k
  size_t num = wrows * wcols;
172
173
117k
  std::vector<float> weights(3 * num);
174
175
117k
  switch (encoding.mode) {
176
0
    case QuantEncoding::kQuantModeLibrary: {
177
      // Library and copy quant encoding should get replaced by the actual
178
      // parameters by the caller.
179
0
      JXL_ENSURE(false);
180
0
      break;
181
0
    }
182
12.1k
    case QuantEncoding::kQuantModeID: {
183
12.1k
      JXL_ENSURE(num == kDCTBlockSize);
184
12.1k
      GetQuantWeightsIdentity(encoding.idweights, weights.data());
185
12.1k
      break;
186
12.1k
    }
187
7.18k
    case QuantEncoding::kQuantModeDCT2: {
188
7.18k
      JXL_ENSURE(num == kDCTBlockSize);
189
7.18k
      GetQuantWeightsDCT2(encoding.dct2weights, weights.data());
190
7.18k
      break;
191
7.18k
    }
192
5.28k
    case QuantEncoding::kQuantModeDCT4: {
193
5.28k
      JXL_ENSURE(num == kDCTBlockSize);
194
5.28k
      float weights4x4[3 * 4 * 4];
195
      // Always use 4x4 GetQuantWeights for DCT4 quantization tables.
196
5.28k
      JXL_RETURN_IF_ERROR(
197
5.28k
          GetQuantWeights(4, 4, encoding.dct_params.distance_bands,
198
5.28k
                          encoding.dct_params.num_distance_bands, weights4x4));
199
21.1k
      for (size_t c = 0; c < 3; c++) {
200
142k
        for (size_t y = 0; y < kBlockDim; y++) {
201
1.14M
          for (size_t x = 0; x < kBlockDim; x++) {
202
1.01M
            weights[c * num + y * kBlockDim + x] =
203
1.01M
                weights4x4[c * 16 + (y / 2) * 4 + (x / 2)];
204
1.01M
          }
205
126k
        }
206
15.8k
        weights[c * num + 1] /= encoding.dct4multipliers[c][0];
207
15.8k
        weights[c * num + N] /= encoding.dct4multipliers[c][0];
208
15.8k
        weights[c * num + N + 1] /= encoding.dct4multipliers[c][1];
209
15.8k
      }
210
5.28k
      break;
211
5.28k
    }
212
6.71k
    case QuantEncoding::kQuantModeDCT4X8: {
213
6.71k
      JXL_ENSURE(num == kDCTBlockSize);
214
6.71k
      float weights4x8[3 * 4 * 8];
215
      // Always use 4x8 GetQuantWeights for DCT4X8 quantization tables.
216
6.71k
      JXL_RETURN_IF_ERROR(
217
6.71k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
218
6.71k
                          encoding.dct_params.num_distance_bands, weights4x8));
219
26.8k
      for (size_t c = 0; c < 3; c++) {
220
181k
        for (size_t y = 0; y < kBlockDim; y++) {
221
1.44M
          for (size_t x = 0; x < kBlockDim; x++) {
222
1.28M
            weights[c * num + y * kBlockDim + x] =
223
1.28M
                weights4x8[c * 32 + (y / 2) * 8 + x];
224
1.28M
          }
225
161k
        }
226
20.1k
        weights[c * num + N] /= encoding.dct4x8multipliers[c];
227
20.1k
      }
228
6.71k
      break;
229
6.71k
    }
230
76.3k
    case QuantEncoding::kQuantModeDCT: {
231
76.3k
      JXL_RETURN_IF_ERROR(GetQuantWeights(
232
76.3k
          wrows, wcols, encoding.dct_params.distance_bands,
233
76.3k
          encoding.dct_params.num_distance_bands, weights.data()));
234
76.3k
      break;
235
76.3k
    }
236
76.3k
    case QuantEncoding::kQuantModeRAW: {
237
4
      if (!encoding.qraw.qtable || encoding.qraw.qtable->size() != 3 * num) {
238
0
        return JXL_FAILURE("Invalid table encoding");
239
0
      }
240
4
      int* qtable = encoding.qraw.qtable->data();
241
772
      for (size_t i = 0; i < 3 * num; i++) {
242
768
        weights[i] = 1.f / (encoding.qraw.qtable_den * qtable[i]);
243
768
      }
244
4
      break;
245
4
    }
246
9.50k
    case QuantEncoding::kQuantModeAFV: {
247
9.50k
      constexpr float kFreqs[] = {
248
9.50k
          0xBAD,
249
9.50k
          0xBAD,
250
9.50k
          0.8517778890324296,
251
9.50k
          5.37778436506804,
252
9.50k
          0xBAD,
253
9.50k
          0xBAD,
254
9.50k
          4.734747904497923,
255
9.50k
          5.449245381693219,
256
9.50k
          1.6598270267479331,
257
9.50k
          4,
258
9.50k
          7.275749096817861,
259
9.50k
          10.423227632456525,
260
9.50k
          2.662932286148962,
261
9.50k
          7.630657783650829,
262
9.50k
          8.962388608184032,
263
9.50k
          12.97166202570235,
264
9.50k
      };
265
266
9.50k
      float weights4x8[3 * 4 * 8];
267
9.50k
      JXL_RETURN_IF_ERROR((
268
9.50k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
269
9.50k
                          encoding.dct_params.num_distance_bands, weights4x8)));
270
9.50k
      float weights4x4[3 * 4 * 4];
271
9.50k
      JXL_RETURN_IF_ERROR((GetQuantWeights(
272
9.50k
          4, 4, encoding.dct_params_afv_4x4.distance_bands,
273
9.50k
          encoding.dct_params_afv_4x4.num_distance_bands, weights4x4)));
274
275
9.49k
      constexpr float lo = 0.8517778890324296;
276
9.49k
      constexpr float hi = 12.97166202570235f - lo + 1e-6f;
277
37.9k
      for (size_t c = 0; c < 3; c++) {
278
28.4k
        float bands[4];
279
28.4k
        bands[0] = encoding.afv_weights[c][5];
280
28.4k
        if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
281
113k
        for (size_t i = 1; i < 4; i++) {
282
85.4k
          bands[i] = bands[i - 1] * Mult(encoding.afv_weights[c][i + 5]);
283
85.4k
          if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
284
85.4k
        }
285
28.4k
        size_t start = c * 64;
286
28.4k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
28.4k
          weights[start + y * 8 + x] = val;
288
28.4k
        };
289
28.4k
        weights[start] = 1;  // Not used, but causes MSAN error otherwise.
290
        // Weights for (0, 1) and (1, 0).
291
28.4k
        set_weight(0, 1, encoding.afv_weights[c][0]);
292
28.4k
        set_weight(1, 0, encoding.afv_weights[c][1]);
293
        // AFV special weights for 3-pixel corner.
294
28.4k
        set_weight(0, 2, encoding.afv_weights[c][2]);
295
28.4k
        set_weight(2, 0, encoding.afv_weights[c][3]);
296
28.4k
        set_weight(2, 2, encoding.afv_weights[c][4]);
297
298
        // All other AFV weights.
299
142k
        for (size_t y = 0; y < 4; y++) {
300
569k
          for (size_t x = 0; x < 4; x++) {
301
455k
            if (x < 2 && y < 2) continue;
302
683k
            JXL_ASSIGN_OR_RETURN(
303
683k
                float val, Interpolate(kFreqs[y * 4 + x] - lo, hi, bands, 4));
304
683k
            set_weight(2 * x, 2 * y, val);
305
683k
          }
306
113k
        }
307
308
        // Put 4x8 weights in odd rows, except (1, 0).
309
142k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
310
1.02M
          for (size_t x = 0; x < kBlockDim; x++) {
311
911k
            if (x == 0 && y == 0) continue;
312
882k
            weights[c * num + (2 * y + 1) * kBlockDim + x] =
313
882k
                weights4x8[c * 32 + y * 8 + x];
314
882k
          }
315
113k
        }
316
        // Put 4x4 weights in even rows / odd columns, except (0, 1).
317
142k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
318
569k
          for (size_t x = 0; x < kBlockDim / 2; x++) {
319
455k
            if (x == 0 && y == 0) continue;
320
427k
            weights[c * num + (2 * y) * kBlockDim + 2 * x + 1] =
321
427k
                weights4x4[c * 16 + y * 4 + x];
322
427k
          }
323
113k
        }
324
28.4k
      }
325
9.48k
      break;
326
9.49k
    }
327
117k
  }
328
117k
  size_t prev_pos = *pos;
329
117k
  HWY_CAPPED(float, 64) d;
330
20.5M
  for (size_t i = 0; i < num * 3; i += Lanes(d)) {
331
20.3M
    auto inv_val = LoadU(d, weights.data() + i);
332
20.3M
    if (JXL_UNLIKELY(!AllFalse(d, Ge(inv_val, Set(d, 1.0f / kAlmostZero))) ||
333
20.3M
                     !AllFalse(d, Lt(inv_val, Set(d, kAlmostZero))))) {
334
57
      return JXL_FAILURE("Invalid quantization table");
335
57
    }
336
20.3M
    auto val = Div(Set(d, 1.0f), inv_val);
337
20.3M
    StoreU(val, d, table + *pos + i);
338
20.3M
    StoreU(inv_val, d, inv_table + *pos + i);
339
20.3M
  }
340
117k
  (*pos) += 3 * num;
341
342
  // Ensure that the lowest frequencies have a 0 inverse table.
343
  // This does not affect en/decoding, but allows AC strategy selection to be
344
  // slightly simpler.
345
117k
  size_t xs = DequantMatrices::required_size_x[quant_table_idx];
346
117k
  size_t ys = DequantMatrices::required_size_y[quant_table_idx];
347
117k
  CoefficientLayout(&ys, &xs);
348
468k
  for (size_t c = 0; c < 3; c++) {
349
968k
    for (size_t y = 0; y < ys; y++) {
350
3.16M
      for (size_t x = 0; x < xs; x++) {
351
2.54M
        inv_table[prev_pos + c * ys * xs * kDCTBlockSize + y * kBlockDim * xs +
352
2.54M
                  x] = 0;
353
2.54M
      }
354
616k
    }
355
351k
  }
356
117k
  return true;
357
117k
}
Unexecuted instantiation: jxl::N_AVX3::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)
Unexecuted instantiation: jxl::N_AVX3_ZEN4::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)
Unexecuted instantiation: jxl::N_AVX3_SPR::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)
Unexecuted instantiation: jxl::N_SSE2::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)
358
359
// NOLINTNEXTLINE(google-readability-namespace-comments)
360
}  // namespace HWY_NAMESPACE
361
}  // namespace jxl
362
HWY_AFTER_NAMESPACE();
363
364
#if HWY_ONCE
365
366
namespace jxl {
367
namespace {
368
369
HWY_EXPORT(ComputeQuantTable);
370
371
constexpr const float kAlmostZero = 1e-8f;
372
373
602
Status DecodeDctParams(BitReader* br, DctQuantWeightParams* params) {
374
602
  params->num_distance_bands =
375
602
      br->ReadFixedBits<DctQuantWeightParams::kLog2MaxDistanceBands>() + 1;
376
1.64k
  for (size_t c = 0; c < 3; c++) {
377
5.34k
    for (size_t i = 0; i < params->num_distance_bands; i++) {
378
4.02k
      JXL_RETURN_IF_ERROR(F16Coder::Read(br, &params->distance_bands[c][i]));
379
4.02k
    }
380
1.31k
    if (params->distance_bands[c][0] < kAlmostZero) {
381
278
      return JXL_FAILURE("Distance band seed is too small");
382
278
    }
383
1.04k
    params->distance_bands[c][0] *= 64.0f;
384
1.04k
  }
385
293
  return true;
386
602
}
387
388
Status Decode(JxlMemoryManager* memory_manager, BitReader* br,
389
              QuantEncoding* encoding, size_t required_size_x,
390
              size_t required_size_y, size_t idx,
391
114k
              ModularFrameDecoder* modular_frame_decoder) {
392
114k
  size_t required_size = required_size_x * required_size_y;
393
114k
  required_size_x *= kBlockDim;
394
114k
  required_size_y *= kBlockDim;
395
114k
  int mode = br->ReadFixedBits<kLog2NumQuantModes>();
396
114k
  switch (mode) {
397
95.8k
    case QuantEncoding::kQuantModeLibrary: {
398
95.8k
      encoding->predefined = br->ReadFixedBits<kCeilLog2NumPredefinedTables>();
399
95.8k
      if (encoding->predefined >= kNumPredefinedTables) {
400
0
        return JXL_FAILURE("Invalid predefined table");
401
0
      }
402
95.8k
      break;
403
95.8k
    }
404
95.8k
    case QuantEncoding::kQuantModeID: {
405
2.47k
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
406
2.62k
      for (size_t c = 0; c < 3; c++) {
407
5.52k
        for (size_t i = 0; i < 3; i++) {
408
5.32k
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->idweights[c][i]));
409
5.26k
          if (std::abs(encoding->idweights[c][i]) < kAlmostZero) {
410
2.30k
            return JXL_FAILURE("ID Quantizer is too small");
411
2.30k
          }
412
2.96k
          encoding->idweights[c][i] *= 64;
413
2.96k
        }
414
2.56k
      }
415
53
      break;
416
2.41k
    }
417
891
    case QuantEncoding::kQuantModeDCT2: {
418
891
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
419
696
      for (size_t c = 0; c < 3; c++) {
420
3.01k
        for (size_t i = 0; i < 6; i++) {
421
2.73k
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->dct2weights[c][i]));
422
2.69k
          if (std::abs(encoding->dct2weights[c][i]) < kAlmostZero) {
423
294
            return JXL_FAILURE("Quantizer is too small");
424
294
          }
425
2.40k
          encoding->dct2weights[c][i] *= 64;
426
2.40k
        }
427
617
      }
428
79
      break;
429
408
    }
430
14.5k
    case QuantEncoding::kQuantModeDCT4X8: {
431
14.5k
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
432
29.0k
      for (size_t c = 0; c < 3; c++) {
433
28.9k
        JXL_RETURN_IF_ERROR(
434
28.9k
            F16Coder::Read(br, &encoding->dct4x8multipliers[c]));
435
28.8k
        if (std::abs(encoding->dct4x8multipliers[c]) < kAlmostZero) {
436
14.1k
          return JXL_FAILURE("DCT4X8 multiplier is too small");
437
14.1k
        }
438
28.8k
      }
439
131
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
440
66
      break;
441
131
    }
442
196
    case QuantEncoding::kQuantModeDCT4: {
443
196
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
444
474
      for (size_t c = 0; c < 3; c++) {
445
1.04k
        for (size_t i = 0; i < 2; i++) {
446
742
          JXL_RETURN_IF_ERROR(
447
742
              F16Coder::Read(br, &encoding->dct4multipliers[c][i]));
448
729
          if (std::abs(encoding->dct4multipliers[c][i]) < kAlmostZero) {
449
82
            return JXL_FAILURE("DCT4 multiplier is too small");
450
82
          }
451
729
        }
452
400
      }
453
74
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
454
46
      break;
455
74
    }
456
149
    case QuantEncoding::kQuantModeAFV: {
457
149
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
458
424
      for (size_t c = 0; c < 3; c++) {
459
3.07k
        for (size_t i = 0; i < 9; i++) {
460
2.78k
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->afv_weights[c][i]));
461
2.78k
        }
462
2.03k
        for (size_t i = 0; i < 6; i++) {
463
1.74k
          encoding->afv_weights[c][i] *= 64;
464
1.74k
        }
465
290
      }
466
90
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
467
26
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params_afv_4x4));
468
22
      break;
469
26
    }
470
281
    case QuantEncoding::kQuantModeDCT: {
471
281
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
472
133
      break;
473
281
    }
474
418
    case QuantEncoding::kQuantModeRAW: {
475
      // Set mode early, to avoid mem-leak.
476
418
      encoding->mode = QuantEncoding::kQuantModeRAW;
477
418
      JXL_RETURN_IF_ERROR(ModularFrameDecoder::DecodeQuantTable(
478
418
          memory_manager, required_size_x, required_size_y, br, encoding, idx,
479
418
          modular_frame_decoder));
480
42
      break;
481
418
    }
482
42
    default:
483
0
      return JXL_FAILURE("Invalid quantization table encoding");
484
114k
  }
485
96.2k
  encoding->mode = static_cast<QuantEncoding::Mode>(mode);
486
96.2k
  return true;
487
114k
}
488
489
}  // namespace
490
491
#if JXL_CXX_LANG < JXL_CXX_17
492
constexpr const std::array<int, 17> DequantMatrices::required_size_x;
493
constexpr const std::array<int, 17> DequantMatrices::required_size_y;
494
constexpr const size_t DequantMatrices::kSumRequiredXy;
495
#endif
496
497
Status DequantMatrices::Decode(JxlMemoryManager* memory_manager, BitReader* br,
498
49.1k
                               ModularFrameDecoder* modular_frame_decoder) {
499
49.1k
  size_t all_default = br->ReadBits(1);
500
49.1k
  size_t num_tables = all_default ? 0 : static_cast<size_t>(kNumQuantTables);
501
49.1k
  encodings_.clear();
502
49.1k
  encodings_.resize(kNumQuantTables, QuantEncoding::Library<0>());
503
145k
  for (size_t i = 0; i < num_tables; i++) {
504
114k
    JXL_RETURN_IF_ERROR(jxl::Decode(memory_manager, br, &encodings_[i],
505
114k
                                    required_size_x[i % kNumQuantTables],
506
114k
                                    required_size_y[i % kNumQuantTables], i,
507
114k
                                    modular_frame_decoder));
508
114k
  }
509
30.6k
  computed_mask_ = 0;
510
30.6k
  return true;
511
49.1k
}
512
513
248k
Status DequantMatrices::DecodeDC(BitReader* br) {
514
248k
  bool all_default = static_cast<bool>(br->ReadBits(1));
515
248k
  if (!br->AllReadsWithinBounds()) return JXL_FAILURE("EOS during DecodeDC");
516
230k
  if (!all_default) {
517
185k
    for (size_t c = 0; c < 3; c++) {
518
141k
      JXL_RETURN_IF_ERROR(F16Coder::Read(br, &dc_quant_[c]));
519
140k
      dc_quant_[c] *= 1.0f / 128.0f;
520
      // Negative values and nearly zero are invalid values.
521
140k
      if (dc_quant_[c] < kAlmostZero) {
522
6.74k
        return JXL_FAILURE("Invalid dc_quant: coefficient is too small.");
523
6.74k
      }
524
133k
      inv_dc_quant_[c] = 1.0f / dc_quant_[c];
525
133k
    }
526
51.5k
  }
527
223k
  return true;
528
230k
}
529
530
0
constexpr float V(float v) { return static_cast<float>(v); }
531
532
namespace {
533
struct DequantMatricesLibraryDef {
534
  // DCT8
535
6
  static constexpr QuantEncodingInternal DCT() {
536
6
    return QuantEncodingInternal::DCT(DctQuantWeightParams({{{{
537
6
                                                                 V(3150.0),
538
6
                                                                 V(0.0),
539
6
                                                                 V(-0.4),
540
6
                                                                 V(-0.4),
541
6
                                                                 V(-0.4),
542
6
                                                                 V(-2.0),
543
6
                                                             }},
544
6
                                                             {{
545
6
                                                                 V(560.0),
546
6
                                                                 V(0.0),
547
6
                                                                 V(-0.3),
548
6
                                                                 V(-0.3),
549
6
                                                                 V(-0.3),
550
6
                                                                 V(-0.3),
551
6
                                                             }},
552
6
                                                             {{
553
6
                                                                 V(512.0),
554
6
                                                                 V(-2.0),
555
6
                                                                 V(-1.0),
556
6
                                                                 V(0.0),
557
6
                                                                 V(-1.0),
558
6
                                                                 V(-2.0),
559
6
                                                             }}}},
560
6
                                                           6));
561
6
  }
562
563
  // Identity
564
6
  static constexpr QuantEncodingInternal IDENTITY() {
565
6
    return QuantEncodingInternal::Identity({{{{
566
6
                                                 V(280.0),
567
6
                                                 V(3160.0),
568
6
                                                 V(3160.0),
569
6
                                             }},
570
6
                                             {{
571
6
                                                 V(60.0),
572
6
                                                 V(864.0),
573
6
                                                 V(864.0),
574
6
                                             }},
575
6
                                             {{
576
6
                                                 V(18.0),
577
6
                                                 V(200.0),
578
6
                                                 V(200.0),
579
6
                                             }}}});
580
6
  }
581
582
  // DCT2
583
6
  static constexpr QuantEncodingInternal DCT2X2() {
584
6
    return QuantEncodingInternal::DCT2({{{{
585
6
                                             V(3840.0),
586
6
                                             V(2560.0),
587
6
                                             V(1280.0),
588
6
                                             V(640.0),
589
6
                                             V(480.0),
590
6
                                             V(300.0),
591
6
                                         }},
592
6
                                         {{
593
6
                                             V(960.0),
594
6
                                             V(640.0),
595
6
                                             V(320.0),
596
6
                                             V(180.0),
597
6
                                             V(140.0),
598
6
                                             V(120.0),
599
6
                                         }},
600
6
                                         {{
601
6
                                             V(640.0),
602
6
                                             V(320.0),
603
6
                                             V(128.0),
604
6
                                             V(64.0),
605
6
                                             V(32.0),
606
6
                                             V(16.0),
607
6
                                         }}}});
608
6
  }
609
610
  // DCT4 (quant_kind 3)
611
12
  static constexpr QuantEncodingInternal DCT4X4() {
612
12
    return QuantEncodingInternal::DCT4(DctQuantWeightParams({{{{
613
12
                                                                  V(2200.0),
614
12
                                                                  V(0.0),
615
12
                                                                  V(0.0),
616
12
                                                                  V(0.0),
617
12
                                                              }},
618
12
                                                              {{
619
12
                                                                  V(392.0),
620
12
                                                                  V(0.0),
621
12
                                                                  V(0.0),
622
12
                                                                  V(0.0),
623
12
                                                              }},
624
12
                                                              {{
625
12
                                                                  V(112.0),
626
12
                                                                  V(-0.25),
627
12
                                                                  V(-0.25),
628
12
                                                                  V(-0.5),
629
12
                                                              }}}},
630
12
                                                            4),
631
                                       /* kMul */
632
12
                                       {{{{
633
12
                                             V(1.0),
634
12
                                             V(1.0),
635
12
                                         }},
636
12
                                         {{
637
12
                                             V(1.0),
638
12
                                             V(1.0),
639
12
                                         }},
640
12
                                         {{
641
12
                                             V(1.0),
642
12
                                             V(1.0),
643
12
                                         }}}});
644
12
  }
645
646
  // DCT16
647
6
  static constexpr QuantEncodingInternal DCT16X16() {
648
6
    return QuantEncodingInternal::DCT(
649
6
        DctQuantWeightParams({{{{
650
6
                                   V(8996.8725711814115328),
651
6
                                   V(-1.3000777393353804),
652
6
                                   V(-0.49424529824571225),
653
6
                                   V(-0.439093774457103443),
654
6
                                   V(-0.6350101832695744),
655
6
                                   V(-0.90177264050827612),
656
6
                                   V(-1.6162099239887414),
657
6
                               }},
658
6
                               {{
659
6
                                   V(3191.48366296844234752),
660
6
                                   V(-0.67424582104194355),
661
6
                                   V(-0.80745813428471001),
662
6
                                   V(-0.44925837484843441),
663
6
                                   V(-0.35865440981033403),
664
6
                                   V(-0.31322389111877305),
665
6
                                   V(-0.37615025315725483),
666
6
                               }},
667
6
                               {{
668
6
                                   V(1157.50408145487200256),
669
6
                                   V(-2.0531423165804414),
670
6
                                   V(-1.4),
671
6
                                   V(-0.50687130033378396),
672
6
                                   V(-0.42708730624733904),
673
6
                                   V(-1.4856834539296244),
674
6
                                   V(-4.9209142884401604),
675
6
                               }}}},
676
6
                             7));
677
6
  }
678
679
  // DCT32
680
6
  static constexpr QuantEncodingInternal DCT32X32() {
681
6
    return QuantEncodingInternal::DCT(
682
6
        DctQuantWeightParams({{{{
683
6
                                   V(15718.40830982518931456),
684
6
                                   V(-1.025),
685
6
                                   V(-0.98),
686
6
                                   V(-0.9012),
687
6
                                   V(-0.4),
688
6
                                   V(-0.48819395464),
689
6
                                   V(-0.421064),
690
6
                                   V(-0.27),
691
6
                               }},
692
6
                               {{
693
6
                                   V(7305.7636810695983104),
694
6
                                   V(-0.8041958212306401),
695
6
                                   V(-0.7633036457487539),
696
6
                                   V(-0.55660379990111464),
697
6
                                   V(-0.49785304658857626),
698
6
                                   V(-0.43699592683512467),
699
6
                                   V(-0.40180866526242109),
700
6
                                   V(-0.27321683125358037),
701
6
                               }},
702
6
                               {{
703
6
                                   V(3803.53173721215041536),
704
6
                                   V(-3.060733579805728),
705
6
                                   V(-2.0413270132490346),
706
6
                                   V(-2.0235650159727417),
707
6
                                   V(-0.5495389509954993),
708
6
                                   V(-0.4),
709
6
                                   V(-0.4),
710
6
                                   V(-0.3),
711
6
                               }}}},
712
6
                             8));
713
6
  }
714
715
  // DCT16X8
716
6
  static constexpr QuantEncodingInternal DCT8X16() {
717
6
    return QuantEncodingInternal::DCT(
718
6
        DctQuantWeightParams({{{{
719
6
                                   V(7240.7734393502),
720
6
                                   V(-0.7),
721
6
                                   V(-0.7),
722
6
                                   V(-0.2),
723
6
                                   V(-0.2),
724
6
                                   V(-0.2),
725
6
                                   V(-0.5),
726
6
                               }},
727
6
                               {{
728
6
                                   V(1448.15468787004),
729
6
                                   V(-0.5),
730
6
                                   V(-0.5),
731
6
                                   V(-0.5),
732
6
                                   V(-0.2),
733
6
                                   V(-0.2),
734
6
                                   V(-0.2),
735
6
                               }},
736
6
                               {{
737
6
                                   V(506.854140754517),
738
6
                                   V(-1.4),
739
6
                                   V(-0.2),
740
6
                                   V(-0.5),
741
6
                                   V(-0.5),
742
6
                                   V(-1.5),
743
6
                                   V(-3.6),
744
6
                               }}}},
745
6
                             7));
746
6
  }
747
748
  // DCT32X8
749
6
  static constexpr QuantEncodingInternal DCT8X32() {
750
6
    return QuantEncodingInternal::DCT(
751
6
        DctQuantWeightParams({{{{
752
6
                                   V(16283.2494710648897),
753
6
                                   V(-1.7812845336559429),
754
6
                                   V(-1.6309059012653515),
755
6
                                   V(-1.0382179034313539),
756
6
                                   V(-0.85),
757
6
                                   V(-0.7),
758
6
                                   V(-0.9),
759
6
                                   V(-1.2360638576849587),
760
6
                               }},
761
6
                               {{
762
6
                                   V(5089.15750884921511936),
763
6
                                   V(-0.320049391452786891),
764
6
                                   V(-0.35362849922161446),
765
6
                                   V(-0.30340000000000003),
766
6
                                   V(-0.61),
767
6
                                   V(-0.5),
768
6
                                   V(-0.5),
769
6
                                   V(-0.6),
770
6
                               }},
771
6
                               {{
772
6
                                   V(3397.77603275308720128),
773
6
                                   V(-0.321327362693153371),
774
6
                                   V(-0.34507619223117997),
775
6
                                   V(-0.70340000000000003),
776
6
                                   V(-0.9),
777
6
                                   V(-1.0),
778
6
                                   V(-1.0),
779
6
                                   V(-1.1754605576265209),
780
6
                               }}}},
781
6
                             8));
782
6
  }
783
784
  // DCT32X16
785
6
  static constexpr QuantEncodingInternal DCT16X32() {
786
6
    return QuantEncodingInternal::DCT(
787
6
        DctQuantWeightParams({{{{
788
6
                                   V(13844.97076442300573),
789
6
                                   V(-0.97113799999999995),
790
6
                                   V(-0.658),
791
6
                                   V(-0.42026),
792
6
                                   V(-0.22712),
793
6
                                   V(-0.2206),
794
6
                                   V(-0.226),
795
6
                                   V(-0.6),
796
6
                               }},
797
6
                               {{
798
6
                                   V(4798.964084220744293),
799
6
                                   V(-0.61125308982767057),
800
6
                                   V(-0.83770786552491361),
801
6
                                   V(-0.79014862079498627),
802
6
                                   V(-0.2692727459704829),
803
6
                                   V(-0.38272769465388551),
804
6
                                   V(-0.22924222653091453),
805
6
                                   V(-0.20719098826199578),
806
6
                               }},
807
6
                               {{
808
6
                                   V(1807.236946760964614),
809
6
                                   V(-1.2),
810
6
                                   V(-1.2),
811
6
                                   V(-0.7),
812
6
                                   V(-0.7),
813
6
                                   V(-0.7),
814
6
                                   V(-0.4),
815
6
                                   V(-0.5),
816
6
                               }}}},
817
6
                             8));
818
6
  }
819
820
  // DCT4X8 and 8x4
821
12
  static constexpr QuantEncodingInternal DCT4X8() {
822
12
    return QuantEncodingInternal::DCT4X8(
823
12
        DctQuantWeightParams({{
824
12
                                 {{
825
12
                                     V(2198.050556016380522),
826
12
                                     V(-0.96269623020744692),
827
12
                                     V(-0.76194253026666783),
828
12
                                     V(-0.6551140670773547),
829
12
                                 }},
830
12
                                 {{
831
12
                                     V(764.3655248643528689),
832
12
                                     V(-0.92630200888366945),
833
12
                                     V(-0.9675229603596517),
834
12
                                     V(-0.27845290869168118),
835
12
                                 }},
836
12
                                 {{
837
12
                                     V(527.107573587542228),
838
12
                                     V(-1.4594385811273854),
839
12
                                     V(-1.450082094097871593),
840
12
                                     V(-1.5843722511996204),
841
12
                                 }},
842
12
                             }},
843
12
                             4),
844
        /* kMuls */
845
12
        {{
846
12
            V(1.0),
847
12
            V(1.0),
848
12
            V(1.0),
849
12
        }});
850
12
  }
851
  // AFV
852
6
  static QuantEncodingInternal AFV0() {
853
6
    return QuantEncodingInternal::AFV(DCT4X8().dct_params, DCT4X4().dct_params,
854
6
                                      {{{{
855
                                            // 4x4/4x8 DC tendency.
856
6
                                            V(3072.0),
857
6
                                            V(3072.0),
858
                                            // AFV corner.
859
6
                                            V(256.0),
860
6
                                            V(256.0),
861
6
                                            V(256.0),
862
                                            // AFV high freqs.
863
6
                                            V(414.0),
864
6
                                            V(0.0),
865
6
                                            V(0.0),
866
6
                                            V(0.0),
867
6
                                        }},
868
6
                                        {{
869
                                            // 4x4/4x8 DC tendency.
870
6
                                            V(1024.0),
871
6
                                            V(1024.0),
872
                                            // AFV corner.
873
6
                                            V(50),
874
6
                                            V(50),
875
6
                                            V(50),
876
                                            // AFV high freqs.
877
6
                                            V(58.0),
878
6
                                            V(0.0),
879
6
                                            V(0.0),
880
6
                                            V(0.0),
881
6
                                        }},
882
6
                                        {{
883
                                            // 4x4/4x8 DC tendency.
884
6
                                            V(384.0),
885
6
                                            V(384.0),
886
                                            // AFV corner.
887
6
                                            V(12.0),
888
6
                                            V(12.0),
889
6
                                            V(12.0),
890
                                            // AFV high freqs.
891
6
                                            V(22.0),
892
6
                                            V(-0.25),
893
6
                                            V(-0.25),
894
6
                                            V(-0.25),
895
6
                                        }}}});
896
6
  }
897
898
  // DCT64
899
6
  static QuantEncodingInternal DCT64X64() {
900
6
    return QuantEncodingInternal::DCT(
901
6
        DctQuantWeightParams({{{{
902
6
                                   V(0.9 * 26629.073922049845),
903
6
                                   V(-1.025),
904
6
                                   V(-0.78),
905
6
                                   V(-0.65012),
906
6
                                   V(-0.19041574084286472),
907
6
                                   V(-0.20819395464),
908
6
                                   V(-0.421064),
909
6
                                   V(-0.32733845535848671),
910
6
                               }},
911
6
                               {{
912
6
                                   V(0.9 * 9311.3238710010046),
913
6
                                   V(-0.3041958212306401),
914
6
                                   V(-0.3633036457487539),
915
6
                                   V(-0.35660379990111464),
916
6
                                   V(-0.3443074455424403),
917
6
                                   V(-0.33699592683512467),
918
6
                                   V(-0.30180866526242109),
919
6
                                   V(-0.27321683125358037),
920
6
                               }},
921
6
                               {{
922
6
                                   V(0.9 * 4992.2486445538634),
923
6
                                   V(-1.2),
924
6
                                   V(-1.2),
925
6
                                   V(-0.8),
926
6
                                   V(-0.7),
927
6
                                   V(-0.7),
928
6
                                   V(-0.4),
929
6
                                   V(-0.5),
930
6
                               }}}},
931
6
                             8));
932
6
  }
933
934
  // DCT64X32
935
6
  static QuantEncodingInternal DCT32X64() {
936
6
    return QuantEncodingInternal::DCT(
937
6
        DctQuantWeightParams({{{{
938
6
                                   V(0.65 * 23629.073922049845),
939
6
                                   V(-1.025),
940
6
                                   V(-0.78),
941
6
                                   V(-0.65012),
942
6
                                   V(-0.19041574084286472),
943
6
                                   V(-0.20819395464),
944
6
                                   V(-0.421064),
945
6
                                   V(-0.32733845535848671),
946
6
                               }},
947
6
                               {{
948
6
                                   V(0.65 * 8611.3238710010046),
949
6
                                   V(-0.3041958212306401),
950
6
                                   V(-0.3633036457487539),
951
6
                                   V(-0.35660379990111464),
952
6
                                   V(-0.3443074455424403),
953
6
                                   V(-0.33699592683512467),
954
6
                                   V(-0.30180866526242109),
955
6
                                   V(-0.27321683125358037),
956
6
                               }},
957
6
                               {{
958
6
                                   V(0.65 * 4492.2486445538634),
959
6
                                   V(-1.2),
960
6
                                   V(-1.2),
961
6
                                   V(-0.8),
962
6
                                   V(-0.7),
963
6
                                   V(-0.7),
964
6
                                   V(-0.4),
965
6
                                   V(-0.5),
966
6
                               }}}},
967
6
                             8));
968
6
  }
969
  // DCT128X128
970
6
  static QuantEncodingInternal DCT128X128() {
971
6
    return QuantEncodingInternal::DCT(
972
6
        DctQuantWeightParams({{{{
973
6
                                   V(1.8 * 26629.073922049845),
974
6
                                   V(-1.025),
975
6
                                   V(-0.78),
976
6
                                   V(-0.65012),
977
6
                                   V(-0.19041574084286472),
978
6
                                   V(-0.20819395464),
979
6
                                   V(-0.421064),
980
6
                                   V(-0.32733845535848671),
981
6
                               }},
982
6
                               {{
983
6
                                   V(1.8 * 9311.3238710010046),
984
6
                                   V(-0.3041958212306401),
985
6
                                   V(-0.3633036457487539),
986
6
                                   V(-0.35660379990111464),
987
6
                                   V(-0.3443074455424403),
988
6
                                   V(-0.33699592683512467),
989
6
                                   V(-0.30180866526242109),
990
6
                                   V(-0.27321683125358037),
991
6
                               }},
992
6
                               {{
993
6
                                   V(1.8 * 4992.2486445538634),
994
6
                                   V(-1.2),
995
6
                                   V(-1.2),
996
6
                                   V(-0.8),
997
6
                                   V(-0.7),
998
6
                                   V(-0.7),
999
6
                                   V(-0.4),
1000
6
                                   V(-0.5),
1001
6
                               }}}},
1002
6
                             8));
1003
6
  }
1004
1005
  // DCT128X64
1006
6
  static QuantEncodingInternal DCT64X128() {
1007
6
    return QuantEncodingInternal::DCT(
1008
6
        DctQuantWeightParams({{{{
1009
6
                                   V(1.3 * 23629.073922049845),
1010
6
                                   V(-1.025),
1011
6
                                   V(-0.78),
1012
6
                                   V(-0.65012),
1013
6
                                   V(-0.19041574084286472),
1014
6
                                   V(-0.20819395464),
1015
6
                                   V(-0.421064),
1016
6
                                   V(-0.32733845535848671),
1017
6
                               }},
1018
6
                               {{
1019
6
                                   V(1.3 * 8611.3238710010046),
1020
6
                                   V(-0.3041958212306401),
1021
6
                                   V(-0.3633036457487539),
1022
6
                                   V(-0.35660379990111464),
1023
6
                                   V(-0.3443074455424403),
1024
6
                                   V(-0.33699592683512467),
1025
6
                                   V(-0.30180866526242109),
1026
6
                                   V(-0.27321683125358037),
1027
6
                               }},
1028
6
                               {{
1029
6
                                   V(1.3 * 4492.2486445538634),
1030
6
                                   V(-1.2),
1031
6
                                   V(-1.2),
1032
6
                                   V(-0.8),
1033
6
                                   V(-0.7),
1034
6
                                   V(-0.7),
1035
6
                                   V(-0.4),
1036
6
                                   V(-0.5),
1037
6
                               }}}},
1038
6
                             8));
1039
6
  }
1040
  // DCT256X256
1041
6
  static QuantEncodingInternal DCT256X256() {
1042
6
    return QuantEncodingInternal::DCT(
1043
6
        DctQuantWeightParams({{{{
1044
6
                                   V(3.6 * 26629.073922049845),
1045
6
                                   V(-1.025),
1046
6
                                   V(-0.78),
1047
6
                                   V(-0.65012),
1048
6
                                   V(-0.19041574084286472),
1049
6
                                   V(-0.20819395464),
1050
6
                                   V(-0.421064),
1051
6
                                   V(-0.32733845535848671),
1052
6
                               }},
1053
6
                               {{
1054
6
                                   V(3.6 * 9311.3238710010046),
1055
6
                                   V(-0.3041958212306401),
1056
6
                                   V(-0.3633036457487539),
1057
6
                                   V(-0.35660379990111464),
1058
6
                                   V(-0.3443074455424403),
1059
6
                                   V(-0.33699592683512467),
1060
6
                                   V(-0.30180866526242109),
1061
6
                                   V(-0.27321683125358037),
1062
6
                               }},
1063
6
                               {{
1064
6
                                   V(3.6 * 4992.2486445538634),
1065
6
                                   V(-1.2),
1066
6
                                   V(-1.2),
1067
6
                                   V(-0.8),
1068
6
                                   V(-0.7),
1069
6
                                   V(-0.7),
1070
6
                                   V(-0.4),
1071
6
                                   V(-0.5),
1072
6
                               }}}},
1073
6
                             8));
1074
6
  }
1075
1076
  // DCT256X128
1077
6
  static QuantEncodingInternal DCT128X256() {
1078
6
    return QuantEncodingInternal::DCT(
1079
6
        DctQuantWeightParams({{{{
1080
6
                                   V(2.6 * 23629.073922049845),
1081
6
                                   V(-1.025),
1082
6
                                   V(-0.78),
1083
6
                                   V(-0.65012),
1084
6
                                   V(-0.19041574084286472),
1085
6
                                   V(-0.20819395464),
1086
6
                                   V(-0.421064),
1087
6
                                   V(-0.32733845535848671),
1088
6
                               }},
1089
6
                               {{
1090
6
                                   V(2.6 * 8611.3238710010046),
1091
6
                                   V(-0.3041958212306401),
1092
6
                                   V(-0.3633036457487539),
1093
6
                                   V(-0.35660379990111464),
1094
6
                                   V(-0.3443074455424403),
1095
6
                                   V(-0.33699592683512467),
1096
6
                                   V(-0.30180866526242109),
1097
6
                                   V(-0.27321683125358037),
1098
6
                               }},
1099
6
                               {{
1100
6
                                   V(2.6 * 4492.2486445538634),
1101
6
                                   V(-1.2),
1102
6
                                   V(-1.2),
1103
6
                                   V(-0.8),
1104
6
                                   V(-0.7),
1105
6
                                   V(-0.7),
1106
6
                                   V(-0.4),
1107
6
                                   V(-0.5),
1108
6
                               }}}},
1109
6
                             8));
1110
6
  }
1111
};
1112
}  // namespace
1113
1114
6
DequantMatrices::DequantLibraryInternal DequantMatrices::LibraryInit() {
1115
6
  static_assert(kNumQuantTables == 17,
1116
6
                "Update this function when adding new quantization kinds.");
1117
6
  static_assert(kNumPredefinedTables == 1,
1118
6
                "Update this function when adding new quantization matrices to "
1119
6
                "the library.");
1120
1121
  // The library and the indices need to be kept in sync manually.
1122
6
  static_assert(0 == static_cast<uint8_t>(QuantTable::DCT),
1123
6
                "Update the DequantLibrary array below.");
1124
6
  static_assert(1 == static_cast<uint8_t>(QuantTable::IDENTITY),
1125
6
                "Update the DequantLibrary array below.");
1126
6
  static_assert(2 == static_cast<uint8_t>(QuantTable::DCT2X2),
1127
6
                "Update the DequantLibrary array below.");
1128
6
  static_assert(3 == static_cast<uint8_t>(QuantTable::DCT4X4),
1129
6
                "Update the DequantLibrary array below.");
1130
6
  static_assert(4 == static_cast<uint8_t>(QuantTable::DCT16X16),
1131
6
                "Update the DequantLibrary array below.");
1132
6
  static_assert(5 == static_cast<uint8_t>(QuantTable::DCT32X32),
1133
6
                "Update the DequantLibrary array below.");
1134
6
  static_assert(6 == static_cast<uint8_t>(QuantTable::DCT8X16),
1135
6
                "Update the DequantLibrary array below.");
1136
6
  static_assert(7 == static_cast<uint8_t>(QuantTable::DCT8X32),
1137
6
                "Update the DequantLibrary array below.");
1138
6
  static_assert(8 == static_cast<uint8_t>(QuantTable::DCT16X32),
1139
6
                "Update the DequantLibrary array below.");
1140
6
  static_assert(9 == static_cast<uint8_t>(QuantTable::DCT4X8),
1141
6
                "Update the DequantLibrary array below.");
1142
6
  static_assert(10 == static_cast<uint8_t>(QuantTable::AFV0),
1143
6
                "Update the DequantLibrary array below.");
1144
6
  static_assert(11 == static_cast<uint8_t>(QuantTable::DCT64X64),
1145
6
                "Update the DequantLibrary array below.");
1146
6
  static_assert(12 == static_cast<uint8_t>(QuantTable::DCT32X64),
1147
6
                "Update the DequantLibrary array below.");
1148
6
  static_assert(13 == static_cast<uint8_t>(QuantTable::DCT128X128),
1149
6
                "Update the DequantLibrary array below.");
1150
6
  static_assert(14 == static_cast<uint8_t>(QuantTable::DCT64X128),
1151
6
                "Update the DequantLibrary array below.");
1152
6
  static_assert(15 == static_cast<uint8_t>(QuantTable::DCT256X256),
1153
6
                "Update the DequantLibrary array below.");
1154
6
  static_assert(16 == static_cast<uint8_t>(QuantTable::DCT128X256),
1155
6
                "Update the DequantLibrary array below.");
1156
6
  return DequantMatrices::DequantLibraryInternal{{
1157
6
      DequantMatricesLibraryDef::DCT(),
1158
6
      DequantMatricesLibraryDef::IDENTITY(),
1159
6
      DequantMatricesLibraryDef::DCT2X2(),
1160
6
      DequantMatricesLibraryDef::DCT4X4(),
1161
6
      DequantMatricesLibraryDef::DCT16X16(),
1162
6
      DequantMatricesLibraryDef::DCT32X32(),
1163
6
      DequantMatricesLibraryDef::DCT8X16(),
1164
6
      DequantMatricesLibraryDef::DCT8X32(),
1165
6
      DequantMatricesLibraryDef::DCT16X32(),
1166
6
      DequantMatricesLibraryDef::DCT4X8(),
1167
6
      DequantMatricesLibraryDef::AFV0(),
1168
6
      DequantMatricesLibraryDef::DCT64X64(),
1169
6
      DequantMatricesLibraryDef::DCT32X64(),
1170
      // Same default for large transforms (128+) as for 64x* transforms.
1171
6
      DequantMatricesLibraryDef::DCT128X128(),
1172
6
      DequantMatricesLibraryDef::DCT64X128(),
1173
6
      DequantMatricesLibraryDef::DCT256X256(),
1174
6
      DequantMatricesLibraryDef::DCT128X256(),
1175
6
  }};
1176
6
}
1177
1178
35.7k
const QuantEncoding* DequantMatrices::Library() {
1179
35.7k
  static const DequantMatrices::DequantLibraryInternal kDequantLibrary =
1180
35.7k
      DequantMatrices::LibraryInit();
1181
  // Downcast the result to a const QuantEncoding* from QuantEncodingInternal*
1182
  // since the subclass (QuantEncoding) doesn't add any new members and users
1183
  // will need to upcast to QuantEncodingInternal to access the members of that
1184
  // class. This allows to have kDequantLibrary as a constexpr value while still
1185
  // allowing to create QuantEncoding::RAW() instances that use std::vector in
1186
  // C++11.
1187
35.7k
  return reinterpret_cast<const QuantEncoding*>(kDequantLibrary.data());
1188
35.7k
}
1189
1190
715k
DequantMatrices::DequantMatrices() {
1191
715k
  encodings_.resize(kNumQuantTables, QuantEncoding::Library<0>());
1192
715k
  size_t pos = 0;
1193
715k
  size_t offsets[kNumQuantTables * 3];
1194
12.8M
  for (size_t i = 0; i < static_cast<size_t>(kNumQuantTables); i++) {
1195
12.1M
    size_t num_blocks =
1196
12.1M
        static_cast<size_t>(required_size_x[i]) * required_size_y[i];
1197
12.1M
    size_t num = num_blocks * kDCTBlockSize;
1198
48.6M
    for (size_t c = 0; c < 3; c++) {
1199
36.5M
      offsets[3 * i + c] = pos + c * num;
1200
36.5M
    }
1201
12.1M
    pos += 3 * num;
1202
12.1M
  }
1203
20.0M
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1204
77.3M
    for (size_t c = 0; c < 3; c++) {
1205
57.9M
      table_offsets_[i * 3 + c] =
1206
57.9M
          offsets[static_cast<size_t>(kAcStrategyToQuantTableMap[i]) * 3 + c];
1207
57.9M
    }
1208
19.3M
  }
1209
715k
}
1210
1211
Status DequantMatrices::EnsureComputed(JxlMemoryManager* memory_manager,
1212
35.7k
                                       uint32_t acs_mask) {
1213
35.7k
  const QuantEncoding* library = Library();
1214
1215
35.7k
  if (!table_storage_) {
1216
35.7k
    size_t table_storage_bytes = 2 * kTotalTableSize * sizeof(float);
1217
35.7k
    JXL_ASSIGN_OR_RETURN(
1218
35.7k
        table_storage_,
1219
35.7k
        AlignedMemory::Create(memory_manager, table_storage_bytes));
1220
35.7k
    table_ = table_storage_.address<float>();
1221
35.7k
    inv_table_ = table_ + kTotalTableSize;
1222
35.7k
  }
1223
1224
35.7k
  size_t offsets[kNumQuantTables * 3 + 1];
1225
35.7k
  size_t pos = 0;
1226
644k
  for (size_t i = 0; i < kNumQuantTables; i++) {
1227
608k
    size_t num_blocks =
1228
608k
        static_cast<size_t>(required_size_x[i]) * required_size_y[i];
1229
608k
    size_t num = num_blocks * kDCTBlockSize;
1230
2.43M
    for (size_t c = 0; c < 3; c++) {
1231
1.82M
      offsets[3 * i + c] = pos + c * num;
1232
1.82M
    }
1233
608k
    pos += 3 * num;
1234
608k
  }
1235
35.7k
  offsets[kNumQuantTables * 3] = pos;
1236
35.7k
  JXL_ENSURE(pos == kTotalTableSize);
1237
1238
35.7k
  uint32_t kind_mask = 0;
1239
1.00M
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1240
966k
    if (acs_mask & (1u << i)) {
1241
165k
      kind_mask |= 1u << static_cast<uint32_t>(kAcStrategyToQuantTableMap[i]);
1242
165k
    }
1243
966k
  }
1244
35.7k
  uint32_t computed_kind_mask = 0;
1245
1.00M
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1246
966k
    if (computed_mask_ & (1u << i)) {
1247
0
      computed_kind_mask |=
1248
0
          1u << static_cast<uint32_t>(kAcStrategyToQuantTableMap[i]);
1249
0
    }
1250
966k
  }
1251
642k
  for (size_t table = 0; table < kNumQuantTables; table++) {
1252
607k
    if ((1 << table) & computed_kind_mask) continue;
1253
607k
    if ((1 << table) & ~kind_mask) continue;
1254
117k
    size_t offset = offsets[table * 3];
1255
117k
    float* mutable_table = table_storage_.address<float>();
1256
117k
    if (encodings_[table].mode == QuantEncoding::kQuantModeLibrary) {
1257
117k
      JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ComputeQuantTable)(
1258
117k
          library[table], mutable_table, mutable_table + kTotalTableSize, table,
1259
117k
          QuantTable(table), &offset));
1260
117k
    } else {
1261
135
      JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ComputeQuantTable)(
1262
135
          encodings_[table], mutable_table, mutable_table + kTotalTableSize,
1263
135
          table, QuantTable(table), &offset));
1264
135
    }
1265
117k
    JXL_ENSURE(offset == offsets[table * 3 + 3]);
1266
117k
  }
1267
35.7k
  computed_mask_ |= acs_mask;
1268
1269
35.7k
  return true;
1270
35.7k
}
1271
1272
}  // namespace jxl
1273
#endif