Coverage Report

Created: 2026-09-14 07:15

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
607
                         float* weights) {
50
2.42k
  for (size_t c = 0; c < 3; c++) {
51
1.82k
    size_t start = c * 64;
52
1.82k
    weights[start] = 0xBAD;
53
1.82k
    weights[start + 1] = weights[start + 8] = dct2weights[c][0];
54
1.82k
    weights[start + 9] = dct2weights[c][1];
55
5.46k
    for (size_t y = 0; y < 2; y++) {
56
10.9k
      for (size_t x = 0; x < 2; x++) {
57
7.28k
        weights[start + y * 8 + x + 2] = dct2weights[c][2];
58
7.28k
        weights[start + (y + 2) * 8 + x] = dct2weights[c][2];
59
7.28k
      }
60
3.64k
    }
61
5.46k
    for (size_t y = 0; y < 2; y++) {
62
10.9k
      for (size_t x = 0; x < 2; x++) {
63
7.28k
        weights[start + (y + 2) * 8 + x + 2] = dct2weights[c][3];
64
7.28k
      }
65
3.64k
    }
66
9.10k
    for (size_t y = 0; y < 4; y++) {
67
36.4k
      for (size_t x = 0; x < 4; x++) {
68
29.1k
        weights[start + y * 8 + x + 4] = dct2weights[c][4];
69
29.1k
        weights[start + (y + 4) * 8 + x] = dct2weights[c][4];
70
29.1k
      }
71
7.28k
    }
72
9.10k
    for (size_t y = 0; y < 4; y++) {
73
36.4k
      for (size_t x = 0; x < 4; x++) {
74
29.1k
        weights[start + (y + 4) * 8 + x + 4] = dct2weights[c][5];
75
29.1k
      }
76
7.28k
    }
77
1.82k
  }
78
607
}
79
80
void GetQuantWeightsIdentity(const QuantEncoding::IdWeights& idweights,
81
1.60k
                             float* weights) {
82
6.40k
  for (size_t c = 0; c < 3; c++) {
83
312k
    for (int i = 0; i < 64; i++) {
84
307k
      weights[64 * c + i] = idweights[c][0];
85
307k
    }
86
4.80k
    weights[64 * c + 1] = idweights[c][1];
87
4.80k
    weights[64 * c + 8] = idweights[c][1];
88
4.80k
    weights[64 * c + 9] = idweights[c][2];
89
4.80k
  }
90
1.60k
}
91
92
StatusOr<float> Interpolate(float pos, float max, const float* array,
93
89.2k
                            size_t len) {
94
89.2k
  float scaled_pos = pos * (len - 1) / max;
95
89.2k
  size_t idx = scaled_pos;
96
89.2k
  JXL_ENSURE(idx + 1 < len);
97
89.2k
  float a = array[idx];
98
89.2k
  float b = array[idx + 1];
99
89.2k
  return a * FastPowf(b / a, scaled_pos - idx);
100
89.2k
}
101
102
244k
float Mult(float v) {
103
244k
  if (v > 0.0f) return 1.0f + v;
104
244k
  return 1.0f / (1.0f - v);
105
244k
}
106
107
using DF4 = HWY_CAPPED(float, 4);
108
109
hwy::HWY_NAMESPACE::Vec<DF4> InterpolateVec(
110
28.6M
    hwy::HWY_NAMESPACE::Vec<DF4> scaled_pos, const float* array) {
111
28.6M
  HWY_CAPPED(int32_t, 4) di;
112
113
28.6M
  auto idx = ConvertTo(di, scaled_pos);
114
115
28.6M
  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
28.6M
  auto a = GatherIndex(DF4(), array, idx);
120
28.6M
  auto b = GatherIndex(DF4(), array + 1, idx);
121
122
28.6M
  return Mul(a, FastPowf(DF4(), Div(b, a), frac));
123
28.6M
}
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
15.4k
    size_t num_bands, float* out) {
133
61.8k
  for (size_t c = 0; c < 3; c++) {
134
46.3k
    float bands[DctQuantWeightParams::kMaxDistanceBands] = {
135
46.3k
        distance_bands[c][0]};
136
46.3k
    if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
137
268k
    for (size_t i = 1; i < num_bands; i++) {
138
221k
      bands[i] = bands[i - 1] * Mult(distance_bands[c][i]);
139
221k
      if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
140
221k
    }
141
46.3k
    float scale = (num_bands - 1) / (kSqrt2 + 1e-6f);
142
46.3k
    float rcpcol = scale / (COLS - 1);
143
46.3k
    float rcprow = scale / (ROWS - 1);
144
46.3k
    JXL_ENSURE(COLS >= Lanes(DF4()));
145
46.3k
    HWY_ALIGN float l0123[4] = {0, 1, 2, 3};
146
546k
    for (uint32_t y = 0; y < ROWS; y++) {
147
499k
      float dy = y * rcprow;
148
499k
      float dy2 = dy * dy;
149
29.1M
      for (uint32_t x = 0; x < COLS; x += Lanes(DF4())) {
150
28.6M
        auto dx =
151
28.6M
            Mul(Add(Set(DF4(), x), Load(DF4(), l0123)), Set(DF4(), rcpcol));
152
28.6M
        auto scaled_distance = Sqrt(MulAdd(dx, dx, Set(DF4(), dy2)));
153
28.6M
        auto weight = num_bands == 1 ? Set(DF4(), bands[0])
154
28.6M
                                     : InterpolateVec(scaled_distance, bands);
155
28.6M
        StoreU(weight, DF4(), out + c * COLS * ROWS + y * COLS + x);
156
28.6M
      }
157
499k
    }
158
46.3k
  }
159
15.4k
  return true;
160
15.4k
}
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
15.1k
                         QuantTable kind, size_t* pos) {
167
15.1k
  constexpr size_t N = kBlockDim;
168
15.1k
  size_t quant_table_idx = static_cast<size_t>(kind);
169
15.1k
  size_t wrows = 8 * DequantMatrices::required_size_x[quant_table_idx];
170
15.1k
  size_t wcols = 8 * DequantMatrices::required_size_y[quant_table_idx];
171
15.1k
  size_t num = wrows * wcols;
172
173
15.1k
  std::vector<float> weights(3 * num);
174
175
15.1k
  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.60k
    case QuantEncoding::kQuantModeID: {
183
1.60k
      JXL_ENSURE(num == kDCTBlockSize);
184
1.60k
      GetQuantWeightsIdentity(encoding.idweights, weights.data());
185
1.60k
      break;
186
1.60k
    }
187
607
    case QuantEncoding::kQuantModeDCT2: {
188
607
      JXL_ENSURE(num == kDCTBlockSize);
189
607
      GetQuantWeightsDCT2(encoding.dct2weights, weights.data());
190
607
      break;
191
607
    }
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
45
    case QuantEncoding::kQuantModeDCT4X8: {
213
45
      JXL_ENSURE(num == kDCTBlockSize);
214
45
      float weights4x8[3 * 4 * 8];
215
      // Always use 4x8 GetQuantWeights for DCT4X8 quantization tables.
216
45
      JXL_RETURN_IF_ERROR(
217
45
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
218
45
                          encoding.dct_params.num_distance_bands, weights4x8));
219
180
      for (size_t c = 0; c < 3; c++) {
220
1.21k
        for (size_t y = 0; y < kBlockDim; y++) {
221
9.72k
          for (size_t x = 0; x < kBlockDim; x++) {
222
8.64k
            weights[c * num + y * kBlockDim + x] =
223
8.64k
                weights4x8[c * 32 + (y / 2) * 8 + x];
224
8.64k
          }
225
1.08k
        }
226
135
        weights[c * num + N] /= encoding.dct4x8multipliers[c];
227
135
      }
228
45
      break;
229
45
    }
