Coverage Report

Created: 2025-06-16 07:00

/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 <vector>
14
15
#include "lib/jxl/ans_common.h"
16
#include "lib/jxl/base/common.h"
17
#include "lib/jxl/base/status.h"
18
#include "lib/jxl/common.h"
19
#include "lib/jxl/dec_ans.h"
20
21
namespace jxl {
22
23
// Forward declaration to break include cycle.
24
struct CompressParams;
25
26
// RebalanceHistogram requires a signed type.
27
using ANSHistBin = int32_t;
28
29
struct HistogramParams {
30
  enum class ClusteringType {
31
    kFastest,  // Only 4 clusters.
32
    kFast,
33
    kBest,
34
  };
35
36
  enum class HybridUintMethod {
37
    kNone,        // just use kHybridUint420Config.
38
    k000,         // force the fastest option.
39
    kFast,        // just try a couple of options.
40
    kContextMap,  // fast choice for ctx map.
41
    kBest,
42
  };
43
44
  enum class LZ77Method {
45
    kNone,     // do not try lz77.
46
    kRLE,      // only try doing RLE.
47
    kLZ77,     // try lz77 with backward references.
48
    kOptimal,  // optimal-matching LZ77 parsing.
49
  };
50
51
  enum class ANSHistogramStrategy {
52
    kFast,         // Only try some methods, early exit.
53
    kApproximate,  // Only try some methods.
54
    kPrecise,      // Try all methods.
55
  };
56
57
36.4k
  HistogramParams() = default;
58
59
186
  HistogramParams(SpeedTier tier, size_t num_ctx) {
60
186
    if (tier > SpeedTier::kFalcon) {
61
0
      clustering = ClusteringType::kFastest;
62
0
      lz77_method = LZ77Method::kNone;
63
186
    } else if (tier > SpeedTier::kTortoise) {
64
186
      clustering = ClusteringType::kFast;
65
186
    } else {
66
0
      clustering = ClusteringType::kBest;
67
0
    }
68
186
    if (tier > SpeedTier::kTortoise) {
69
186
      uint_method = HybridUintMethod::kNone;
70
186
    }
71
186
    if (tier >= SpeedTier::kSquirrel) {
72
186
      ans_histogram_strategy = ANSHistogramStrategy::kApproximate;
73
186
    }
74
186
  }
75
76
  static HistogramParams ForModular(
77
      const CompressParams& cparams,
78
      const std::vector<uint8_t>& extra_dc_precision, bool streaming_mode);
79
80
7.06k
  HybridUintConfig UintConfig() const {
81
7.06k
    if (uint_method == HistogramParams::HybridUintMethod::kContextMap) {
82
5.09k
      return HybridUintConfig(2, 0, 1);
83
5.09k
    }
84
1.97k
    if (uint_method == HistogramParams::HybridUintMethod::k000) {
85
0
      return HybridUintConfig(0, 0, 0);
86
0
    }
87
    // Default config for clustering.
88
1.97k
    return HybridUintConfig();
89
1.97k
  }
90
91
  ClusteringType clustering = ClusteringType::kBest;
92
  HybridUintMethod uint_method = HybridUintMethod::kBest;
93
  LZ77Method lz77_method = LZ77Method::kRLE;
94
  ANSHistogramStrategy ans_histogram_strategy = ANSHistogramStrategy::kPrecise;
95
  std::vector<size_t> image_widths;
96
  size_t max_histograms = ~0;
97
  bool force_huffman = false;
98
  bool initialize_global_state = true;
99
  bool streaming_mode = false;
100
  bool add_missing_symbols = false;
101
  bool add_fixed_histograms = false;
102
};
103
104
struct Histogram {
105
598k
  Histogram() = default;
106
107
0
  explicit Histogram(size_t length) {
108
0
    counts.resize(DivCeil(length, kRounding) * kRounding);
109
0
  }
110
111
  // Create flat histogram
112
0
  static Histogram Flat(int length, int total_count) {
113
0
    Histogram flat;
114
0
    flat.counts = CreateFlatHistogram(length, total_count);
115
0
    flat.total_count = static_cast<size_t>(total_count);
116
0
    return flat;
117
0
  }
118
52.3k
  void Clear() {
119
52.3k
    counts.clear();
120
52.3k
    total_count = 0;
121
52.3k
    entropy = 0.0;
122
52.3k
  }
123
116M
  void Add(size_t symbol) {
124
116M
    if (counts.size() <= symbol) {
125
407k
      counts.resize(DivCeil(symbol + 1, kRounding) * kRounding);
126
407k
    }
127
116M
    ++counts[symbol];
128
116M
    ++total_count;
129
116M
  }
130
155k
  void AddHistogram(const Histogram& other) {
131
155k
    if (other.counts.size() > counts.size()) {
132
7.65k
      counts.resize(other.counts.size());
133
7.65k
    }
134
3.12M
    for (size_t i = 0; i < other.counts.size(); ++i) {
135
2.97M
      counts[i] += other.counts[i];
136
2.97M
    }
137
155k
    total_count += other.total_count;
138
155k
  }
139
186k
  size_t alphabet_size() const {
140
880k
    for (int i = counts.size() - 1; i >= 0; --i) {
141
880k
      if (counts[i] > 0) {
142
186k
        return i + 1;
143
186k
      }
144
880k
    }
145
0
    return 0;
146
186k
  }
147
148
  // Returns an estimate of the number of bits required to encode the given
149
  // histogram (header bits plus data bits).
150
  StatusOr<float> ANSPopulationCost() const;
151
152
  float ShannonEntropy() const;
153
154
  std::vector<ANSHistBin> counts;
155
  size_t total_count = 0;
156
  mutable float entropy = 0;  // WARNING: not kept up-to-date.
157
  static constexpr size_t kRounding = 8;
158
};
159
160
}  // namespace jxl
161
162
#endif  // LIB_JXL_ENC_ANS_PARAMS_H_