Coverage Report

Created: 2026-06-30 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libjxl/lib/jxl/splines.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_SPLINES_H_
7
#define LIB_JXL_SPLINES_H_
8
9
#include <jxl/memory_manager.h>
10
11
#include <array>
12
#include <cmath>
13
#include <cstddef>
14
#include <cstdint>
15
#include <utility>
16
#include <vector>
17
18
#include "lib/jxl/base/compiler_specific.h"
19
#include "lib/jxl/base/rect.h"
20
#include "lib/jxl/base/span.h"
21
#include "lib/jxl/base/status.h"
22
#include "lib/jxl/chroma_from_luma.h"
23
#include "lib/jxl/image.h"
24
#include "lib/jxl/memory_manager_internal.h"
25
26
namespace jxl {
27
28
class ANSSymbolReader;
29
class BitReader;
30
31
static constexpr float kDesiredRenderingDistance = 1.f;
32
33
using Dct32 = std::array<float, 32>;
34
35
enum SplineEntropyContexts : size_t {
36
  kQuantizationAdjustmentContext = 0,
37
  kStartingPositionContext,
38
  kNumSplinesContext,
39
  kNumControlPointsContext,
40
  kControlPointsContext,
41
  kDCTContext,
42
  kNumSplineContexts
43
};
44
45
struct Spline {
46
  struct Point {
47
5.48M
    Point() : x(0.0f), y(0.0f) {}
48
26.1M
    Point(float x, float y) : x(x), y(y) {}
49
    float x, y;
50
74.5k
    bool operator==(const Point& other) const {
51
74.5k
      return std::fabs(x - other.x) < 1e-3f && std::fabs(y - other.y) < 1e-3f;
52
74.5k
    }
53
  };
54
  std::vector<Point> control_points;
55
  // X, Y, B.
56
  std::array<Dct32, 3> color_dct;
57
  // Splines are draws by normalized Gaussian splatting. This controls the
58
  // Gaussian's parameter along the spline.
59
  Dct32 sigma_dct;
60
};
61
62
class QuantizedSplineEncoder;
63
64
class QuantizedSpline {
65
 public:
66
71.5k
  QuantizedSpline() = default;
67
68
  // TODO(eustas): move this out of library code
69
  static StatusOr<QuantizedSpline> Create(const Spline& original,
70
                                          int32_t quantization_adjustment,
71
                                          float y_to_x, float y_to_b);
72
73
  Status Dequantize(const Spline::Point& starting_point,
74
                    int32_t quantization_adjustment, float y_to_x, float y_to_b,
75
                    uint64_t image_size, uint64_t* total_estimated_area_reached,
76
                    Spline& result) const;
77
78
  Status Decode(const std::vector<uint8_t>& context_map,
79
                ANSSymbolReader* decoder, BitReader* br,
80
                size_t max_control_points, size_t* total_num_control_points);
81
82
 private:
83
  friend class QuantizedSplineEncoder;
84
85
  std::vector<std::pair<int64_t, int64_t>>
86
      control_points_;  // Double delta-encoded.
87
  int color_dct_[3][32] = {};
88
  int sigma_dct_[32] = {};
89
};
90
91
// A single "drawable unit" of a spline, i.e. a line of the region in which we
92
// render each Gaussian. The structure doesn't actually depend on the exact
93
// row, which allows reuse for different y values (which are tracked
94
// separately).
95
struct SplineSegment {
96
  float center_x, center_y;
97
  float maximum_distance;
98
  float inv_sigma;
99
  float sigma_over_4_times_intensity;
100
  float color[3];
101
};
102
103
struct SplineSegmentSpan {
104
  SplineSegmentSpan() = default;
105
1.11M
  SplineSegmentSpan(size_t start, size_t end) : start(start), end(end) {}
106
  size_t start;  // inclusive
107
  size_t end;    // exclusive
108
};
109
110
struct SplineDataView {
111
  Span<const QuantizedSpline> splines;
112
  Span<const Spline::Point> starting_points;
113
20.6k
  bool HasAny() const { return !splines.empty(); }
114
};
115
116
class Splines {
117
 public:
118
  explicit Splines(JxlMemoryManager* memory_manager)
119
30.8k
      : memory_manager_(memory_manager) {
120
30.8k
    Clear();
121
30.8k
  }
122
123
  // Cannot copy.
124
  Splines(const Splines&) = delete;
125
  Splines& operator=(const Splines&) = delete;
126
127
  // Move default.
128
  Splines(Splines&&) noexcept = default;
129
2.68k
  Splines& operator=(Splines&&) noexcept = default;
130
131
  void SetData(SplineDataView data);
132
133
16.1k
  bool HasAny() const { return data_.HasAny(); }
134
135
  void Clear();
136
137
  Status Decode(BitReader* br, size_t num_pixels);
138
139
  void AddTo(Image3F* opsin, const Rect& opsin_rect) const;
140
  void AddToRow(float* JXL_RESTRICT row_x, float* JXL_RESTRICT row_y,
141
                float* JXL_RESTRICT row_b, size_t y, size_t x0,
142
                size_t x1) const;
143
  void SubtractFrom(Image3F* opsin) const;
144
145
0
  Span<const QuantizedSpline> QuantizedSplines() const { return data_.splines; }
146
0
  Span<const Spline::Point> StartingPoints() const {
147
0
    return data_.starting_points;
148
0
  }
149
150
0
  int32_t GetQuantizationAdjustment() const { return quantization_adjustment_; }
151
152
  Status InitializeDrawCache(size_t image_xsize, size_t image_ysize,
153
                             const ColorCorrelation& color_correlation);
154
155
 private:
156
  template <bool>
157
  void ApplyToRow(float* JXL_RESTRICT row_x, float* JXL_RESTRICT row_y,
158
                  float* JXL_RESTRICT row_b, size_t y, size_t x0,
159
                  size_t x1) const;
160
  template <bool>
161
  void Apply(Image3F* opsin, const Rect& opsin_rect) const;
162
163
  // If positive, quantization weights are multiplied by 1 + this/8, which
164
  // increases precision. If negative, they are divided by 1 - this/8. If 0,
165
  // they are unchanged.
166
  JxlMemoryManager* memory_manager_;
167
  int32_t quantization_adjustment_ = 0;
168
169
  // Spline data storage
170
  // TODO(eustas): make memory-manager-tracked.
171
  std::vector<QuantizedSpline> splines_storage_;
172
  std::vector<Spline::Point> starting_points_storage_;
173
174
  SplineDataView data_;
175
  std::vector<SplineSegment> segments_;
176
  AlignedMemory /*size_t*/ segment_indices_;
177
  AlignedMemory /*ptrdiff_t*/ segment_y_start_;
178
};
179
180
}  // namespace jxl
181
182
#endif  // LIB_JXL_SPLINES_H_