Grok  7.6.3
util.h
Go to the documentation of this file.
1 
19 #pragma once
20 
21 #include "grok.h"
22 #include "logger.h"
23 #include <iostream>
24 #include <cstdint>
25 #include "grk_intmath.h"
26 #include <limits> // std::numeric_limits
27 
28 namespace grk {
29 
30 inline bool mult_will_overflow(uint32_t a, uint32_t b) {
31  return (b && (a > UINT_MAX / b));
32 }
33 inline bool mult64_will_overflow(uint64_t a, uint64_t b) {
34  return (b && (a > UINT64_MAX / b));
35 }
36 
37 template<typename T> struct grk_point {
38  grk_point() : x(0), y(0){}
39  grk_point(T _x, T _y) : x(_x), y(_y){}
40  T x;
41  T y;
42 };
44 
45 
46 template<typename T> struct grk_rectangle;
49 
50 
51 template<typename T> T clip(int64_t val) {
52  static_assert(sizeof(T) <= 4);
53  if(val < (std::numeric_limits<T>::min)())
54  val = (std::numeric_limits<T>::min)();
55  else if (val > (std::numeric_limits<T>::max)())
56  val = (std::numeric_limits<T>::max)();
57  return (T)val;
58 }
59 
60 template<typename T> T sat_add(int64_t lhs, int64_t rhs) {
61  return clip<T>(lhs + rhs);
62 }
63 
64 template<typename T> T sat_add(T lhs, T rhs) {
65  return clip<T>((int64_t)lhs + rhs);
66 }
67 
68 template<typename T> T sat_sub(T lhs, T rhs) {
69  return clip<T>((int64_t)lhs - rhs);
70 }
71 
72 template<typename T> T sat_sub(int64_t lhs, int64_t rhs) {
73  return clip<T>(lhs - rhs);
74 }
75 
76 template<typename T> struct grk_rectangle {
77  T x0, y0,x1,y1;
78 
79  grk_rectangle(T x0, T y0, T x1, T y1) :
80  x0(x0), y0(y0), x1(x1), y1(y1) {
81  }
83  *this = rhs;
84  }
85  grk_rectangle(void) :
86  x0(0), y0(0), x1(0), y1(0) {
87  }
88  void print(void) const{
89  std::cout << "[" << x0 << "," << y0 << "," << x1 << "," << y1 << "]"
90  << std::endl;
91  }
92  bool is_valid(void) const {
93  return x0 <= x1 && y0 <= y1;
94  }
95  bool non_empty(void) const{
96  return x0 < x1 && y0 < y1;
97  }
99  return pt.x >= x0 && pt.y >= y0 && pt.x < x1 && pt.y < y1;
100  }
102  {
103  if (this != &rhs) { // self-assignment check expected
104  x0 = rhs.x0;
105  y0 = rhs.y0;
106  x1 = rhs.x1;
107  y1 = rhs.y1;
108  }
109 
110  return *this;
111  }
112  bool operator== (const grk_rectangle<T> &rhs) const
113  {
114  if (this == &rhs)
115  return true;
116  return x0 == rhs.x0 && y0 == rhs.y0 && x1 == rhs.x1 && y1 == rhs.y1;
117  }
118 
120  *this = *rhs;
121  }
122 
124  set_rect(&rhs);
125  }
126  grk_rectangle<T> rectceildivpow2(uint32_t power) const{
127  return grk_rectangle<T>(ceildivpow2(x0, power),
128  ceildivpow2(y0, power),
129  ceildivpow2(x1, power),
130  ceildivpow2(y1, power));
131  }
132  grk_rectangle<T> rectceildiv(uint32_t den) const{
133  return grk_rectangle<T>(ceildiv(x0, den),
134  ceildiv(y0, den),
135  ceildiv(x1, den),
136  ceildiv(y1, den));
137  }
138  grk_rectangle<T> rectceildiv(uint32_t denx, uint32_t deny) const{
139  return grk_rectangle<T>(ceildiv(x0, denx),
140  ceildiv(y0, deny),
141  ceildiv(x1, denx),
142  ceildiv(y1, deny));
143  }
145  return intersection(&rhs);
146  }
147  bool isContainedIn(const grk_rectangle<T> rhs) const{
148  return (intersection(&rhs)== *this);
149  }
151  return grk_rectangle<T>(std::max<T>(x0,rhs->x0),
152  std::max<T>(y0,rhs->y0),
153  std::min<T>(x1,rhs->x1),
154  std::min<T>(y1,rhs->y1));
155  }
156 
158  return grk_rectangle<T>(std::min<T>(x0,rhs->x0),
159  std::min<T>(y0,rhs->y0),
160  std::max<T>(x1,rhs->x1),
161  std::max<T>(y1,rhs->y1));
162  }
164  return rect_union(&rhs);
165  }
166  uint64_t area(void) const {
167  return (uint64_t)(x1 - x0) * (y1 - y0);
168  }
169  T width() const{
170  return x1 - x0;
171  }
172  T height() const{
173  return y1 - y0;
174  }
175 
176  grk_rectangle<T> pan(int64_t x, int64_t y) const {
177  return grk_rectangle<T>( sat_add<T>((int64_t)x0, (int64_t)x),
178  sat_add<T>((int64_t)y0, (int64_t)y),
179  sat_add<T>((int64_t)x1, (int64_t)x),
180  sat_add<T>((int64_t)y1, (int64_t)y));
181  }
182  grk_rectangle<T>& grow(T boundary) {
183  return grow(boundary, boundary,(std::numeric_limits<T>::max)(),(std::numeric_limits<T>::max)());
184  }
185  grk_rectangle<T>& grow(T boundaryx, T boundaryy) {
186  return grow(boundaryx, boundaryy,(std::numeric_limits<T>::max)(),(std::numeric_limits<T>::max)());
187  }
188  grk_rectangle<T>& grow(T boundary, T maxX, T maxY) {
189  return grow(boundary, boundary,maxX,maxY);
190  }
191  grk_rectangle<T>& grow(T boundaryx, T boundaryy, T maxX, T maxY) {
192  x0 = sat_sub<T>(x0, boundaryx);
193  y0 = sat_sub<T>(y0, boundaryy);
194  x1 = sat_add<T>(x1, boundaryx);
195  y1 = sat_add<T>(y1, boundaryx);
196  if (x1 > maxX)
197  x1 = maxX;
198  if (y1 > maxY)
199  y1 = maxY;
200  return *this;
201  }
202 };
203 
204 using grk_rect = grk_rectangle<int64_t>;
205 using grk_rect_u32 = grk_rectangle<uint32_t>;
206 
207 template <typename T> struct grk_buffer {
208  grk_buffer() : buf(nullptr), offset(0), len(0), owns_data(false)
209  {}
210 
211  grk_buffer(T *buffer, size_t off, size_t length, bool ownsData) : buf(buffer),
212  offset(off),
213  len(length),
214  owns_data(ownsData)
215  {}
216 
217  grk_buffer(T *buffer, size_t length, bool ownsData) : grk_buffer(buffer,0,length,ownsData)
218  {}
219 
220  virtual ~grk_buffer() {
221  dealloc();
222  }
223 
224  void dealloc(){
225  if (owns_data)
226  delete[] buf;
227  buf = nullptr;
228  owns_data = false;
229  offset = 0;
230  len = 0;
231  }
232 
233  size_t get_remaining_length(void){
234  return len - offset;
235  }
236 
237  void incr_offset(ptrdiff_t off) {
238  /* we allow the offset to move to one location beyond end of buffer segment*/
239  if (off > 0 ){
240  if (offset > (size_t)(SIZE_MAX - (size_t)off)){
241  GRK_WARN("grk_buf: overflow");
242  offset = len;
243  } else if (offset + (size_t)off > len){
244  #ifdef DEBUG_SEG_BUF
245  GRK_WARN("grk_buf: attempt to increment buffer offset out of bounds");
246  #endif
247  offset = len;
248  } else {
249  offset = offset + (size_t)off;
250  }
251  }
252  else if (off < 0){
253  if (offset < (size_t)(-off)) {
254  GRK_WARN("grk_buf: underflow");
255  offset = 0;
256  } else {
257  offset = (size_t)((ptrdiff_t)offset + off);
258  }
259  }
260 
261  }
262 
263  T* curr_ptr(){
264  if (!buf)
265  return nullptr;
266  return buf + offset;
267  }
268 
269 
270  T *buf; /* internal array*/
271  size_t offset; /* current offset into array */
272  size_t len; /* length of array */
273  bool owns_data; /* true if buffer manages the buf array */
274 } ;
276 
277 
278 template <typename T> struct grk_buffer_2d : public grk_rect_u32 {
279 
280  grk_buffer_2d(T *buffer,bool ownsData, uint32_t w, uint32_t strd, uint32_t h) : grk_rect_u32(0,0,w,h),
281  data(buffer),
282  owns_data(ownsData),
283  stride(strd)
284  {}
285  grk_buffer_2d(uint32_t w, uint32_t strd, uint32_t h) : grk_buffer_2d(nullptr,false,w,strd,h)
286  {}
287  grk_buffer_2d(uint32_t w, uint32_t h) : grk_buffer_2d(w,0,h)
288  {}
289  explicit grk_buffer_2d(grk_rect_u32 b) : grk_rect_u32(b.x0,b.y0,b.x1,b.y1),
290  data(nullptr),
291  owns_data(false),
292  stride(0)
293  {}
294  grk_buffer_2d(void) : grk_buffer_2d(nullptr,0,0,0,false)
295  {}
296 
297  grk_buffer_2d& operator=(const grk_buffer_2d& rhs) // copy assignment
298  {
299  return operator=(&rhs);
300  }
301  grk_buffer_2d& operator=(const grk_buffer_2d* rhs) // copy assignment
302  {
303  if (this != rhs) { // self-assignment check expected
304  data = rhs->data;
305  owns_data = false;
306  stride = rhs->stride;
307  *((grk_rect_u32*)this) = *((grk_rect_u32*)rhs);
308  }
309  return *this;
310  }
311 
312  virtual ~grk_buffer_2d() {
313  if (owns_data)
315  }
316 
317 
319  x0 = b.x0;
320  x1 = b.x1;
321  y0 = b.y0;
322  y1 = b.y1;
323  }
324 
325  bool alloc(bool clear){
326  if (!data && width() && height()) {
328  uint64_t data_size_needed = (uint64_t)stride * height() * sizeof(T);
329  if (!data_size_needed)
330  return true;
331  data = (T*) grk_aligned_malloc(data_size_needed);
332  if (!data) {
333  grk::GRK_ERROR("Failed to allocate aligned memory buffer of dimensions %u x %u "
334  "@ alignment %d",stride, height(), grk::default_align);
335  return false;
336  }
337  if (clear)
338  memset(data, 0, data_size_needed);
339  owns_data = true;
340  }
341 
342  return true;
343  }
344 
345  // set data to buf without owning it
346  void attach(T* buffer, uint32_t strd){
347  if (owns_data)
349  data = buffer;
350  owns_data = false;
351  stride = strd;
352  }
353  // set data to buf and own it
354  void acquire(T* buffer, uint32_t strd){
355  if (owns_data)
357  buffer = data;
358  owns_data = true;
359  stride = strd;
360  }
361  // transfer data to buf, and cease owning it
362  void transfer(T** buffer, bool* owns, uint32_t *strd){
363  if (buffer && owns){
364  *buffer = data;
365  data = nullptr;
366  *owns = owns_data;
367  owns_data = false;
368  *strd = stride;
369  }
370  }
371 
372  // rhs coordinates are in "this" coordinate system
373  template<typename F> void copy(grk_buffer_2d &rhs, F filter){
374  auto inter = this->intersection(rhs);
375  if (!inter.non_empty())
376  return;
377 
378  T* dest = data + (inter.y0 * stride + inter.x0);
379  T* src = rhs.data + ((inter.y0 - rhs.y0) * rhs.stride + inter.x0 - rhs.x0);
380  uint32_t len = inter.width();
381  for (uint32_t j = inter.y0; j < inter.y1; ++j){
382  filter.copy(dest,src, len);
383  dest += stride;
384  src += rhs.stride;
385  }
386  }
387 
388  T *data; /* internal array*/
389  bool owns_data; /* true if buffer manages the data array */
390  uint32_t stride;
391 } ;
392 
393 
394 }
395 
grk::grk_buffer::grk_buffer
grk_buffer(T *buffer, size_t length, bool ownsData)
Definition: util.h:217
grk::grk_point
Definition: util.h:37
grk::grk_buffer_2d::transfer
void transfer(T **buffer, bool *owns, uint32_t *strd)
Definition: util.h:362
grk::grk_buffer_2d::~grk_buffer_2d
virtual ~grk_buffer_2d()
Definition: util.h:312
grk::grk_buffer
Definition: util.h:207
grk::grk_aligned_free
void grk_aligned_free(void *ptr)
Definition: MemManager.cpp:123
grk::grk_buffer::grk_buffer
grk_buffer(T *buffer, size_t off, size_t length, bool ownsData)
Definition: util.h:211
grk::grk_rectangle
Definition: util.h:76
grk::grk_rectangle::height
T height() const
Definition: util.h:172
grk::mult_will_overflow
bool mult_will_overflow(uint32_t a, uint32_t b)
Definition: util.h:30
grk::grk_buffer::~grk_buffer
virtual ~grk_buffer()
Definition: util.h:220
grk::grk_buffer::offset
size_t offset
Definition: util.h:271
grk::grk_buffer_2d::owns_data
bool owns_data
Definition: util.h:389
grk::grk_rectangle::isContainedIn
bool isContainedIn(const grk_rectangle< T > rhs) const
Definition: util.h:147
logger.h
grk::grk_buffer_2d::acquire
void acquire(T *buffer, uint32_t strd)
Definition: util.h:354
grk::grk_rectangle::grow
grk_rectangle< T > & grow(T boundaryx, T boundaryy, T maxX, T maxY)
Definition: util.h:191
grk::grk_rectangle::grk_rectangle
grk_rectangle(T x0, T y0, T x1, T y1)
Definition: util.h:79
grk::grk_rectangle::grow
grk_rectangle< T > & grow(T boundaryx, T boundaryy)
Definition: util.h:185
grk::grk_rect
grk_rectangle< int64_t > grk_rect
Definition: util.h:47
grk::grk_rectangle::pan
grk_rectangle< T > pan(int64_t x, int64_t y) const
Definition: util.h:176
grk::GRK_WARN
void GRK_WARN(const char *fmt,...)
Definition: logger.cpp:49
grk::grk_buffer_2d::grk_buffer_2d
grk_buffer_2d(uint32_t w, uint32_t h)
Definition: util.h:287
grk::grk_buffer_2d::attach
void attach(T *buffer, uint32_t strd)
Definition: util.h:346
grk::grk_buffer_2d::alloc
bool alloc(bool clear)
Definition: util.h:325
grk::ceildivpow2
T ceildivpow2(T a, uint32_t b)
Definition: grk_intmath.h:37
grk::grk_rectangle::x1
T x1
Definition: util.h:77
grk::grk_rectangle::is_valid
bool is_valid(void) const
Definition: util.h:92
grk::grk_buffer_2d::operator=
grk_buffer_2d & operator=(const grk_buffer_2d &rhs)
Definition: util.h:297
grk::grk_buffer::get_remaining_length
size_t get_remaining_length(void)
Definition: util.h:233
grk::ceildiv
uint32_t ceildiv(T a, T b)
Divide an integer by another integer and round upwards.
Definition: grk_intmath.h:32
grk::grk_buffer::owns_data
bool owns_data
Definition: util.h:273
grk_intmath.h
grk::grk_rectangle::grk_rectangle
grk_rectangle(const grk_rectangle &rhs)
Definition: util.h:82
grk::grk_buffer::curr_ptr
T * curr_ptr()
Definition: util.h:263
grk::grk_rectangle::rect_union
grk_rectangle< T > rect_union(const grk_rectangle< T > *rhs) const
Definition: util.h:157
grk::grk_buffer::dealloc
void dealloc()
Definition: util.h:224
grk::grk_make_aligned_width
uint32_t grk_make_aligned_width(uint32_t width)
Definition: MemManager.cpp:40
grk::grk_point::grk_point
grk_point(T _x, T _y)
Definition: util.h:39
grk::grk_point::x
T x
Definition: util.h:40
grk::grk_rectangle::grow
grk_rectangle< T > & grow(T boundary)
Definition: util.h:182
grk::sat_sub
T sat_sub(T lhs, T rhs)
Definition: util.h:68
grk::grk_buffer::buf
T * buf
Definition: util.h:270
grk::grk_aligned_malloc
void * grk_aligned_malloc(size_t size)
Allocate memory aligned to a 16 byte boundary.
Definition: MemManager.cpp:119
grk::grk_buffer_2d::copy
void copy(grk_buffer_2d &rhs, F filter)
Definition: util.h:373
grk::grk_buffer_2d::operator=
grk_buffer_2d & operator=(const grk_buffer_2d *rhs)
Definition: util.h:301
grk::grk_buffer_2d::grk_buffer_2d
grk_buffer_2d(void)
Definition: util.h:294
grk::grk_point::grk_point
grk_point()
Definition: util.h:38
grk::grk_buffer_2d::stride
uint32_t stride
Definition: util.h:390
grk::grk_rectangle::print
void print(void) const
Definition: util.h:88
grk::grk_rectangle::width
T width() const
Definition: util.h:169
grk::grk_rectangle::contains
bool contains(grk_point< T > pt)
Definition: util.h:98
grk::grk_rectangle::rect_union
grk_rectangle< T > rect_union(const grk_rectangle< T > &rhs) const
Definition: util.h:163
grk::grk_rectangle::intersection
grk_rectangle< T > intersection(const grk_rectangle< T > *rhs) const
Definition: util.h:150
grk::grk_buffer_2d
Definition: util.h:278
grk
Copyright (C) 2016-2021 Grok Image Compression Inc.
Definition: BitIO.cpp:23
grk::grk_point::y
T y
Definition: util.h:41
grk::grk_buffer::len
size_t len
Definition: util.h:272
grk::grk_rectangle::area
uint64_t area(void) const
Definition: util.h:166
grok.h
grk::sat_add
T sat_add(int64_t lhs, int64_t rhs)
Definition: util.h:60
grk::grk_rect_u32
grk_rectangle< uint32_t > grk_rect_u32
Definition: util.h:48
grk::grk_buffer_2d::copy_rect
void copy_rect(grk_rect_u32 b)
Definition: util.h:318
grk::grk_rectangle::intersection
grk_rectangle< T > intersection(const grk_rectangle< T > rhs) const
Definition: util.h:144
grk::grk_buffer::incr_offset
void incr_offset(ptrdiff_t off)
Definition: util.h:237
grk::grk_buffer_2d::grk_buffer_2d
grk_buffer_2d(uint32_t w, uint32_t strd, uint32_t h)
Definition: util.h:285
grk::grk_rectangle::grow
grk_rectangle< T > & grow(T boundary, T maxX, T maxY)
Definition: util.h:188
grk::grk_buffer::grk_buffer
grk_buffer()
Definition: util.h:208
grk::grk_rectangle::rectceildiv
grk_rectangle< T > rectceildiv(uint32_t den) const
Definition: util.h:132
grk::grk_rectangle::operator==
bool operator==(const grk_rectangle< T > &rhs) const
Definition: util.h:112
grk::grk_rectangle::rectceildivpow2
grk_rectangle< T > rectceildivpow2(uint32_t power) const
Definition: util.h:126
grk::grk_rectangle::set_rect
void set_rect(grk_rectangle< T > *rhs)
Definition: util.h:119
grk::grk_rectangle::set_rect
void set_rect(grk_rectangle< T > rhs)
Definition: util.h:123
grk::grk_buffer_2d::data
T * data
Definition: util.h:388
grk::grk_rectangle::operator=
grk_rectangle< T > & operator=(const grk_rectangle< T > &rhs)
Definition: util.h:101
grk::grk_rectangle::x0
T x0
Definition: util.h:77
grk::grk_rectangle::y1
T y1
Definition: util.h:77
grk::clip
T clip(int64_t val)
Definition: util.h:51
grk::grk_rectangle::rectceildiv
grk_rectangle< T > rectceildiv(uint32_t denx, uint32_t deny) const
Definition: util.h:138
grk::mult64_will_overflow
bool mult64_will_overflow(uint64_t a, uint64_t b)
Definition: util.h:33
grk::grk_buffer_2d::grk_buffer_2d
grk_buffer_2d(T *buffer, bool ownsData, uint32_t w, uint32_t strd, uint32_t h)
Definition: util.h:280
grk::grk_buffer_2d::grk_buffer_2d
grk_buffer_2d(grk_rect_u32 b)
Definition: util.h:289
grk::default_align
const size_t default_align
Definition: MemManager.h:28
grk::grk_rectangle::y0
T y0
Definition: util.h:77
SIZE_MAX
#define SIZE_MAX
Definition: MemManager.cpp:33
grk::GRK_ERROR
void GRK_ERROR(const char *fmt,...)
Definition: logger.cpp:57
grk::grk_rectangle::non_empty
bool non_empty(void) const
Definition: util.h:95
grk::grk_rectangle::grk_rectangle
grk_rectangle(void)
Definition: util.h:85