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