/src/libjxl/lib/jxl/base/rect.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_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.61M | : x0_(xbegin), |
34 | 1.61M | y0_(ybegin), |
35 | 1.61M | xsize_(ClampedSize(xbegin, xsize_max, xend)), |
36 | 1.61M | 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.59M | : x0_(xbegin), | 34 | 1.59M | y0_(ybegin), | 35 | 1.59M | xsize_(ClampedSize(xbegin, xsize_max, xend)), | 36 | 1.59M | ysize_(ClampedSize(ybegin, ysize_max, yend)) {} |
jxl::RectT<long>::RectT(long, long, unsigned long, unsigned long, long, long) Line | Count | Source | 33 | 23.4k | : x0_(xbegin), | 34 | 23.4k | y0_(ybegin), | 35 | 23.4k | xsize_(ClampedSize(xbegin, xsize_max, xend)), | 36 | 23.4k | 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 | 2.17M | : 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 | 1.69M | : x0_(xbegin), y0_(ybegin), xsize_(xsize), ysize_(ysize) {} |
jxl::RectT<long>::RectT(long, long, unsigned long, unsigned long) Line | Count | Source | 40 | 477k | : 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 | 146k | : RectT(0, 0, image.xsize(), image.ysize()) {} jxl::RectT<unsigned long>::RectT<jxl::Image3<float> >(jxl::Image3<float> const&) Line | Count | Source | 45 | 841 | : RectT(0, 0, image.xsize(), image.ysize()) {} |
jxl::RectT<unsigned long>::RectT<jxl::Plane<unsigned char> >(jxl::Plane<unsigned char> const&) Line | Count | Source | 45 | 744 | : RectT(0, 0, image.xsize(), image.ysize()) {} |
jxl::RectT<unsigned long>::RectT<jxl::Plane<float> >(jxl::Plane<float> const&) Line | Count | Source | 45 | 68.9k | : RectT(0, 0, image.xsize(), image.ysize()) {} |
jxl::RectT<unsigned long>::RectT<jxl::Plane<int> >(jxl::Plane<int> const&) Line | Count | Source | 45 | 75.4k | : RectT(0, 0, image.xsize(), image.ysize()) {} |
|
46 | | |
47 | 653k | 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 | 67.5k | RectT Crop(const ImageT& image) const { |
55 | 67.5k | return Intersection(RectT(image)); |
56 | 67.5k | } |
57 | | |
58 | | // Construct a subrect that resides in the [0, ysize) x [0, xsize) region of |
59 | | // the current rect. |
60 | 23.7k | RectT Crop(size_t area_xsize, size_t area_ysize) const { |
61 | 23.7k | return Intersection(RectT(0, 0, area_xsize, area_ysize)); |
62 | 23.7k | } |
63 | | |
64 | 114k | JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const { |
65 | 114k | return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_, |
66 | 114k | ysize_, std::min(x1(), other.x1()), |
67 | 114k | std::min(y1(), other.y1())); |
68 | 114k | } jxl::RectT<unsigned long>::Intersection(jxl::RectT<unsigned long> const&) const Line | Count | Source | 64 | 91.2k | JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const { | 65 | 91.2k | return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_, | 66 | 91.2k | ysize_, std::min(x1(), other.x1()), | 67 | 91.2k | std::min(y1(), other.y1())); | 68 | 91.2k | } |
jxl::RectT<long>::Intersection(jxl::RectT<long> const&) const Line | Count | Source | 64 | 23.4k | JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const { | 65 | 23.4k | return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_, | 66 | 23.4k | ysize_, std::min(x1(), other.x1()), | 67 | 23.4k | std::min(y1(), other.y1())); | 68 | 23.4k | } |
|
69 | | |
70 | | JXL_MUST_USE_RESULT RectT Translate(int64_t x_offset, |
71 | 188k | int64_t y_offset) const { |
72 | 188k | return RectT(x0_ + x_offset, y0_ + y_offset, xsize_, ysize_); |
73 | 188k | } jxl::RectT<unsigned long>::Translate(long, long) const Line | Count | Source | 71 | 595 | int64_t y_offset) const { | 72 | 595 | return RectT(x0_ + x_offset, y0_ + y_offset, xsize_, ysize_); | 73 | 595 | } |
jxl::RectT<long>::Translate(long, long) const Line | Count | Source | 71 | 188k | int64_t y_offset) const { | 72 | 188k | return RectT(x0_ + x_offset, y0_ + y_offset, xsize_, ysize_); | 73 | 188k | } |
|
74 | | |
75 | | template <template <class> class P, typename V> |
76 | 12.6M | V* Row(P<V>* image, size_t y) const { |
77 | 12.6M | JXL_DASSERT(y + y0_ >= 0); |
78 | 12.6M | return image->Row(y + y0_) + x0_; |
79 | 12.6M | } unsigned char* jxl::RectT<unsigned long>::Row<jxl::Plane, unsigned char>(jxl::Plane<unsigned char>*, unsigned long) const Line | Count | Source | 76 | 81.0k | V* Row(P<V>* image, size_t y) const { | 77 | 81.0k | JXL_DASSERT(y + y0_ >= 0); | 78 | 81.0k | return image->Row(y + y0_) + x0_; | 79 | 81.0k | } |
float* jxl::RectT<unsigned long>::Row<jxl::Plane, float>(jxl::Plane<float>*, unsigned long) const Line | Count | Source | 76 | 9.95M | V* Row(P<V>* image, size_t y) const { | 77 | 9.95M | JXL_DASSERT(y + y0_ >= 0); | 78 | 9.95M | return image->Row(y + y0_) + x0_; | 79 | 9.95M | } |
int* jxl::RectT<unsigned long>::Row<jxl::Plane, int>(jxl::Plane<int>*, unsigned long) const Line | Count | Source | 76 | 2.52M | V* Row(P<V>* image, size_t y) const { | 77 | 2.52M | JXL_DASSERT(y + y0_ >= 0); | 78 | 2.52M | return image->Row(y + y0_) + x0_; | 79 | 2.52M | } |
signed char* jxl::RectT<unsigned long>::Row<jxl::Plane, signed char>(jxl::Plane<signed char>*, unsigned long) const Line | Count | Source | 76 | 7.08k | V* Row(P<V>* image, size_t y) const { | 77 | 7.08k | JXL_DASSERT(y + y0_ >= 0); | 78 | 7.08k | return image->Row(y + y0_) + x0_; | 79 | 7.08k | } |
float* jxl::RectT<long>::Row<jxl::Plane, float>(jxl::Plane<float>*, unsigned long) const Line | Count | Source | 76 | 82.3k | V* Row(P<V>* image, size_t y) const { | 77 | 82.3k | JXL_DASSERT(y + y0_ >= 0); | 78 | 82.3k | return image->Row(y + y0_) + x0_; | 79 | 82.3k | } |
|
80 | | |
81 | | template <template <class> class P, typename V> |
82 | 228M | const V* Row(const P<V>* image, size_t y) const { |
83 | 228M | JXL_DASSERT(y + y0_ >= 0); |
84 | 228M | return image->Row(y + y0_) + x0_; |
85 | 228M | } |
86 | | |
87 | | template <template <class> class MP, typename V> |
88 | 156k | V* PlaneRow(MP<V>* image, const size_t c, size_t y) const { |
89 | 156k | JXL_DASSERT(y + y0_ >= 0); |
90 | 156k | return image->PlaneRow(c, y + y0_) + x0_; |
91 | 156k | } |
92 | | |
93 | | template <template <class> class P, typename V> |
94 | 35.5M | const V* ConstRow(const P<V>& image, size_t y) const { |
95 | 35.5M | JXL_DASSERT(y + y0_ >= 0); |
96 | 35.5M | return image.ConstRow(y + y0_) + x0_; |
97 | 35.5M | } float const* jxl::RectT<unsigned long>::ConstRow<jxl::Plane, float>(jxl::Plane<float> const&, unsigned long) const Line | Count | Source | 94 | 35.2M | const V* ConstRow(const P<V>& image, size_t y) const { | 95 | 35.2M | JXL_DASSERT(y + y0_ >= 0); | 96 | 35.2M | return image.ConstRow(y + y0_) + x0_; | 97 | 35.2M | } |
int const* jxl::RectT<unsigned long>::ConstRow<jxl::Plane, int>(jxl::Plane<int> const&, unsigned long) const Line | Count | Source | 94 | 169k | const V* ConstRow(const P<V>& image, size_t y) const { | 95 | 169k | JXL_DASSERT(y + y0_ >= 0); | 96 | 169k | return image.ConstRow(y + y0_) + x0_; | 97 | 169k | } |
signed char const* jxl::RectT<unsigned long>::ConstRow<jxl::Plane, signed char>(jxl::Plane<signed char> const&, unsigned long) const Line | Count | Source | 94 | 31.0k | const V* ConstRow(const P<V>& image, size_t y) const { | 95 | 31.0k | JXL_DASSERT(y + y0_ >= 0); | 96 | 31.0k | return image.ConstRow(y + y0_) + x0_; | 97 | 31.0k | } |
unsigned char const* jxl::RectT<unsigned long>::ConstRow<jxl::Plane, unsigned char>(jxl::Plane<unsigned char> const&, unsigned long) const Line | Count | Source | 94 | 60.0k | const V* ConstRow(const P<V>& image, size_t y) const { | 95 | 60.0k | JXL_DASSERT(y + y0_ >= 0); | 96 | 60.0k | return image.ConstRow(y + y0_) + x0_; | 97 | 60.0k | } |
|
98 | | |
99 | | template <template <class> class MP, typename V> |
100 | 57.5M | const V* ConstPlaneRow(const MP<V>& image, size_t c, size_t y) const { |
101 | 57.5M | JXL_DASSERT(y + y0_ >= 0); |
102 | 57.5M | return image.ConstPlaneRow(c, y + y0_) + x0_; |
103 | 57.5M | } |
104 | | |
105 | 82.6k | bool IsInside(const RectT& other) const { |
106 | 82.6k | return x0_ >= other.x0() && x1() <= other.x1() && y0_ >= other.y0() && |
107 | 82.6k | y1() <= other.y1(); |
108 | 82.6k | } |
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 | 71.8k | bool IsInside(const ImageT& image) const { |
119 | 71.8k | return IsInside(RectT(image)); |
120 | 71.8k | } bool jxl::RectT<unsigned long>::IsInside<jxl::Plane<float> >(jxl::Plane<float> const&) const Line | Count | Source | 118 | 68.7k | bool IsInside(const ImageT& image) const { | 119 | 68.7k | return IsInside(RectT(image)); | 120 | 68.7k | } |
bool jxl::RectT<unsigned long>::IsInside<jxl::Plane<int> >(jxl::Plane<int> const&) const Line | Count | Source | 118 | 3.12k | bool IsInside(const ImageT& image) const { | 119 | 3.12k | return IsInside(RectT(image)); | 120 | 3.12k | } |
|
121 | | |
122 | 17.0M | T x0() const { return x0_; } jxl::RectT<unsigned long>::x0() const Line | Count | Source | 122 | 17.0M | T x0() const { return x0_; } |
jxl::RectT<long>::x0() const Line | Count | Source | 122 | 17.0k | T x0() const { return x0_; } |
|
123 | 15.0M | T y0() const { return y0_; } jxl::RectT<unsigned long>::y0() const Line | Count | Source | 123 | 15.0M | T y0() const { return y0_; } |
jxl::RectT<long>::y0() const Line | Count | Source | 123 | 6.32k | T y0() const { return y0_; } |
|
124 | 174M | size_t xsize() const { return xsize_; } jxl::RectT<unsigned long>::xsize() const Line | Count | Source | 124 | 174M | size_t xsize() const { return xsize_; } |
jxl::RectT<long>::xsize() const Line | Count | Source | 124 | 22.4k | size_t xsize() const { return xsize_; } |
|
125 | 35.3M | size_t ysize() const { return ysize_; } jxl::RectT<unsigned long>::ysize() const Line | Count | Source | 125 | 35.3M | size_t ysize() const { return ysize_; } |
jxl::RectT<long>::ysize() const Line | Count | Source | 125 | 19.7k | size_t ysize() const { return ysize_; } |
|
126 | 1.13M | T x1() const { return x0_ + xsize_; } jxl::RectT<unsigned long>::x1() const Line | Count | Source | 126 | 1.06M | T x1() const { return x0_ + xsize_; } |
jxl::RectT<long>::x1() const Line | Count | Source | 126 | 63.9k | T x1() const { return x0_ + xsize_; } |
|
127 | 470k | T y1() const { return y0_ + ysize_; } jxl::RectT<unsigned long>::y1() const Line | Count | Source | 127 | 417k | T y1() const { return y0_ + ysize_; } |
jxl::RectT<long>::y1() const Line | Count | Source | 127 | 53.1k | T y1() const { return y0_ + ysize_; } |
|
128 | | |
129 | 106k | RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const { |
130 | 106k | return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx, |
131 | 106k | ysize_ << shifty); |
132 | 106k | } jxl::RectT<long>::ShiftLeft(unsigned long, unsigned long) const Line | Count | Source | 129 | 82.3k | RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const { | 130 | 82.3k | return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx, | 131 | 82.3k | ysize_ << shifty); | 132 | 82.3k | } |
jxl::RectT<unsigned long>::ShiftLeft(unsigned long, unsigned long) const Line | Count | Source | 129 | 23.7k | RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const { | 130 | 23.7k | return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx, | 131 | 23.7k | ysize_ << shifty); | 132 | 23.7k | } |
|
133 | 106k | RectT<T> ShiftLeft(size_t shift) const { return ShiftLeft(shift, shift); } jxl::RectT<long>::ShiftLeft(unsigned long) const Line | Count | Source | 133 | 82.3k | RectT<T> ShiftLeft(size_t shift) const { return ShiftLeft(shift, shift); } |
jxl::RectT<unsigned long>::ShiftLeft(unsigned long) const Line | Count | Source | 133 | 23.7k | 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 | 273k | StatusOr<RectT<T>> CeilShiftRight(std::pair<size_t, size_t> shift) const { |
137 | 273k | size_t shiftx = shift.first; |
138 | 273k | size_t shifty = shift.second; |
139 | 273k | JXL_ENSURE((x0_ % (1 << shiftx) == 0) && (y0_ % (1 << shifty) == 0)); |
140 | 273k | return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty), |
141 | 273k | DivCeil(xsize_, T{1} << shiftx), |
142 | 273k | DivCeil(ysize_, T{1} << shifty)); |
143 | 273k | } jxl::RectT<long>::CeilShiftRight(std::__1::pair<unsigned long, unsigned long>) const Line | Count | Source | 136 | 82.3k | StatusOr<RectT<T>> CeilShiftRight(std::pair<size_t, size_t> shift) const { | 137 | 82.3k | size_t shiftx = shift.first; | 138 | 82.3k | size_t shifty = shift.second; | 139 | 82.3k | JXL_ENSURE((x0_ % (1 << shiftx) == 0) && (y0_ % (1 << shifty) == 0)); | 140 | 82.3k | return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty), | 141 | 82.3k | DivCeil(xsize_, T{1} << shiftx), | 142 | 82.3k | DivCeil(ysize_, T{1} << shifty)); | 143 | 82.3k | } |
jxl::RectT<unsigned long>::CeilShiftRight(std::__1::pair<unsigned long, unsigned long>) const Line | Count | Source | 136 | 191k | StatusOr<RectT<T>> CeilShiftRight(std::pair<size_t, size_t> shift) const { | 137 | 191k | size_t shiftx = shift.first; | 138 | 191k | size_t shifty = shift.second; | 139 | 191k | JXL_ENSURE((x0_ % (1 << shiftx) == 0) && (y0_ % (1 << shifty) == 0)); | 140 | 191k | return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty), | 141 | 191k | DivCeil(xsize_, T{1} << shiftx), | 142 | 191k | DivCeil(ysize_, T{1} << shifty)); | 143 | 191k | } |
|
144 | | |
145 | 469 | RectT<T> Extend(T border, RectT<T> parent) const { |
146 | 469 | T new_x0 = x0() > parent.x0() + border ? x0() - border : parent.x0(); |
147 | 469 | T new_y0 = y0() > parent.y0() + border ? y0() - border : parent.y0(); |
148 | 469 | T new_x1 = x1() + border > parent.x1() ? parent.x1() : x1() + border; |
149 | 469 | T new_y1 = y1() + border > parent.y1() ? parent.y1() : y1() + border; |
150 | 469 | return RectT<T>(new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0); |
151 | 469 | } |
152 | | |
153 | | template <typename U> |
154 | 82.3k | RectT<U> As() const { |
155 | 82.3k | return RectT<U>(static_cast<U>(x0_), static_cast<U>(y0_), |
156 | 82.3k | static_cast<U>(xsize_), static_cast<U>(ysize_)); |
157 | 82.3k | } |
158 | | |
159 | | private: |
160 | | // Returns size_max, or whatever is left in [begin, end). |
161 | 3.22M | static constexpr size_t ClampedSize(T begin, size_t size_max, T end) { |
162 | 3.22M | return (static_cast<T>(begin + size_max) <= end) |
163 | 3.22M | ? size_max |
164 | 3.22M | : (end > begin ? end - begin : 0); |
165 | 3.22M | } jxl::RectT<unsigned long>::ClampedSize(unsigned long, unsigned long, unsigned long) Line | Count | Source | 161 | 3.18M | static constexpr size_t ClampedSize(T begin, size_t size_max, T end) { | 162 | 3.18M | return (static_cast<T>(begin + size_max) <= end) | 163 | 3.18M | ? size_max | 164 | 3.18M | : (end > begin ? end - begin : 0); | 165 | 3.18M | } |
jxl::RectT<long>::ClampedSize(long, unsigned long, long) Line | Count | Source | 161 | 46.8k | static constexpr size_t ClampedSize(T begin, size_t size_max, T end) { | 162 | 46.8k | return (static_cast<T>(begin + size_max) <= end) | 163 | 46.8k | ? size_max | 164 | 46.8k | : (end > begin ? end - begin : 0); | 165 | 46.8k | } |
|
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_ |