/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 | 1.00k | bool HasSamples() const { |
32 | 1.00k | return !residuals.empty() && !residuals[0].empty(); |
33 | 1.00k | } |
34 | 2.05M | size_t NumDistinctSamples() const { return sample_counts.size(); } |
35 | 1.00k | 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 | 297M | const ResidualToken &RToken(size_t pred, size_t i) const { |
44 | 297M | return residuals[pred][i]; |
45 | 297M | } |
46 | 37.2M | size_t Token(size_t pred, size_t i) const { return residuals[pred][i].tok; } |
47 | 297M | size_t Count(size_t i) const { return sample_counts[i]; } |
48 | 121k | size_t PredictorIndex(Predictor predictor) const { |
49 | 121k | const auto predictor_elem = |
50 | 121k | std::find(predictors.begin(), predictors.end(), predictor); |
51 | 121k | JXL_DASSERT(predictor_elem != predictors.end()); |
52 | 121k | return predictor_elem - predictors.begin(); |
53 | 121k | } |
54 | 0 | size_t PropertyIndex(size_t property) const { |
55 | 0 | const auto property_elem = |
56 | 0 | std::find(props_to_use.begin(), props_to_use.end(), property); |
57 | 0 | JXL_DASSERT(property_elem != props_to_use.end()); |
58 | 0 | return property_elem - props_to_use.begin(); |
59 | 0 | } |
60 | 838k | size_t NumPropertyValues(size_t property_index) const { |
61 | 838k | return compact_properties[property_index].size() + 1; |
62 | 838k | } |
63 | | // Returns the *quantized* property value. |
64 | 553M | size_t Property(size_t property_index, size_t i) const { |
65 | 553M | return property_index < num_static_props |
66 | 553M | ? static_props[property_index][i] |
67 | 553M | : props[property_index - num_static_props][i]; |
68 | 553M | } |
69 | 60.3k | int UnquantizeProperty(size_t property_index, uint32_t quant) const { |
70 | 60.3k | JXL_DASSERT(quant < compact_properties[property_index].size()); |
71 | 60.3k | return compact_properties[property_index][quant]; |
72 | 60.3k | } |
73 | | |
74 | 69.1M | Predictor PredictorFromIndex(size_t index) const { |
75 | 69.1M | JXL_DASSERT(index < predictors.size()); |
76 | 69.1M | return predictors[index]; |
77 | 69.1M | } |
78 | 8.88M | size_t PropertyFromIndex(size_t index) const { |
79 | 8.88M | JXL_DASSERT(index < props_to_use.size()); |
80 | 8.88M | return props_to_use[index]; |
81 | 8.88M | } |
82 | 4.00k | size_t NumPredictors() const { return predictors.size(); } |
83 | 2.00k | size_t NumProperties() const { return props_to_use.size(); } |
84 | | |
85 | | // Preallocate data for a given number of samples. MUST be called before |
86 | | // adding any sample. |
87 | | void PrepareForSamples(size_t extra_num_samples); |
88 | | // Add a sample. |
89 | | void AddSample(pixel_type_w pixel, const Properties &properties, |
90 | | const pixel_type_w *predictions); |
91 | | // Pre-cluster property values. |
92 | | void PreQuantizeProperties( |
93 | | const StaticPropRange &range, |
94 | | const std::vector<ModularMultiplierInfo> &multiplier_info, |
95 | | const std::vector<uint32_t> &group_pixel_count, |
96 | | const std::vector<uint32_t> &channel_pixel_count, |
97 | | std::vector<pixel_type> &pixel_samples, |
98 | | std::vector<pixel_type> &diff_samples, size_t max_property_values); |
99 | | |
100 | 1.00k | void AllSamplesDone() { dedup_table_ = std::vector<uint32_t>(); } |
101 | | |
102 | 60.8M | uint32_t QuantizeProperty(uint32_t prop, pixel_type v) const { |
103 | 60.8M | JXL_DASSERT(prop >= num_static_props); |
104 | 60.8M | v = jxl::Clamp1(v, -kPropertyRange, kPropertyRange) + kPropertyRange; |
105 | 60.8M | return property_mapping[prop - num_static_props][v]; |
106 | 60.8M | } |
107 | | |
108 | 24.3M | uint32_t QuantizeStaticProperty(uint32_t prop, pixel_type v) const { |
109 | 24.3M | JXL_DASSERT(prop < num_static_props); |
110 | 24.3M | v = jxl::Clamp1(v, -kPropertyRange, kPropertyRange) + kPropertyRange; |
111 | 24.3M | return static_property_mapping[prop][v]; |
112 | 24.3M | } |
113 | | |
114 | | // Swaps samples in position a and b. Does nothing if a == b. |
115 | | void Swap(size_t a, size_t b); |
116 | | |
117 | | private: |
118 | | // TODO(veluca): as the total number of properties and predictors are known |
119 | | // before adding any samples, it might be better to interleave predictors, |
120 | | // properties and counts in a single vector to improve locality. |
121 | | // A first attempt at doing this actually results in much slower encoding, |
122 | | // possibly because of the more complex addressing. |
123 | | // Residual information: token and number of extra bits, per predictor. |
124 | | std::vector<std::vector<ResidualToken>> residuals; |
125 | | // Number of occurrences of each sample. |
126 | | std::vector<uint16_t> sample_counts; |
127 | | // Quantized static property values |
128 | | size_t num_static_props; |
129 | | std::array<std::vector<uint32_t>, kNumStaticProperties> static_props; |
130 | | // Property values, quantized to at most 256 distinct values. |
131 | | std::vector<std::vector<uint8_t>> props; |
132 | | // Decompactification info for `props`. |
133 | | std::vector<std::vector<int32_t>> compact_properties; |
134 | | // List of properties to use. |
135 | | std::vector<uint32_t> props_to_use; |
136 | | // List of predictors to use. |
137 | | std::vector<Predictor> predictors; |
138 | | // Mapping property value -> quantized property value. |
139 | | static constexpr int32_t kPropertyRange = 511; |
140 | | std::array<std::vector<uint16_t>, kNumStaticProperties> |
141 | | static_property_mapping; |
142 | | std::vector<std::vector<uint8_t>> property_mapping; |
143 | | // Number of samples seen. |
144 | | size_t num_samples = 0; |
145 | | // Table for deduplication. |
146 | | static constexpr uint32_t kDedupEntryUnused{static_cast<uint32_t>(-1)}; |
147 | | std::vector<uint32_t> dedup_table_; |
148 | | |
149 | | // Functions for sample deduplication. |
150 | | bool IsSameSample(size_t a, size_t b) const; |
151 | | size_t Hash1(size_t a) const; |
152 | | size_t Hash2(size_t a) const; |
153 | | void InitTable(size_t log_size); |
154 | | // Returns true if `a` was already present in the table. |
155 | | bool AddToTableAndMerge(size_t a); |
156 | | void AddToTable(size_t a); |
157 | | }; |
158 | | |
159 | | Status TokenizeTree(const Tree &tree, std::vector<Token> *tokens, |
160 | | Tree *decoder_tree); |
161 | | |
162 | | void CollectPixelSamples(const Image &image, const ModularOptions &options, |
163 | | uint32_t group_id, |
164 | | std::vector<uint32_t> &group_pixel_count, |
165 | | std::vector<uint32_t> &channel_pixel_count, |
166 | | std::vector<pixel_type> &pixel_samples, |
167 | | std::vector<pixel_type> &diff_samples); |
168 | | |
169 | | Status ComputeBestTree(TreeSamples &tree_samples, float threshold, |
170 | | const std::vector<ModularMultiplierInfo> &mul_info, |
171 | | StaticPropRange static_prop_range, |
172 | | float fast_decode_multiplier, Tree *tree); |
173 | | |
174 | | } // namespace jxl |
175 | | #endif // LIB_JXL_MODULAR_ENCODING_ENC_MA_H_ |