Coverage Report

Created: 2025-08-12 07:37

/src/libjxl/lib/jxl/modular/encoding/enc_ma.h
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
#ifndef LIB_JXL_MODULAR_ENCODING_ENC_MA_H_
7
#define LIB_JXL_MODULAR_ENCODING_ENC_MA_H_
8
9
#include <algorithm>
10
#include <array>
11
#include <cstddef>
12
#include <cstdint>
13
#include <vector>
14
15
#include "lib/jxl/base/common.h"
16
#include "lib/jxl/base/status.h"
17
#include "lib/jxl/enc_ans.h"
18
#include "lib/jxl/modular/encoding/dec_ma.h"
19
#include "lib/jxl/modular/modular_image.h"
20
#include "lib/jxl/modular/options.h"
21
22
namespace jxl {
23
24
struct ResidualToken {
25
  uint8_t tok;
26
  uint8_t nbits;
27
};
28
29
// Struct to collect all the data needed to build a tree.
30
struct TreeSamples {
31
74
  bool HasSamples() const {
32
74
    return !residuals.empty() && !residuals[0].empty();
33
74
  }
34
51.9k
  size_t NumDistinctSamples() const { return sample_counts.size(); }
35
73
  size_t NumSamples() const { return num_samples; }
36
  // Set the predictor to use. Must be called before adding any samples.
37
  Status SetPredictor(Predictor predictor,
38
                      ModularOptions::TreeMode wp_tree_mode);
39
  // Set the properties to use. Must be called before adding any samples.
40
  Status SetProperties(const std::vector<uint32_t> &properties,
41
                       ModularOptions::TreeMode wp_tree_mode);
42
43
40.1k
  const std::vector<ResidualToken>& RTokens(size_t pred) const {
44
40.1k
    return residuals[pred];
45
40.1k
  }
46
0
  const ResidualToken &RToken(size_t pred, size_t i) const {
47
0
    return residuals[pred][i];
48
0
  }
49
1.11M
  size_t Token(size_t pred, size_t i) const { return residuals[pred][i].tok; }
50
8.93M
  size_t Count(size_t i) const { return sample_counts[i]; }
51
5.05k
  size_t PredictorIndex(Predictor predictor) const {
52
5.05k
    const auto predictor_elem =
53
5.05k
        std::find(predictors.begin(), predictors.end(), predictor);
54
5.05k
    JXL_DASSERT(predictor_elem != predictors.end());
55
5.05k
    return predictor_elem - predictors.begin();
56
5.05k
  }
57
0
  size_t PropertyIndex(size_t property) const {
58
0
    const auto property_elem =
59
0
        std::find(props_to_use.begin(), props_to_use.end(), property);
60
0
    JXL_DASSERT(property_elem != props_to_use.end());
61
0
    return property_elem - props_to_use.begin();
62
0
  }
63
35.0k
  size_t NumPropertyValues(size_t property_index) const {
64
35.0k
    return compact_properties[property_index].size() + 1;
65
35.0k
  }
66
124k
  size_t NumStaticProps() const { return num_static_props; }
67
  // Returns the *quantized* property value.
68
  template<bool S>
69
16.5M
  size_t Property(size_t property_index, size_t i) const {
70
16.5M
    if (S) {
71
4.67M
      return static_props[property_index][i];
72
11.9M
    } else {
73
11.9M
      return props[property_index][i];
74
11.9M
    }
75
16.5M
  }
unsigned long jxl::TreeSamples::Property<true>(unsigned long, unsigned long) const
Line
Count
Source
69
4.67M
  size_t Property(size_t property_index, size_t i) const {
70
4.67M
    if (S) {
71
4.67M
      return static_props[property_index][i];
72
4.67M
    } else {
73
0
      return props[property_index][i];
74
0
    }
75
4.67M
  }
unsigned long jxl::TreeSamples::Property<false>(unsigned long, unsigned long) const
Line
Count
Source
69
11.9M
  size_t Property(size_t property_index, size_t i) const {
70
11.9M
    if (S) {
71
0
      return static_props[property_index][i];
72
11.9M
    } else {
73
11.9M
      return props[property_index][i];
74
11.9M
    }
75
11.9M
  }
76
2.49k
  int UnquantizeProperty(size_t property_index, uint32_t quant) const {
77
2.49k
    JXL_DASSERT(quant < compact_properties[property_index].size());
78
2.49k
    return compact_properties[property_index][quant];
79
2.49k
  }
80
81
3.20M
  Predictor PredictorFromIndex(size_t index) const {
82
3.20M
    JXL_DASSERT(index < predictors.size());
83
3.20M
    return predictors[index];
84
3.20M
  }
85
373k
  size_t PropertyFromIndex(size_t index) const {
86
373k
    JXL_DASSERT(index < props_to_use.size());
87
373k
    return props_to_use[index];
88
373k
  }
89
274
  size_t NumPredictors() const { return predictors.size(); }
90
146
  size_t NumProperties() const { return props_to_use.size(); }
91
92
  // Preallocate data for a given number of samples. MUST be called before
93
  // adding any sample.
94
  void PrepareForSamples(size_t extra_num_samples);
95
  // Add a sample.
96
  void AddSample(pixel_type_w pixel, const Properties &properties,
97
                 const pixel_type_w *predictions);
98
  // Pre-cluster property values.
99
  void PreQuantizeProperties(
100
      const StaticPropRange &range,
101
      const std::vector<ModularMultiplierInfo> &multiplier_info,
102
      const std::vector<uint32_t> &group_pixel_count,
103
      const std::vector<uint32_t> &channel_pixel_count,
104
      std::vector<pixel_type> &pixel_samples,
105
      std::vector<pixel_type> &diff_samples, size_t max_property_values);
106
107
73
  void AllSamplesDone() { dedup_table_ = std::vector<uint32_t>(); }
108
109
3.01M
  uint32_t QuantizeProperty(uint32_t prop, pixel_type v) const {
110
3.01M
    JXL_DASSERT(prop >= num_static_props);
111
3.01M
    v = jxl::Clamp1(v, -kPropertyRange, kPropertyRange) + kPropertyRange;
112
3.01M
    return property_mapping[prop - num_static_props][v];
113
3.01M
  }
114
115
1.13M
  uint32_t QuantizeStaticProperty(uint32_t prop, pixel_type v) const {
116
1.13M
    JXL_DASSERT(prop < num_static_props);
117
1.13M
    v = jxl::Clamp1(v, -kPropertyRange, kPropertyRange) + kPropertyRange;
118
1.13M
    return static_property_mapping[prop][v];
119
1.13M
  }
120
121
  // Swaps samples in position a and b. Does nothing if a == b.
122
  void Swap(size_t a, size_t b);
123
124
 private:
125
  // TODO(veluca): as the total number of properties and predictors are known
126
  // before adding any samples, it might be better to interleave predictors,
127
  // properties and counts in a single vector to improve locality.
128
  // A first attempt at doing this actually results in much slower encoding,
129
  // possibly because of the more complex addressing.
130
  // Residual information: token and number of extra bits, per predictor.
131
  std::vector<std::vector<ResidualToken>> residuals;
132
  // Number of occurrences of each sample.
133
  std::vector<uint16_t> sample_counts;
134
  // Quantized static property values
135
  size_t num_static_props;
136
  std::array<std::vector<uint32_t>, kNumStaticProperties> static_props;
137
  // Property values, quantized to at most 256 distinct values.
138
  std::vector<std::vector<uint8_t>> props;
139
  // Decompactification info for `props`.
140
  std::vector<std::vector<int32_t>> compact_properties;
141
  // List of properties to use.
142
  std::vector<uint32_t> props_to_use;
143
  // List of predictors to use.
144
  std::vector<Predictor> predictors;
145
  // Mapping property value -> quantized property value.
146
  static constexpr int32_t kPropertyRange = 511;
147
  std::array<std::vector<uint16_t>, kNumStaticProperties>
148
      static_property_mapping;
149
  std::vector<std::vector<uint8_t>> property_mapping;
150
  // Number of samples seen.
151
  size_t num_samples = 0;
152
  // Table for deduplication.
153
  static constexpr uint32_t kDedupEntryUnused{static_cast<uint32_t>(-1)};
154
  std::vector<uint32_t> dedup_table_;
155
156
  // Functions for sample deduplication.
157
  bool IsSameSample(size_t a, size_t b) const;
158
  size_t Hash1(size_t a) const;
159
  size_t Hash2(size_t a) const;
160
  void InitTable(size_t log_size);
161
  // Returns true if `a` was already present in the table.
162
  bool AddToTableAndMerge(size_t a);
163
  void AddToTable(size_t a);
164
};
165
166
Status TokenizeTree(const Tree &tree, std::vector<Token> *tokens,
167
                    Tree *decoder_tree);
168
169
void CollectPixelSamples(const Image &image, const ModularOptions &options,
170
                         uint32_t group_id,
171
                         std::vector<uint32_t> &group_pixel_count,
172
                         std::vector<uint32_t> &channel_pixel_count,
173
                         std::vector<pixel_type> &pixel_samples,
174
                         std::vector<pixel_type> &diff_samples);
175
176
Status ComputeBestTree(TreeSamples &tree_samples, float threshold,
177
                       const std::vector<ModularMultiplierInfo> &mul_info,
178
                       StaticPropRange static_prop_range,
179
                       float fast_decode_multiplier, Tree *tree);
180
181
}  // namespace jxl
182
#endif  // LIB_JXL_MODULAR_ENCODING_ENC_MA_H_