230
10.4k
    case QuantEncoding::kQuantModeDCT: {
231
10.4k
      JXL_RETURN_IF_ERROR(GetQuantWeights(
232
10.4k
          wrows, wcols, encoding.dct_params.distance_bands,
233
10.4k
          encoding.dct_params.num_distance_bands, weights.data()));
234
10.4k
      break;
235
10.4k
    }
236
10.4k
    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.47k
    case QuantEncoding::kQuantModeAFV: {
247
2.47k
      constexpr float kFreqs[] = {
248
2.47k
          0xBAD,
249
2.47k
          0xBAD,
250
2.47k
          0.8517778890324296,
251
2.47k
          5.37778436506804,
252
2.47k
          0xBAD,
253
2.47k
          0xBAD,
254
2.47k
          4.734747904497923,
255
2.47k
          5.449245381693219,
256
2.47k
          1.6598270267479331,
257
2.47k
          4,
258
2.47k
          7.275749096817861,
259
2.47k
          10.423227632456525,
260
2.47k
          2.662932286148962,
261
2.47k
          7.630657783650829,
262
2.47k
          8.962388608184032,
263
2.47k
          12.97166202570235,
264
2.47k
      };
265
266
2.47k
      float weights4x8[3 * 4 * 8];
267
2.47k
      JXL_RETURN_IF_ERROR((
268
2.47k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
269
2.47k
                          encoding.dct_params.num_distance_bands, weights4x8)));
