Coverage Report

Created: 2026-05-24 07:45

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
    kLZ77,     // try lz77 with backward references.
49
    kOptimal,  // optimal-matching LZ77 parsing.
50
  };
51
52
  enum class ANSHistogramStrategy {
53
    kFast,         // Only try some methods, early exit.
54
    kApproximate,  // Only try some methods.
55
    kPrecise,      // Try all methods.
56
  };
57
58
347k
  HistogramParams() = default;
59
60
3.96k
  HistogramParams(SpeedTier tier, size_t num_ctx) {
61
3.96k
    if (tier > SpeedTier::kFalcon) {
62
0
      clustering = ClusteringType::kFastest;
63
0
      lz77_method = LZ77Method::kNone;
64
3.96k
    } else if (tier > SpeedTier::kTortoise) {
65
3.96k
      clustering = ClusteringType::kFast;
66
3.96k
    } else {
67
0
      clustering = ClusteringType::kBest;
68
0
    }
69
3.96k
    if (tier > SpeedTier::kTortoise) {
70
3.96k
      uint_method = HybridUintMethod::kNone;
71
3.96k
    }
72
3.96k
    if (tier >= SpeedTier::kSquirrel) {
73
3.96k
      ans_histogram_strategy = ANSHistogramStrategy::kApproximate;
74
3.96k
    }
75
3.96k
  }
76
77
  static HistogramParams ForModular(
78
      const CompressParams& cparams,
79
      const std::vector<uint8_t>& extra_dc_precision, bool streaming_mode);
80
81
133k
  HybridUintConfig UintConfig() const {
82
133k
    if (uint_method == HistogramParams::HybridUintMethod::kContextMap) {
83
92.5k
      return HybridUintConfig(2, 0, 1);
84
92.5k
    }
85
41.3k
    if (uint_method == HistogramParams::HybridUintMethod::k000) {
86
0
      return HybridUintConfig(0, 0, 0);
87
0
    }
88
    // Default config for clustering.
89
41.3k
    return HybridUintConfig();
90
41.3k
  }
91
92
  ClusteringType clustering = ClusteringType::kBest;
93
  HybridUintMethod uint_method = HybridUintMethod::kBest;
94
  LZ77Method lz77_method = LZ77Method::kRLE;
95
  ANSHistogramStrategy ans_histogram_strategy = ANSHistogramStrategy::kPrecise;
96
  std::vector<size_t> image_widths;
97
  size_t max_histograms = ~0;
98
  bool force_huffman = false;
99
  bool initialize_global_state = true;
100
  bool streaming_mode = false;
101
  bool add_missing_symbols = false;
102
  bool add_fixed_histograms = false;
103
};
104
105
struct Histogram {
106
26.4M
  Histogram() = default;
107
108
0
  explicit Histogram(size_t length) { EnsureCapacity(length); }
109
110
  // Create flat histogram
111
46
  static Histogram Flat(int length, int total_count) {
112
46
    Histogram flat;
113
46
    flat.counts = CreateFlatHistogram(length, total_count);
114
46
    flat.total_count = static_cast<size_t>(total_count);
115
46
    return flat;
116
46
  }
117
0
  void Clear() {
118
0
    counts.clear();
119
0
    total_count = 0;
120
0
    entropy = 0.0;
121
0
  }
122
471M
  void Add(size_t symbol) {
123
471M
    if (counts.size() <= symbol) {
124
5.68M
      counts.resize(DivCeil(symbol + 1, kRounding) * kRounding);
125
5.68M
    }
126
471M
    ++counts[symbol];
127
471M
    ++total_count;
128
471M
  }
129
130
  // Use this before FastAdd sequence.
131
731k
  void EnsureCapacity(size_t length) {
132
731k
    counts.resize(DivCeil(length, kRounding) * kRounding);
133
731k
  }
134
  // Just increment symbol counter; caller must stretch Histogram beforehead.
135
389M
  void FastAdd(size_t symbol) { (*(counts.data() + symbol))++; }
136
  // Should be called after sequence of FastAdd to actualize total_count.
137
  void Condition();
138
139
4.06M
  void AddHistogram(const Histogram& other) {
140
4.06M
    if (other.counts.size() > counts.size()) {
141
99.3k
      counts.resize(other.counts.size());
142
99.3k
    }
143
57.5M
    for (size_t i = 0; i < other.counts.size(); ++i) {
144
53.4M
      counts[i] += other.counts[i];
145
53.4M
    }
146
4.06M
    total_count += other.total_count;
147
4.06M
  }
148
2.46M
  size_t alphabet_size() const {
149
11.2M
    for (int i = counts.size() - 1; i >= 0; --i) {
150
11.2M
      if (counts[i] > 0) {
151
2.46M
        return i + 1;
152
2.46M
      }
153
11.2M
    }
154
0
    return 0;
155
2.46M
  }
156
157
87.8k
  size_t MaxSymbol() const {
158
87.8k
    if (total_count == 0) return 0;
159
380k
    for (int i = counts.size() - 1; i > 0; --i) {
160
380k
      if (counts[i]) return i;
161
380k
    }
162
455
    return 0;
163
87.8k
  }
164
165
  // Returns an estimate of the number of bits required to encode the given
166
  // histogram (header bits plus data bits).
167
  StatusOr<float> ANSPopulationCost() const;
168
169
  float ShannonEntropy() const;
170
171
192k
  void swap(Histogram& other) {
172
192k
    counts.swap(other.counts);
173
192k
    std::swap(total_count, other.total_count);
174
192k
    std::swap(entropy, other.entropy);
175
192k
  }
176
177
  std::vector<ANSHistBin> counts;
178
  size_t total_count = 0;
179
  mutable float entropy = 0;  // WARNING: not kept up-to-date.
180
  static constexpr size_t kRounding = 8;
181
};
182
183
}  // namespace jxl
184
185
#endif  // LIB_JXL_ENC_ANS_PARAMS_H_