/src/libjxl/lib/jxl/base/rect.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_BASE_RECT_H_ |
7 | | #define LIB_JXL_BASE_RECT_H_ |
8 | | |
9 | | #include <algorithm> |
10 | | #include <cstddef> |
11 | | #include <cstdint> |
12 | | #include <cstring> |
13 | | #include <sstream> |
14 | | #include <string> |
15 | | #include <utility> // std::move |
16 | | |
17 | | #include "lib/jxl/base/compiler_specific.h" |
18 | | #include "lib/jxl/base/status.h" |
19 | | |
20 | | namespace jxl { |
21 | | |
22 | | // Rectangular region in image(s). Factoring this out of Image instead of |
23 | | // shifting the pointer by x0/y0 allows this to apply to multiple images with |
24 | | // different resolutions (e.g. color transform and quantization field). |
25 | | // Can compare using SameSize(rect1, rect2). |
26 | | template <typename T> |
27 | | class RectT { |
28 | | public: |
29 | | // Most windows are xsize_max * ysize_max, except those on the borders where |
30 | | // begin + size_max > end. |
31 | | constexpr RectT(T xbegin, T ybegin, size_t xsize_max, size_t ysize_max, |
32 | | T xend, T yend) |
33 | 1.10M | : x0_(xbegin), |
34 | 1.10M | y0_(ybegin), |
35 | 1.10M | xsize_(ClampedSize(xbegin, xsize_max, xend)), |
36 | 1.10M | ysize_(ClampedSize(ybegin, ysize_max, yend)) {} jxl::RectT<unsigned long>::RectT(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) Line | Count | Source | 33 | 1.06M | : x0_(xbegin), | 34 | 1.06M | y0_(ybegin), | 35 | 1.06M | xsize_(ClampedSize(xbegin, xsize_max, xend)), | 36 | 1.06M | ysize_(ClampedSize(ybegin, ysize_max, yend)) {} |
jxl::RectT<long>::RectT(long, long, unsigned long, unsigned long, long, long) Line | Count | Source | 33 | 41.1k | : x0_(xbegin), | 34 | 41.1k | y0_(ybegin), | 35 | 41.1k | xsize_(ClampedSize(xbegin, xsize_max, xend)), | 36 | 41.1k | ysize_(ClampedSize(ybegin, ysize_max, yend)) {} |
|
37 | | |
38 | | // Construct with origin and known size (typically from another Rect). |
39 | | constexpr RectT(T xbegin, T ybegin, size_t xsize, size_t ysize) |
40 | 5.33M | : x0_(xbegin), y0_(ybegin), xsize_(xsize), ysize_(ysize) {} jxl::RectT<unsigned long>::RectT(unsigned long, unsigned long, unsigned long, unsigned long) Line | Count | Source | 40 | 4.05M | : x0_(xbegin), y0_(ybegin), xsize_(xsize), ysize_(ysize) {} |
jxl::RectT<long>::RectT(long, long, unsigned long, unsigned long) Line | Count | Source | 40 | 1.28M | : x0_(xbegin), y0_(ybegin), xsize_(xsize), ysize_(ysize) {} |
|
41 | | |
42 | | // Construct a rect that covers a whole image/plane/ImageBundle etc. |
43 | | template <typename ImageT> |
44 | | explicit RectT(const ImageT& image) |
45 | 485k | : RectT(0, 0, image.xsize(), image.ysize()) {} jxl::RectT<unsigned long>::RectT<jxl::Plane<float> >(jxl::Plane<float> const&) Line | Count | Source | 45 | 251k | : RectT(0, 0, image.xsize(), image.ysize()) {} |
jxl::RectT<unsigned long>::RectT<jxl::Plane<int> >(jxl::Plane<int> const&) Line | Count | Source | 45 | 234k | : RectT(0, 0, image.xsize(), image.ysize()) {} |
Unexecuted instantiation: jxl::RectT<unsigned long>::RectT<jxl::Image3<float> >(jxl::Image3<float> const&) |
46 | | |
47 | 1.43M | RectT() : RectT(0, 0, 0, 0) {} |
48 | | |
49 | | RectT(const RectT&) = default; |
50 | | RectT& operator=(const RectT&) = default; |
51 | | |
52 | | // Construct a subrect that resides in an image/plane/ImageBundle etc. |
53 | | template <typename ImageT> |
54 | 191k | RectT Crop(const ImageT& image) const { |
55 | 191k | return Intersection(RectT(image)); |
56 | 191k | } |
57 | | |
58 | | // Construct a subrect that resides in the [0, ysize) x [0, xsize) region of |
59 | | // the current rect. |
60 | 63.6k | RectT Crop(size_t area_xsize, size_t area_ysize) const { |
61 | 63.6k | return Intersection(RectT(0, 0, area_xsize, area_ysize)); |
62 | 63.6k | } |
63 | | |
64 | 296k | JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const { |
65 | 296k | return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_, |
66 | 296k | ysize_, std::min(x1(), other.x1()), |
67 | 296k | std::min(y1(), other.y1())); |
68 | 296k | } jxl::RectT<unsigned long>::Intersection(jxl::RectT<unsigned long> const&) const Line | Count | Source | 64 | 255k | JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const { | 65 | 255k | return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_, | 66 | 255k | ysize_, std::min(x1(), other.x1()), | 67 | 255k | std::min(y1(), other.y1())); | 68 | 255k | } |
jxl::RectT<long>::Intersection(jxl::RectT<long> const&) const Line | Count | Source | 64 | 41.1k | JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const { | 65 | 41.1k | return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_, | 66 | 41.1k | ysize_, std::min(x1(), other.x1()), | 67 | 41.1k | std::min(y1(), other.y1())); | 68 | 41.1k | } |
|
69 | | |
70 | | JXL_MUST_USE_RESULT RectT Translate(int64_t x_offset, |
71 | 509k | int64_t y_offset) const { |
72 | 509k | return RectT(x0_ + x_offset, y0_ + y_offset, xsize_, ysize_); |
73 | 509k | } Unexecuted instantiation: jxl::RectT<unsigned long>::Translate(long, long) const jxl::RectT<long>::Translate(long, long) const Line | Count | Source | 71 | 509k | int64_t y_offset) const { | 72 | 509k | return RectT(x0_ + x_offset, y0_ + y_offset, xsize_, ysize_); | 73 | 509k | } |
|
74 | | |
75 | | template <template <class> class P, typename V> |
76 | 26.7M | V* Row(P<V>* image, size_t y) const { |
77 | 26.7M | JXL_DASSERT(y + y0_ >= 0); |
78 | 26.7M | return image->Row(y + y0_) + x0_; |
79 | 26.7M | } float* jxl::RectT<unsigned long>::Row<jxl::Plane, float>(jxl::Plane<float>*, unsigned long) const Line | Count | Source | 76 | 15.5M | V* Row(P<V>* image, size_t y) const { | 77 | 15.5M | JXL_DASSERT(y + y0_ >= 0); | 78 | 15.5M | return image->Row(y + y0_) + x0_; | 79 | 15.5M | } |
unsigned char* jxl::RectT<unsigned long>::Row<jxl::Plane, unsigned char>(jxl::Plane<unsigned char>*, unsigned long) const Line | Count | Source | 76 | 403k | V* Row(P<V>* image, size_t y) const { | 77 | 403k | JXL_DASSERT(y + y0_ >= 0); | 78 | 403k | return image->Row(y + y0_) + x0_; | 79 | 403k | } |
int* jxl::RectT<unsigned long>::Row<jxl::Plane, int>(jxl::Plane<int>*, unsigned long) const Line | Count | Source | 76 | 10.5M | V* Row(P<V>* image, size_t y) const { | 77 | 10.5M | JXL_DASSERT(y + y0_ >= 0); | 78 | 10.5M | return image->Row(y + y0_) + x0_; | 79 | 10.5M | } |
signed char* jxl::RectT<unsigned long>::Row<jxl::Plane, signed char>(jxl::Plane<signed char>*, unsigned long) const Line | Count | Source | 76 | 61.4k | V* Row(P<V>* image, size_t y) const { | 77 | 61.4k | JXL_DASSERT(y + y0_ >= 0); | 78 | 61.4k | return image->Row(y + y0_) + x0_; | 79 | 61.4k | } |
float* jxl::RectT<long>::Row<jxl::Plane, float>(jxl::Plane<float>*, unsigned long) const Line | Count | Source | 76 | 234k | V* Row(P<V>* image, size_t y) const { | 77 | 234k | JXL_DASSERT(y + y0_ >= 0); | 78 | 234k | return image->Row(y + y0_) + x0_; | 79 | 234k | } |
|
80 | | |
81 | | template <template <class> class P, typename V> |
82 | | const V* Row(const P<V>* image, size_t y) const { |
83 | | JXL_DASSERT(y + y0_ >= 0); |
84 | | return image->Row(y + y0_) + x0_; |
85 | | } |
86 | | |
87 | | template <template <class> class MP, typename V> |
88 | 596k | V* PlaneRow(MP<V>* image, const size_t c, size_t y) const { |
89 | 596k | JXL_DASSERT(y + y0_ >= 0); |
90 | 596k | return image->PlaneRow(c, y + y0_) + x0_; |
91 | 596k | } |
92 | | |
93 | | template <template <class> class P, typename V> |
94 | 3.10M | const V* ConstRow(const P<V>& image, size_t y) const { |
95 | 3.10M | JXL_DASSERT(y + y0_ >= 0); |
96 | 3.10M | return image.ConstRow(y + y0_) + x0_; |
97 | 3.10M | } float const* jxl::RectT<unsigned long>::ConstRow<jxl::Plane, float>(jxl::Plane<float> const&, unsigned long) const Line | Count | Source | 94 | 2.28M | const V* ConstRow(const P<V>& image, size_t y) const { | 95 | 2.28M | JXL_DASSERT(y + y0_ >= 0); | 96 | 2.28M | return image.ConstRow(y + y0_) + x0_; | 97 | 2.28M | } |
int const* jxl::RectT<unsigned long>::ConstRow<jxl::Plane, int>(jxl::Plane<int> const&, unsigned long) const Line | Count | Source | 94 | 677k | const V* ConstRow(const P<V>& image, size_t y) const { | 95 | 677k | JXL_DASSERT(y + y0_ >= 0); | 96 | 677k | return image.ConstRow(y + y0_) + x0_; | 97 | 677k | } |
unsigned char const* jxl::RectT<unsigned long>::ConstRow<jxl::Plane, unsigned char>(jxl::Plane<unsigned char> const&, unsigned long) const Line | Count | Source | 94 | 141k | const V* ConstRow(const P<V>& image, size_t y) const { | 95 | 141k | JXL_DASSERT(y + y0_ >= 0); | 96 | 141k | return image.ConstRow(y + y0_) + x0_; | 97 | 141k | } |
|
98 | | |
99 | | template <template <class> class MP, typename V> |
100 | 510k | const V* ConstPlaneRow(const MP<V>& image, size_t c, size_t y) const { |
101 | 510k | JXL_DASSERT(y + y0_ >= 0); |
102 | 510k | return image.ConstPlaneRow(c, y + y0_) + x0_; |
103 | 510k | } |
104 | | |
105 | 318k | bool IsInside(const RectT& other) const { |
106 | 318k | return x0_ >= other.x0() && x1() <= other.x1() && y0_ >= other.y0() && |
107 | 318k | y1() <= other.y1(); |
108 | 318k | } |
109 | | |
110 | | bool IsSame(const RectT& other) const { |
111 | | return x0_ == other.x0_ && xsize_ == other.xsize_ && y0_ == other.y0_ && |
112 | | ysize_ <= other.ysize_; |
113 | | } |
114 | | |
115 | | // Returns true if this Rect fully resides in the given image. ImageT could be |
116 | | // Plane<T> or Image3<T>; however if ImageT is Rect, results are nonsensical. |
117 | | template <class ImageT> |
118 | 275k | bool IsInside(const ImageT& image) const { |
119 | 275k | return IsInside(RectT(image)); |
120 | 275k | } bool jxl::RectT<unsigned long>::IsInside<jxl::Plane<float> >(jxl::Plane<float> const&) const Line | Count | Source | 118 | 251k | bool IsInside(const ImageT& image) const { | 119 | 251k | return IsInside(RectT(image)); | 120 | 251k | } |
bool jxl::RectT<unsigned long>::IsInside<jxl::Plane<int> >(jxl::Plane<int> const&) const Line | Count | Source | 118 | 23.7k | bool IsInside(const ImageT& image) const { | 119 | 23.7k | return IsInside(RectT(image)); | 120 | 23.7k | } |
|
121 | | |
122 | 42.5M | T x0() const { return x0_; } jxl::RectT<unsigned long>::x0() const Line | Count | Source | 122 | 42.5M | T x0() const { return x0_; } |
jxl::RectT<long>::x0() const Line | Count | Source | 122 | 28.3k | T x0() const { return x0_; } |
|
123 | 44.0M | T y0() const { return y0_; } jxl::RectT<unsigned long>::y0() const Line | Count | Source | 123 | 44.0M | T y0() const { return y0_; } |
jxl::RectT<long>::y0() const Line | Count | Source | 123 | 12.7k | T y0() const { return y0_; } |
|
124 | 70.2M | size_t xsize() const { return xsize_; } jxl::RectT<unsigned long>::xsize() const Line | Count | Source | 124 | 70.2M | size_t xsize() const { return xsize_; } |
jxl::RectT<long>::xsize() const Line | Count | Source | 124 | 35.8k | size_t xsize() const { return xsize_; } |
|
125 | 52.3M | size_t ysize() const { return ysize_; } jxl::RectT<unsigned long>::ysize() const Line | Count | Source | 125 | 52.3M | size_t ysize() const { return ysize_; } |
jxl::RectT<long>::ysize() const Line | Count | Source | 125 | 28.0k | size_t ysize() const { return ysize_; } |
|
126 | 1.32M | T x1() const { return x0_ + xsize_; } jxl::RectT<unsigned long>::x1() const Line | Count | Source | 126 | 1.21M | T x1() const { return x0_ + xsize_; } |
jxl::RectT<long>::x1() const Line | Count | Source | 126 | 110k | T x1() const { return x0_ + xsize_; } |
|
127 | 1.24M | T y1() const { return y0_ + ysize_; } jxl::RectT<unsigned long>::y1() const Line | Count | Source | 127 | 1.14M | T y1() const { return y0_ + ysize_; } |
jxl::RectT<long>::y1() const Line | Count | Source | 127 | 94.9k | T y1() const { return y0_ + ysize_; } |
|
128 | | |
129 | 297k | RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const { |
130 | 297k | return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx, |
131 | 297k | ysize_ << shifty); |
132 | 297k | } jxl::RectT<long>::ShiftLeft(unsigned long, unsigned long) const Line | Count | Source | 129 | 234k | RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const { | 130 | 234k | return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx, | 131 | 234k | ysize_ << shifty); | 132 | 234k | } |
jxl::RectT<unsigned long>::ShiftLeft(unsigned long, unsigned long) const Line | Count | Source | 129 | 63.6k | RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const { | 130 | 63.6k | return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx, | 131 | 63.6k | ysize_ << shifty); | 132 | 63.6k | } |
|
133 | 297k | RectT<T> ShiftLeft(size_t shift) const { return ShiftLeft(shift, shift); } jxl::RectT<long>::ShiftLeft(unsigned long) const Line | Count | Source | 133 | 234k | RectT<T> ShiftLeft(size_t shift) const { return ShiftLeft(shift, shift); } |
jxl::RectT<unsigned long>::ShiftLeft(unsigned long) const Line | Count | Source | 133 | 63.6k | RectT<T> ShiftLeft(size_t shift) const { return ShiftLeft(shift, shift); } |
|
134 | | |
135 | | // Requires x0(), y0() to be multiples of 1<<shiftx, 1<<shifty. |
136 | 612k | StatusOr<RectT<T>> CeilShiftRight(std::pair<size_t, size_t> shift) const { |
137 | 612k | size_t shiftx = shift.first; |
138 | 612k | size_t shifty = shift.second; |
139 | 612k | JXL_ENSURE((x0_ % (1 << shiftx) == 0) && (y0_ % (1 << shifty) == 0)); |
140 | 612k | return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty), |
141 | 612k | DivCeil(xsize_, T{1} << shiftx), |
142 | 612k | DivCeil(ysize_, T{1} << shifty)); |
143 | 612k | } jxl::RectT<long>::CeilShiftRight(std::__1::pair<unsigned long, unsigned long>) const Line | Count | Source | 136 | 234k | StatusOr<RectT<T>> CeilShiftRight(std::pair<size_t, size_t> shift) const { | 137 | 234k | size_t shiftx = shift.first; | 138 | 234k | size_t shifty = shift.second; | 139 | 234k | JXL_ENSURE((x0_ % (1 << shiftx) == 0) && (y0_ % (1 << shifty) == 0)); | 140 | 234k | return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty), | 141 | 234k | DivCeil(xsize_, T{1} << shiftx), | 142 | 234k | DivCeil(ysize_, T{1} << shifty)); | 143 | 234k | } |
jxl::RectT<unsigned long>::CeilShiftRight(std::__1::pair<unsigned long, unsigned long>) const Line | Count | Source | 136 | 378k | StatusOr<RectT<T>> CeilShiftRight(std::pair<size_t, size_t> shift) const { | 137 | 378k | size_t shiftx = shift.first; | 138 | 378k | size_t shifty = shift.second; | 139 | 378k | JXL_ENSURE((x0_ % (1 << shiftx) == 0) && (y0_ % (1 << shifty) == 0)); | 140 | 378k | return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty), | 141 | 378k | DivCeil(xsize_, T{1} << shiftx), | 142 | 378k | DivCeil(ysize_, T{1} << shifty)); | 143 | 378k | } |
|
144 | | |
145 | | RectT<T> Extend(T border, RectT<T> parent) const { |
146 | | T new_x0 = x0() > parent.x0() + border ? x0() - border : parent.x0(); |
147 | | T new_y0 = y0() > parent.y0() + border ? y0() - border : parent.y0(); |
148 | | T new_x1 = x1() + border > parent.x1() ? parent.x1() : x1() + border; |
149 | | T new_y1 = y1() + border > parent.y1() ? parent.y1() : y1() + border; |
150 | | return RectT<T>(new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0); |
151 | | } |
152 | | |
153 | | template <typename U> |
154 | 234k | RectT<U> As() const { |
155 | 234k | return RectT<U>(static_cast<U>(x0_), static_cast<U>(y0_), |
156 | 234k | static_cast<U>(xsize_), static_cast<U>(ysize_)); |
157 | 234k | } |
158 | | |
159 | | private: |
160 | | // Returns size_max, or whatever is left in [begin, end). |
161 | 2.21M | static constexpr size_t ClampedSize(T begin, size_t size_max, T end) { |
162 | 2.21M | return (static_cast<T>(begin + size_max) <= end) |
163 | 2.21M | ? size_max |
164 | 2.21M | : (end > begin ? end - begin : 0); |
165 | 2.21M | } jxl::RectT<unsigned long>::ClampedSize(unsigned long, unsigned long, unsigned long) Line | Count | Source | 161 | 2.13M | static constexpr size_t ClampedSize(T begin, size_t size_max, T end) { | 162 | 2.13M | return (static_cast<T>(begin + size_max) <= end) | 163 | 2.13M | ? size_max | 164 | 2.13M | : (end > begin ? end - begin : 0); | 165 | 2.13M | } |
jxl::RectT<long>::ClampedSize(long, unsigned long, long) Line | Count | Source | 161 | 82.2k | static constexpr size_t ClampedSize(T begin, size_t size_max, T end) { | 162 | 82.2k | return (static_cast<T>(begin + size_max) <= end) | 163 | 82.2k | ? size_max | 164 | 82.2k | : (end > begin ? end - begin : 0); | 165 | 82.2k | } |
|
166 | | |
167 | | T x0_; |
168 | | T y0_; |
169 | | |
170 | | size_t xsize_; |
171 | | size_t ysize_; |
172 | | }; |
173 | | |
174 | | template <typename T> |
175 | | std::string Description(RectT<T> r) { |
176 | | std::ostringstream os; |
177 | | os << "[" << r.x0() << ".." << r.x1() << ")x" |
178 | | << "[" << r.y0() << ".." << r.y1() << ")"; |
179 | | return os.str(); |
180 | | } |
181 | | |
182 | | using Rect = RectT<size_t>; |
183 | | |
184 | | } // namespace jxl |
185 | | |
186 | | #endif // LIB_JXL_BASE_RECT_H_ |