splines.h (4819B)
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 typedef std::array<float, 32> Dct32; 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 Point() : x(0.0f), y(0.0f) {} 46 Point(float x, float y) : x(x), y(y) {} 47 float x, y; 48 bool operator==(const Point& other) const { 49 return std::fabs(x - other.x) < 1e-3f && std::fabs(y - other.y) < 1e-3f; 50 } 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 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 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 starting_points_(std::move(starting_points)) {} 110 111 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 const std::vector<QuantizedSpline>& QuantizedSplines() const { 125 return splines_; 126 } 127 const std::vector<Spline::Point>& StartingPoints() const { 128 return starting_points_; 129 } 130 131 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_