Coverage Report

Created: 2025-07-16 07:53

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