rect.h (6217B)
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 : x0_(xbegin), 34 y0_(ybegin), 35 xsize_(ClampedSize(xbegin, xsize_max, xend)), 36 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 : 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 : RectT(0, 0, image.xsize(), image.ysize()) {} 46 47 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 RectT Crop(const ImageT& image) const { 55 return Intersection(RectT(image)); 56 } 57 58 // Construct a subrect that resides in the [0, ysize) x [0, xsize) region of 59 // the current rect. 60 RectT Crop(size_t area_xsize, size_t area_ysize) const { 61 return Intersection(RectT(0, 0, area_xsize, area_ysize)); 62 } 63 64 JXL_MUST_USE_RESULT RectT Intersection(const RectT& other) const { 65 return RectT(std::max(x0_, other.x0_), std::max(y0_, other.y0_), xsize_, 66 ysize_, std::min(x1(), other.x1()), 67 std::min(y1(), other.y1())); 68 } 69 70 JXL_MUST_USE_RESULT RectT Translate(int64_t x_offset, 71 int64_t y_offset) const { 72 return RectT(x0_ + x_offset, y0_ + y_offset, xsize_, ysize_); 73 } 74 75 template <template <class> class P, typename V> 76 V* Row(P<V>* image, size_t y) const { 77 JXL_DASSERT(y + y0_ >= 0); 78 return image->Row(y + y0_) + x0_; 79 } 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 V* PlaneRow(MP<V>* image, const size_t c, size_t y) const { 89 JXL_DASSERT(y + y0_ >= 0); 90 return image->PlaneRow(c, y + y0_) + x0_; 91 } 92 93 template <template <class> class P, typename V> 94 const V* ConstRow(const P<V>& image, size_t y) const { 95 JXL_DASSERT(y + y0_ >= 0); 96 return image.ConstRow(y + y0_) + x0_; 97 } 98 99 template <template <class> class MP, typename V> 100 const V* ConstPlaneRow(const MP<V>& image, size_t c, size_t y) const { 101 JXL_DASSERT(y + y0_ >= 0); 102 return image.ConstPlaneRow(c, y + y0_) + x0_; 103 } 104 105 bool IsInside(const RectT& other) const { 106 return x0_ >= other.x0() && x1() <= other.x1() && y0_ >= other.y0() && 107 y1() <= other.y1(); 108 } 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 bool IsInside(const ImageT& image) const { 119 return IsInside(RectT(image)); 120 } 121 122 T x0() const { return x0_; } 123 T y0() const { return y0_; } 124 size_t xsize() const { return xsize_; } 125 size_t ysize() const { return ysize_; } 126 T x1() const { return x0_ + xsize_; } 127 T y1() const { return y0_ + ysize_; } 128 129 RectT<T> ShiftLeft(size_t shiftx, size_t shifty) const { 130 return RectT<T>(x0_ * (1 << shiftx), y0_ * (1 << shifty), xsize_ << shiftx, 131 ysize_ << shifty); 132 } 133 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 StatusOr<RectT<T>> CeilShiftRight(std::pair<size_t, size_t> shift) const { 137 size_t shiftx = shift.first; 138 size_t shifty = shift.second; 139 JXL_ENSURE((x0_ % (1 << shiftx) == 0) && (y0_ % (1 << shifty) == 0)); 140 return RectT<T>(x0_ / (1 << shiftx), y0_ / (1 << shifty), 141 DivCeil(xsize_, T{1} << shiftx), 142 DivCeil(ysize_, T{1} << shifty)); 143 } 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 RectT<U> As() const { 155 return RectT<U>(static_cast<U>(x0_), static_cast<U>(y0_), 156 static_cast<U>(xsize_), static_cast<U>(ysize_)); 157 } 158 159 private: 160 // Returns size_max, or whatever is left in [begin, end). 161 static constexpr size_t ClampedSize(T begin, size_t size_max, T end) { 162 return (static_cast<T>(begin + size_max) <= end) 163 ? size_max 164 : (end > begin ? end - begin : 0); 165 } 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_