Coverage Report

Created: 2025-07-23 08:18

/src/libjxl/lib/jxl/enc_ans_params.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_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
88.3k
  HistogramParams() = default;
59
60
2.13k
  HistogramParams(SpeedTier tier, size_t num_ctx) {
61
2.13k
    if (tier > SpeedTier::kFalcon) {
62
0
      clustering = ClusteringType::kFastest;
63
0
      lz77_method = LZ77Method::kNone;
64
2.13k
    } else if (tier > SpeedTier::kTortoise) {
65
2.13k
      clustering = ClusteringType::kFast;
66
2.13k
    } else {
67
0
      clustering = ClusteringType::kBest;
68
0
    }
69
2.13k
    if (tier > SpeedTier::kTortoise) {
70
2.13k
      uint_method = HybridUintMethod::kNone;
71
2.13k
    }
72
2.13k
    if (tier >= SpeedTier::kSquirrel) {
73
2.13k
      ans_histogram_strategy = ANSHistogramStrategy::kApproximate;
74
2.13k
    }
75
2.13k
  }
76
77
  static HistogramParams ForModular(
78
      const CompressParams& cparams,
79
      const std::vector<uint8_t>& extra_dc_precision, bool streaming_mode);
80
81
69.0k
  HybridUintConfig UintConfig() const {
82
69.0k
    if (uint_method == HistogramParams::HybridUintMethod::kContextMap) {
83
47.3k
      return HybridUintConfig(2, 0, 1);
84
47.3k
    }
85
21.7k
    if (uint_method == HistogramParams::HybridUintMethod::k000) {
86
0
      return HybridUintConfig(0, 0, 0);
87
0
    }
88
    // Default config for clustering.
89
21.7k
    return HybridUintConfig();
90
21.7k
  }
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
12.9M
  Histogram() = default;
107
108
0
  explicit Histogram(size_t length) { EnsureCapacity(length); }
109
110
  // Create flat histogram
111
0
  static Histogram Flat(int length, int total_count) {
112
0
    Histogram flat;
113
0
    flat.counts = CreateFlatHistogram(length, total_count);
114
0
    flat.total_count = static_cast<size_t>(total_count);
115
0
    return flat;
116
0
  }
117
0
  void Clear() {
118
0
    counts.clear();
119
0
    total_count = 0;
120
0
    entropy = 0.0;
121
0
  }
122
253M
  void Add(size_t symbol) {
123
253M
    if (counts.size() <= symbol) {
124
2.67M
      counts.resize(DivCeil(symbol + 1, kRounding) * kRounding);
125
2.67M
    }
126
253M
    ++counts[symbol];
127
253M
    ++total_count;
128
253M
  }
129
130
  // Use this before FastAdd sequence.
131
404k
  void EnsureCapacity(size_t length) {
132
404k
    counts.resize(DivCeil(length, kRounding) * kRounding);
133
404k
  }
134
  // Just increment symbol counter; caller must stretch Histogram beforehead.
135
267M
  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
1.72M
  void AddHistogram(const Histogram& other) {
140
1.72M
    if (other.counts.size() > counts.size()) {
141
47.7k
      counts.resize(other.counts.size());
142
47.7k
    }
143
25.4M
    for (size_t i = 0; i < other.counts.size(); ++i) {
144
23.7M
      counts[i] += other.counts[i];
145
23.7M
    }
146
1.72M
    total_count += other.total_count;
147
1.72M
  }
148
1.37M
  size_t alphabet_size() const {
149
6.15M
    for (int i = counts.size() - 1; i >= 0; --i) {
150
6.15M
      if (counts[i] > 0) {
151
1.37M
        return i + 1;
152
1.37M
      }
153
6.15M
    }
154
0
    return 0;
155
1.37M
  }
156
157
57.0k
  size_t MaxSymbol() const {
158
57.0k
    if (total_count == 0) return 0;
159
255k
    for (int i = counts.size() - 1; i > 0; --i) {
160
254k
      if (counts[i]) return i;
161
254k
    }
162
429
    return 0;
163
57.0k
  }
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
122k
  void swap(Histogram& other) {
172
122k
    counts.swap(other.counts);
173
122k
    std::swap(total_count, other.total_count);
174
122k
    std::swap(entropy, other.entropy);
175
122k
  }
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_