270
2.47k
      float weights4x4[3 * 4 * 4];
271
2.47k
      JXL_RETURN_IF_ERROR((GetQuantWeights(
272
2.47k
          4, 4, encoding.dct_params_afv_4x4.distance_bands,
273
2.47k
          encoding.dct_params_afv_4x4.num_distance_bands, weights4x4)));
274
275
2.47k
      constexpr float lo = 0.8517778890324296;
276
2.47k
      constexpr float hi = 12.97166202570235f - lo + 1e-6f;
277
9.91k
      for (size_t c = 0; c < 3; c++) {
278
7.43k
        float bands[4];
279
7.43k
        bands[0] = encoding.afv_weights[c][5];
280
7.43k
        if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
281
29.7k
        for (size_t i = 1; i < 4; i++) {
282
22.3k
          bands[i] = bands[i - 1] * Mult(encoding.afv_weights[c][i + 5]);
283
22.3k
          if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
284
22.3k
        }
285
7.43k
        size_t start = c * 64;
286
126k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
126k
          weights[start + y * 8 + x] = val;
288
126k
        };
289
7.43k
        weights[start] = 1;  // Not used, but causes MSAN error otherwise.
290
        // Weights for (0, 1) and (1, 0).
291
7.43k
        set_weight(0, 1, encoding.afv_weights[c][0]);
292
7.43k
        set_weight(1, 0, encoding.afv_weights[c][1]);
293
        // AFV special weights for 3-pixel corner.
294
7.43k
        set_weight(0, 2, encoding.afv_weights[c][2]);
295
7.43k
        set_weight(2, 0, encoding.afv_weights[c][3]);
296
7.43k
        set_weight(2, 2, encoding.afv_weights[c][4]);
297
298
        // All other AFV weights.
299
37.1k
        for (size_t y = 0; y < 4; y++) {
300
148k
          for (size_t x = 0; x < 4; x++) {
301
118k
            if (x < 2 && y < 2) continue;
302
178k
            JXL_ASSIGN_OR_RETURN(
303
178k
                float val, Interpolate(kFreqs[y * 4 + x] - lo, hi, bands, 4));
304
178k
            set_weight(2 * x, 2 * y, val);
305
178k
          }
306
29.7k
        }
307
308
        // Put 4x8 weights in odd rows, except (1, 0).
309
37.1k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
310
267k
          for (size_t x = 0; x < kBlockDim; x++) {
311
237k
            if (x == 0 && y == 0) continue;
312
230k
            weights[c * num + (2 * y + 1) * kBlockDim + x] =
313
230k
                weights4x8[c * 32 + y * 8 + x];
314
230k
          }
315
29.7k
        }
