Coverage Report

Created: 2023-08-28 07:24

/src/libjxl/lib/jxl/enc_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
6
#include "lib/jxl/enc_quant_weights.h"
7
8
#include <stdio.h>
9
#include <stdlib.h>
10
11
#include <algorithm>
12
#include <cmath>
13
#include <limits>
14
#include <utility>
15
16
#include "lib/jxl/base/bits.h"
17
#include "lib/jxl/base/status.h"
18
#include "lib/jxl/common.h"
19
#include "lib/jxl/dct_scales.h"
20
#include "lib/jxl/enc_aux_out.h"
21
#include "lib/jxl/enc_bit_writer.h"
22
#include "lib/jxl/enc_modular.h"
23
#include "lib/jxl/fields.h"
24
#include "lib/jxl/image.h"
25
#include "lib/jxl/modular/encoding/encoding.h"
26
#include "lib/jxl/modular/options.h"
27
28
namespace jxl {
29
30
struct AuxOut;
31
32
namespace {
33
34
0
Status EncodeDctParams(const DctQuantWeightParams& params, BitWriter* writer) {
35
0
  JXL_ASSERT(params.num_distance_bands >= 1);
36
0
  writer->Write(DctQuantWeightParams::kLog2MaxDistanceBands,
37
0
                params.num_distance_bands - 1);
38
0
  for (size_t c = 0; c < 3; c++) {
39
0
    for (size_t i = 0; i < params.num_distance_bands; i++) {
40
0
      JXL_RETURN_IF_ERROR(F16Coder::Write(
41
0
          params.distance_bands[c][i] * (i == 0 ? (1 / 64.0f) : 1.0f), writer));
42
0
    }
43
0
  }
44
0
  return true;
45
0
}
46
47
Status EncodeQuant(const QuantEncoding& encoding, size_t idx, size_t size_x,
48
                   size_t size_y, BitWriter* writer,
49
0
                   ModularFrameEncoder* modular_frame_encoder) {
50
0
  writer->Write(kLog2NumQuantModes, encoding.mode);
51
0
  size_x *= kBlockDim;
52
0
  size_y *= kBlockDim;
53
0
  switch (encoding.mode) {
54
0
    case QuantEncoding::kQuantModeLibrary: {
55
0
      writer->Write(kCeilLog2NumPredefinedTables, encoding.predefined);
56
0
      break;
57
0
    }
58
0
    case QuantEncoding::kQuantModeID: {
59
0
      for (size_t c = 0; c < 3; c++) {
60
0
        for (size_t i = 0; i < 3; i++) {
61
0
          JXL_RETURN_IF_ERROR(
62
0
              F16Coder::Write(encoding.idweights[c][i] * (1.0f / 64), writer));
63
0
        }
64
0
      }
65
0
      break;
66
0
    }
67
0
    case QuantEncoding::kQuantModeDCT2: {
68
0
      for (size_t c = 0; c < 3; c++) {
69
0
        for (size_t i = 0; i < 6; i++) {
70
0
          JXL_RETURN_IF_ERROR(F16Coder::Write(
71
0
              encoding.dct2weights[c][i] * (1.0f / 64), writer));
72
0
        }
73
0
      }
74
0
      break;
75
0
    }
76
0
    case QuantEncoding::kQuantModeDCT4X8: {
77
0
      for (size_t c = 0; c < 3; c++) {
78
0
        JXL_RETURN_IF_ERROR(
79
0
            F16Coder::Write(encoding.dct4x8multipliers[c], writer));
80
0
      }
81
0
      JXL_RETURN_IF_ERROR(EncodeDctParams(encoding.dct_params, writer));
82
0
      break;
83
0
    }
84
0
    case QuantEncoding::kQuantModeDCT4: {
85
0
      for (size_t c = 0; c < 3; c++) {
86
0
        for (size_t i = 0; i < 2; i++) {
87
0
          JXL_RETURN_IF_ERROR(
88
0
              F16Coder::Write(encoding.dct4multipliers[c][i], writer));
89
0
        }
90
0
      }
91
0
      JXL_RETURN_IF_ERROR(EncodeDctParams(encoding.dct_params, writer));
92
0
      break;
93
0
    }
94
0
    case QuantEncoding::kQuantModeDCT: {
95
0
      JXL_RETURN_IF_ERROR(EncodeDctParams(encoding.dct_params, writer));
96
0
      break;
97
0
    }
98
0
    case QuantEncoding::kQuantModeRAW: {
99
0
      ModularFrameEncoder::EncodeQuantTable(size_x, size_y, writer, encoding,
100
0
                                            idx, modular_frame_encoder);
101
0
      break;
102
0
    }
103
0
    case QuantEncoding::kQuantModeAFV: {
104
0
      for (size_t c = 0; c < 3; c++) {
105
0
        for (size_t i = 0; i < 9; i++) {
106
0
          JXL_RETURN_IF_ERROR(F16Coder::Write(
107
0
              encoding.afv_weights[c][i] * (i < 6 ? 1.0f / 64 : 1.0f), writer));
108
0
        }
109
0
      }
110
0
      JXL_RETURN_IF_ERROR(EncodeDctParams(encoding.dct_params, writer));
111
0
      JXL_RETURN_IF_ERROR(EncodeDctParams(encoding.dct_params_afv_4x4, writer));
112
0
      break;
113
0
    }
114
0
  }
115
0
  return true;
116
0
}
117
118
}  // namespace
119
120
Status DequantMatricesEncode(const DequantMatrices* matrices, BitWriter* writer,
121
                             size_t layer, AuxOut* aux_out,
122
0
                             ModularFrameEncoder* modular_frame_encoder) {
123
0
  bool all_default = true;
124
0
  const std::vector<QuantEncoding>& encodings = matrices->encodings();
125
126
0
  for (size_t i = 0; i < encodings.size(); i++) {
127
0
    if (encodings[i].mode != QuantEncoding::kQuantModeLibrary ||
128
0
        encodings[i].predefined != 0) {
129
0
      all_default = false;
130
0
    }
131
0
  }
132
  // TODO(janwas): better bound
133
0
  BitWriter::Allotment allotment(writer, 512 * 1024);
134
0
  writer->Write(1, all_default);
135
0
  if (!all_default) {
136
0
    for (size_t i = 0; i < encodings.size(); i++) {
137
0
      JXL_RETURN_IF_ERROR(EncodeQuant(
138
0
          encodings[i], i, DequantMatrices::required_size_x[i],
139
0
          DequantMatrices::required_size_y[i], writer, modular_frame_encoder));
140
0
    }
141
0
  }
142
0
  allotment.ReclaimAndCharge(writer, layer, aux_out);
143
0
  return true;
144
0
}
145
146
Status DequantMatricesEncodeDC(const DequantMatrices* matrices,
147
                               BitWriter* writer, size_t layer,
148
0
                               AuxOut* aux_out) {
149
0
  bool all_default = true;
150
0
  const float* dc_quant = matrices->DCQuants();
151
0
  for (size_t c = 0; c < 3; c++) {
152
0
    if (dc_quant[c] != kDCQuant[c]) {
153
0
      all_default = false;
154
0
    }
155
0
  }
156
0
  BitWriter::Allotment allotment(writer, 1 + sizeof(float) * kBitsPerByte * 3);
157
0
  writer->Write(1, all_default);
158
0
  if (!all_default) {
159
0
    for (size_t c = 0; c < 3; c++) {
160
0
      JXL_RETURN_IF_ERROR(F16Coder::Write(dc_quant[c] * 128.0f, writer));
161
0
    }
162
0
  }
163
0
  allotment.ReclaimAndCharge(writer, layer, aux_out);
164
0
  return true;
165
0
}
166
167
0
void DequantMatricesSetCustomDC(DequantMatrices* matrices, const float* dc) {
168
0
  matrices->SetDCQuant(dc);
169
  // Roundtrip encode/decode DC to ensure same values as decoder.
170
0
  BitWriter writer;
171
0
  JXL_CHECK(DequantMatricesEncodeDC(matrices, &writer, 0, nullptr));
172
0
  writer.ZeroPadToByte();
173
0
  BitReader br(writer.GetSpan());
174
  // Called only in the encoder: should fail only for programmer errors.
175
0
  JXL_CHECK(matrices->DecodeDC(&br));
176
0
  JXL_CHECK(br.Close());
177
0
}
178
179
0
void DequantMatricesScaleDC(DequantMatrices* matrices, const float scale) {
180
0
  float dc[3];
181
0
  for (size_t c = 0; c < 3; ++c) {
182
0
    dc[c] = matrices->InvDCQuant(c) * (1.0f / scale);
183
0
  }
184
0
  DequantMatricesSetCustomDC(matrices, dc);
185
0
}
186
187
0
void DequantMatricesRoundtrip(DequantMatrices* matrices) {
188
  // Do not pass modular en/decoder, as they only change entropy and not
189
  // values.
190
0
  BitWriter writer;
191
0
  JXL_CHECK(DequantMatricesEncode(matrices, &writer, 0, nullptr));
192
0
  writer.ZeroPadToByte();
193
0
  BitReader br(writer.GetSpan());
194
  // Called only in the encoder: should fail only for programmer errors.
195
0
  JXL_CHECK(matrices->Decode(&br));
196
0
  JXL_CHECK(br.Close());
197
0
}
198
199
void DequantMatricesSetCustom(DequantMatrices* matrices,
200
                              const std::vector<QuantEncoding>& encodings,
201
0
                              ModularFrameEncoder* encoder) {
202
0
  JXL_ASSERT(encodings.size() == DequantMatrices::kNum);
203
0
  matrices->SetEncodings(encodings);
204
0
  for (size_t i = 0; i < encodings.size(); i++) {
205
0
    if (encodings[i].mode == QuantEncodingInternal::kQuantModeRAW) {
206
0
      encoder->AddQuantTable(DequantMatrices::required_size_x[i] * kBlockDim,
207
0
                             DequantMatrices::required_size_y[i] * kBlockDim,
208
0
                             encodings[i], i);
209
0
    }
210
0
  }
211
0
  DequantMatricesRoundtrip(matrices);
212
0
}
213
214
}  // namespace jxl