Coverage Report

Created: 2025-06-16 07:00

/src/libjxl/lib/jxl/splines.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_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/status.h"
21
#include "lib/jxl/chroma_from_luma.h"
22
#include "lib/jxl/image.h"
23
24
namespace jxl {
25
26
class ANSSymbolReader;
27
class BitReader;
28
29
static constexpr float kDesiredRenderingDistance = 1.f;
30
31
using Dct32 = std::array<float, 32>;
32
33
enum SplineEntropyContexts : size_t {
34
  kQuantizationAdjustmentContext = 0,
35
  kStartingPositionContext,
36
  kNumSplinesContext,
37
  kNumControlPointsContext,
38
  kControlPointsContext,
39
  kDCTContext,
40
  kNumSplineContexts
41
};
42
43
struct Spline {
44
  struct Point {
45
6.46M
    Point() : x(0.0f), y(0.0f) {}
46
19.9M
    Point(float x, float y) : x(x), y(y) {}
47
    float x, y;
48
92.3k
    bool operator==(const Point& other) const {
49
92.3k
      return std::fabs(x - other.x) < 1e-3f && std::fabs(y - other.y) < 1e-3f;
50
92.3k
    }
51
  };
52
  std::vector<Point> control_points;
53
  // X, Y, B.
54
  std::array<Dct32, 3> color_dct;
55
  // Splines are draws by normalized Gaussian splatting. This controls the
56
  // Gaussian's parameter along the spline.
57
  Dct32 sigma_dct;
58
};
59
60
class QuantizedSplineEncoder;
61
62
class QuantizedSpline {
63
 public:
64
13.7k
  QuantizedSpline() = default;
65
66
  // TODO(eustas): move this out of library code
67
  static StatusOr<QuantizedSpline> Create(const Spline& original,
68
                                          int32_t quantization_adjustment,
69
                                          float y_to_x, float y_to_b);
70
71
  Status Dequantize(const Spline::Point& starting_point,
72
                    int32_t quantization_adjustment, float y_to_x, float y_to_b,
73
                    uint64_t image_size, uint64_t* total_estimated_area_reached,
74
                    Spline& result) const;
75
76
  Status Decode(const std::vector<uint8_t>& context_map,
77
                ANSSymbolReader* decoder, BitReader* br,
78
                size_t max_control_points, size_t* total_num_control_points);
79
80
 private:
81
  friend class QuantizedSplineEncoder;
82
83
  std::vector<std::pair<int64_t, int64_t>>
84
      control_points_;  // Double delta-encoded.
85
  int color_dct_[3][32] = {};
86
  int sigma_dct_[32] = {};
87
};
88
89
// A single "drawable unit" of a spline, i.e. a line of the region in which we
90
// render each Gaussian. The structure doesn't actually depend on the exact
91
// row, which allows reuse for different y values (which are tracked
92
// separately).
93
struct SplineSegment {
94
  float center_x, center_y;
95
  float maximum_distance;
96
  float inv_sigma;
97
  float sigma_over_4_times_intensity;
98
  float color[3];
99
};
100
101
class Splines {
102
 public:
103
11.7k
  Splines() = default;
104
  explicit Splines(const int32_t quantization_adjustment,
105
                   std::vector<QuantizedSpline> splines,
106
                   std::vector<Spline::Point> starting_points)
107
      : quantization_adjustment_(quantization_adjustment),
108
        splines_(std::move(splines)),
109
0
        starting_points_(std::move(starting_points)) {}
110
111
4.69k
  bool HasAny() const { return !splines_.empty(); }
112
113
  void Clear();
114
115
  Status Decode(JxlMemoryManager* memory_manager, BitReader* br,
116
                size_t num_pixels);
117
118
  void AddTo(Image3F* opsin, const Rect& opsin_rect) const;
119
  void AddToRow(float* JXL_RESTRICT row_x, float* JXL_RESTRICT row_y,
120
                float* JXL_RESTRICT row_b, size_t y, size_t x0,
121
                size_t x1) const;
122
  void SubtractFrom(Image3F* opsin) const;
123
124
0
  const std::vector<QuantizedSpline>& QuantizedSplines() const {
125
0
    return splines_;
126
0
  }
127
0
  const std::vector<Spline::Point>& StartingPoints() const {
128
0
    return starting_points_;
129
0
  }
130
131
0
  int32_t GetQuantizationAdjustment() const { return quantization_adjustment_; }
132
133
  Status InitializeDrawCache(size_t image_xsize, size_t image_ysize,
134
                             const ColorCorrelation& color_correlation);
135
136
 private:
137
  template <bool>
138
  void ApplyToRow(float* JXL_RESTRICT row_x, float* JXL_RESTRICT row_y,
139
                  float* JXL_RESTRICT row_b, size_t y, size_t x0,
140
                  size_t x1) const;
141
  template <bool>
142
  void Apply(Image3F* opsin, const Rect& opsin_rect) const;
143
144
  // If positive, quantization weights are multiplied by 1 + this/8, which
145
  // increases precision. If negative, they are divided by 1 - this/8. If 0,
146
  // they are unchanged.
147
  int32_t quantization_adjustment_ = 0;
148
  std::vector<QuantizedSpline> splines_;
149
  std::vector<Spline::Point> starting_points_;
150
  std::vector<SplineSegment> segments_;
151
  std::vector<size_t> segment_indices_;
152
  std::vector<size_t> segment_y_start_;
153
};
154
155
}  // namespace jxl
156
157
#endif  // LIB_JXL_SPLINES_H_