316
        // Put 4x4 weights in even rows / odd columns, except (0, 1).
317
37.1k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
318
148k
          for (size_t x = 0; x < kBlockDim / 2; x++) {
319
118k
            if (x == 0 && y == 0) continue;
320
111k
            weights[c * num + (2 * y) * kBlockDim + 2 * x + 1] =
321
111k
                weights4x4[c * 16 + y * 4 + x];
322
111k
          }
323
29.7k
        }
324
7.43k
      }
325
2.47k
      break;
326
2.47k
    }
327
15.1k
  }
328
15.1k
  size_t prev_pos = *pos;
329
15.1k
  HWY_CAPPED(float, 64) d;
330
29.1M
  for (size_t i = 0; i < num * 3; i += Lanes(d)) {
331
29.1M
    auto inv_val = LoadU(d, weights.data() + i);
332
29.1M
    if (JXL_UNLIKELY(!AllFalse(d, Ge(inv_val, Set(d, 1.0f / kAlmostZero))) ||
333
29.1M
                     !AllFalse(d, Lt(inv_val, Set(d, kAlmostZero))))) {
334
0
      return JXL_FAILURE("Invalid quantization table");
335
0
    }
336
29.1M
    auto val = Div(Set(d, 1.0f), inv_val);
337
29.1M
    StoreU(val, d, table + *pos + i);
338
29.1M
    StoreU(inv_val, d, inv_table + *pos + i);
339
29.1M
  }
340
15.1k
  (*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
15.1k
  size_t xs = DequantMatrices::required_size_x[quant_table_idx];
346
15.1k
  size_t ys = DequantMatrices::required_size_y[quant_table_idx];
347
15.1k
  CoefficientLayout(&ys, &xs);
348
60.7k
  for (size_t c = 0; c < 3; c++) {
349
114k
    for (size_t y = 0; y < ys; y++) {
350
525k
      for (size_t x = 0; x < xs; x++) {
351
455k
        inv_table[prev_pos + c * ys * xs * kDCTBlockSize + y * kBlockDim * xs +
352
455k
                  x] = 0;
353
455k
      }
354
69.1k
    }
355
45.5k
  }
356
15.1k
  return true;
357
15.1k
}
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
3
Status DecodeDctParams(BitReader* br, DctQuantWeightParams* params) {
374
3
  params->num_distance_bands =
375
3
      br->ReadFixedBits<DctQuantWeightParams::kLog2MaxDistanceBands>() + 1;
376
11
  for (size_t c = 0; c < 3; c++) {
377
132
    for (size_t i = 0; i < params->num_distance_bands; i++) {
378
123
      JXL_RETURN_IF_ERROR(F16Coder::Read(br, &params->distance_bands[c][i]));
379
123
    }
380
9
    if (params->distance_bands[c][0] < kAlmostZero) {
381
1
      return JXL_FAILURE("Distance band seed is too small");
382
1
    }
383
8
    params->distance_bands[c][0] *= 64.0f;
384
8
  }
385
2
  return true;
386
3
}
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
1.45k
              ModularFrameDecoder* modular_frame_decoder) {
392
1.45k
  size_t required_size = required_size_x * required_size_y;
393
1.45k
  required_size_x *= kBlockDim;
394
1.45k
  required_size_y *= kBlockDim;
395
1.45k
  int mode = br->ReadFixedBits<kLog2NumQuantModes>();
396
1.45k
  switch (mode) {
397
1.45k
    case QuantEncoding::kQuantModeLibrary: {
398
1.45k
      encoding->predefined = br->ReadFixedBits<kCeilLog2NumPredefinedTables>();
399
1.45k
      if (encoding->predefined >= kNumPredefinedTables) {
400
0
        return JXL_FAILURE("Invalid predefined table");
401
0
      }
402
1.45k
      break;
403
1.45k
    }
404
1.45k
    case QuantEncoding::kQuantModeID: {
405
2
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
406
4
      for (size_t c = 0; c < 3; c++) {
407
12
        for (size_t i = 0; i < 3; i++) {
408
9
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->idweights[c][i]));
409
9
          if (std::abs(encoding->idweights[c][i]) < kAlmostZero) {
410
0
            return JXL_FAILURE("ID Quantizer is too small");
411
0
          }
412
9
          encoding->idweights[c][i] *= 64;
413
9
        }
414
3
      }
415
1
      break;
416
1
    }
