Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libjxl/lib/jxl/enc_ans_params.h
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
6
#ifndef LIB_JXL_ENC_ANS_PARAMS_H_
7
#define LIB_JXL_ENC_ANS_PARAMS_H_
8
9
// Encoder-only parameter needed for ANS entropy encoding methods.
10
11
#include <cstdint>
12
#include <cstdlib>
13
#include <utility>
14
#include <vector>
15
16
#include "lib/jxl/ans_common.h"
17
#include "lib/jxl/base/common.h"
18
#include "lib/jxl/base/status.h"
19
#include "lib/jxl/common.h"
20
#include "lib/jxl/dec_ans.h"
21
22
namespace jxl {
23
24
// Forward declaration to break include cycle.
25
struct CompressParams;
26
27
// RebalanceHistogram requires a signed type.
28
using ANSHistBin = int32_t;
29
30
struct HistogramParams {
31
  enum class ClusteringType {
32
    kFastest,  // Only 4 clusters.
33
    kFast,
34
    kBest,
35
  };
36
37
  enum class HybridUintMethod {
38
    kNone,        // just use kHybridUint420Config.
39
    k000,         // force the fastest option.
40
    kFast,        // just try a couple of options.
41
    kContextMap,  // fast choice for ctx map.
42
    kBest,
43
  };
44
45
  enum class LZ77Method {
46
    kNone,          // do not try lz77.
47
    kRLE,           // only try doing RLE.
48
    kLZ77b1w3f,     // lz77 fast without runtime cost comparison
49
    kLZ77b3w3f,     // lz77
50
    kLZ77b7w3f,     // lz77
51
    kLZ77b15w3f,    // lz77
52
    kLZ77b31w3f,    // lz77 slow
53
    kLZ77b1w3t,     // lz77 fast with runtime cost comparison (almost always worse)
54
    kLZ77b3w3t,     // lz77
55
    kLZ77b7w3t,     // lz77
56
    kLZ77b15w3t,    // lz77
57
    kLZ77b31w3t,    // lz77 slow
58
    kOptc1,         // optimal-matching LZ77 fast.
59
    kOptc3,         // optimal-matching LZ77
60
    kOptc8,         // optimal-matching LZ77
61
    kOptc256,       // optimal-matching LZ77 parsing big chain length.
62
  };
63
64
  enum class ANSHistogramStrategy {
65
    kFast,         // Only try some methods, early exit.
66
    kApproximate,  // Only try some methods.
67
    kPrecise,      // Try all methods.
68
  };
69
70
49.2k
  HistogramParams() = default;
71
72
0
  HistogramParams(SpeedTier tier, size_t num_ctx) {
73
0
    if (tier > SpeedTier::kFalcon) {
74
0
      clustering = ClusteringType::kFastest;
75
0
      lz77_method = LZ77Method::kNone;
76
0
    } else if (tier > SpeedTier::kTortoise) {
77
0
      clustering = ClusteringType::kFast;
78
0
    } else {
79
0
      clustering = ClusteringType::kBest;
80
0
    }
81
0
    if (tier > SpeedTier::kTortoise) {
82
0
      uint_method = HybridUintMethod::kNone;
83
0
    }
84
0
    if (tier >= SpeedTier::kSquirrel) {
85
0
      ans_histogram_strategy = ANSHistogramStrategy::kApproximate;
86
0
    }
87
0
  }
88
89
  static HistogramParams ForModular(
90
      const CompressParams& cparams,
91
      const std::vector<uint8_t>& extra_dc_precision, bool streaming_mode);
92
93
0
  HybridUintConfig UintConfig() const {
94
0
    if (uint_method == HistogramParams::HybridUintMethod::kContextMap) {
95
0
      return HybridUintConfig(2, 0, 1);
96
0
    }
97
0
    if (uint_method == HistogramParams::HybridUintMethod::k000) {
98
0
      return HybridUintConfig(0, 0, 0);
99
0
    }
100
    // Default config for clustering.
101
0
    return HybridUintConfig();
102
0
  }
103
104
  ClusteringType clustering = ClusteringType::kBest;
105
  HybridUintMethod uint_method = HybridUintMethod::kBest;
106
  LZ77Method lz77_method = LZ77Method::kRLE;
107
  ANSHistogramStrategy ans_histogram_strategy = ANSHistogramStrategy::kPrecise;
108
  std::vector<size_t> image_widths;
109
  size_t max_histograms = ~0;
110
  bool force_huffman = false;
111
  bool initialize_global_state = true;
112
  bool streaming_mode = false;
113
  bool add_missing_symbols = false;
114
  bool add_fixed_histograms = false;
115
};
116
117
struct Histogram {
118
0
  Histogram() = default;
119
120
0
  explicit Histogram(size_t length) { EnsureCapacity(length); }
121
122
  // Create flat histogram
123
0
  static Histogram Flat(int length, int total_count) {
124
0
    Histogram flat;
125
0
    flat.counts = CreateFlatHistogram(length, total_count);
126
0
    flat.total_count = static_cast<size_t>(total_count);
127
0
    return flat;
128
0
  }
129
0
  void Clear() {
130
0
    counts.clear();
131
0
    total_count = 0;
132
0
    entropy = 0.0;
133
0
  }
134
0
  void Add(size_t symbol) {
135
0
    if (counts.size() <= symbol) {
136
0
      counts.resize(DivCeil(symbol + 1, kRounding) * kRounding);
137
0
    }
138
0
    ++counts[symbol];
139
0
    ++total_count;
140
0
  }
141
142
  // Use this before FastAdd sequence.
143
0
  void EnsureCapacity(size_t length) {
144
0
    counts.resize(DivCeil(length, kRounding) * kRounding);
145
0
  }
146
  // Just increment symbol counter; caller must stretch Histogram beforehead.
147
0
  void FastAdd(size_t symbol) { (*(counts.data() + symbol))++; }
148
  // Should be called after sequence of FastAdd to actualize total_count.
149
  void Condition();
150
151
0
  void AddHistogram(const Histogram& other) {
152
0
    if (other.counts.size() > counts.size()) {
153
0
      counts.resize(other.counts.size());
154
0
    }
155
0
    for (size_t i = 0; i < other.counts.size(); ++i) {
156
0
      counts[i] += other.counts[i];
157
0
    }
158
0
    total_count += other.total_count;
159
0
  }
160
0
  size_t alphabet_size() const {
161
0
    for (int i = counts.size() - 1; i >= 0; --i) {
162
0
      if (counts[i] > 0) {
163
0
        return i + 1;
164
0
      }
165
0
    }
166
0
    return 0;
167
0
  }
168
169
0
  size_t MaxSymbol() const {
170
0
    if (total_count == 0) return 0;
171
0
    for (int i = counts.size() - 1; i > 0; --i) {
172
0
      if (counts[i]) return i;
173
0
    }
174
0
    return 0;
175
0
  }
176
177
  // Returns an estimate of the number of bits required to encode the given
178
  // histogram (header bits plus data bits).
179
  StatusOr<float> ANSPopulationCost() const;
180
181
  float ShannonEntropy() const;
182
183
0
  void swap(Histogram& other) {
184
0
    counts.swap(other.counts);
185
0
    std::swap(total_count, other.total_count);
186
0
    std::swap(entropy, other.entropy);
187
0
  }
188
189
  std::vector<ANSHistBin> counts;
190
  size_t total_count = 0;
191
  mutable float entropy = 0;  // WARNING: not kept up-to-date.
192
  static constexpr size_t kRounding = 8;
193
};
194
195
}  // namespace jxl
196
197
#endif  // LIB_JXL_ENC_ANS_PARAMS_H_