Grok 20.3.2
geometry.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016-2026 Grok Image Compression Inc.
3 *
4 * This source code is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License, version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This source code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Affero General Public License for more details.
12 *
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#pragma once
19
20#include <iostream>
21#include <cstdint>
22#include <cstddef>
23#include <limits>
24#include <sstream>
25#include <atomic>
26#include <cassert>
27
28#include "grok.h"
29#include "Logger.h"
30#include "intmath.h"
31
32namespace grk
33{
34template<typename T>
35struct Point
36{
37 Point() : x(0), y(0) {}
38 Point(T _x, T _y) : x(_x), y(_y) {}
39 T x;
40 T y;
41};
45
46template<typename T>
47struct Line
48{
49 Line() : x0(0), x1(0) {}
50 Line(T _x0, T _x1) : x0(_x0), x1(_x1) {}
51 T x0;
52 T x1;
53
54 T length() const
55 {
56 assert(x1 >= x0);
57 return (T)(x1 - x0);
58 }
59};
61
62template<typename T>
63struct Rect;
68
69template<typename T>
70T clip(int64_t val)
71{
72 static_assert(sizeof(T) <= 4);
73 if(val < (std::numeric_limits<T>::min)())
74 val = (std::numeric_limits<T>::min)();
75 else if(val > (std::numeric_limits<T>::max)())
76 val = (std::numeric_limits<T>::max)();
77 return (T)val;
78}
79
80template<typename T>
81T satAdd(int64_t lhs, int64_t rhs)
82{
83 return clip<T>(lhs + rhs);
84}
85
86template<typename T>
87T satAdd(T lhs, T rhs)
88{
89 return clip<T>((int64_t)lhs + rhs);
90}
91
92template<typename T>
93T satSub(T lhs, T rhs)
94{
95 return clip<T>((int64_t)lhs - rhs);
96}
97
98template<typename T>
99T satSub(int64_t lhs, int64_t rhs)
100{
101 return clip<T>(lhs - rhs);
102}
103
105{
106 Rect32_16(uint32_t x0, uint32_t y0, uint16_t w, uint16_t h) : x0_(x0), y0_(y0), w_(w), h_(h) {}
107 Rect32_16(void) : Rect32_16(0, 0, 0, 0) {}
108 virtual ~Rect32_16() = default;
109 uint32_t x0(void) const
110 {
111 return x0_;
112 }
113 uint32_t y0(void) const
114 {
115 return y0_;
116 }
117 uint32_t x1(void) const
118 {
119 return x0_ + w_;
120 }
121 uint32_t y1(void) const
122 {
123 return y0_ + h_;
124 }
125 uint16_t width() const
126 {
127 return w_;
128 }
129 uint16_t height() const
130 {
131 return h_;
132 }
133 bool valid() const
134 {
135 return x0_ <= x1() && y0_ <= y1();
136 }
137 bool empty(void) const
138 {
139 return x0_ >= x1() || y0_ >= y1();
140 }
141
142 uint32_t area(void) const
143 {
144 return (uint32_t)w_ * h_;
145 }
147 {
148 uint32_t x = std::max<uint32_t>(x0(), rhs->x0());
149 uint32_t y = std::max<uint32_t>(y0(), rhs->y0());
150 uint16_t w = uint16_t(std::min<uint32_t>(x1(), rhs->x1()) - x);
151 uint16_t h = uint16_t(std::min<uint32_t>(y1(), rhs->y1()) - y);
152 return Rect32_16(x, y, w, h);
153 }
154 void setRect(const Rect32_16* rhs)
155 {
156 *this = *rhs;
157 }
158 void setRect(const Rect32_16 rhs)
159 {
160 setRect(&rhs);
161 }
162 virtual void print(void) const
163 {
164 grklog.info("[%u,%u,%u,%u]", x0_, y0_, x1(), y1());
165 }
166
167private:
168 uint32_t x0_, y0_;
169 uint16_t w_, h_;
170};
171
172template<typename T>
173struct Rect
174{
175 Rect(T origin_x0, T origin_y0, T x0, T y0, T x1, T y1)
177 x1(x1), y1(y1)
178 {}
179 Rect(T x0, T y0, T x1, T y1) : Rect(x0, y0, x0, y0, x1, y1) {}
180 Rect(const Rect& rhs) : Rect(&rhs) {}
181 explicit Rect(const Rect* rhs)
182 : origin_x0(rhs->origin_x0), origin_y0(rhs->origin_y0), x0(rhs->x0), y0(rhs->y0), x1(rhs->x1),
183 y1(rhs->y1)
184 {
186 }
187 Rect(void) : Rect(0, 0, 0, 0) {}
188 virtual ~Rect() = default;
189
192 T x0, y0, x1, y1;
193
194 Rect<T>& setOrigin(T origx, T origy, bool absolute)
195 {
196 absoluteCoordinates = absolute;
197
198 assert(x0 >= origx);
199 assert(y0 >= origy);
200
201 origin_x0 = origx;
202 origin_y0 = origy;
203
204 return *this;
205 }
206 Rect<T>& setOrigin(const Rect<T>& rhs, bool absolute)
207 {
208 return setOrigin(&rhs, absolute);
209 }
210 Rect<T>& setOrigin(const Rect<T>* rhs, bool absolute)
211 {
212 absoluteCoordinates = absolute;
213
214 if(rhs)
215 {
216 assert(x0 >= rhs->origin_x0);
217 assert(y0 >= rhs->origin_y0);
218 origin_x0 = rhs->origin_x0;
219 origin_y0 = rhs->origin_y0;
220 }
221
222 return *this;
223 }
225 {
226 assert(x0 >= origin_x0);
227 assert(y0 >= origin_y0);
229 pan_IN_PLACE(-(int64_t)origin_x0, -(int64_t)origin_y0);
230 absoluteCoordinates = false;
231
232 return *this;
233 }
235 {
238 absoluteCoordinates = true;
239
240 return *this;
241 }
242 virtual void print(void) const
243 {
244 grklog.info("[%u,%u,%u,%u,%u,%u]", origin_x0, origin_y0, x0, y0, x1, y1);
245 }
246 bool valid(void) const
247 {
248 return x0 <= x1 && y0 <= y1;
249 }
250 bool empty(void) const
251 {
252 return x0 >= x1 || y0 >= y1;
253 }
255 {
256 return contains(pt.x, pt.y);
257 }
258 bool contains(T x, T y)
259 {
260 return x >= x0 && y >= y0 && x < x1 && y < y1;
261 }
262 Rect<T>& operator=(const Rect& rhs)
263 {
264 if(*this != rhs)
265 { // self-assignment check expected
267 origin_x0 = rhs.origin_x0;
268 origin_y0 = rhs.origin_y0;
269 x0 = rhs.x0;
270 y0 = rhs.y0;
271 x1 = rhs.x1;
272 y1 = rhs.y1;
273 }
274 return *this;
275 }
276 Rect<T>& operator=(const Rect* rhs)
277 {
278 if(!rhs)
279 {
280 throw std::invalid_argument("Null pointer passed to Rect::operator=");
281 }
282 return *this = *rhs;
283 }
284 // Define operator!=
285 bool operator!=(const Rect& other) const
286 {
287 return !(*this == other);
288 }
289 bool operator==(const Rect& rhs) const
290 {
291 if(this == &rhs)
292 return true;
294 origin_y0 == rhs.origin_y0 && x0 == rhs.x0 && y0 == rhs.y0 && x1 == rhs.x1 &&
295 y1 == rhs.y1;
296 }
297 void setRect(const Rect* rhs)
298 {
299 *this = *rhs;
300 }
301 void setRect(const Rect& rhs)
302 {
303 setRect(&rhs);
304 }
305 Rect<T> scaleDownCeil(uint32_t den) const
306 {
307 return Rect<T>(ceildiv(origin_x0, den), ceildiv(origin_y0, den), ceildiv(x0, den),
308 ceildiv(y0, den), ceildiv(x1, den), ceildiv(y1, den));
309 }
310 Rect<T> scale(uint32_t scalex, uint32_t scaley) const
311 {
312 return Rect<T>(origin_x0 * scalex, origin_y0 * scaley, x0 * scalex, y0 * scaley, x1 * scalex,
313 y1 * scaley);
314 }
315 Rect<T> scaleDown(uint64_t denx, uint64_t deny) const
316 {
317 return Rect((T)(origin_x0 / denx), (T)(origin_y0 / deny), (T)(x0 / denx), (T)(y0 / deny),
318 (T)ceildiv<uint64_t>(x1, denx), (T)ceildiv<uint64_t>(y1, deny));
319 }
320 Rect<T> scaleDownPow2(uint8_t powx, uint8_t powy) const
321 {
322 return Rect((T)(origin_x0 >> powx), (T)(origin_y0 >> powy), (T)(x0 >> powx), (T)(y0 >> powy),
323 (T)ceildivpow2<uint64_t>(x1, powx), (T)ceildivpow2<uint64_t>(y1, powy));
324 }
326 {
327 return scaleDownPow2(pow.x, pow.y);
328 }
329 Rect<T> scaleDownCeil(uint64_t denx, uint64_t deny) const
330 {
334 }
335 Rect<T> scaleDownCeilPow2(uint8_t power) const
336 {
337 return Rect(ceildivpow2(origin_x0, power), ceildivpow2(origin_y0, power),
338 ceildivpow2(x0, power), ceildivpow2(y0, power), ceildivpow2(x1, power),
339 ceildivpow2(y1, power));
340 }
341 Rect<T> scaleDownCeilPow2(uint8_t powx, uint8_t powy) const
342 {
346 }
347 Rect<T> intersection(const Rect<T>& rhs) const
348 {
350
351 return intersection(&rhs);
352 }
353 Rect<T> clip(const Rect* rhs) const
354 {
356 return Rect<T>(std::max<T>(x0, rhs->x0), std::max<T>(y0, rhs->y0), std::min<T>(x1, rhs->x1),
357 std::min<T>(y1, rhs->y1));
358 }
359 Rect<T> clip(const Rect32_16& rhs) const
360 {
361 return clip(&rhs);
362 }
363 Rect<T> clip(const Rect32_16* rhs) const
364 {
365 return Rect<T>(std::max<T>(x0, rhs->x0()), std::max<T>(y0, rhs->y0()),
366 std::min<T>(x1, rhs->x1()), std::min<T>(y1, rhs->y1()));
367 }
368 Rect<T> clip(const Rect& rhs) const
369 {
370 return clip(&rhs);
371 }
373 {
375 *this = Rect<T>(std::max<T>(x0, rhs.x0), std::max<T>(y0, rhs.y0), std::min<T>(x1, rhs.x1),
376 std::min<T>(y1, rhs.y1));
377
378 return *this;
379 }
380 Rect<T> intersection(const Rect* rhs) const
381 {
383 return Rect<T>(std::max<T>(x0, rhs->x0), std::max<T>(y0, rhs->y0), std::min<T>(x1, rhs->x1),
384 std::min<T>(y1, rhs->y1));
385 }
386 bool nonEmptyIntersection(const Rect* rhs) const
387 {
389 return std::max<T>(x0, rhs->x0) < std::min<T>(x1, rhs->x1) &&
390 std::max<T>(y0, rhs->y0) < std::min<T>(y1, rhs->y1);
391 }
392 bool nonEmptyIntersection(const Rect32_16* rhs) const
393 {
394 return std::max<T>(x0, rhs->x0()) < std::min<T>(x1, rhs->x1()) &&
395 std::max<T>(y0, rhs->y0()) < std::min<T>(y1, rhs->y1());
396 }
397 Rect<T> rectUnion(const Rect* rhs) const
398 {
400 return Rect<T>(std::min<T>(x0, rhs->x0), std::min<T>(y0, rhs->y0), std::max<T>(x1, rhs->x1),
401 std::max<T>(y1, rhs->y1));
402 }
403 Rect<T> rectUnion(const Rect& rhs) const
404 {
405 return rectUnion(&rhs);
406 }
407 uint64_t area(void) const
408 {
409 return (uint64_t)(x1 - x0) * (y1 - y0);
410 }
411 T width() const
412 {
413 return x1 - x0;
414 }
415 T height() const
416 {
417 return y1 - y0;
418 }
419 Line<T> dimX() const
420 {
421 return Line<T>(x0, x1);
422 }
423 Line<T> dimY() const
424 {
425 return Line<T>(y0, y1);
426 }
427 // pan doesn't affect origin
428 Rect<T> pan(int64_t x, int64_t y) const
429 {
430 auto rc = (*this);
431
432 return rc.pan_IN_PLACE(x, y);
433 }
434 Rect<T>& pan_IN_PLACE(int64_t x, int64_t y)
435 {
436 x0 = satAdd<T>((int64_t)x0, (int64_t)x);
437 y0 = satAdd<T>((int64_t)y0, (int64_t)y);
438 x1 = satAdd<T>((int64_t)x1, (int64_t)x);
439 y1 = satAdd<T>((int64_t)y1, (int64_t)y);
440
441 return *this;
442 }
443 // grow doesn't affect origin
445 {
446 return grow_IN_PLACE(boundary, boundary, (std::numeric_limits<T>::max)(),
447 (std::numeric_limits<T>::max)());
448 }
449 Rect<T>& grow_IN_PLACE(T boundaryx, T boundaryy)
450 {
451 return grow_IN_PLACE(boundaryx, boundaryy, (std::numeric_limits<T>::max)(),
452 (std::numeric_limits<T>::max)());
453 }
454 Rect<T>& grow_IN_PLACE(T boundary, T maxX, T maxY)
455 {
456 return grow_IN_PLACE(boundary, boundary, maxX, maxY);
457 }
458 Rect<T>& grow_IN_PLACE(T boundaryx, T boundaryy, T maxX, T maxY)
459 {
460 return grow_IN_PLACE(boundaryx, boundaryy, Rect<T>((T)0, (T)0, maxX, maxY));
461 }
462 Rect<T>& grow_IN_PLACE(T boundary, const Rect<T>& bounds)
463 {
464 return grow_IN_PLACE(boundary, boundary, bounds);
465 }
466 Rect<T>& grow_IN_PLACE(T boundaryx, T boundaryy, Rect bounds)
467 {
468 x0 = std::max<T>(satSub<T>(x0, boundaryx), bounds.x0);
469 y0 = std::max<T>(satSub<T>(y0, boundaryy), bounds.y0);
470 x1 = std::min<T>(satAdd<T>(x1, boundaryx), bounds.x1);
471 y1 = std::min<T>(satAdd<T>(y1, boundaryy), bounds.y1);
472
473 return *this;
474 }
475};
476
477using Rect32 = Rect<uint32_t>;
478using Rect16 = Rect<uint16_t>;
479
480} // namespace grk
ResWindow.
Definition CompressedChunkCache.h:36
T satAdd(int64_t lhs, int64_t rhs)
Definition geometry.h:81
T clip(int64_t val)
Definition geometry.h:70
uint32_t ceildiv(T a, T b)
Divide an integer by another integer and round upwards.
Definition intmath.h:32
ILogger & grklog
Definition Logger.cpp:24
T satSub(T lhs, T rhs)
Definition geometry.h:93
Line< uint32_t > Line32
Definition geometry.h:60
Rect< uint32_t > Rect32
Definition geometry.h:64
Rect< float > RectF
Definition geometry.h:66
T ceildivpow2(T a, uint8_t b)
Definition intmath.h:39
Point< uint16_t > Point16
Definition geometry.h:43
Rect< uint16_t > Rect16
Definition geometry.h:65
Point< uint8_t > Point8
Definition geometry.h:44
Point< uint32_t > Point32
Definition geometry.h:42
Rect< double > RectD
Definition geometry.h:67
Definition geometry.h:48
Line(T _x0, T _x1)
Definition geometry.h:50
uint32_t x0
Definition geometry.h:51
uint32_t x1
Definition geometry.h:52
T length() const
Definition geometry.h:54
Line()
Definition geometry.h:49
Definition geometry.h:36
Point()
Definition geometry.h:37
uint32_t y
Definition geometry.h:40
uint32_t x
Definition geometry.h:39
Point(T _x, T _y)
Definition geometry.h:38
Definition geometry.h:105
uint16_t w_
Definition geometry.h:169
uint32_t x0_
Definition geometry.h:168
void setRect(const Rect32_16 *rhs)
Definition geometry.h:154
uint32_t x0(void) const
Definition geometry.h:109
uint32_t y0(void) const
Definition geometry.h:113
uint32_t x1(void) const
Definition geometry.h:117
uint32_t area(void) const
Definition geometry.h:142
Rect32_16(uint32_t x0, uint32_t y0, uint16_t w, uint16_t h)
Definition geometry.h:106
Rect32_16(void)
Definition geometry.h:107
virtual void print(void) const
Definition geometry.h:162
uint16_t height() const
Definition geometry.h:129
bool empty(void) const
Definition geometry.h:137
virtual ~Rect32_16()=default
bool valid() const
Definition geometry.h:133
uint32_t y0_
Definition geometry.h:168
Rect32_16 intersection(const Rect32_16 *rhs) const
Definition geometry.h:146
uint32_t y1(void) const
Definition geometry.h:121
uint16_t width() const
Definition geometry.h:125
uint16_t h_
Definition geometry.h:169
void setRect(const Rect32_16 rhs)
Definition geometry.h:158
Definition geometry.h:174
T width() const
Definition geometry.h:411
Rect(const Rect &rhs)
Definition geometry.h:180
Line< T > dimY() const
Definition geometry.h:423
Rect< T > & pan_IN_PLACE(int64_t x, int64_t y)
Definition geometry.h:434
Rect< T > clip(const Rect32_16 *rhs) const
Definition geometry.h:363
Rect< T > & setOrigin(const Rect< T > *rhs, bool absolute)
Definition geometry.h:210
bool valid(void) const
Definition geometry.h:246
uint32_t x1
Definition geometry.h:192
T height() const
Definition geometry.h:415
uint32_t origin_x0
Definition geometry.h:191
Rect< T > scaleDownCeil(uint64_t denx, uint64_t deny) const
Definition geometry.h:329
Rect< T > & clip_IN_PLACE(const Rect &rhs)
Definition geometry.h:372
Rect< T > rectUnion(const Rect *rhs) const
Definition geometry.h:397
Rect< T > scaleDownPow2(uint8_t powx, uint8_t powy) const
Definition geometry.h:320
Rect< T > intersection(const Rect< T > &rhs) const
Definition geometry.h:347
bool contains(T x, T y)
Definition geometry.h:258
Rect< T > clip(const Rect *rhs) const
Definition geometry.h:353
Rect< T > & grow_IN_PLACE(T boundary, T maxX, T maxY)
Definition geometry.h:454
Rect< T > scale(uint32_t scalex, uint32_t scaley) const
Definition geometry.h:310
virtual ~Rect()=default
bool nonEmptyIntersection(const Rect *rhs) const
Definition geometry.h:386
void setRect(const Rect *rhs)
Definition geometry.h:297
Rect(T x0, T y0, T x1, T y1)
Definition geometry.h:179
Rect< T > scaleDownPow2(Point8 pow) const
Definition geometry.h:325
Rect< T > & setOrigin(const Rect< T > &rhs, bool absolute)
Definition geometry.h:206
uint64_t area(void) const
Definition geometry.h:407
Rect< T > & toRelative(void)
Definition geometry.h:224
Rect< T > rectUnion(const Rect &rhs) const
Definition geometry.h:403
Line< T > dimX() const
Definition geometry.h:419
Rect< T > pan(int64_t x, int64_t y) const
Definition geometry.h:428
Rect< T > & grow_IN_PLACE(T boundaryx, T boundaryy, Rect bounds)
Definition geometry.h:466
Rect(void)
Definition geometry.h:187
uint32_t origin_y0
Definition geometry.h:191
Rect(const Rect *rhs)
Definition geometry.h:181
Rect< T > & grow_IN_PLACE(T boundaryx, T boundaryy, T maxX, T maxY)
Definition geometry.h:458
Rect< T > scaleDownCeilPow2(uint8_t powx, uint8_t powy) const
Definition geometry.h:341
uint32_t x0
Definition geometry.h:192
Rect< T > & operator=(const Rect &rhs)
Definition geometry.h:262
bool operator==(const Rect &rhs) const
Definition geometry.h:289
bool contains(Point< T > pt)
Definition geometry.h:254
virtual void print(void) const
Definition geometry.h:242
bool operator!=(const Rect &other) const
Definition geometry.h:285
bool empty(void) const
Definition geometry.h:250
Rect< T > clip(const Rect &rhs) const
Definition geometry.h:368
Rect< T > & operator=(const Rect *rhs)
Definition geometry.h:276
bool nonEmptyIntersection(const Rect32_16 *rhs) const
Definition geometry.h:392
Rect< T > & setOrigin(T origx, T origy, bool absolute)
Definition geometry.h:194
bool absoluteCoordinates
Definition geometry.h:190
Rect< T > & grow_IN_PLACE(T boundaryx, T boundaryy)
Definition geometry.h:449
Rect< T > intersection(const Rect *rhs) const
Definition geometry.h:380
Rect< T > & grow_IN_PLACE(T boundary, const Rect< T > &bounds)
Definition geometry.h:462
Rect< T > scaleDown(uint64_t denx, uint64_t deny) const
Definition geometry.h:315
Rect< T > scaleDownCeil(uint32_t den) const
Definition geometry.h:305
uint32_t y0
Definition geometry.h:192
Rect< T > & grow_IN_PLACE(T boundary)
Definition geometry.h:444
Rect(T origin_x0, T origin_y0, T x0, T y0, T x1, T y1)
Definition geometry.h:175
Rect< T > clip(const Rect32_16 &rhs) const
Definition geometry.h:359
uint32_t y1
Definition geometry.h:192
Rect< T > scaleDownCeilPow2(uint8_t power) const
Definition geometry.h:335
void setRect(const Rect &rhs)
Definition geometry.h:301
Rect< T > & toAbsolute(void)
Definition geometry.h:234