417
1
    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
1
    case QuantEncoding::kQuantModeAFV: {
457
1
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
458
4
      for (size_t c = 0; c < 3; c++) {
459
30
        for (size_t i = 0; i < 9; i++) {
460
27
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->afv_weights[c][i]));
461
27
        }
462
21
        for (size_t i = 0; i < 6; i++) {
463
18
          encoding->afv_weights[c][i] *= 64;
464
18
        }
465
3
      }
466
1
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
467
1
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params_afv_4x4));
468
1
      break;
469
1
    }
470
1
    case QuantEncoding::kQuantModeDCT: {
471
1
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
472
0
      break;
473
1
    }
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
1.45k
  }
485
1.45k
  encoding->mode = static_cast<QuantEncoding::Mode>(mode);
486
1.45k
  return true;
487
1.45k
}
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
7.26k
                               ModularFrameDecoder* modular_frame_decoder) {
499
7.26k
  size_t all_default = br->ReadBits(1);
500
7.26k
  size_t num_tables = all_default ? 0 : static_cast<size_t>(kNumQuantTables);
501
7.26k
  encodings_.clear();
502
7.26k
  encodings_.resize(kNumQuantTables, QuantEncoding::Library<0>());
503
8.72k
  for (size_t i = 0; i < num_tables; i++) {
504
1.45k
    JXL_RETURN_IF_ERROR(jxl::Decode(memory_manager, br, &encodings_[i],
505
1.45k
                                    required_size_x[i % kNumQuantTables],
506
1.45k
                                    required_size_y[i % kNumQuantTables], i,
507
1.45k
                                    modular_frame_decoder));
508
1.45k
  }
509
7.26k
  computed_mask_ = 0;
510
7.26k
  return true;
511
7.26k
}
512
513
24.6k
Status DequantMatrices::DecodeDC(BitReader* br) {
514
24.6k
  bool all_default = static_cast<bool>(br->ReadBits(1));
515
24.6k
  if (!br->AllReadsWithinBounds()) return JXL_FAILURE("EOS during DecodeDC");
516
24.6k
  if (!all_default) {
517
5.50k
    for (size_t c = 0; c < 3; c++) {
518
4.13k
      JXL_RETURN_IF_ERROR(F16Coder::Read(br, &dc_quant_[c]));
519
4.13k
      dc_quant_[c] *= 1.0f / 128.0f;
520
      // Negative values and nearly zero are invalid values.
521
4.13k
      if (dc_quant_[c] < kAlmostZero) {
522
33
        return JXL_FAILURE("Invalid dc_quant: coefficient is too small.");
523
33
      }
524
4.10k
      inv_dc_quant_[c] = 1.0f / dc_quant_[c];
525
4.10k
    }
526
1.39k
  }
527
24.6k
  return true;
528
24.6k
}
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
7.26k
const QuantEncoding* DequantMatrices::Library() {
1179
7.26k
  static const DequantMatrices::DequantLibraryInternal kDequantLibrary =
1180
7.26k
      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
7.26k
  return reinterpret_cast<const QuantEncoding*>(kDequantLibrary.data());
1188
7.26k
}
1189
1190
255k
DequantMatrices::DequantMatrices() {
1191
255k
  encodings_.resize(kNumQuantTables, QuantEncoding::Library<0>());
1192
255k
  size_t pos = 0;
1193
255k
  size_t offsets[kNumQuantTables * 3];
1194
4.60M
  for (size_t i = 0; i < static_cast<size_t>(kNumQuantTables); i++) {
1195
4.34M
    size_t num_blocks =
1196
4.34M
        static_cast<size_t>(required_size_x[i]) * required_size_y[i];
1197
4.34M
    size_t num = num_blocks * kDCTBlockSize;
1198
17.3M
    for (size_t c = 0; c < 3; c++) {
1199
13.0M
      offsets[3 * i + c] = pos + c * num;
1200
13.0M
    }
1201
4.34M
    pos += 3 * num;
1202
4.34M
  }
1203
7.15M
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1204
27.6M
    for (size_t c = 0; c < 3; c++) {
1205
20.7M
      table_offsets_[i * 3 + c] =
1206
20.7M
          offsets[static_cast<size_t>(kAcStrategyToQuantTableMap[i]) * 3 + c];
1207
20.7M
    }
1208
6.90M
  }
