Coverage Report

Created: 2026-07-25 07:03

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