1209
255k
}
1210
1211
Status DequantMatrices::EnsureComputed(JxlMemoryManager* memory_manager,
1212
7.26k
                                       uint32_t acs_mask) {
1213
7.26k
  const QuantEncoding* library = Library();
1214
1215
7.26k
  if (!table_storage_) {
1216
7.26k
    size_t table_storage_bytes = 2 * kTotalTableSize * sizeof(float);
1217
7.26k
    JXL_ASSIGN_OR_RETURN(
1218
7.26k
        table_storage_,
1219
7.26k
        AlignedMemory::Create(memory_manager, table_storage_bytes));
1220
7.26k
    table_ = table_storage_.address<float>();
1221
7.26k
    inv_table_ = table_ + kTotalTableSize;
1222
7.26k
  }
1223
1224
7.26k
  size_t offsets[kNumQuantTables * 3 + 1];
1225
7.26k
  size_t pos = 0;
1226
130k
  for (size_t i = 0; i < kNumQuantTables; i++) {
1227
123k
    size_t num_blocks =
1228
123k
        static_cast<size_t>(required_size_x[i]) * required_size_y[i];
1229
123k
    size_t num = num_blocks * kDCTBlockSize;
1230
494k
    for (size_t c = 0; c < 3; c++) {
1231
370k
      offsets[3 * i + c] = pos + c * num;
1232
370k
    }
1233
123k
    pos += 3 * num;
1234
123k
  }
1235
7.26k
  offsets[kNumQuantTables * 3] = pos;
1236
7.26k
  JXL_ENSURE(pos == kTotalTableSize);
1237
1238
7.26k
  uint32_t kind_mask = 0;
1239
203k
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1240
196k
    if (acs_mask & (1u << i)) {
1241
15.2k
      kind_mask |= 1u << static_cast<uint32_t>(kAcStrategyToQuantTableMap[i]);
1242
15.2k
    }
1243
196k
  }
1244
7.26k
  uint32_t computed_kind_mask = 0;
1245
203k
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1246
196k
    if (computed_mask_ & (1u << i)) {
1247
0
      computed_kind_mask |=
1248
0
          1u << static_cast<uint32_t>(kAcStrategyToQuantTableMap[i]);
1249
0
    }
1250
196k
  }
1251
130k
  for (size_t table = 0; table < kNumQuantTables; table++) {
1252
123k
    if ((1 << table) & computed_kind_mask) continue;
1253
123k
    if ((1 << table) & ~kind_mask) continue;
1254
15.1k
    size_t offset = offsets[table * 3];
1255
15.1k
    float* mutable_table = table_storage_.address<float>();
1256
15.1k
    if (encodings_[table].mode == QuantEncoding::kQuantModeLibrary) {
1257
15.1k
      JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ComputeQuantTable)(
1258
15.1k
          library[table], mutable_table, mutable_table + kTotalTableSize, table,
1259
15.1k
          QuantTable(table), &offset));
1260
15.1k
    } 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
15.1k
    JXL_ENSURE(offset == offsets[table * 3 + 3]);
1266
15.1k
  }
1267
7.26k
  computed_mask_ |= acs_mask;
1268
1269
7.26k
  return true;
1270
7.26k
}
1271
1272
}  // namespace jxl
1273
#endif